On Mon, May 9, 2011 at 7:42 PM, Ondrej Certik <[email protected]> wrote: > On Mon, May 9, 2011 at 6:39 PM, Ondrej Certik <[email protected]> wrote: >> On Mon, May 9, 2011 at 6:33 PM, Aaron Meurer <[email protected]> wrote: >>> On Mon, May 9, 2011 at 7:30 PM, Ronan Lamy <[email protected]> wrote: >>>> Le lundi 09 mai 2011 à 17:30 -0700, Luke a écrit : >>>>> Here is a more explicit example of what Gilbert is talking about: >>>>> In [1]: from sympy import * >>>>> In [2]: from pydy import * >>>>> In [3]: x = symbols('x') >>>>> In [4]: N = ReferenceFrame('N') >>>>> In [5]: type(N[1]) >>>>> Out[5]: pydy.pydy.UnitVector >>>>> In [9]: test = x*N[1] + x*x*N[2] >>>>> In [10]: type(test) >>>>> Out[10]: sympy.core.add.Add >>>>> In [11]: test2 = Vector(test) >>>>> In [12]: test2 >>>>> Out[12]: x*n1> + x**2*n2> >>>>> In [13]: type(test2) >>>>> Out[13]: pydy.pydy.Vector >>>>> In [14]: test3 = x*test2 >>>>> In [15]: test3 >>>>> Out[15]: x*x*n1> + x**2*n2> >>>>> In [16]: type(test3) >>>>> Out[16]: sympy.core.mul.Mul >>>>> >>>>> As you can see, in Out[15], the multiplication of x and test2 is being >>>>> printed in a way that doesn't make sense, and in Out[16] we can see >>>>> that this multiplication isn't resulting in another Vector object, >>>>> instead it is of type Mul. >>>>> >>>>> Currently, to create a Vector object, you need to explicitly call >>>>> Vector on a sympy expression that is composed from terms that have >>>>> UnitVectors in them, or pass a dictionary with UnitVectors as the keys >>>>> and sympy expressions as the values. >>>>> >>>>> Once you have that Vector object, you might want to multiply it by a >>>>> scalar (sympy expression) and have it return another Vector object. >>>>> This could be done using a somewhat user unfriendly approach: >>>>> >>>>> In [22]: Vector(dict([(k, x*v) for k, v in test2.dict.items()])) >>>>> Out[22]: x**2*n1> + x**3*n2> >>>>> >>>>> This gets the job done, but it isn't very convenient. >>>>> >>>>> So basically, the question is whether >>>>> 1) Is it easy enough in Sympy to make something like x*aVectorObject >>>>> evaluate to another Vector object? Where the x is a "scalar part" >>>>> (probably a sympy Expression) and aVectorObject is of type Vector >>>>> (which currently subclasses from Basic)? >>>> >>>> No, currently, it's not possible to do it correctly. Expr objects don't >>>> expect to be multiplied by non-Expr objects. However, changing this >>>> should be possible: you'd have to add to all relevant __mul__ methods >>>> something like 'if not isinstance(other, Expr): return NotImplemented'. >>>> And then, you'll only have to fight Python's labyrinthine model for >>>> double-dispatch inside your vector classes. >>> >>> Oh, OK, so you were thinking the same thing that I was. Yes, let's do >>> this then. It seems to make the most sense. Expr is supposed to be >>> only mathematical objects, like things that can be part of a Mul, so >>> allowing non-Exprs to multiply Exprs doesn't make much sense. >> >> That'd be great to allow people to extend sympy with their own objects. >> >> So is the proposal to try to coerce an object to an Expr instance, so >> things like Symbol, Python int, etc. would succeed, and if so, Expr >> will take over. Otherwise the other non Expr instance will be given a >> chance to take over the operation (no matter which side you operate on >> the Expr object)? If this can be implemented, that'd be great. >> >> But I thought that exactly this was already implemented using the >> _op_priority, see sympy/core/expr.py, line 22: >> >> # Expr and its sublcasses use _op_priority to determine which object >> # passed to a binary special method (__mul__, etc.) will handle the >> # operation. In general, the 'call_highest_priority' decorator will choose >> # the object with the highest _op_priority to handle the call. >> # Custom subclasses that want to define their own binary special methods >> # should set an _op_priority value that is higher than the default. >> _op_priority = 10.0 >> >> >> What am I missing? > > For usage, see: > > sympy/core/tests/test_priority.py > > Ondrej >
I think the difference is that op_priority allows other Expr objects to take higher precedence. The idea here is that Expr shouldn't even try to include non-Expr (i.e., Basic only) objects, because it doesn't make sense. And example of an object that is Basic but not Expr is Tuple. Why do we allow this: In [9]: Tuple(x, y)*x Out[9]: x⋅Tuple(x, y) In [10]: x*Tuple(x, y) Out[10]: x⋅Tuple(x, y) It doesn't make sense. If it did, then Tuple would have been Expr. That's the whole reason why we split Basic and Expr, I thought. Aaron Meurer -- 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.
