On Thu, Jul 4, 2013 at 12:09 PM, Ronan Lamy <[email protected]> wrote: > 2013/7/4 Ondřej Čertík <[email protected]> >> >> 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. > > > It would rather be something like AsymptoticExpansion(expr, order, > variable), but the user would still write x**2 + x + O(x). ( O(x) would mean > AsymptoticExpansion(0, x, x) ) > >> >> > >> >> 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? > > > No, because pow(x, 2) needs to return something, i.e. a Pow object. If Pow > called pow(), we'd have a circular logic requiring a lot of work to avoid > infinite recursion. > >> 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? > > I don't know. IIRC, I didn't find any benchmark where the speed of pow() > itself made much of a difference. > >> >> >> * 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? > > > Yes, it would be possible to cache the dispatch. There are two problems with > this: > * the cache needs to remain consistent when the dispatch dictionary is > updated - the simplest solution being to clear it every time the dict is > modified. > * the cache could grow quite big, because we have many classes that can be > combined in many ways > > The first issue is just a small matter of programming, but the second one > may be more fundamental and would need to be tested (particularly with add > and mul). >> >> >> 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 we need to use is the class of objects, not their metaclass. Expr, One, > Zero, NaN are unique, hashable objects so we can use them as dictionary > keys.
To clarify something here, Symbol, One, and Zero already *are* classes. You want something like x.__class__ or S(1).__class__. Getting the class of the class does indeed give you the metaclass (that's what metaclasses are). Aaron Meurer > >> >> >> * 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. >> >> > > -- > 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. > > -- 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.
