On Wed, Jul 3, 2013 at 2:42 PM, Ondřej Čertík <[email protected]> wrote: > On Wed, Jul 3, 2013 at 3:19 PM, Brian Granger <[email protected]> wrote: >> On Wed, Jul 3, 2013 at 1:42 PM, Ondřej Čertík <[email protected]> >> wrote: >>> On Wed, Jul 3, 2013 at 1:48 PM, Aaron Meurer <[email protected]> wrote: >>>> Brian, I think you dropped off list. Forwarding to sympy. >>>> >>>> Aaron Meurer >>>> >>>> On Wed, Jul 3, 2013 at 2:29 PM, Brian Granger <[email protected]> wrote: >>>>> I think that having multiple dispatch is something that is needed within >>>>> SymPy. Multiple people have run into the difficulties with providing >>>>> custom >>>>> Add/Mul logic for their new types. In quantum, we just punted and used >>>>> the >>>>> builtin Add/Mul logic, but it was a bad compromise to make. >>>>> >>>>> For this, I think looking at Mathematica is really important. This is >>>>> handled by Mathematica's Rules and Patterns which are documented here: >>>>> >>>>> http://reference.wolfram.com/mathematica/guide/RulesAndPatterns.html >>>>> http://reference.wolfram.com/mathematica/tutorial/Introduction-Patterns.html >>>>> >>>>> If we don't have first class, nested and general pattern matching, we >>>>> can't >>>>> do multiple dispatch. The case in point is classes that accept *args such >>>>> as Add and Mul. Good fast pattern matching would also allow us to do much >>>>> of the logic in Add/Mul constructors using patterns: >>>>> >>>>> Add(x_, x_) -> 2*x_ >>>>> Mul(x_, x_) -> x**2 >>> >>> Pattern matching is another way to implement CAS, but I am actually not >>> sure this is how Mathematica works inside. Also in pure Python, this might >>> be really slow (I don't know). I don't see all the little details for >>> pattern matching >>> approach. I think I can see more of the details for the sympy approach >>> though. >>> >>>>> >>>>> etc. >>>>> >>>>> Summary - simple type based dispatch won't do - we need full blown pattern >>>>> matching and transformation logic. >>> >>> Why wouldn't simple type based dispatch work? >>> You might be right, I just want to understand the problem more. >> >> For example take a quantum time evolution operator exp(-I*t*H). What >> if I wanted to develop custom logic for that operator. Simply >> matching on type type (exp) won't work. You need to be able to say: >> >> exp(-I*Numer(x_)*HermitianOperator(y_)) >> >> That requires pattern matching... > > So first of all, since H does not commute, H will not be a Symbol, but > rather an NCSymbol. > Then the "*" in there will not be Mul but NCMul, thanks to our binary > dispatch. > exp can in principle be NCFunction or something.
But that is besides the point - there are infinitely other examples where you need to apply pattern matching logic that is not merely type based. > What kind of custom logic are you thinking of? The automatic canonical > simplification should only be very simple things, most probably in > this case just things that NCMul can do. I am thinking that the automatic canonical simplification logic everywhere in sympy would be replaced by rules+patterns. > Anything more advanced (like perturbation expansion of "exp") should > be implemented as an extra function. I completely agree... >> >>> >>> >>> 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. >>> >>> 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. >>> >>> The general idea is that you create a new type, let's say Infinity and >>> register mul, add, div, sub, pow using dispatch, which specify how >>> your new type should be handled. >>> >>> In particular, it would look something like: >>> >>> @dispatch(Infinity, Basic) >>> def mul(a, b): >>> if isinstance(b, Integer): >>> return a >>> else: >>> return Add(a, b) >> >> But Mul is not a binary operator in SymPy - we could make it so and >> build the overall *args version by repeatedly calling the binary >> version. That would be nice... and would somewhat help our >> situation... > > Roughly that's how it works internally, that you take each term and > try to apply/combine it with all the previous ones. The actual > implementation in sympy has gotten quite complicated over the years. > > 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. > > -- Brian E. Granger Cal Poly State University, San Luis Obispo [email protected] and [email protected] -- 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.
