Here is another idea that might help: What if we *always* mapped the *args logic for operators like Mul/Add to the binary ones:
if len(args)==2: self.dispatch(*args) else: return Mul(Mul(args[0],args[1]),args[2]) etc Then we could focus on the rules and patterns for binary versions. This doesn't solve the issue of needing pattern matching... On Wed, Jul 3, 2013 at 2: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... > >> >> >> 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... > >> This covers most usecases for "oo", since when you construct it in >> Python, you always use the two argument mul(a, b). Also when Add is >> constructed, the algorithm simply takes one term at a time and "adds" >> it to what is in Add already. So those are all binary operations that >> could be overridden in principle. >> >> For example a faster core might decide for speed reasons to not allow >> "oo" and O(x) terms. Then multiple dispatch would pretty much make >> sure that either the fast core will be used if you do add(x, y), but >> slow and more general sympy core will be used if you do add(x, oo). >> >> >> 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. >> >> Ondrej >> >>>> >>>> Cheers, >>>> >>>> Brian >>>> >>>> >>>> On Wednesday, July 3, 2013 10:27:19 AM UTC-7, Aaron Meurer wrote: >>>>> >>>>> No, Add(x, y, z, t) is not just used for fast construction. Any >>>>> algorithm that recurses through an expression tree and rebuilds things >>>>> will rebuild an Add in that way, using expr.func(*expr.args). >>>>> >>>>> Aaron Meurer >>>>> >>>>> On Wed, Jul 3, 2013 at 12:22 PM, Ondřej Čertík <[email protected]> >>>>> wrote: >>>>> > On Wed, Jul 3, 2013 at 11:15 AM, Aaron Meurer <[email protected]> wrote: >>>>> >> I don't think it's so easy, because Add has *args. >>>>> > >>>>> > If you are talking about things like: >>>>> > >>>>> > In [2]: Add(x, x, x, y, x, x) >>>>> > Out[2]: 5⋅x + y >>>>> > >>>>> > Then those are of course needed for fast construction many terms into >>>>> > on Add, but this not really exposed to user's code and it is used >>>>> > inside things like expand(). As such, we can provide a special static >>>>> > method or function for doing the same. On the other hand, if you >>>>> > write: >>>>> > >>>>> > x + x + x + y + x + x >>>>> > >>>>> > in Python, then Python itself will call Symbol.__add__ etc., so this >>>>> > would work well with our new dispatch. >>>>> > >>>>> > -- >>>>> > 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. >> >> > > > > -- > Brian E. Granger > Cal Poly State University, San Luis Obispo > [email protected] and [email protected] -- 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.
