On Fri, Mar 10, 2017 at 7:31 PM, Richard Fateman <fate...@gmail.com> wrote: > There is a version of Albert Rich's project that > uses if-then-else rather than a rule set.
I'm unclear, how do you have if-then-else that isn't pattern matching? If you have some input expression, say (1 + 2*x)**n you have to know if it looks like a given rule (in this case, (a + b*x)**n) , and what the various constants are (a = 1, b = 2, n = n) to apply it. So you have to pattern match it one way or the other. But maybe I'm missing something. > > Writing a pattern matcher that mimicks Mathematica's pattern > matcher would be irrelevant if you used that alternative. > > On the other hand, mimicking Mathematica might have other > uses. There are at least 2 in the open source; one in Lisp, > which I wrote, and another in the Mathics project, written in > python (!) Mathics uses SymPy as the symbolic backend. So that is an interesting idea. It is currently licensed incompatibly (GPL). We might want to ask the author (Angus Griffith) if he would be willing to relicense the matching code (assuming it is something that can be easily reused for SymPy). Aaron Meurer > RJF > > On Friday, March 10, 2017 at 1:16:19 PM UTC-8, Aaron Meurer wrote: >> >> I recommend using the method I outlined above to figure out which >> algorithm is actually handling this. Or just run integrate() through a >> debugger. >> >> For the pattern matching integrator, there is a discussion in another >> thread here on how to make patterns match expressions that are >> mathematically equivalent, but don't match exactly. >> >> Aaron Meurer >> >> On Fri, Mar 10, 2017 at 9:05 AM, Abdullah Javed Nesar >> <abdulja...@gmail.com> wrote: >> > Aaron in case like this, >> > >> >>>> integrate(E**(n*log(a+b*x)), x) >> > ⎧⎩⎨1blog(ab+x)abn+benlog(a+bx)+bxbn+benlog(a+bx)forn=−1otherwise >> > E**(n*log(a+b*x))should better be simplified to (a+b*x)**n to proceed >> > further, can you tell me how SymPy currently handles such cases? >> > >> > Abdullah Javed Nesar >> > On Thursday, March 9, 2017 at 11:54:32 PM UTC+5:30, Aaron Meurer wrote: >> >> >> >> Can you clarify what you mean by this? >> >> >> >> Aaron Meurer >> >> >> >> On Thu, Mar 9, 2017 at 1:14 PM Abdullah Javed Nesar >> >> <abdulja...@gmail.com> >> >> wrote: >> >>> >> >>> Hi, >> >>> >> >>> I am not able to figure out how exactly we will use replacement >> >>> allowing >> >>> technique in Rubi and when do we use it, can anyone explain this? >> >>> >> >>> Thanks. >> >>> >> >>> >> >>> On Thursday, March 9, 2017 at 9:47:10 PM UTC+5:30, Abdullah Javed >> >>> Nesar >> >>> wrote: >> >>>> >> >>>> Hi, >> >>>> Arihant thanks for those suggestions, I guess if rule name contains >> >>>> Algebraic then just >> >>>> >> >>>> >>> def rule_algebraic_integrand_1_1(expr, symbol) >> >>>> >> >>>> would suffice, no need for >>>def >> >>>> rule_algebraic_integrand_1_1_1_1(expr, >> >>>> symbol) (indicating algebraic integrand>linear product>(a + >> >>>> b*x)**m). Yes, >> >>>> this way the functions would be named in a systematic way, >> >>>> necessarily >> >>>> supported by a docstring which would explain those rules in details, >> >>>> as >> >>>> Aaron pointed. >> >>>> >> >>>> Pattern matching used in manualintegrate() is a simple one without a >> >>>> decision tree and hence less efficient. The tree for (a + b*x)**m >> >>>> would be >> >>>> better represented as >> >>>> Pow(Add(a, Mul(b, x)), m), well explained in #7748. >> >>>> >> >>>> >> >>>> On Thursday, March 9, 2017 at 3:36:30 PM UTC+5:30, Arihant Parsoya >> >>>> wrote: >> >>>>> >> >>>>> Thanks Aaron, >> >>>>> >> >>>>> I read the discussion to improve pattern matching algorithm. Can you >> >>>>> give some information about which algorithm is currently being used >> >>>>> for >> >>>>> pattern matching? >> >>>>> >> >>>>> I have been testing `match()` to check if it works properly for >> >>>>> complex >> >>>>> expressions. It gives correct answer if we `exclude` the integration >> >>>>> variable. However, there can be issues in matching expression when >> >>>>> brackets >> >>>>> are automatically evaluated by SymPy: >> >>>>> >> >>>>> >>> x, y, z, F, fx = symbols('x, y, z, F, fx') >> >>>>> >> >>>>> >>> a = Wild('a', exclude=[x]) >> >>>>> >> >>>>> >>> b = Wild('b', exclude=[x]) >> >>>>> >> >>>>> >>> c = Wild('c', exclude=[x]) >> >>>>> >> >>>>> >>> d = Wild('d', exclude=[x]) >> >>>>> >> >>>>> >>> e = Wild('e', exclude=[x]) >> >>>>> >> >>>>> >>> f = Wild('f', exclude=[x]) >> >>>>> >> >>>>> >>> g = Wild('g', exclude=[x]) >> >>>>> >> >>>>> >>> p = Wild('p', exclude=[x]) >> >>>>> >> >>>>> >>> n = Wild('n', exclude=[x]) >> >>>>> >> >>>>> >>> m = Wild('m', exclude=[x]) >> >>>>> >> >>>>> >>> expr = ((1 + 2*x)**3) * ((F**(4*(5 + fx)))**6) * (6 + >> >>>>> >>> 7*(F**(4*(5 + >> >>>>> >>> fx))))**8 >> >>>>> >> >>>>> >>> pattern = ((c + d*x)**m) * ((F**(g*(e + fx)))**n) * (a + >> >>>>> >>> b*(F**(g*(e + fx))))**p >> >>>>> >> >>>>> >>> pprint(pattern) >> >>>>> >> >>>>> p n >> >>>>> >> >>>>> ⎛ g⋅(fx + e) ⎞ m ⎛ g⋅(fx + e)⎞ >> >>>>> >> >>>>> ⎝F ⋅b + a⎠ ⋅(x⋅d + c) ⋅⎝F ⎠ >> >>>>> >> >>>>> >>> pprint(expr) >> >>>>> >> >>>>> 8 >> >>>>> >> >>>>> 24⋅fx + 120 ⎛ 4⋅fx + 20 ⎞ 3 >> >>>>> >> >>>>> F ⋅⎝7⋅F + 6⎠ ⋅(2⋅x + 1) >> >>>>> >> >>>>> >>> expr.match(pattern) >> >>>>> >> >>>>> {p_: 1, g_: 1, m_: 3, d_: 2, n_: 0, e_: 23*fx + 120, c_: 1, a_: 0, >> >>>>> b_: >> >>>>> (7*F**(4*fx + 20) + 6)**8} >> >>>>> >> >>>>> >> >>>>> We need to find a way to convert the expresison into known standard >> >>>>> form so pattern matching can be done peoperly or implement such >> >>>>> functionality in `.match()` itself. >> >>>>> >> >>>>> >> >>>>> Thanks >> >>>>> >> >>>>> >> >>>>> >> >>>>> On Thursday, March 9, 2017 at 12:16:41 AM UTC+5:30, Aaron Meurer >> >>>>> wrote: >> >>>>>> >> >>>>>> That's sounds fine, though it should also include a docstring that >> >>>>>> lists the rule so we don't have to depend on the Rubi site. This >> >>>>>> will also >> >>>>>> let us generate some documentation on what rules are supported. >> >>>>>> >> >>>>>> We will likely want to extend the rules beyond what Rubi has >> >>>>>> eventually, so we should also consider that. >> >>>>>> >> >>>>>> Aaron Meurer >> >>>>>> >> >>>>>> On Wed, Mar 8, 2017 at 12:07 PM Arihant Parsoya >> >>>>>> <parsoya...@gmail.com> >> >>>>>> wrote: >> >>>>>>> >> >>>>>>> Hi, >> >>>>>>> >> >>>>>>> I observed that rules in manualintegrate() are countable in >> >>>>>>> number. >> >>>>>>> While implementing ~7000 rules, naming each rule is also going to >> >>>>>>> be a big >> >>>>>>> issue. I was thinking, names should be given based on the serial >> >>>>>>> number of >> >>>>>>> the rule in Rubi website. For example algebric rules for linear >> >>>>>>> products >> >>>>>>> should be named as: >> >>>>>>> >> >>>>>>> >>> def rule_algebric_integrand_1_1_1_1(expr, symbol): >> >>>>>>> >> >>>>>>> ... return log(expr) >> >>>>>>> >> >>>>>>> >> >>>>>>> Using the above syntax for names of rules, we will be able to >> >>>>>>> uniquely identify each rule. Is this desirable? >> >>>>>>> >> >>>>>>> Thanks, >> >>>>>>> Arihant Parsoya >> >>>>>>> >> >>>>>>> On Monday, March 6, 2017 at 10:44:41 PM UTC+5:30, Abdullah Javed >> >>>>>>> Nesar wrote: >> >>>>>>>> >> >>>>>>>> Hi, >> >>>>>>>> >> >>>>>>>> I was looking into sympy.integrals.manualintegrate.py it seems >> >>>>>>>> that >> >>>>>>>> the pattern matching (in manualintegrate) is quite different from >> >>>>>>>> what is >> >>>>>>>> expected in Rubi. As PR #7748 mentions we'll be using a better >> >>>>>>>> approach >> >>>>>>>> using decision tree, can you elaborate on what is expected? How >> >>>>>>>> decision >> >>>>>>>> tree concludes to a rule of integration then falls into function >> >>>>>>>> integrate() >> >>>>>>>> which contains rules like 1.1.1 (a + b*x)**m? >> >>>>>>>> >> >>>>>>>> Abdullah Javed Nesar >> >>>>>>>> >> >>>>>>>> On Monday, March 6, 2017 at 2:59:38 AM UTC+5:30, Aaron Meurer >> >>>>>>>> wrote: >> >>>>>>>>> >> >>>>>>>>> integrate() uses several algorithms, and one or more algorithms >> >>>>>>>>> may >> >>>>>>>>> apply to any specific integral. Some algorithms, if you know how >> >>>>>>>>> they >> >>>>>>>>> work, you can easily see if they won't apply to a specific >> >>>>>>>>> integrand. >> >>>>>>>>> The best way to tell how it works for a specific integral is to >> >>>>>>>>> check >> >>>>>>>>> the various algorithms. Another thing that I highly suggest is >> >>>>>>>>> to >> >>>>>>>>> run >> >>>>>>>>> the integrate() function through a debugger, so you can see how >> >>>>>>>>> it >> >>>>>>>>> works (I like PuDB, but any debugger that you are comfortable >> >>>>>>>>> with >> >>>>>>>>> will work). >> >>>>>>>>> >> >>>>>>>>> Here are the algorithms used by integrate() (I hope I didn't >> >>>>>>>>> forget >> >>>>>>>>> any). You can import each algorithm from the specified module >> >>>>>>>>> to >> >>>>>>>>> try >> >>>>>>>>> it >> >>>>>>>>> >> >>>>>>>>> sympy.integrals.risch.risch_integrate() - Risch algorithm. >> >>>>>>>>> Currently >> >>>>>>>>> only works for transcendental equations with exp() and log(). >> >>>>>>>>> >> >>>>>>>>> sympy.integrals.manualintegrate.manualintegrate() - Manual >> >>>>>>>>> integration. That means, integration akin to how you would do >> >>>>>>>>> things >> >>>>>>>>> by hand. This is very similar to Rubi in that it does pattern >> >>>>>>>>> matching >> >>>>>>>>> against some rules. Ideally any implementation of Rubi would >> >>>>>>>>> merge >> >>>>>>>>> with manualintegrate() so we don't have two pattern matching >> >>>>>>>>> integrators. >> >>>>>>>>> >> >>>>>>>>> sympy.integrals.trigonometry.trigintegrate() - Integrate trig >> >>>>>>>>> functions. Also uses pattern matching. >> >>>>>>>>> >> >>>>>>>>> sympy.integrals.rationaltools.ratint() - Integrate rational >> >>>>>>>>> functions. >> >>>>>>>>> >> >>>>>>>>> sympy.integrals.meijerint.meijerg_definite() and >> >>>>>>>>> sympy.integrals.meijerint.meijerg_indefinite() - Integration >> >>>>>>>>> using >> >>>>>>>>> the >> >>>>>>>>> Meijer G algorithm (roughly, by translating the integral to a >> >>>>>>>>> Meijer >> >>>>>>>>> G-function, integrating, then translating back). >> >>>>>>>>> >> >>>>>>>>> sympy.integrals.heurisch.heurisch() - The heuristic Risch >> >>>>>>>>> algorithm. >> >>>>>>>>> This is tried last, because it can be very slow (sometimes >> >>>>>>>>> hanging >> >>>>>>>>> the >> >>>>>>>>> integrator), but there are cases where only it can produce an >> >>>>>>>>> answer. >> >>>>>>>>> >> >>>>>>>>> You should be able to apply any of these functions directly on >> >>>>>>>>> an >> >>>>>>>>> integrand to see if they can produce an answer. >> >>>>>>>>> >> >>>>>>>>> The algorithms are tried in order until one gives an answer. I >> >>>>>>>>> don't >> >>>>>>>>> remember exactly what order, but I think it's similar to the >> >>>>>>>>> above. >> >>>>>>>>> I >> >>>>>>>>> do know that heurisch() is last, because it's the worst. >> >>>>>>>>> >> >>>>>>>>> Aaron Meurer >> >>>>>>>>> >> >>>>>>>>> >> >>>>>>>>> On Sun, Mar 5, 2017 at 12:00 PM, Abdullah Javed Nesar >> >>>>>>>>> <abdulja...@gmail.com> wrote: >> >>>>>>>>> > Hi Aaron, >> >>>>>>>>> > >> >>>>>>>>> > Thanks for your explanation. >> >>>>>>>>> > >> >>>>>>>>> > How does SymPy evaluates integrals like, >> >>>>>>>>> > >> >>>>>>>>> >>>integrate((a + b*u)**m, x) when u = c + dx (i.e. Integration >> >>>>>>>>> >>> by >> >>>>>>>>> >>> substitution) >> >>>>>>>>> > >> >>>>>>>>> > I couldn't find such an example can give one? >> >>>>>>>>> > >> >>>>>>>>> > Abdullah Javed Nesar >> >>>>>>>>> > >> >>>>>>>>> > On Sunday, March 5, 2017 at 11:58:20 AM UTC+5:30, Aaron Meurer >> >>>>>>>>> > wrote: >> >>>>>>>>> >> >> >>>>>>>>> >> The SymPy assumptions system lets you define x = Symbol('x', >> >>>>>>>>> >> positive=True) (and query like x.is_positive). The pattern >> >>>>>>>>> >> matcher >> >>>>>>>>> >> will need to be able to set and define restrictions like >> >>>>>>>>> >> this. >> >>>>>>>>> >> Also >> >>>>>>>>> >> note that expand_log() and logcombine() already expand and >> >>>>>>>>> >> combine >> >>>>>>>>> >> logarithms and check the domain restrictions. >> >>>>>>>>> >> >> >>>>>>>>> >> Another thing is that the integrator should return a >> >>>>>>>>> >> Piecewise >> >>>>>>>>> >> whenever possible. For example, the current integrator: >> >>>>>>>>> >> >> >>>>>>>>> >> In [6]: integrate(x**n, x) >> >>>>>>>>> >> Out[6]: >> >>>>>>>>> >> ⎧log(x) for n = -1 >> >>>>>>>>> >> ⎪ >> >>>>>>>>> >> ⎪ n + 1 >> >>>>>>>>> >> ⎨x >> >>>>>>>>> >> ⎪────── otherwise >> >>>>>>>>> >> ⎪n + 1 >> >>>>>>>>> >> ⎩ >> >>>>>>>>> >> >> >>>>>>>>> >> This way we get results that are mathematically correct, even >> >>>>>>>>> >> when >> >>>>>>>>> >> assumptions aren't set. >> >>>>>>>>> >> >> >>>>>>>>> >> Aaron Meurer >> >>>>>>>>> >> >> >>>>>>>>> >> On Thu, Mar 2, 2017 at 8:56 AM, Abdullah Javed Nesar >> >>>>>>>>> >> <abdulja...@gmail.com> wrote: >> >>>>>>>>> >> > Hi Ondřej, >> >>>>>>>>> >> > >> >>>>>>>>> >> > I am willing to work on Rubi Integrator this summer. I went >> >>>>>>>>> >> > through the >> >>>>>>>>> >> > issues you raised for this project and this idea really >> >>>>>>>>> >> > sounds >> >>>>>>>>> >> > cool. It >> >>>>>>>>> >> > would be great to segregate the different methods of >> >>>>>>>>> >> > integration into a >> >>>>>>>>> >> > decision tree which would hence improve its performance. >> >>>>>>>>> >> > >> >>>>>>>>> >> > Before implementing Rule-based integrator we need to >> >>>>>>>>> >> > implement >> >>>>>>>>> >> > fast >> >>>>>>>>> >> > pattern >> >>>>>>>>> >> > matching/replacement for the set of 10,000 rules so we need >> >>>>>>>>> >> > to >> >>>>>>>>> >> > plan out >> >>>>>>>>> >> > an >> >>>>>>>>> >> > efficient decision tree for it. >> >>>>>>>>> >> > >> >>>>>>>>> >> > log(x*y) -> log(x) + log(y); x > 0, y > 0 >> >>>>>>>>> >> > >> >>>>>>>>> >> > >> >>>>>>>>> >> > In the above example how do we exactly move on with domain >> >>>>>>>>> >> > restrictions >> >>>>>>>>> >> > (i.e. x, y). >> >>>>>>>>> >> > >> >>>>>>>>> >> > On Wednesday, March 1, 2017 at 8:39:41 PM UTC+5:30, Ondřej >> >>>>>>>>> >> > Čertík wrote: >> >>>>>>>>> >> >> >> >>>>>>>>> >> >> Hi, >> >>>>>>>>> >> >> >> >>>>>>>>> >> >> Here is a project that I would love to see happen: >> >>>>>>>>> >> >> >> >>>>>>>>> >> >> https://github.com/sympy/sympy/issues/12233 >> >>>>>>>>> >> >> >> >>>>>>>>> >> >> I am available to mentor it, and I think quite a few >> >>>>>>>>> >> >> people >> >>>>>>>>> >> >> are >> >>>>>>>>> >> >> excited about it and such a system/framework (i.e. set of >> >>>>>>>>> >> >> rules for >> >>>>>>>>> >> >> patter matching + compiler to generate a fast if/then/else >> >>>>>>>>> >> >> decision >> >>>>>>>>> >> >> tree) would have applications beyond just integration, but >> >>>>>>>>> >> >> integration >> >>>>>>>>> >> >> would already be super useful. As you can browse on Rubi >> >>>>>>>>> >> >> web >> >>>>>>>>> >> >> page, the >> >>>>>>>>> >> >> integrator's capabilities are very impressive, i.e. the >> >>>>>>>>> >> >> rule >> >>>>>>>>> >> >> based >> >>>>>>>>> >> >> system Rubi 4.9 can do more integrals than Mathematica, >> >>>>>>>>> >> >> and >> >>>>>>>>> >> >> is about >> >>>>>>>>> >> >> as fast, due to the large number of rules, and the >> >>>>>>>>> >> >> if/then/else >> >>>>>>>>> >> >> decision tree Rubi 5 promises an order of magnitude (or >> >>>>>>>>> >> >> more) >> >>>>>>>>> >> >> speedup, >> >>>>>>>>> >> >> but it's still in development. >> >>>>>>>>> >> >> >> >>>>>>>>> >> >> The project is big in scope, so there could even be >> >>>>>>>>> >> >> multiple >> >>>>>>>>> >> >> projects. >> >>>>>>>>> >> >> If anybody is interested in this, please get in touch, and >> >>>>>>>>> >> >> try to >> >>>>>>>>> >> >> propose a good plan. >> >>>>>>>>> >> >> >> >>>>>>>>> >> >> 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 sympy+un...@googlegroups.com. >> >>>>>>>>> >> > To post to this group, send email to >> >>>>>>>>> >> > sy...@googlegroups.com. >> >>>>>>>>> >> > Visit this group at https://groups.google.com/group/sympy. >> >>>>>>>>> >> > To view this discussion on the web visit >> >>>>>>>>> >> > >> >>>>>>>>> >> > >> >>>>>>>>> >> > >> >>>>>>>>> >> > https://groups.google.com/d/msgid/sympy/05a4ee3e-7a0b-485b-9918-0a68bb4f3350%40googlegroups.com. >> >>>>>>>>> >> > >> >>>>>>>>> >> > For more options, visit https://groups.google.com/d/optout. >> >>>>>>>>> > >> >>>>>>>>> > -- >> >>>>>>>>> > 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 sympy+un...@googlegroups.com. >> >>>>>>>>> > To post to this group, send email to sy...@googlegroups.com. >> >>>>>>>>> > Visit this group at https://groups.google.com/group/sympy. >> >>>>>>>>> > To view this discussion on the web visit >> >>>>>>>>> > >> >>>>>>>>> > >> >>>>>>>>> > https://groups.google.com/d/msgid/sympy/0cc84418-0eac-4ab2-b975-c74eeec47d64%40googlegroups.com. >> >>>>>>>>> > >> >>>>>>>>> > For more options, visit https://groups.google.com/d/optout. >> >>>>>>> >> >>>>>>> -- >> >>>>>>> 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 sympy+un...@googlegroups.com. >> >>>>>>> To post to this group, send email to sy...@googlegroups.com. >> >>>>>>> Visit this group at https://groups.google.com/group/sympy. >> >>>>>>> To view this discussion on the web visit >> >>>>>>> >> >>>>>>> https://groups.google.com/d/msgid/sympy/8efee19b-fedd-4188-b00f-e68ecf288eb5%40googlegroups.com. >> >>>>>>> For more options, visit https://groups.google.com/d/optout. >> >>> >> >>> -- >> >>> 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 sympy+un...@googlegroups.com. >> >>> To post to this group, send email to sy...@googlegroups.com. >> >>> Visit this group at https://groups.google.com/group/sympy. >> >>> To view this discussion on the web visit >> >>> >> >>> https://groups.google.com/d/msgid/sympy/6e64ae8e-2c19-49ca-9d74-fb873ac77112%40googlegroups.com. >> >>> For more options, visit https://groups.google.com/d/optout. >> > >> > -- >> > 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 sympy+un...@googlegroups.com. >> > To post to this group, send email to sy...@googlegroups.com. >> > Visit this group at https://groups.google.com/group/sympy. >> > To view this discussion on the web visit >> > >> > https://groups.google.com/d/msgid/sympy/2d53f1c8-52b3-4a0a-89af-bf70d83d4df1%40googlegroups.com. >> > >> > For more options, visit https://groups.google.com/d/optout. > > -- > 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 sympy+unsubscr...@googlegroups.com. > To post to this group, send email to sympy@googlegroups.com. > Visit this group at https://groups.google.com/group/sympy. > To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/65969745-6320-4861-b193-b7844e00c8f8%40googlegroups.com. > > For more options, visit https://groups.google.com/d/optout. -- 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 sympy+unsubscr...@googlegroups.com. To post to this group, send email to sympy@googlegroups.com. Visit this group at https://groups.google.com/group/sympy. To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAKgW%3D6LLhDwDv%2BOn05FHy4kYi3aZc0QHYSTPjQFeFbZZkh0Mvw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.