On Fri, Feb 5, 2021 at 3:35 AM [email protected] wrote:
[...]
> I believe the mathematical concept of an equation that connects two
> expressions with an equals sign also implies an assignment.
I think that very much depends on the conventions of the field you are
working in.
In case of doubt I would probably use `:=` for assignment.
> When you write `a = b/c` on a piece of paper the equation implies: `a==b/c`
> assuming no mistake is made.
I would say both mean the same, once written in a "math" style and
once in a "programming" style.
In this case, `b/c = a` means exactly the same (as does `b/c==a`),
which is a hint that this is in fact not an assignment.
> It implies you can calculate a by taking b and dividing it by c. It implies
> that you can rearrange it to calculate b or c from the other two variable.
I guess there are some limitations depending on what type of things
those symbols represent, but in many cases you should be able to
rearrange them.
> It also implies: `da/db = 1/c` and so on.
Only if `c` doesn't represent a sub-expression containing `b`.
An on the other hand, if `a` doesn't represent such a sub-expression,
the LHS will be 0.
Which I think is the crux of this discussion.
I think it would work as expected if you defined your symbols like this:
import sympy as sp
b, c = sp.symbols('b c')
a = sp.Function('a')(b)
> I see little value to the equation class if it simply is the equivalent of a
> list of two expressions that operations are distributed over. I think SymPy
> pretty much covers that behavior with vectors or just Python lists.
I'm not sure about Python lists, but it would indeed be very similar
to a sp.Matrix with two elements.
There may or may not be additional functionality, but I think the main
feature would be its display.
It would be displayed like an equation in a text book.
And I think this is very valuable.
And if its behavior is nicely generic and consistent, it can probably
be used as a building block for more specialized custom helper
classes/functions/etc.
> I have also made some more elaborate comments in the draft SymPEP for the
> equation class. But in summary they point out that if we apply operations
> such as diff() the same to both sides of an equation we arrive at expressions
> that are not consistent in a general way with the application of derivatives
> to an equation.
Does it work with the definition I showed above, using sp.Function?
> An equation class that behaves as a list of two expressions which is
> displayed with an equals sign between the two expressions is certainly easier
> to implement. However, IMHO an equation with an equals sign is more than that.
That's why in my previous post I was suggesting to create two separate classes.
One for the "equation" aspect (the simpler the better!), and one
(derived from Equation) for whatever additional behavior is needed.
cheers,
Matthias
>
> Jonathan
> On Thursday, February 4, 2021 at 4:51:31 PM UTC-6 [email protected] wrote:
>>
>> On Thu, Feb 4, 2021 at 2:18 PM Matthias Geier <[email protected]> wrote:
>> >
>> > Hi all.
>> >
>> > First of all, thanks for all the effort all of you are putting into
>> > SymPy in general and into the upcoming Equation class specifically!
>> >
>> > I'm not sure whether I fully understand either side of the contentious
>> > questions mentioned in this thread, but let me nevertheless add my
>> > opinion:
>> >
>> > I think what Jonathan describes is a mixture of two things:
>> >
>> > * an "equation" where operations can be applied on both sides
>> > * a "definition" or "assignment" where an expression (on the right
>> > side) gets a new name (on the left side)
>> >
>> > I'm quite sure that those should be two separate classes, but I'm not
>> > sure whether *both* should be part of SymPy.
>> >
>> > I think the "Equation" class should never treat the two sides
>> > differently (unless explicitly requested by "rhs" or "lhs" stuff, and
>> > probably as argument to subs()?).
>>
>> I agree with this.
>>
>> Incidentally, there is an Assignment class in SymPy, in the codegen
>> module. It is designed specifically around generating code, so it
>> might not apply to the use cases here.
>>
>> Aaron Meurer
>>
>> >
>> > However, I can very much appreciate the desire to have a symbol that
>> > represents an expression, where both are displayed nicely with an
>> > equals sign in between.
>> >
>> > FWIW, I've somewhat recently created an ad-hoc class called
>> > "NamedExpression" that does some of what Jonathan describes.
>> >
>> > It's defined there:
>> > https://github.com/AudioSceneDescriptionFormat/splines/blob/master/doc/euclidean/utility.py
>> >
>> > And there's an example using it:
>> > https://splines.readthedocs.io/en/latest/euclidean/hermite-uniform.html
>> >
>> > Apart from derivatives, there is also .evaluate_at() which treats the
>> > two sides of the equation differently.
>> >
>> > On top of that, I've also made a "NamedMatrix" class with a few
>> > additional features specific to matrices.
>> > For example it allows to invert and transpose both sides (which is
>> > also shown in the example mentioned above).
>> >
>> > As a special feature it has also a .pull_out() method, which allows to
>> > pull a common factor out of all matrix coefficients.
>> >
>> > I'm not suggesting to implement any of this in SymPy, probably it is
>> > much too specific and uses some assumptions that are not appropriate
>> > for general use.
>> >
>> > Probably something like this could become a separate Python module
>> > (targeted at teaching) using building blocks from SymPy (like the
>> > upcoming Equation class)?
>> >
>> > cheers,
>> > Matthias
>> >
>> > On Thu, Jan 21, 2021 at 4:29 AM Aaron Meurer <[email protected]> wrote:
>> > >
>> > > On Wed, Jan 20, 2021 at 3:49 PM [email protected] <[email protected]> wrote:
>> > > >
>> > > > First, Oscar thank you for taking the time to summarize for everyone
>> > > > the key issues we are trying to make decisions on.
>> > > >
>> > > > Second, I think I can help people understand a little more about why
>> > > > these are issues.
>> > > >
>> > > > Most of them arise because in code we make a distinction between a
>> > > > function and a symbol. As a physical scientist I routinely work with
>> > > > equations where all the symbols can be thought of as functions of all
>> > > > the other symbols. Consider the ideal gas law: P = nRT/V, where P =
>> > > > pressure, n = moles, R = gas constant, T = absolute temperature and V
>> > > > = volume. You can solve this equation for any of the symbols. In the
>> > > > form it is written it makes perfect sense to say dP/dT = nR/V. If I
>> > > > had solved for V => dV/dT = nR/P. Measurements in the laboratory show
>> > > > that both relationships are true. Thus the following does not make
>> > > > sense for this simple example:
>> > > > >>>diff(P=n*R*T/V,T)
>> > > > 0 = n*R/V
>> > > > n*R/V is generally not equal to zero (only two cases: n = 0 and V =
>> > > > oo; both physically not very important).
>> > > >
>> > > > Because of the way SymPy presently treats functions, getting the
>> > > > behavior that I would expect as a scientists for an equation such as
>> > > > the ideal gas law cannot be achieved by using functions instead of
>> > > > symbols.
>> > >
>> > > This starts to get into the question of what the semantic meaning of
>> > > Eqn is. Should Derivative treat the variables in Eqn as depending on
>> > > each other, because the equality implies they do? What about Eqn(f(x),
>> > > a*x)? Does the presence of f(x) prevent a from depending on x? You
>> > > could also write Eqn(a, f(x)/x). The first one "looks" like a doesn't
>> > > depend on x and the second one "looks" like it does. But shouldn't the
>> > > two Eqns be treated in the same way, since one can be obtained from
>> > > the other by a simple, reversible transformation?
>> > >
>> > > My feeling on this is that Derivative already solves this problem by
>> > > implicitly assuming that variables are independent of one another,
>> > > unless explicitly stated otherwise via a functional relationship. I
>> > > don't think Eqn should change this behavior. As an aside, it may be
>> > > useful, independently of Eqn, to have a function that can take
>> > > derivatives under the assumption that certain symbols depend on one
>> > > another, as a convenience over creating explicit Function objects
>> > > (idiff() is an example of this sort of thing).
>> > >
>> > > But the underlying question about the semantic meaning is, to what
>> > > degree does Eqn represent an "equality", vs. just being a convenient
>> > > way to manipulate two expressions in tandem. This question also comes
>> > > up with some of my suggestions about manipulating an Eqn in my
>> > > previous post. I think an Eqn *is* more than just a pair of
>> > > expressions. But we should think about a clear way to define an
>> > > "equality" so that it is clearer what an Eqn should and shouldn't do.
>> > >
>> > > >
>> > > > The fundamental question, as Oscar points out, is whether we want to
>> > > > be able to wrap an equation in an operation and have that default to
>> > > > application of the operation to both sides. We are clear that this
>> > > > should work for simple binary math operations, but for other things it
>> > > > is less clear.
>> > > >
>> > > > From an ease of use and consistency with how expressions behave, I am
>> > > > inclined towards being able to wrap equations in operations such as
>> > > > `cos(eqn)`. However, there are clearly some cases where this can cause
>> > > > problems. So, two important questions we would like the community to
>> > > > respond to:
>> > >
>> > > This really boils down to how we want to answer the question I posed
>> > > above.
>> > >
>> > > I think that ideally cos(eq) would work. If it works with operations
>> > > like + and *, it should work with any mathematical function. I also
>> > > think Eqn should be an Expr so that it has all the same methods.
>> > >
>> > > The problem is how to make this work technically. As Oscar said, you
>> > > can get most mathematical "functions" in SymPy by hooking into
>> > > Function. But that doesn't do anything for manipulation or
>> > > simplification functions, like simplify(). Ideally, any generic
>> > > function that doesn't know about Eqn would just operate on both sides
>> > > of the equation, and so long as it is a function that normally takes
>> > > an expression and returns an expression, it should work. But how do we
>> > > make this work technically? Does every function need to be decorated
>> > > with some special logic to pass through equations? The ability to
>> > > "pass through" or dispatch on arbitrary functions is a larger question
>> > > that has come up in a lot of other places in SymPy. I don't know if
>> > > we have a solution for it yet, but it is something we'd like to solve.
>> > >
>> > > Aaron Meurer
>> > >
>> > > >
>> > > > How important is the convenience of being able to wrap equations in
>> > > > operations?
>> > > > What operations are you aware of where this behavior could cause
>> > > > problems?
>> > > >
>> > > >
>> > > > On Wednesday, January 20, 2021 at 2:45:44 PM UTC-6 Oscar wrote:
>> > > >>
>> > > >> I'll add my thoughts in a lengthy post here.
>> > > >>
>> > > >> Firstly some background on why the existing Eq (full name Equality)
>> > > >> class is problematic. The Eq class is a Boolean and its intention is
>> > > >> to represent the truth of an expression. What this means is that it
>> > > >> will often evaluate to True or False e.g.:
>> > > >>
>> > > >> >>> x = Symbol('x')
>> > > >> >>> Eq(x, 1)
>> > > >> Eq(x, 1)
>> > > >> >>> Eq(1, 2)
>> > > >> False
>> > > >> >>> Eq(1, 1)
>> > > >> True
>> > > >>
>> > > >> This is useful in contexts where we want to use the Boolean-ness
>> > > >> because it allows simplifications to happen. Here simply substituting
>> > > >> a value for x into Eq(x, 1) turns it into a True or False and then the
>> > > >> Piecewise can simplify automatically.
>> > > >>
>> > > >> >>> p = Piecewise((1, Eq(x, 1)), (2, True))
>> > > >> >>> p
>> > > >> Piecewise((1, Eq(x, 1)), (2, True))
>> > > >> >>> p.subs(x, 1)
>> > > >> 1
>> > > >> >>> p.subs(x, 2)
>> > > >> 2
>> > > >>
>> > > >> However this can be quite awkward in other contexts when you want to
>> > > >> manipulate equations. Any code that operates with instances of Eq
>> > > >> needs to be prepared for the possibility that any operation (subs,
>> > > >> simplify, evalf etc) might happen to turn the Eq into True or False
>> > > >> which then does not have the same methods or attributes as Eq. For
>> > > >> example:
>> > > >>
>> > > >> >>> eq = Eq(x, 2)
>> > > >> >>> eq
>> > > >> Eq(x, 2)
>> > > >> >>> eq.lhs
>> > > >> x
>> > > >> >>> eq.subs(x, 1)
>> > > >> False
>> > > >> >>> eq.subs(x, 1).lhs
>> > > >> Traceback (most recent call last):
>> > > >> File "<stdin>", line 1, in <module>
>> > > >> AttributeError: 'BooleanFalse' object has no attribute 'lhs'
>> > > >>
>> > > >> That means that code that operates on Eq needs a lot of checking to be
>> > > >> robust (and many bugs in sympy come from forgetting this). It's also
>> > > >> necessary to check for these every time you have a function like solve
>> > > >> or linsolve etc that can take a list of equations as inputs. The
>> > > >> possible presence of True/False needs to be checked in all inputs
>> > > >> every time before we can begin to e.g. ask for the rhs of the
>> > > >> equation.
>> > > >>
>> > > >> For interactive use it would be nice to be able to do things like 2*eq
>> > > >> to multiply both sides of an equation. We could make that work with Eq
>> > > >> but we would have the danger that at any time any operation might turn
>> > > >> into True/False and then subsequent arithmetic operations would fail
>> > > >> because 2*True is meaningless.
>> > > >>
>> > > >> It's not just arithmetic but any operation that you might want to
>> > > >> apply to one or both sides of an equation. For example to factor both
>> > > >> sides of an equation you have to do
>> > > >>
>> > > >> eq = Eq(factor(eq.lhs), factor(eq.rhs))
>> > > >>
>> > > >> which doesn't look so bad but then for example integrating both sides
>> > > >> wrt x from 0 to 1 looks like:
>> > > >>
>> > > >> eq = Eq(Integral(eq.lhs, (x, 0, 1)), Integral(eq.rhs, (x, 0, 1))
>> > > >>
>> > > >> which begins to show the awkwardness of needing to repeat the same
>> > > >> operation. There are ugly constructs to work around the need to avoid
>> > > >> repetition such as
>> > > >>
>> > > >> eq = Eq(*(Integral(side, (x, 0, 1)) for side in [eq.lhs, eq.rhs]))
>> > > >>
>> > > >> but that's fairly awkward and cryptic in itself.
>> > > >>
>> > > >> The proposal here adds a new Eqn (full name Equation) class that does
>> > > >> not evaluate to True/False. It also defined various operations like
>> > > >> 2*eq to make interactive manipulation of equations easier. Here's a
>> > > >> demonstration using that to derive a formula for cos in terms of exp:
>> > > >>
>> > > >> >>> theta = Symbol('theta', real=True)
>> > > >> >>> eq = Eqn(exp(I*theta), cos(theta) + I*sin(theta))
>> > > >> >>> eq
>> > > >> exp(I*theta) = I*sin(theta) + cos(theta)
>> > > >> >>> conjugate(eq)
>> > > >> exp(-I*theta) = -I*sin(theta) + cos(theta)
>> > > >> >>> (eq + conjugate(eq))/2
>> > > >> exp(I*theta)/2 + exp(-I*theta)/2 = cos(theta)
>> > > >> >>> _.reversed
>> > > >> cos(theta) = exp(I*theta)/2 + exp(-I*theta)/2
>> > > >>
>> > > >> This kind of derivation won't work in general with Eq because at any
>> > > >> step it could evaluate to True. All of the equations above are true -
>> > > >> that's the whole point in a derivation!
>> > > >>
>> > > >> So I really like this feature and I want to get some form of it into
>> > > >> the next release. There is a longstanding issue to add this to sympy:
>> > > >> https://github.com/sympy/sympy/pull/19479
>> > > >> Some time ago I had a quick go at adding it myself but it turned out
>> > > >> other things needed to be fixed first. In the end I fixed those other
>> > > >> things but didn't get round to adding the new Equation class itself.
>> > > >>
>> > > >> It is worth trying to get the details right though. In this proposal
>> > > >> there are several mechanisms for applying an operation to either the
>> > > >> lhs, rhs, or both sides of an equation:
>> > > >>
>> > > >> 1. Methods apply/applylhs/appylrhs to apply a function to either/both
>> > > >> sides
>> > > >> 2. Methods do/dolhs/dorhs to call a method on either/both sides
>> > > >> 3. Some functions work on the equation like together(eq)
>> > > >> 4. Some methods are defined on the equation like eq.together()
>> > > >>
>> > > >> Here's a demo of these:
>> > > >>
>> > > >> >>> x = Symbol('x')
>> > > >> >>> eq = Eqn(x*(x + 1), x**2 + x)
>> > > >> >>> eq
>> > > >> x*(x + 1) = x**2 + x
>> > > >> >>> expand(eq)
>> > > >> x**2 + x = x**2 + x
>> > > >> >>> eq.applylhs(expand)
>> > > >> x**2 + x = x**2 + x
>> > > >> >>> factor(eq)
>> > > >> x*(x + 1) = x*(x + 1)
>> > > >> >>> eq.applyrhs(factor)
>> > > >> x*(x + 1) = x*(x + 1)
>> > > >> >>> eq.dorhs.factor()
>> > > >> x*(x + 1) = x*(x + 1)
>> > > >> >>> eq.factor()
>> > > >> x*(x + 1) = x*(x + 1)
>> > > >>
>> > > >> The first question that comes to mind is do we need all of these?
>> > > >>
>> > > >> If eq.dorhs was callable then it could replace eq.applyrhs and we
>> > > >> could use eq.dorhs(factor) instead of eq.applyrhs(factor).
>> > > >>
>> > > >> For many operations that only apply to one side only it is not that
>> > > >> bad to do eq = Eqn(eq.lhs, factor(eq.rhs)). We could even have a
>> > > >> setrhs method so it becomes eq = eq.setrhs(factor(eq.rhs)) although
>> > > >> doesn't seem like a major advantage.
>> > > >>
>> > > >> For common operations like factor it maybe makes sense to add those as
>> > > >> methods on Eqn but otherwise are we going to want to add basically all
>> > > >> of the methods that Expr has?
>> > > >>
>> > > >> Functions can be made to work with Eqn like factor(eq) but where do we
>> > > >> draw the line with this? As soon as we have Eqn and there are some
>> > > >> functions that can work with it then there will be an expectation to
>> > > >> be able to pass Eqn to almost any possible function and we will have
>> > > >> to add support for it everywhere.
>> > > >>
>> > > >> The PR adds a special case in Function.__new__ to make the following
>> > > >> work:
>> > > >>
>> > > >> >>> eq
>> > > >> x*(x + 1) = x**2 + x
>> > > >> >>> cos(eq)
>> > > >> cos(x*(x + 1)) = cos(x**2 + x)
>> > > >>
>> > > >> Adding that special case in Function.__new__ makes it work for most
>> > > >> common mathematical functions but then the question is how to handle
>> > > >> functions that take more than one argument:
>> > > >>
>> > > >> >>> atan2(eq, 1)
>> > > >> atan2(x*(x + 1), 1) = atan2(x**2 + x, 1)
>> > > >> >>> atan2(1, eq)
>> > > >> atan2(1, x*(x + 1) = x**2 + x)
>> > > >> >>> atan2(eq, eq)
>> > > >> atan2(x*(x + 1), x*(x + 1) = x**2 + x) = atan2(x**2 + x, x*(x + 1) =
>> > > >> x**2 + x)
>> > > >>
>> > > >> The last example has generated an equation with nonsensical objects on
>> > > >> each side. Of course that aspect of the PR can be improved but I show
>> > > >> that example to illustrate the more general point that if we have an
>> > > >> expectation that we can pass an Eqn in place of an expression to any
>> > > >> function then we need a way to draw the line between what should work
>> > > >> and what should not. Also adding this to Function.__new__ covers a lot
>> > > >> of Expr subclasses but there are still plenty more that have their own
>> > > >> __new__ methods and the expectation will arise that all of them should
>> > > >> be able to handle Eqn.
>> > > >>
>> > > >> This is my biggest concern: making things like cos(eq) work in a way
>> > > >> that seems coherent for users requires adding little bits of support
>> > > >> code widely across the codebase. However we do that there will always
>> > > >> be gaps and in general I think it will give the impression that sympy
>> > > >> is buggy (other things like this already have that effect).
>> > > >>
>> > > >> I would much rather stick to an API that can work in general without
>> > > >> risk of bugs and I would prefer users to learn something that will
>> > > >> always work. That means that rather than having cos(eq) I think it
>> > > >> would be better to use eq.apply(cos) or perhaps there could be an
>> > > >> apply function like apply(eq, cos). More complicated cases can be
>> > > >> handled with a lambda function like apply(eq, lambda x: (cos(x) +
>> > > >> 1)/2)
>> > > >>
>> > > >> With a mechanism like apply it's clear that the function we apply to
>> > > >> the sides of the equation needs to be a callable that can only take
>> > > >> one argument so there is no confusion with something like atan2. This
>> > > >> approach also generalises completely to any function that you could
>> > > >> apply to the sides including both symbolic functions like cos and
>> > > >> manipulation routines like trigsimp. That way users only have to learn
>> > > >> one thing that can always work and is always well defined. It also
>> > > >> means that there is no need to add haphazard support for Eqn
>> > > >> throughout the codebase.
>> > > >>
>> > > >> There are a couple of other quirks in the PR such as:
>> > > >>
>> > > >> >>> Derivative(eq)
>> > > >> Derivative(x*(x + 1) = x**2 + x, x)
>> > > >> >>> Derivative(eq).doit()
>> > > >> 2*x + 1 = 2*x + 1
>> > > >>
>> > > >> The unevaluated Derivative in the first output there is nonsensical.
>> > > >> We also have e.g.
>> > > >>
>> > > >> >>> P, V, T = symbols('P, V, T')
>> > > >> >>> eq = Eqn(P*V, T)
>> > > >> >>> eq
>> > > >> P*V = T
>> > > >> >>> diff(eq, T)
>> > > >> Derivative(P*V, T) = 1
>> > > >> >>> diff(eq, T).doit()
>> > > >> 0 = 1
>> > > >>
>> > > >> Here the way the derivative is evaluated treats the lhs and rhs
>> > > >> differently giving an unevaluated derivative on the left. I think the
>> > > >> idea is to prevent the left hand side from fully evaluating although
>> > > >> it will if you call doit. I expect that a lot of users will find this
>> > > >> surprising (I certainly wouldn't want/expect this effect from
>> > > >> differentiating the equation).
>> > > >>
>> > > >> Another quirk is the way that integration is handled:
>> > > >>
>> > > >> >>> integrate(eq, T)
>> > > >> Traceback (most recent call last):
>> > > >> File "<stdin>", line 1, in <module>
>> > > >> File "/Users/enojb/current/sympy/sympy/sympy/integrals/integrals.py",
>> > > >> line 1567, in integrate
>> > > >> integral = Integral(*args, **kwargs)
>> > > >> File "/Users/enojb/current/sympy/sympy/sympy/integrals/integrals.py",
>> > > >> line 81, in __new__
>> > > >> return function._eval_Integral(*symbols, **assumptions)
>> > > >> File "/Users/enojb/current/sympy/sympy/sympy/core/equation.py", line
>> > > >> 491, in _eval_Integral
>> > > >> raise ValueError('You must specify `side="lhs"` or `side="rhs"` '
>> > > >> ValueError: You must specify `side="lhs"` or `side="rhs"` when
>> > > >> integrating an Equation
>> > > >>
>> > > >> You have pass a "side" argument to integrate to specify which side to
>> > > >> integrate:
>> > > >>
>> > > >> >>> integrate(eq, T, side='lhs')
>> > > >> P*T*V
>> > > >>
>> > > >> I would rather just pass the lhs to integrate if that's all this is
>> > > >> doing:
>> > > >>
>> > > >> >>> integrate(eq.lhs, T)
>> > > >> P*T*V
>> > > >>
>> > > >> I think that for integration and differentiation we should stick to
>> > > >> the general approach implied by apply or do e.g. we use apply to
>> > > >> integrate both sides and applylhs to integrate one side.
>> > > >>
>> > > >> >>> eq.apply(lambda s: Integral(s, (x, 0, 1)))
>> > > >> Integral(P*V, (x, 0, 1)) = Integral(T, (x, 0, 1))
>> > > >>
>> > > >> If we want a convenience method for integrating both sides like
>> > > >> eq.integrate(x, (x, 0, 1)) then that could make sense. I could
>> > > >> potentially countenance diff and integrate as functions that make a
>> > > >> specific exception to support Eqn so that diff(eq, x) works. I do not
>> > > >> think that Derivative(eq) should be allowed though as the unevaluated
>> > > >> derivative of an equation is nonsensical as a symbolic expression.
>> > > >>
>> > > >> I think this is what we want and we should try to get it in for the
>> > > >> next release. I have problems with specific parts of it though. As
>> > > >> discussed on GitHub Jonathan and I are in disagreement over things
>> > > >> like whether cos(eq) should work. We would like to hear what others
>> > > >> think about these kinds of details about how working with Eqn should
>> > > >> work or what makes more sense as an interface. That's why we have
>> > > >> brought the discussion here to the mailing list so if anyone has any
>> > > >> thoughts about any of these things then please say so.
>> > > >>
>> > > >> --
>> > > >> Oscar
>> > > >>
>> > > >>
>> > > >>
>> > > >>
>> > > >>
>> > > >> On Wed, 20 Jan 2021 at 00:58, [email protected] <[email protected]> wrote:
>> > > >> >
>> > > >> > Aaron,
>> > > >> > Thank you for the comments. I need go through them more carefully,
>> > > >> > but I did want to direct you to the SymPy pull request for the
>> > > >> > `Eqn` class that implements everything in the Binder except for the
>> > > >> > ability to use `solve` on an `Eqn`. My preference would be to get
>> > > >> > the `Eqn` class into SymPy and then make it work with solve as a
>> > > >> > separate project/pull.
>> > > >> >
>> > > >> > As you will see there has been quite a bit of discussion within the
>> > > >> > pull request. Hence this request for more input from the community.
>> > > >> >
>> > > >> > Jonathan
>> > > >> >
>> > > >> > On Tuesday, January 19, 2021 at 5:34:47 PM UTC-6 [email protected]
>> > > >> > wrote:
>> > > >> >>
>> > > >> >> Is there a pull request with the code associated with this, or is
>> > > >> >> it
>> > > >> >> only in the Binder for now?
>> > > >> >>
>> > > >> > --
>> > > >> > 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 view this discussion on the web visit
>> > > >> > https://groups.google.com/d/msgid/sympy/3627a868-7cf0-42a8-92b2-b29b723ddca5n%40googlegroups.com.
>> > > >
>> > > > --
>> > > > 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 view this discussion on the web visit
>> > > > https://groups.google.com/d/msgid/sympy/d7f67a32-381b-4ca1-baa0-da6c240c4c98n%40googlegroups.com.
>> > >
>> > > --
>> > > 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 view this discussion on the web visit
>> > > https://groups.google.com/d/msgid/sympy/CAKgW%3D6KSj3NTWDgqr7WjeTFf%3DkHrAtvk7sxkW%2Bzm_RbLO72ZWg%40mail.gmail.com.
>> >
>> > --
>> > 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 view this discussion on the web visit
>> > https://groups.google.com/d/msgid/sympy/CAFesC-c1SzDeVd%3D5iz%3Dm6dRUWs2Y24%2Bpw-6g6%3DK4KoEG7T5cJg%40mail.gmail.com.
>
> --
> 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 view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/979503cf-84e1-4d58-b939-bde8b055c36an%40googlegroups.com.
--
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 view this discussion on the web visit
https://groups.google.com/d/msgid/sympy/CAFesC-fhKUD77CvLBTp%2BGR%2B%2Btio3FeJTDeeGLL00VvMj9cMZqQ%40mail.gmail.com.