Repository: sympy/sympy
Pull request: Fix ask(Q.finite(x**-1), Q.real(x)) to handle potential division by zero
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
<!-- 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. -->Fixes #27707


#### Brief description of what is fixed or changed
This PR addresses the issue where ```ask(Q.finite(x**-1), Q.real(x))``` incorrectly returns ```True```, ignoring the potential for division by zero when x could be zero.

Changes made:

- Modified the ```Pow``` handler for FinitePredicate to check if the base of an exponent could be zero and the exponent could be negative.
- Added a condition to return ```None``` when there's a possibility of division by zero.
- Added tests to verify the correct behavior for expressions like ```x**-1``` when x is real (and could be zero).



#### 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:

* solvers
  * Added a new solver for logarithmic equations.

* functions
  * Fixed a bug with log of integers. Formerly, `log(-x)` incorrectly gave `-log(x)`.

* physics.units
  * Corrected a semantical error in the conversion between volt and statvolt which
    reported the volt as being larger than the statvolt.

or if no release note(s) should be included use:

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
  * Bug fix: Now ```ask(Q.finite(x**-1), Q.real(x))``` correctly returns ```None``` instead of ```True```.
<!-- END RELEASE NOTES -->


Problem statement:
ask(Q.finite(x**-1), Q.real(x)) incorrectly returns True, ignoring potential division by zero
**Description:**

There is an issue with the handling of assumptions for the expression x**-1 when x is real and could potentially be zero. The current implementation doesn't account for the possibility of x being zero, which leads to an incorrect result.

**Current behavior:**

```
from sympy import ask, Q, Symbol
x = Symbol('x')
print(ask(Q.finite(x**-1), Q.real(x))) # Output: True
```
**Expected behavior:**
The function should return ```None``` to indicate uncertainty, as x**-1 is undefined when x = 0.

Hints from issue discussion:

Commit message: Added tests

Patch to review:
diff --git a/sympy/assumptions/handlers/calculus.py b/sympy/assumptions/handlers/calculus.py
index bb4f387eb582..43b0a62bf341 100644
--- a/sympy/assumptions/handlers/calculus.py
+++ b/sympy/assumptions/handlers/calculus.py
@@ -195,6 +195,8 @@ def _(expr, assumptions):
     if base_bounded is False and ask(Q.extended_nonzero(expr.exp), assumptions):
         return False
     if base_bounded and exp_bounded:
+        if ask(Q.zero(expr.base),assumptions) is not False and ask(Q.negative(expr.exp),assumptions) is not False:
+            return None
         return True
     if (abs(expr.base) <= 1) == True and ask(Q.extended_positive(expr.exp), assumptions):
         return True
diff --git a/sympy/assumptions/tests/test_query.py b/sympy/assumptions/tests/test_query.py
index 5e0eeb50a037..72ea4ae06fdd 100644
--- a/sympy/assumptions/tests/test_query.py
+++ b/sympy/assumptions/tests/test_query.py
@@ -1082,6 +1082,15 @@ def test_bounded():
     assert ask(Q.finite(2**x), ~Q.finite(x)) is False
     assert ask(Q.finite(x**2), ~Q.finite(x)) is False
 
+    # https://github.com/sympy/sympy/issues/27707
+    assert ask(Q.finite(x**y),Q.real(x) & Q.real(y)) is None
+    assert ask(Q.finite(x**y),Q.real(x) & Q.negative(y)) is None
+    assert ask(Q.finite(x**y),Q.zero(x) & Q.negative(y)) is None
+    assert ask(Q.finite(x**y),Q.real(x) & Q.positive(y)) is True
+    assert ask(Q.finite(x**y),Q.nonzero(x) & Q.real(y)) is True
+    assert ask(Q.finite(x**y),Q.nonzero(x) & Q.negative(y)) is True
+    assert ask(Q.finite(x**y),Q.zero(x) & Q.positive(y)) is True
+
     # sign function
     assert ask(Q.finite(sign(x))) is True
     assert ask(Q.finite(sign(x)), ~Q.finite(x)) is True


Code review comments:
diff_hunk: @@ -195,6 +195,8 @@ def _(expr, assumptions):
     if base_bounded is False and ask(Q.extended_nonzero(expr.exp), assumptions):
         return False
     if base_bounded and exp_bounded:
+        if ask(Q.zero(expr.base),assumptions) is not False and ask(Q.negative(expr.exp),assumptions) is not False:
+            return None
path: sympy/assumptions/handlers/calculus.py
text: @user1:
If the base is zero and exponent is negative you could return False.

@author:
Ohh right. Just to understand it a bit better we are doing this because finite should return False when the expression is either nan or infinity right ?