sympy / sympy

A computer algebra system written in pure Python
https://sympy.org/
Other
12.84k stars 4.4k forks source link

MatrixSymbol as a function of a scalar Symbol #23221

Open curvi opened 2 years ago

curvi commented 2 years ago

I've never seen a proper functionality for symbolic matrix manipulation, such as MatrixSymbol in any CAS. Thanks for adding this great feature! I would need one tiny change to it, such that it reveals it's power for the community of robotics and control engineering: the Matrix needs to be dependent on a scalar Symbol, so that I can differentiate w.r.t. this time Symbol. I've asked https://stackoverflow.com/questions/71362669/abstract-matrix-algebra-and-calculus-in-sympy here and found no way to do this (in doc, code, asking, searching,...).

It seems to me there would be some dirty hacks achieving the functionality of some sorts: converting to a matrix and back or similar. However, the greatest thing would be if one could take a Matrix and convert it to a SymbolicMatrix and do some symbolic math with it and then convert back. If this is too difficult having some sort of FunctionalMatrix could also do the trick I think. I'm thinking of a SymbolicMatrix similar to a scalar Function type.

ThePauliPrinciple commented 2 years ago

I agree that it would be useful to have this (I have come across this problem several times before myself, Indexed has the same issue). Although I don't think it is easy to do considering how functions work at the moment in SymPy.

For matrices, it is possible by populating an "explicit" matrix with functions. Like so: afbeelding Note that it actually is possible to get a symbolic derivative of a MatrixSymbol using the Derivative class rather than .diff, you just need to substitute it with something explicit before you .doit().

curvi commented 2 years ago

Yes, thank you. Those ideas are really nice, the problem is just, that for example the entries are easily done using Matrix(Function). Here, I can do all calculations in a nice fashion, but only on scalar element basis. The abstract notation would have a lot of benefits in finding patterns, understanding expressions and dependencies. I'm a researcher... Sadly Derivative cannot apply the differentiation rules for an expression of MatrixSymbols. So it again can only work properly after substitution on elements.

I'm curious why you think this is hard to do - I feel the derivatives w.r.t. MatrixSymbol are much more complex. Maybe we can get a grasp of how this integration would work the best and I can tinker around and maybe this way we could even propose some code snippets. I've never done such intricate things in python, but I could try if I have a better understanding how the result should look exactly.

ThePauliPrinciple commented 2 years ago

I'm curious why you think this is hard to do

Mostly because "functions" in sympy are actually classes, and only become an instance once you make them a "function of something". You can see this in how function is used Function(<name>)(<variable>) with two sets of brackets, the first creating a new class and the second creating a new isntance. So you'd need to create a metaclass version of MatrixSymbol. It is then also not straightforward to make this work with substitutions and possibly other algorithms in SymPy.

You are free to create a PR (very much welcome) to propose a solution, but I wouldn't be able to tell you "how it should look like".

curvi commented 2 years ago

Actually I'm quite motivated for this feature, because it is something that Maple, Mathematica, ..... lack completely. And it is the Number 1 type of calculation we do in control systems, robotics, system engineering, etc.. Also I could guide my colleagues away from maple to sympy - at least a bit :)

Hehe, I think you got me another way here: I was hoping to talk a bit about what a solution should be able to do and from that figure out where it should be seated. Yes, I agree a SymbolicFunctionMatrix class seems appropriate. And yes, I think I know what this means for integration with all the other classes and algorithms.

So basically the class should be manipulated like a MatrixSymbol and act just like a Function. I will try to have a look at those and see if I can figure out how these things work.

oscarbenjamin commented 2 years ago

"functions" in sympy are actually classes

I think that this design for functions is not a good one and ideally would be changed (#4787). It would be better if a function object was just like a symbol that has a __call__ method that creates an expression like Call(f, x).

ThePauliPrinciple commented 2 years ago

I agree that this would be a good way to tackle function, but it doesn't seem straightforward to implement this (especially while keeping backwards competability) I believe there were already several attempts and discussions.

Ideally the object wouldn't be named Call since to me it implies it is something in the context of computer science (I am not aware of the use of the term "call" for functions in a mathematical context, but I could obviously be wrong). Something like Function(FunctionSymbol(...), ...) would have my preference. In addition perhaps even a dedicated variables object rather than using *args would be helpful, so that we can also have functions of symbolic "arbitrary" or "infinite" variables.

It is not clear to me how this helps directly with creating functions of more complex objects though. How would Call (or whatever we name it) then expose matrix properties? Or would we need MatrixCall, IndexedCall etc. Derivative would then also need to expose those properties somehow.

oscarbenjamin commented 2 years ago

especially while keeping backwards competability

Since there is not a MatrixFunction class yet there are no backwards compatibility issues with a new class following a better structure.

curvi commented 2 years ago

I looked at it, but it seems this is well above my league. Especially with a new implementation of Function, I wouldn't know how to make this work properly. As I don't use python regularly and I'm not a software engineer I am stuck at the "know how you would imagine this in terms of code" part. It would be one of the greatest things for me and many colleagues in control and systems engineering, though to have this functionality even in the most basic form of being able to use a function of one scalar.

CallumJHays commented 1 year ago

@curvi I'm looking into this now. I also have a background in Robotics & Control Systems but am a whiz with python and open source. I'm no longer working in Robotics but I've been working on an integrated CAS workflow library that could really use this.

CallumJHays commented 1 year ago

Here's what I have so far. Tests are only simple though - I have yet to try it on any useful application. Usage is as follows:

image