I agree with Julien that vectorization is a different question. The question at hand is (I think) the following:
We have a function simplify that tries to reduce the complexity of a scalar expression (for example by turning y* x / y into x). We have grown accustomed to asking SymPy to reduce the complexity of an object by calling `simplify(object)`. Should we extend the meaning of simplify to non-Exprs? Many classes know some way to reduce their complexity. For example matrices have a Matrix.simplify() method. Some sets like Union and Intersection have a Set.reduce() method. Should we expose these methods through simplify? I.e. do we want things like the following to work `simplify(Set)` ? On Tue, Oct 16, 2012 at 8:05 AM, Julien Rioux <[email protected]>wrote: > Hi, > > > On Tuesday, 16 October 2012 07:48:52 UTC+2, Aaron Meurer wrote: >> >> I think the real question here is, do we want most functions in sympy >> to automatically vectorize over matrices (or similar objects)? And I >> think the answer is no. > > > > I'm not sure how you end up at this question, but fine. The answer is no. > I'm fine with that. > > > >> > Consider for example if we had an unevaluated >> Matrix type that didn't multiply through by default (what >> ImmutableMatrix used to be). We might want something like >> simplify(A*B + A*C) to give A*(B + C), where A, B, and C are all >> explicit unevaluated matrices. >> >> > Sure, we might want that. Simplifying a MatAdd or MatMul should be > implemented, too. Of course what we mean by "simpler" is always ambiguous. > There might be different "strategies", but simplify is the general one. The > point is that it actually works right now to some extend: > > In [9]: A = ImmutableMatrix(2, 2, [x*y + x*z, 0, 0, 0]) > > In [10]: B = ImmutableMatrix(2, 2, [x*y + x*z, 0, 0, 1]) > > In [11]: C = ImmutableMatrix(2, 2, [x*y + x*z, 1, 1, 0]) > > In [12]: A*B + A*C # automatically evaluated > Out[12]: > [ 2 ] > [2*(x*y + x*z) x*y + x*z] > [ ] > [ 0 0 ] > > In [13]: simplify(A*B + A*C) > Out[13]: > [ 2 2 ] > [2*x *(y + z) x*(y + z)] > [ ] > [ 0 0 ] > > In [14]: MatAdd(MatMul(A, B), MatMul(A, C)) # unevaluated > Out[14]: > [x*y + x*z 0]*[x*y + x*z 0] + [x*y + x*z 0]*[x*y + x*z 1] > [ ] [ ] [ ] [ ] > [ 0 0] [ 0 1] [ 0 0] [ 1 0] > > In [15]: simplify(MatAdd(MatMul(A, B), MatMul(A, C))) > Out[15]: > [x*(y + z) 0]*[x*(y + z) 0] + [x*(y + z) 0]*[x*(y + z) 1] > [ ] [ ] [ ] [ ] > [ 0 0] [ 0 1] [ 0 0] [ 1 0] > > Should it work better? yes absolutely. We see that it doesn't factor out > the identical part. But why should it be removed? > > >> It's similar to the reason that solve() does not automatically call >> dsolve() on ODEs. It's useful to be able solve for the function >> algebraically, i.e., both >> >> >>> dsolve(f(x).diff(x, x) + f(x) - 1, f(x)) >> f(x) == C1*sin(x) + C2*cos(x) + 1 >> >> and >> >> >>> solve(f(x).diff(x, x) + f(x) - 1, f(x)) >> [-Derivative(f(x), x, x) + 1] >> >> can be useful. >> >> > > So you mean that solving a differential equation for f(x) is ambiguous. At > least here, we can identify two clearly distinct strategies, and define a > function for each approach. It sure can be useful to have both. There are > such different "strategies" in the simplify module. One could think of > strategies specific to matrices, I guess. simplify itself has been the > wrapper around those strategies. > > >> Another good argument for matrices is exp(). We want exp(Matrix) to >> give the exponential of a Matrix, which is not the matrix of >> exponentials. And actually you can define f(Matrix) for any analytic >> f. > > > > To map mathematical functions to each element of the matrix does not make > mathematical sense to me. If we were talking about an Array type, maybe. > > >> Won't it be a little confusing if math_function(Matrix) works >> different from simplify_function(Matrix)? > > > > At least not to me. These are vastly different things. > > >> And again, what if you have >> simplify_function(combination_**of_math_functions(unevaluated_**matrices))? >> >> >> > > I suppose what would happen is something akin to > > In [16]: sin(x*y + x*z) > Out[16]: sin(x*y + x*z) > > In [17]: simplify(sin(x*y + x*z)) > Out[17]: sin(x*(y + z)) > > Well yes it is in fact what happens: > > In [23]: sin(A) > Out[23]: > sin/[x*y + x*z 0]\ > |[ ]| > \[ 0 0]/ > > In [24]: simplify(sin(A)) > Out[24]: > sin/[x*(y + z) 0]\ > |[ ]| > \[ 0 0]/ > > Now I can't use sin(MatAdd), that does not currently work, but I would > expect it to, and calling simplify on that would, you know, simplify the > argument of the sin(). > > > >> And aside from that, automatic vectorization would be a mess, because >> only the most popular functions would support it, and the rest >> wouldn't. So we would end up with a situation where function `a` >> works as expected, but very similar function `b` doesn't, and it's not >> clear why (and even if `b` doesn't support it, it doesn't mean that >> Matrix defines `_b`). It's similar to automatic sympification of >> strings that some but not all SymPy functions support. >> >> Aaron Meurer >> >> > > I don't want automatic map of a function to all elements of a matrix, > either. You introduced that idea. > > Regards, > Julien > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To view this discussion on the web visit > https://groups.google.com/d/msg/sympy/-/-eALL2LJk7kJ. > > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. > -- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
