On Wed, 3 Mar 2021 at 21:40, Aaron Meurer <[email protected]> wrote:
>
> On Wed, Mar 3, 2021 at 11:58 AM JSS95 <[email protected]> wrote:
> >
> > Also, `Q.eq(x, y)` will be able to support algebra between the relational
> > as @sylee957 shared in this comment. `Q.eq(x, 1) + Q.eq(y, 1)` will return
> > `AddSides(Q.eq(x, 1), Q.eq(y, 1), evaluate=True)`, which in turn will be
> > evaluated to `Q.eq(x + y, 2)`. `Q.gt(x, 2) * -1` will return `Q.lt(-x,
> > -2)`, and `Q.gt(x, 2) * y` will return `MultiplySides(Q.gt(x, 2), y)` if
> > the sign of `y` cannot be determined.
> >
> > This way, `Q.eq` can make `Equation` no longer be required to be
> > implemented. However this idea can be discarded if it does not get approved.
>
> I still think this is a bad idea. Making symbolic and boolean
> relationals the same leads to too much type confusion. The evaluation
> of relationals to booleans is not the only reason this is problematic.
> There's a reason Boolean and Expr are separate objects, and for
> example, S.true and S.false are not allowed to be treated as numbers
> (S.true + 1 gives an error). Treating booleans and expressions
> (numbers) as the same thing leads to all sorts of errors.
>
> This is the main issue for this, for reference
> https://github.com/sympy/sympy/issues/4986.
>
> I appreciate that it might be confusing to users, but I think we can
> mitigate that to some degree with error messages. If Eq and Eqn are
> strict about their types, so that Eq only works in boolean contexts
> and Eqn only works in expression contexts, then users can
> unambiguously tell if they need to use the right object.
We need to be very careful to define what "in expression contexts"
means. Personally I see a big difference between allowing the use of
operators like + and * and allowing in Eq to be used as one of the
terms in a symbolic Add or Mul expression.
To be clear the first means saying:
Given an equation object eq=Eq(x, y), the Python code 2*eq will
give Eq(2*x, 2*y).
To me that does not imply that there is any mathematical meaning to
multiplication between an equation and an integer. It just means that
we can use Python's infix arithmetic operators for convenient
manipulations of equations. In Python you can also add lists like [1,
2] + [3]. That does not imply that we should allow the list [1, 2] to
be substituted for x in a symbolic expression like x**2 + 1.
On the other hand in sympy 1.4 the Relational class which is a
superclass of Eq was actually a subclass of Expr meaning that it could
be used as part of any symbolic expression in any place where an
expression ought to be e.g.:
In [4]: Eq(x, 2)**(x > 1)
Out[4]:
x > 1
(x = 2)
To me that is just a gibberish expression object and should not be
allowed under any variant of an equation/inequality object (I removed
this behaviour in sympy 1.5 I think). I would not propose that any
kind of equation object could appear in place of an expression as part
of any *symbolic* expression. That is very different from allowing
some operations that can conveniently manipulate equation objects
while still keeping them entirely separate from symbolic expressions.
> > 4. Compatibility with Eq around codebase
> >
> > Every codebase will be modified so that `Q.eq` can be used instead of `Eq`
> > everywhere. For example `Piecewise((1, Q.eq(x, 0)), (0, True))` will be
> > supported, and `solveset(Q.eq(x**2, 1))` will return `{-1, 1}`.
> >
> > 5. Migration from Eq to Q.eq
> >
> > `Eq` and other relational will be retained only for backwards
> > compatibility. Documentation for `Q.eq` will be thoroughly made and users
> > will be informed to use `Q.eq` instead of `Eq`. After a few release, `Q.eq`
> > will be renamed to `Eq`.
>
> I still maintain that adding a new *name*, Q.eq, is unnecessary and
> confusing. A new name is appropriate for a new object (like Equation),
> but what you are suggesting is to replace Eq with Q.eq. So why not
> just change Eq to be what you are proposing Q.eq to be? I think we can
> remove the automatic evaluation from Eq. It would be less of a
> backwards compatibility break than renaming the name (you could argue
> it isn't even technically a break, since nothing guarantees when or if
> Eq() will evaluate to a boolean).
There are different perspectives on this. It's also possible to argue
that *any* change to anything is a compatibility break!
I think in this case that this is not only a change in behaviour but
also clearly departing from the documented purpose of the Eq class.
These changes contradict most of the opening section of the docstring
for Eq:
"""
Represents that two objects are equal. If they can be easily shown to
be definitively equal (or unequal), this will reduce to True (or
False). Otherwise, the relation is maintained as an unevaluated
Equality object. Use the simplify function on this object for more
nontrivial evaluation of the equality relation.
As usual, the keyword argument evaluate=False can be used to prevent
any evaluation.
"""
https://docs.sympy.org/latest/modules/core.html#sympy.core.relational.Equality
I do think that a clear rationale is needed before any significant
backwards compatible change and these specific points need to be
addressed:
1. Why is an incompatible change needed?
2. How would the incompatibility cause downstream user/library code to break?
3. Does it seem like much code would break?
4. Are there ways to mitigate that breakage?
5. How would someone change code to be compatible with sympy both
before and after the break?
> And to reiterate a point I made on one of your pull requests: "As an
> aside, I never realised there were so many ways to spell '='.
> 'Equation', 'equality', 'equal', 'equals', 'equivalent', 'eq', ....
> And at the rate things are going, we are going to have a separate
> class in SymPy for each one, each with its own distinct semantic
> meaning. This is very confusing for users, so I would like to avoid
> it."
>
> The way I could see this being a good idea is if we want to convert Eq
> to instead be the symbolic equation class and make Q.eq the boolean
> variant. But as Oscar pointed out on one of the issues, this would
> break a lot of code that currently assumes Eq is a boolean (it's often
> used inside of boolean expressions, like in Piecewise).
I don't think that Piecewise is a problem because it can just be made
to call ask(cond) or bool(cond). It knows the condition is supposed to
be boolean so it can do that explicitly.
The problem is more code that tries to use Eq directly like:
if Eq(x, y) is S.true:
# do something
For example right now all of the logic in the FiniteSet class is built
around using this as a way of sometimes being able to tell when two
objects are equal. I have no idea how much this is used outside of the
sympy codebase though.
--
OScar
--
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/CAHVvXxQhyA14kRTswJ2CSiPsBbMa9GZuvfGraprH%3Dv%3DePOYiKQ%40mail.gmail.com.