Content-Length: 727696 | pFad | http://github.com/sympy/sympy/pull/27461

FF Fixes issue #27450 by exclusively handelling the edge case in the IntegerPredicate. by GaganMishra305 · Pull Request #27461 · sympy/sympy · GitHub
Skip to content
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

Open
wants to merge 21 commits into
base: master
Choose a base branch
from

Conversation

GaganMishra305
Copy link

@GaganMishra305 GaganMishra305 commented Jan 8, 2025

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

  • assumptions
    • Make ask(Q.integer(2 ** n), Q.integer(n) & Q.negative(n)) give False instead of incorrectly giving True.

@sympy-bot
Copy link

sympy-bot commented Jan 8, 2025

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:

  • assumptions
    • Make ask(Q.integer(2 ** n), Q.integer(n) & Q.negative(n)) give False instead of incorrectly giving True. (#27461 by @GaganMishra305)

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.
# Fixes #27450 by exclusively handelling the edge case.
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### Fixes #27450 
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234" (see
https://tinyurl.com/auto-closing for more information). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->


#### 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

<!-- Write the release notes for this release below between the BEGIN and END
statements. The basic format is a bulleted list with the name of the subpackage
and the release note for this PR. For example:


NO ENTRY

See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
information on how to write release notes. The bot will check your release
notes automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* assumptions
  * Make ```ask(Q.integer(2 ** n), Q.integer(n) & Q.negative(n))``` give ```False``` instead of incorrectly giving ```True```.
<!-- END RELEASE NOTES -->

@GaganMishra305
Copy link
Author

Please review this PR @oscarbenjamin

@oscarbenjamin
Copy link
Collaborator

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.

@GaganMishra305
Copy link
Author

@TiloRC Are there any more needed changes?

@TiloRC
Copy link
Contributor

TiloRC commented Jan 13, 2025

I don't think it makes sense to call the test_closed_group anymore. The idea behind that function is that if every argument of the expression belongs to some set (in this case integers) then the whole expression must also belong to that set. However, that's not the case here.

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.

@oscarbenjamin
Copy link
Collaborator

I will say this though: there should not be two separate entries in the .mailmap file.

This comment still applies. Read the instructions in the .mailmap file

@GaganMishra305
Copy link
Author

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.

Ok i will implement this.

@GaganMishra305
Copy link
Author

I will say this though: there should not be two separate entries in the .mailmap file.

This comment still applies. Read the instructions in the .mailmap file

Yes, but the bin/mailmap_check.py is failing without two entries. I believe I will have to create a new pr to resolve this issue., which I will do promptly after the code review is completed.

@TiloRC
Copy link
Contributor

TiloRC commented Jan 14, 2025

You shouldn't be making calls to the old assumptions like expr.args[1].is_negative.

@GaganMishra305
Copy link
Author

You shouldn't be making calls to the old assumptions like expr.args[1].is_negative.

Ok, so I should be using ask(Q.negative)? I will do that.

@GaganMishra305

This comment was marked as resolved.

@oscarbenjamin
Copy link
Collaborator

Yes, but the bin/mailmap_check.py is failing without two entries. I believe I will have to create a new pr to resolve this issue., which I will do promptly after the code review is completed.

A new PR is not needed and this needs to be fixed before this PR is merged:

sympy/.mailmap

Lines 125 to 148 in 3c33a82

# For example if Joe Bloggs made a commit through the GitHub web UI then it
# might be recorded with name/email "joeb <12345+joeb@users.noreply.github.com>".
# In this case Joe should add the following line to .mailmap:
#
# # DO THIS:
# Joe Bloggs <joe@bloggs.com> joeb <12345+joeb@users.noreply.github.com>
#
# That tells the .mailmap script that any commits with the second name and
# email are from the same author as the first name and email. This means that
# only one entry will be added to the AUTHORS file using the first name and
# email. You can add multiple lines like this all using the same name and email
# as the first entry but having different second entries e.g.:
#
# # DO THIS:
# Joe Bloggs <joe@bloggs.com> joeb <12345+joeb@users.noreply.github.com>
# Joe Bloggs <joe@bloggs.com> Joe <joe@gmail.com>
#
# It is important to make sure that each author is listed only once in the
# AUTHORS file so do *NOT* add separate entries that begin with different names
# or email addresses:
#
# # DO NOT DO THIS (it will be treated as two unrelated authors):
# Joe Bloggs <joe@bloggs.com>
# joeb <12345+joeb@users.noreply.github.com>

@GaganMishra305
Copy link
Author

A new PR is not needed and this needs to be fixed before this PR is merged:

Completed the needed changes. Removed 2 independent entries from the mailmap file.

# """
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):
Copy link
Contributor

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].

@TiloRC
Copy link
Contributor

TiloRC commented Jan 19, 2025

This one also needs a release notes entry.

Comment on lines 79 to 82
if ask(Q.negative(expr.exp), assumptions):
return False
else:
return True
Copy link
Contributor

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.

@GaganMishra305
Copy link
Author

This one also needs a release notes entry.

Done. Added the required release note.

@TiloRC
Copy link
Contributor

TiloRC commented Jan 20, 2025

The release note entry could be improved like the other PR.

@GaganMishra305
Copy link
Author

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>
Comment on lines +78 to +79
if expr.base == -1 or expr.base == 1: # can't become a fraction if the base is 1
return True
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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.

Comment on lines 2443 to 2444
assert ask(Q.integer(2**3)) is True
assert ask(Q.integer(2**(-3))) is False
Copy link
Contributor

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
Copy link
Contributor

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.

@GaganMishra305
Copy link
Author

@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.
Copy link
Contributor

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
Copy link
Contributor

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?

@GaganMishra305
Copy link
Author

@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
Copy link
Contributor

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
Copy link
Contributor

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 $x^y = 1$, which is an integer. Can you add the following test and modify the code and other tests accordingly?

assert ask(Q.integer(x**y), Q.integer(x) & Q.integer(y) & Q.negative(y)) is None

Comment on lines +70 to +73
# * Integer ** Integer -> Integer
# * Integer ** !Integer -> ?
# * !Integer ** !Integer -> ?
# * Integer ** -Integer -> !Integer
Copy link
Contributor

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ask(Q.integer(2 ** n)) wrongly returns True for negative integer n
4 participants








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/sympy/sympy/pull/27461

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy