-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
modify Basic.__eq__ to detect dissimilar Numbers #16924
Conversation
✅ Hi, I am the SymPy bot (v147). I'm here to help you write a release notes entry. Please read the guide on how to write release notes. Your release notes are in good order. Here is what the release notes will look like:
This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.5. Note: This comment will be updated with the latest check if you edit the pull request. You need to reload the page to see it. Click here to see the pull request description that was parsed.
Update The release notes on the wiki have been updated. |
02c114c
to
5c133b9
Compare
I think that taking types into account is a good idea. I wonder if that could be applied to all objects, not only numbers. So maybe something like this:
|
Codecov Report
@@ Coverage Diff @@
## master #16924 +/- ##
=============================================
+ Coverage 73.922% 73.975% +0.052%
=============================================
Files 620 620
Lines 160262 160369 +107
Branches 37606 37632 +26
=============================================
+ Hits 118469 118633 +164
+ Misses 36305 36249 -56
+ Partials 5488 5487 -1 |
This breaks the transitivity of In [5]: Tuple(2) == Tuple(2.0)
Out[5]: False
In [6]: Tuple(2) == (2,) == Tuple(2.0)
Out[6]: True
In [7]: Tuple(2) == (2,) == (2.0,) == Tuple(2.0)
Out[7]: True |
And for FiniteSet In [15]: FiniteSet(2) == {2} == {2.0} == FiniteSet(2.0)
Out[15]: True
In [16]: FiniteSet(2) == FiniteSet(2.0)
Out[16]: False |
Maybe it is |
This looks promising. |
I just tried excluding numbers from the type test. Since FiniteSet is not an Expr, it should pass compare the items via number/number (Expr/Expr) comparison. I am thinking this will come to this routine, skip the type test and go to the hashable content test where a==b will pass. So outside of an Expr, |
The first time the following is solved, the right answer is obtained in Py2. The next time, it is not:
|
Does the |
I can't reproduce that. Python 2.7 and SymPy master: In [1]: f,g=symbols('f g',cls=Function); eqn = Eq(Derivative(f(x), x), Derivative(g(x), x))
In [2]: dsolve(eqn,f(x))
Out[2]: f(x) = C₁ + g(x)
In [3]: f,g=symbols('f g',cls=Function); eqn = Eq(Derivative(f(x), x), Derivative(g(x), x))
In [4]: dsolve(eqn,f(x))
Out[4]: f(x) = C₁ + g(x)
In [5]: dsolve(eqn,f(x))
Out[5]: f(x) = C₁ + g(x) |
Yes: not a problem in master, but a problem here. I don't know how to fix it and have just put the test in an |
It seems that the local class Lines 4106 to 4129 in ab7dbc8
is first introduced in replace and then removed in unreplace to make integration of a derivative possible. That is what happens in current master but in this PR replace and unreplace see different versions of diffx .
|
That makes sense. The diffx class is in the cached expression during a second call to dsolve which tried to unreplace a new diffx class. The simple solution is for diffx to be defined at module scope instead of in a function |
I used to keep track of such details with common blocks and such with Fortran, but this level of thinking is not something I usually need for Python. Really appreciate the help on this. |
In PY2, when the unreplace step is performed, the diffx is not being found by replace. Although func_name could be used to identify it, an attribute is being used instead. This did not appear to be necessary in pY3 so can (perhaps) be dropped when PY2 is dropped.
This seems to be working well. |
A way to make |
This already works for Interval(1., 2) == Interval(1, 2).
If all looks well, please feel free to commit. I have nothing further to add. This eliminates the irritating assymmetry of the former |
Not sure where this error is coming from:
|
@sylee957 , do you have an idea of how to fix the Sphinx error? |
I think the build had started failing from the master after new update to sphinx |
return eq.replace(diffx, lambda e: Derivative(e, var)) | ||
if PY3: | ||
return eq.replace(diffx, lambda e: Derivative(e, var)) | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why this is different between Python 2 and 3.
I added the diffx class and I now realise (seeing the work you've done) that it is fragile in the face of caching. That needs to be fixed and you've added a fix for Python 2 but I'm now worried about how safe it is for Python 3 as well. I'll look into it... (don't let that hold up this PR though)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen issues before with classes defined inside of functions. In this case, the class really does have to be defined inside the function, because it is different for each function call. Perhaps it would be better to store var
and constant
in the diffx.args.
If I had to guess, the Python 2-ness of this points to the accursed class registry and the __cmp__
(see #13059).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep:
$ cat test.py
from sympy.core.core import all_classes
from sympy import Function, symbols, dsolve, Derivative, Eq
x = symbols('x')
f, g = symbols('f g', cls=Function)
eqn = Eq(Derivative(f(x), x), Derivative(g(x), x))
dsolve(eqn, f(x), hint='nth_algebraic')
dsolve(eqn, f(x), hint='nth_algebraic')
diffxs = [i for i in all_classes if 'diffx' in str(i)]
print(diffxs[0] == diffxs[1])
$ python3 test.py
False
$ python2 test.py
True
Because Python 2 uses the ill conceived __cmp__
method of BasicMeta
(__cmp__
does nothing in Python 3).
This looks fine to me. The diffx issue is puzzling but I think that the implementation was questionable in view of caching. This PR only happened to bring that forth. |
Did you check if this introduces any performance regressions? |
References to other Issues or PRs
closes #16916
Brief description of what is fixed or changed
Float(2) == 2
but the use of Float in an Expr will test as unequalx**2.0 != x**2
.Other comments
Release Notes
Float(1) == 1
) except when they appear in an Expression, e.g.x**2.0 != x**2
disambiguate
was madeFiniteSet(1) == FiniteSet(1.0)