On Wed, Jul 3, 2013 at 4:40 PM, Ronan Lamy <[email protected]> wrote:
> 2013/7/3 Ondřej Čertík <[email protected]>
>>
>> On Wed, Jul 3, 2013 at 1:48 PM, Aaron Meurer <[email protected]> wrote:
>>
>> Why wouldn't simple type based dispatch work?
>> You might be right, I just want to understand the problem more.
>>
>> To answer Aaron's question:
>>
>> On Wed, Jul 3, 2013 at 12:58 PM, Aaron Meurer <[email protected]> wrote:
>> > So, going back to what we discussed the first time we met in Los
>> > Alamos, how would you reimplement something like the oo logic so that
>> > it lives entirely in the Infinity class, not in Add.flatten (say for
>> > simplicity, oo + 3 should go to oo, but oo + 3*I should remain as oo +
>> > 3*I)?
>>
>> This, and another example is x + O(x). Let's stick to oo + 3.
>
>
> x + O(x) is a bad example, because it should really not be represented by an
> Add.

So the Order class would simply contain both the expression and the
"x", so for example to put this into sympy:

x^2 + x + O(x)

the user would write:

Order(x^2 + x, x)

? I think that's a good idea.

>
>> This is a very good question and it is one of the details that I don't
>> know the answer 100% yet.
>> But I feel it is solvable.
>>
>> I think the best would be to create a demo (from scratch) where we can
>> play with these ideas. Hopefully I'll get to this eventually.
>
>
> How about this: https://github.com/rlamy/sympy/commits/binop ?

Yes! Thanks. Here is how to view changes once you are in this branch:

git diff c84e5df


So I can see that you defined the __pow__ operator in Expr to return
power(a, b) instead of the Power(a, b) class directly. The power(a, b)
is just a function, double dispatched. Then you change all Pow(a, b)
occurrences in sympy to a**b, which gets dispatched to power(a, b)
then. I assume you could have also just changed Power -> power?

Finally power() is then defined as follows:

[email protected](Expr, Expr)
+def _power_basecase(x, y):
+    return Pow(x, y)

[email protected](Expr, One)
+def _pow_Expr_One(x, one):
+    return x

[email protected](One, Expr)
[email protected](One, NaN)
[email protected](One, One)
[email protected](One, Zero)
+def _pow_One_Expr(one, x):
+    return one

etc. (there are some more rules, not important here)

So from this it is clear that power(Expr, One) is used first if
available, otherwise pow(Expr, Expr) is used as a backup plan.

Here are my questions:

* how is performance doing?

* currently your dispatch implementation uses issubclass(c_left, left)
etc., which potentially might be quite slow. Is there any way to just
check the types in a dictionary and only if it is not there, only then
do the slow dispatch that you implemented based on inheritance?

So for example if you put in (Add, One), then on the first run it
would figure out that it should call (Expr, One), and this first run
might be slower, that's ok. But on subsequent runs it would simply
return it from the dictionary directly, so this should be very fast?

Currently we can't use __class__ for it, because:

In [9]: Symbol.__class__
Out[9]: sympy.core.assumptions.ManagedProperties

In [10]: Zero.__class__
Out[10]: sympy.core.singleton.Singleton

In [11]: One.__class__
Out[11]: sympy.core.singleton.Singleton

Due to some sympy metaclasses machinery or something.
But we can create some attribute like _sympy_class_, which would be a
string or a number, unique for each sympy class. User defined types
would write there the name of the class, so that Expr, One, Zero, NaN
would all return unique name.


* What are your other conclusions or impressions from implementing it?

Ondrej

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to