Opened 9 years ago
Closed 8 years ago
#11309 closed defect (fixed)
Sage sees - x + y > 0, - y + x >= 0, and x - y > 0 as equivalent
Reported by: | tnv | Owned by: | burcin |
---|---|---|---|
Priority: | major | Milestone: | sage-5.1 |
Component: | symbolics | Keywords: | inequality equality relational sd31 __richcmp__ sd40.5 |
Cc: | kini, kcrisman, tnv | Merged in: | sage-5.1.beta3 |
Authors: | Keshav Kini, Burcin Erocal | Reviewers: | Karl-Dieter Crisman, ThanhVu Nguyen |
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description (last modified by )
-x + y > 0 and x - y > 0 are treated the same in Sage.
sage: version() 'Sage Version 4.6.2, Release Date: 2011-02-25' sage: (-x +y < 0) in [x -y < 0] True Set([-x +y >= 0,x -y >= 0]) {-x + y >= 0}
and they have the same Hash
sage: var('x,y') (x, y) sage: hash(-x + y > 0 ) 1221566266 sage: hash(-x + y >= 0 ) 1221566266 sage: hash(x - y >= 0 ) 1221566266 sage: hash(-y + x >= 0 ) 1221566266 sage: hash(x - y > 0 ) 1221566266
It seems to me that Sage treats >
, >=
, and ==
the same (see #7660). If this is true then it's a serious problem and needs to be addressed.
Apply:
Attachments (2)
Change History (60)
comment:1 Changed 9 years ago by
- Description modified (diff)
comment:2 Changed 9 years ago by
- Cc kini added
comment:3 Changed 8 years ago by
- Description modified (diff)
comment:4 Changed 8 years ago by
- Status changed from new to needs_review
comment:5 Changed 8 years ago by
Thanks for creating the patch!!
I don't know how to apply this patch though - if you can walk me through it then I can test.
But in the mean time, what are the result for these commands ? If the results are different than the defected version above and as expected then probably the patch is correct.
sage: (-x +y < 0) in [x -y < 0]
Set([-x +y >= 0,x -y >= 0])
sage: var('x,y') (x, y) sage: hash(-x + y > 0 ) sage: hash(-x + y >= 0 ) sage: hash(x - y >= 0 ) sage: hash(-y + x >= 0 ) sage: hash(x - y > 0 )
comment:6 Changed 8 years ago by
I've changed the patch a little bit just now, by the way.
To apply the patch, go to devel/sage/
inside your sage directory, and type sage -hg qimport http://trac.sagemath.org/sage_trac/raw-attachment/ticket/11309/trac_11309-fix-comparison-of-comparisons.patch
, type sage -hg qpush
, type sage -b
, and finally launch sage to test the patch!
Your examples are fixed, yes. You can see them listed inside the patch, where I added some more examples in the documentation of the function I changed.
comment:7 Changed 8 years ago by
Oh, by the way, I didn't fix the hashes. They're screwed up anyway, so this solution avoids using them to decide anything about whether expressions are the same or not. We might fix that in a later ticket...
comment:8 Changed 8 years ago by
Thanks for the info.
Which Sage version do I apply the patch to ? the latest 4.7 ? I'll do that tomorrow at work
if they still give the same hashes then (-x +y < 0) in [x -y < 0] still gives True and Set([-x +y >= 0,x -y >= 0]) still eliminates one of them . Correct ?
comment:9 Changed 8 years ago by
No, incorrect, because I changed the code to not use the hashes at all when doing the comparison. The hashes are now irrelevant to this operation. However kcrisman found a bug in my patch so I will update it again in just a second...
comment:10 Changed 8 years ago by
- Status changed from needs_review to needs_work
OK, this looks like it's going to take a little while, I'm getting some unexpected doctest errors... I'll fix it in the morning :)
comment:11 Changed 8 years ago by
- Status changed from needs_work to needs_review
Never mind, ready for review again!
comment:12 Changed 8 years ago by
- Cc kcrisman added
- Owner changed from burcin to (none)
comment:13 Changed 8 years ago by
- Owner changed from (none) to burcin
burcin got deleted from this ticket... that trac bug is annoying!
comment:14 Changed 8 years ago by
Code is correct (corner cases discussed in person, so that e.g. (x < y) != x
is True.
GEx e
seems far from where it comes from.
Changed 8 years ago by
comment:15 Changed 8 years ago by
fixed! (sorry, that was left over from when I was doing something that made cython not like that declaration where it was)
comment:16 Changed 8 years ago by
- Keywords relational sd31 __richcmp__ added
comment:17 Changed 8 years ago by
This looks good. Passing relevant tests.
comment:18 Changed 8 years ago by
- Status changed from needs_review to positive_review
comment:19 Changed 8 years ago by
- Reviewers set to Karl-Dieter Crisman
comment:20 Changed 8 years ago by
It now can tell that -x +y >0 is different than -y + x >= 0 but it says that -x+y >0 is not the same as y > x ---
or may be this is another problem ?
sage: ( -x+y >0 ) == (y > x ) False sage: (-x + y < 0) == (-x < -y) False sage: (x + y == 0) == (x == -y) False sage: (x - y == 0) == (x == y) False sage: (- x + y == 0) == (0 == -x + y) False sage: (x < y) == (y > x) False sage: (x == y) == (-x == -y) False sage: (x + y < 1 ) == (x + y -1 < 0) False
comment:21 Changed 8 years ago by
- Status changed from positive_review to needs_work
This patch *breaks* the following
{{ Sage 4.7 (prepatched)
sage: (- x + y == 0) == (0 == -x + y) True sage: (-x + y == 0) == (0 == -x + y) True sage: (x < y) == (y > x) True
Sage 4.7 (postpatched)
sage: (- x + y == 0) == (0 == -x + y) False sage: (-x + y == 0) == (0 == -x + y) False sage: (x < y) == (y > x) False
}}}
comment:22 Changed 8 years ago by
Sage 4.7 (prepatched) sage: (- x + y == 0) == (0 == -x + y) True sage: (-x + y == 0) == (0 == -x + y) True sage: (x < y) == (y > x) True Sage 4.7 (postpatched) sage: (- x + y == 0) == (0 == -x + y) False sage: (-x + y == 0) == (0 == -x + y) False sage: (x < y) == (y > x) False
comment:23 Changed 8 years ago by
{{ Sage 4.7 (prepatched)
sage: (- x + y == 0) == (0 == -x + y) True sage: (-x + y == 0) == (0 == -x + y) True sage: (x < y) == (y > x) True
Sage 4.7 (postpatched)
sage: (- x + y == 0) == (0 == -x + y) False sage: (-x + y == 0) == (0 == -x + y) False sage: (x < y) == (y > x) False
}}}
comment:24 Changed 8 years ago by
Finally used preview...
Sage 4.7 (prepatched) sage: (- x + y == 0) == (0 == -x + y) True sage: (-x + y == 0) == (0 == -x + y) True sage: (x < y) == (y > x) True Sage 4.7 (postpatched) sage: (- x + y == 0) == (0 == -x + y) False sage: (-x + y == 0) == (0 == -x + y) False sage: (x < y) == (y > x) False
comment:25 Changed 8 years ago by
-x+y >0 is not the same as y > x
Correct. We use the philosophy (used elsewhere) that a comparison is True if you can prove it is True, and that otherwise it is False. False means that we can't prove it's True, and in general these kinds of simplifications are super hard. So all your examples need to be False, sadly.
As for the thing that breaks... I agree that is a problem. Great catch! Can you put your (real) name as a reviewer? (You should also feel free to add yourself to the main Trac page as a developer/contributor.
comment:26 follow-up: ↓ 30 Changed 8 years ago by
- Cc tnv added
- Reviewers changed from Karl-Dieter Crisman to Karl-Dieter Crisman, ThanhVu Nguyen
just put my name as reviewer -- thanks.
From your msg, would it be reasonable to add a SMT theorem prover package to Sage ? So that it can show equivalence of expressions (at least under some specific theories).
comment:27 Changed 8 years ago by
There are some tickets open for things like this, I think, or something related, but I don't really know. Keshav or Burcin may know more.
comment:28 Changed 8 years ago by
Hm. In order to eventually solve #2778 and other such things, I think we need to allow nested relations after all. I talked to Burcin on IRC and he agrees. So we would plan to have all of these return an output which is the same as the input. If you wanted to force it to resolve, you could run bool() on them, and you would always get false, except when comparing x < y
and y > x
, x <= y
and y >= x
, x == y
and y == x
, and x != y
and y != x
, for symbolic expressions x
and y
(on kcrisman's insistence :) ). I'll need to implement this and figure out how it influences existing doctests (probably severely), so I'm leaving this as "needs_work" for now...
comment:29 Changed 8 years ago by
comment:30 in reply to: ↑ 26 ; follow-up: ↓ 31 Changed 8 years ago by
Replying to tnv:
From your msg, would it be reasonable to add a SMT theorem prover package to Sage ? So that it can show equivalence of expressions (at least under some specific theories).
Sage is really large as it is. While I'd be really interested to have this capability in Sage, I don't know how many others would want it in the standard distribution. The first step is to start with an optional package/prototype. We can see where it goes from there. :)
Which prover are you thinking of? What would this let us do in Sage? Perhaps you should write a message to sage-devel about this.
comment:31 in reply to: ↑ 30 ; follow-up: ↓ 32 Changed 8 years ago by
Which prover are you thinking of? What would this let us do in Sage? Perhaps you should write a message to sage-devel about this.
I am thinking about the optional package too. Someone told me qepcad (not exactly SMT but can be used for many similar purpose) already in Sage as an optional package.
The good thing about these SMT solvers is that most of them support a standard language (smtlib) and therefore you can use any of the SMT's out there with a single interface. SMT can be used to show if something (a set of expressions or constraints) is valid or satisfiable under different types of theories (not just boolean), or simplify a set of expression, etc. I rely on these for implications on my project-- to see if 2 sets of expressions are equi-satisfiable .
So all the above examples of whether if exp1 == exp2 should be easily answered with SMT.
comment:32 in reply to: ↑ 31 Changed 8 years ago by
Replying to tnv:
So all the above examples of whether if exp1 == exp2 should be easily answered with SMT.
I'd really like to see Sage have it's own framework to handle assumptions (see assume?
-- this relies completely on maxima right now), so I'm really interested in this. I'd be glad to help with the first steps of making a package, writing an interface, etc. We should have this conversation in sage-devel instead of this ticket though. ;)
comment:33 Changed 8 years ago by
This still applies, and fixes another issue.
sage: c = (x-2<=0) sage: assume(c) sage: a = (x-1<=0) sage: if a in sage.symbolic.assumptions._assumptions: ....: print 'yes' ....: sage: assumptions() [x - 2 <= 0] sage: assume(a) sage: assumptions() [x - 2 <= 0, x - 1 <= 0]
Before, the second assumption didn't obtain, because currently
sage: c = (x-2<=0) sage: L = [c] sage: L [x - 2 <= 0] sage: a = (x-1<=0) sage: a in L True
which is not good. See this sage-support thread.
comment:34 Changed 8 years ago by
Since #2744 is on sage-wishlist, would it suffice to do some sort of "switch lhs and rhs" check as a last branch in the code to fix tnv's point in comment:21 (formatted in comment:24)? It would be nice to finally resolve this at the upcoming Bug Days.
comment:35 Changed 8 years ago by
In the patch, why is this evaluated to True
?
+ sage: (x < y) != (y > x)
+ True
EDIT: Oops. I should have read the earlier comments. Sorry.
comment:36 Changed 8 years ago by
kcrisman: OK, I'll try to implement those minimal checks for now, and we can do nesting expressions later.
comment:37 Changed 8 years ago by
- Description modified (diff)
- Status changed from needs_work to needs_review
Added a new patch. Burcin, can you look over it to make sure I'm doing this the right way? In particular are those operator comparisons optimizable somehow?
comment:38 Changed 8 years ago by
Update: added three more lines to the doctests
comment:39 Changed 8 years ago by
Hey patchbot:
Apply trac_11309-fix-comparison-of-comparisons.patch trac_11309-equate-flipped-comparisons.patch
comment:40 Changed 8 years ago by
The code itself seems fine right now, thanks for such fast action and especially for actual comments in the code!
Did you do any timing runs on previously-working comparisons? I agree that it would be good for someone who knows to comment on whether there is some obvious optimization missing. For instance, lines 1241ff. would be nicer if it so happened there was a "operator.opposite()" function which reversed <=
and >=
(though someone else might want them to be complements, <=
and >
). Similarly for the rhs/lhs comparisons.
Keshav, do you mind putting in a test in your patch for
sage: (x-1<0) in [x-2<0] False
just to test for the comment:33 issue? While we wait for someone more knowledgeable... but as I said it does seem good to go.
comment:41 Changed 8 years ago by
Done! Glad you like the comments :)
I did not do any timing, no. I'm not sure what you mean by "lines 1241ff", but function calls should typically be avoided if you're optimizing for speed, afaik. The main thing I was wondering was, the argument op
to the function _richcmp_c_impl()
is an integer, but operator.*
as seen in lines 1245-1252 seem to be strings, if I'm not mistaken. So I'm just wondering if that many string operations for a single comparison of symbolic expression couldn't be better optimized by somehow getting the operator of the lhs and rhs of the big relation as integers rather than strings. Well, not to mention that I'm calling .operator()
a bunch of times, but I don't know if it would actually be any faster to compute it once and store it in a variable.
They say you shouldn't try to second-guess compilers... I guess the best way to find out is to try a few different ways and see how timeit
behaves. I'll do that later, I guess...
comment:42 Changed 8 years ago by
Hey patchbot:
Apply trac_11309-fix-comparison-of-comparisons.patch trac_11309-equate-flipped-comparisons.patch
comment:43 Changed 8 years ago by
- Keywords sd40.5 added
I guess there isn't any reason to put this off, unless the timing issue really is a biggie. Did you want to run a few of them first?
comment:44 Changed 8 years ago by
Hmm, this is a big slowdown in at least one case.
# old sage: timeit("(x < y) != (y > x)") 625 loops, best of 3: 2.76 µs per loop # new sage: timeit("(x < y) != (y > x)") 625 loops, best of 3: 13.3 µs per loop
It looks like it's fairly constantly adding this. Here, in the much slower checking of a list
# old sage: timeit("(x - 1 < 0) in [x - 2 < 0]") 625 loops, best of 3: 104 µs per loop # new sage: timeit("(x - 1 < 0) in [x - 2 < 0]") 625 loops, best of 3: 116 µs per loop
Here's another one.
# old sage: timeit("(y > y) != (y > y) ") 625 loops, best of 3: 2.24 µs per loop # new sage: timeit("(y > y) != (y > y) ") 625 loops, best of 3: 8.45 µs per loop
comment:45 Changed 8 years ago by
I'm kind of OK with this slowdown. It's in the low microseconds range, and it's also understandable considering the new code actually checks some stuff, whereas the old code doesn't really.
I guess I will ping Burcin about this via email.
comment:46 follow-up: ↓ 48 Changed 8 years ago by
Burcin says he's too busy to look carefully but that the code probably can't be optimized much further.
comment:47 Changed 8 years ago by
- Summary changed from Sage sees -x +y > 0, -y + x >= 0, and x -y > 0 as equivalent to Sage sees - x + y > 0, - y + x >= 0, and x - y > 0 as equivalent
comment:48 in reply to: ↑ 46 Changed 8 years ago by
- Status changed from needs_review to positive_review
Burcin says he's too busy to look carefully but that the code probably can't be optimized much further.
Good enough for me.
comment:49 Changed 8 years ago by
Thanks!
comment:50 follow-up: ↓ 51 Changed 8 years ago by
I am interested in trying this patch but not sure how to apply it correctly. This is what I did on Sage 5.0 (Mac OS Snow Leopard)
$ pwd /Users/tnguyen/Src/Devel/SAGE/sage-5.0/devel/sage $ sage -hg qimport http://trac.sagemath.org/sage_trac/raw-attachment/ticket/11309/trac_11309-equate-flipped-comparisons.patch adding trac_11309-equate-flipped-comparisons.patch to series file Godel Wed May 30:23:05:42 (4714) ~/Src/Devel/SAGE/sage-5.0/devel/sage $ sage -hg qpushapplying trac_11309-equate-flipped-comparisons.patch patching file sage/symbolic/expression.pyx Hunk #1 FAILED at 1179 Hunk #2 FAILED at 1186 Hunk #3 FAILED at 1204 3 out of 3 hunks FAILED -- saving rejects to file sage/symbolic/expression.pyx.rej patch failed, unable to continue (try -v) patch failed, rejects left in working dir errors during apply, please fix and refresh trac_11309-equate-flipped-comparisons.patch Godel Wed May 30:23:05:51 (4715) ~/Src/Devel/SAGE/sage-5.0/devel/sage
comment:51 in reply to: ↑ 50 Changed 8 years ago by
Replying to tnv:
I am interested in trying this patch but not sure how to apply it correctly.
You need to apply both the patches in the order mentioned in the description of this ticket. Try these commands (assuming you are in devel/sage)
../../sage -hg qimport -P http://trac.sagemath.org/sage_trac/raw-attachment/ticket/11309/trac_11309-fix-comparison-of-comparisons.patch ../../sage -hg qimport -P http://trac.sagemath.org/sage_trac/raw-attachment/ticket/11309/trac_11309-equate-flipped-comparisons.patch ../../sage -br
comment:52 Changed 8 years ago by
Patchbot: Apply trac_11309-fix-comparison-of-comparisons.patch trac_11309-equate-flipped-comparisons.patch
comment:53 follow-up: ↓ 55 Changed 8 years ago by
Hi, may be I've missed something but these patches still break things as listed in my comment:24.
(prepatched) sage: (- x + y == 0) == (0 == -x + y) True sage: (-x + y == 0) == (0 == -x + y) True sage: (x < y) == (y > x) True (postpatched) sage: (- x + y == 0) == (0 == -x + y) False sage: (-x + y == 0) == (0 == -x + y) False sage: (x < y) == (y > x) False
The main reason why I report this in the first place is because of this error in which multiplying by -1 does not switch the sign. I think they are related but not sure.
sage: -1 * (x<5) -x < -5
comment:54 Changed 8 years ago by
Did you forget to rebuild Sage after applying the patches?
[1] fs-boone@zhenghe /opt/sage/devel/sage $ hg qapplied trac_13057-no-intersphinx.patch trac_11309-fix-comparison-of-comparisons.patch trac_11309-equate-flipped-comparisons.patch [1] fs-boone@zhenghe /opt/sage/devel/sage $ sage -b &> /dev/null [1] fs-boone@zhenghe /opt/sage/devel/sage $ sage -q sage: var('y') y sage: (- x + y == 0) == (0 == -x + y) True sage: (-x + y == 0) == (0 == -x + y) True sage: (x < y) == (y > x) True sage: -(x < 5) -x < -5 sage:
Personally I don't see why x * (y < z)
should even be simplified to anything other than x * (y < z)
. y < z
is a mathematical object which does not live in a space which has a multiplication operation - it lives in the space of logical predicates. But that is something to address in a different ticket. Testing the title of this ticket:
sage: Set([-x + y > 0, -y + x >= 0, x - y > 0]) {-x + y > 0, x - y >= 0, x - y > 0} sage: len(_) 3
So the patches do at least address and solve the issue in the ticket's name.
comment:55 in reply to: ↑ 53 Changed 8 years ago by
Replying to tnv:
The main reason why I report this in the first place is because of this error in which multiplying by -1 does not switch the sign. I think they are related but not sure.
sage: -1 * (x<5) -x < -5
This is #7660. It would be quite easy to remove the if is_a_relational(left._gobj)
checks in _add_,
_mul_, etc. in
sage/symbolic/expression.pyx` to revert back to GiNaC behavior.
comment:56 Changed 8 years ago by
It seems to work fine now -- not sure what I did previously. So if you don't use hash for comparison , what do you use ? Thanks all of those who spend time to create these patches.
comment:57 Changed 8 years ago by
Given two relations a ? b
and c ! d
, first I check whether ?
and !
are the same relation. If so, I have a couple of cases. One, if ?
and !
are both ==
or are both !=
, then I check whether a == c
and b == d
, or a == d
and b == c
. Two, if ?
and !
are some other relation than ==
or !=
, then I only allow the case a == c
and b == d
.
If ?
and !
are different from each other, I check whether they are reversals of each other (like one is <
and the other is >
, etc.). If that is the case, then I allow a == d
and b == c
.
In all other cases, the two relations are considered unequal.
... that explanation looks kind of confusing. Maybe it's better if you just look at the patch... it's probably easier to understand :)
comment:58 Changed 8 years ago by
- Merged in set to sage-5.1.beta3
- Resolution set to fixed
- Status changed from positive_review to closed
Ready for review! Thanks to Burcin for walking me through the Cython code.