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

(-x).is_extended_positive fails for extended_real and infinite #17555

Open
oscarbenjamin opened this issue Aug 31, 2019 · 1 comment
Open

(-x).is_extended_positive fails for extended_real and infinite #17555

oscarbenjamin opened this issue Aug 31, 2019 · 1 comment

Comments

@oscarbenjamin
Copy link
Contributor

oscarbenjamin commented Aug 31, 2019

When an expression is only known to be extended_real and infinite its sign is unknown so is_extended_positive should give None but

In [1]: x = Symbol('x', infinite=True, extended_real=True)                                                                        

In [2]: print(x.is_extended_positive)                                                                                             
None

In [3]: print((-x).is_extended_positive)                                                                                          
True

The obvious fix is

diff --git a/sympy/core/mul.py b/sympy/core/mul.py
index da2a8b18e7..ea0df52dfc 100644
--- a/sympy/core/mul.py
+++ b/sympy/core/mul.py
@@ -1401,12 +1401,12 @@ def _eval_pos_neg(self, sign):
                 saw_NON = True
             elif t.is_extended_nonnegative:
                 saw_NON = True
-            elif t.is_positive is False:
+            elif t.is_extended_positive is False:
                 sign = -sign
                 if saw_NOT:
                     return
                 saw_NOT = True
-            elif t.is_negative is False:
+            elif t.is_extended_negative is False:
                 if saw_NOT:
                     return
                 saw_NOT = True

Which gives

In [3]: print((-x).is_extended_positive)                                                                                          
None

However it also leads to test failures in other places where positive=False is used:

$ pytest sympy/core/ -n4

...
============================================================ FAILURES ============================================================
_________________________________________________ test_symbol_falsepositive_mul __________________________________________________
[gw1] darwin -- Python 3.5.7 /Users/enojb/current/sympy/35venv/bin/python3.5

    def test_symbol_falsepositive_mul():
        # To test pull request 9379
        # Explicit handling of arg.is_positive=False was added to Mul._eval_is_positive
        x = 2*Symbol('x', positive=False)
>       assert x.is_positive is False  # This was None before
E       assert None is False
E        +  where None = 2*x.is_positive

sympy/core/tests/test_assumptions.py:460: AssertionError
_________________________________________________ test_neg_symbol_falsepositive __________________________________________________
[gw1] darwin -- Python 3.5.7 /Users/enojb/current/sympy/35venv/bin/python3.5

    def test_neg_symbol_falsepositive():
        x = -Symbol('x', positive=False)
        assert x.is_positive is None
        assert x.is_nonpositive is None
>       assert x.is_negative is False
E       assert None is False
E        +  where None = -x.is_negative

sympy/core/tests/test_assumptions.py:472: AssertionError
_________________________________________________ test_neg_symbol_falsenegative __________________________________________________
[gw1] darwin -- Python 3.5.7 /Users/enojb/current/sympy/35venv/bin/python3.5

    def test_neg_symbol_falsenegative():
        # To test pull request 9379
        # Explicit handling of arg.is_negative=False was added to Mul._eval_is_positive
        x = -Symbol('x', negative=False)
>       assert x.is_positive is False  # This was None before
E       assert None is False
E        +  where None = -x.is_positive

sympy/core/tests/test_assumptions.py:482: AssertionError
                                                         DO *NOT* COMMIT!                                                         
================================= 3 failed, 1696 passed, 65 skipped, 41 xfailed in 60.70 seconds =================================

The fix for that is probably to add Mul._eval_is_positive (and Mul._eval_is_negative) as well as Mul._eval_is_extended_positive. However this should be done intelligently to avoid duplicating the _eval_pos_neg routine. Maybe just:

def _eval_is_positive(self):
    if self._eval_is_finite() is False:
        return False
    return self._eval_pos_neg(1)

It should be checked that this doesn't lead to any slowdown though.

@oscarbenjamin
Copy link
Contributor Author

In #17535 I've added some comments about this and an XFAIL test.

skirpichev added a commit to skirpichev/diofant that referenced this issue Sep 2, 2019
skirpichev added a commit to skirpichev/diofant that referenced this issue Sep 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant