Starting with Francesco's work is a good idea. He has thought about
pattern matching in SymPy more than anyone else.

Aaron Meurer

On Mon, Mar 13, 2017 at 2:48 PM, Abdullah Javed Nesar
<[email protected]> wrote:
> Hi,
>
> Thanks Aaron for your reply, that really helped. I think I've collected
> sufficient information about the project and I'll need your help to complete
> my proposal and organize tasks better.
>
> I think framing of rules is lengthy but quite straightforward. Pattern
> matching which needs to be implemented prior to it is where I need your
> help. I was looking at Francesco Bonazzi's proposal on new pattern matching
> and it seems fine to me. Do we need to add anything more to it or improve on
> anything? What do you think?
>
> Abdullah Javed Nesar
>
> On Saturday, March 11, 2017 at 2:46:19 AM UTC+5:30, 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
>> <[email protected]> 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
>> >> <[email protected]>
>> >> 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
>> >>>>>> <[email protected]>
>> >>>>>> 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
>> >>>>>>>>> <[email protected]> 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
>> >>>>>>>>> >> <[email protected]> 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 [email protected].
>> >>>>>>>>> >> > To post to this group, send email to
>> >>>>>>>>> >> > [email protected].
>> >>>>>>>>> >> > 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 [email protected].
>> >>>>>>>>> > To post to this group, send email to [email protected].
>> >>>>>>>>> > 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 [email protected].
>> >>>>>>> To post to this group, send email to [email protected].
>> >>>>>>> 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 [email protected].
>> >>> To post to this group, send email to [email protected].
>> >>> 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 [email protected].
>> > To post to this group, send email to [email protected].
>> > 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 [email protected].
> To post to this group, send email to [email protected].
> 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/06665b8f-9e0e-4231-8032-1610a9c01072%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 [email protected].
To post to this group, send email to [email protected].
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%3D6LcUGRLWX-KU2r7dKvB4sLz9_ZMq9-gXcqkOeQ82LeNdw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to