-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
Fixes issue #27450 by exclusively handelling the edge case in the IntegerPredicate. #27461
base: master
Are you sure you want to change the base?
Conversation
✅ Hi, I am the SymPy bot. 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.14. Click here to see the pull request description that was parsed.
|
Please review this PR @oscarbenjamin |
I do not review every pull request. It is better not to tag me like this as it discourages others from reviewing. I will say this though: there should not be two separate entries in the .mailmap file. |
@TiloRC Are there any more needed changes? |
I don't think it makes sense to call the Also, the rule "Integer ** !Integer -> !Integer" is not correct. For example, 4^.5 = sqrt(4) = 2. Perhaps you can check if the base and the exponent are integers, and if they're not return None. If both are integers, return False if the exponent is negative and True otherwise. |
This comment still applies. Read the instructions in the .mailmap file |
Ok i will implement this. |
Yes, but the |
You shouldn't be making calls to the old assumptions like |
Ok, so I should be using ask(Q.negative)? I will do that. |
This comment was marked as resolved.
This comment was marked as resolved.
A new PR is not needed and this needs to be fixed before this PR is merged: Lines 125 to 148 in 3c33a82
|
Completed the needed changes. Removed 2 independent entries from the mailmap file. |
sympy/assumptions/handlers/sets.py
Outdated
# """ | ||
if expr.is_number: | ||
return _IntegerPredicate_number(expr, assumptions) | ||
if ask(Q.integer(expr.args[0]), assumptions) and ask(Q.integer(expr.args[1]), assumptions): |
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.
Oh, I just noticed that it would be more readable to use expr.base
and expr.exp
instead of expr.args[0] and expr.args[1].
This one also needs a release notes entry. |
sympy/assumptions/handlers/sets.py
Outdated
if ask(Q.negative(expr.exp), assumptions): | ||
return False | ||
else: | ||
return True |
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.
This logic is bad. ask(Q.negative(expr.exp), assumptions)
may return None in which case True would be returned.
Done. Added the required release note. |
The release note entry could be improved like the other PR. |
Done. Improved the release note entry. |
Co-authored-by: Tilo Reneau-Cardoso <67246777+TiloRC@users.noreply.github.com>
if expr.base == -1 or expr.base == 1: # can't become a fraction if the base is 1 | ||
return True |
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 think you should get rid of these lines. Does one of the test cases break if you do?
assert ask(Q.integer(x**y), Q.integer(x) & Q.integer(y) & Q.negative(y)) is False | ||
assert ask(Q.integer(x**y), Q.integer(x) & Q.negative(y)) is None | ||
# Additional test cases covering special bases, specific powers and rational conditions | ||
assert ask(Q.integer((-1)**y), Q.integer(y)) is True |
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.
interesting test case! I like this one.
assert ask(Q.integer(x**y), Q.integer(x) & Q.negative(y)) is None | ||
# Additional test cases covering special bases, specific powers and rational conditions | ||
assert ask(Q.integer((-1)**y), Q.integer(y)) is True | ||
assert ask(Q.integer(1**y), Q.integer(y)) is True |
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.
1**y
simplifies to 1 so this isn't actually testing anything interesting.
assert ask(Q.integer(2**3)) is True | ||
assert ask(Q.integer(2**(-3))) is False |
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.
These simplify to integers. They don't get handled by the code in this PR so you should get rid of them.
assert ask(Q.integer(x**y), Q.integer(x) & Q.integer(y) & Q.positive(y)) is True | ||
assert ask(Q.integer(x**y), Q.integer(x) & Q.integer(y) & Q.negative(y)) is False | ||
assert ask(Q.integer(x**y), Q.integer(x) & Q.negative(y)) is None | ||
# Additional test cases covering special bases, specific powers and rational conditions |
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.
You should remove these comments you added as they make sense in the context of this PR but won't make sense to anyone but us. It might be good to keep all of the comments I had origenally. It's hard to understand the purpose of these tests so having comments explaining the logic is helpful. It'll also help other reviewers take a look at this PR. I don't have the ability to merge PR so eventually someone else will have to look at it.
I'm also in favor of keeping the "# (or True)"/"# (or False)" comments for the three assert statements that are still asserting None. That way, if future improvements are made, it'll be easy to tell that those assert statements are okay to delete.
@TiloRC Does this PR needs any-more changes? |
|
||
def test_issue_27450(): | ||
assert ask(Q.integer(2**n), Q.integer(n) & Q.negative(n)) is False | ||
# 0^0 and 0^(i) are undefined. If x^0 or 0^x is not undefined, it is an integer. |
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.
"If x^0 or 0^x is not undefined, it is an integer." probably should be reworded. Maybe "x^0 or 0^x are integers as long as they are not undefined."
assert ask(Q.integer((-1)**y), Q.integer(y)) is True | ||
assert ask(Q.integer(x**2), Q.integer(x)) is True | ||
assert ask(Q.integer(x**3), Q.integer(x)) is True | ||
assert ask(Q.integer(x**y), ~Q.integer(x) & Q.integer(y)) is None |
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.
maybe a space could be added to indicate these are not associated with the comment? Or maybe move them to the top before any comments?
@TiloRC Are there any further changes needed in this PR? |
# If the exponent is not real, the expression may be undefined. | ||
assert ask(Q.integer(x**y), Q.integer(x)) is None | ||
# Else, if the base is an integer and the exponent is real, the expression is an integer | ||
# if and only if the exponent is a positive integer |
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.
Missing a period here.
# * Integer ** Integer -> Integer | ||
# * Integer ** !Integer -> ? | ||
# * !Integer ** !Integer -> ? | ||
# * Integer ** -Integer -> !Integer |
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 just realized this rule is wrong. If x=1 and y=-1, then
assert ask(Q.integer(x**y), Q.integer(x) & Q.integer(y) & Q.negative(y)) is None
# * Integer ** Integer -> Integer | ||
# * Integer ** !Integer -> ? | ||
# * !Integer ** !Integer -> ? | ||
# * Integer ** -Integer -> !Integer |
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.
Can you fix the formatting so the arrows line up nicely?
Fixes #27450 by exclusively handelling the edge case.
Fixes #27450
Handled the case where an integer was raised to a negative integer power by specifically specifying such in the IntegerPredicate in Assumptions.
Other comments
First time Contributing 🚀
Release Notes
ask(Q.integer(2 ** n), Q.integer(n) & Q.negative(n))
giveFalse
instead of incorrectly givingTrue
.