On Mon, May 9, 2011 at 7:42 PM, Ondrej Certik <ond...@certik.cz> wrote:
> On Mon, May 9, 2011 at 6:39 PM, Ondrej Certik <ond...@certik.cz> wrote:
>> On Mon, May 9, 2011 at 6:33 PM, Aaron Meurer <asmeu...@gmail.com> wrote:
>>> On Mon, May 9, 2011 at 7:30 PM, Ronan Lamy <ronan.l...@gmail.com> 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 sympy@googlegroups.com.
To unsubscribe from this group, send email to 
sympy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sympy?hl=en.

Reply via email to