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

'limit' in combination with 'positive=True' gives wrong result #22893

Open
mkellerressel opened this issue Jan 20, 2022 · 2 comments
Open

'limit' in combination with 'positive=True' gives wrong result #22893

mkellerressel opened this issue Jan 20, 2022 · 2 comments
Labels

Comments

@mkellerressel
Copy link

mkellerressel commented Jan 20, 2022

I have encountered a problem with the 'limit' function in combination with the 'positive=True' assumption on symbols. Here is a minimal example that reproduces the problem:

a, b = symbols("a b", positive=True)
my_expr = (a * exp(-a*x) + b * exp(-b * x)) * exp(b * x)
limit(my_expr,x,oo)

which returns

oo

while the result should be b, a+b or oo, depending on the sign of (b-a).

When the 'positive=True' assumption is removed, as in

a, b = symbols("a b")
my_expr = (a * exp(-a*x) + b * exp(-b * x)) * exp(b * x)
limit(my_expr,x,oo)

the result is

NotImplementedError: Result depends on the sign of -sign(a)

which is OK, but actually the result depends on the sign of b-a only, not on the sign of a.

If the expression is expanded before evaluation, as in

a, b = symbols("a b", positive = True)
my_expr = (a * exp(-a*x) + b * exp(-b * x)) * exp(b * x)
limit(my_expr.expand(),x,oo)

the result is

NotImplementedError: Result depends on the sign of sign(-a + b)

which is the correct behavior from my point of view.

@anutosh491
Copy link
Member

anutosh491 commented Jan 21, 2022

True , this is a somewhat distantly known error in sympy and has been reported various at multiple locations . Check this one out which I did catch myself #22334 .It's not that difficult to find sympy returning different results for limits evaluated for different forms of the expressions(using expand/simplify/trigsimp and other methods give different forms).

This seems to be due to the mrv_leadterm method in gruntz.py which end up returning different results for different forms of the expression .I'm not too sure how we could counter this (I am still finishing my reading on gruntz thesis and once I fully read it I will be able to comment better ) but as per what I read it states

"As the mrv set depends on the form of the expression which represents the function f (x), mathematically equivalent expressions may have diferent mrv sets"
I feel returning different mrv sets is okay untill we don't get wrong and different answers eventually !!

skirpichev added a commit to skirpichev/diofant that referenced this issue Jan 21, 2022
skirpichev added a commit to skirpichev/diofant that referenced this issue Jan 24, 2022
@anutosh491
Copy link
Member

@jksuom @0sidharth Currently there are more than a couple of issues based on such backgrounds(I remember 3 atleast at this moment) . These problems basically boil down to calculating symbolic limits (in different forms after simplifying, using expand or even just placing a bracket here and there ( I was suprised when I saw this)) under different assumptions on the extra variables considered like a , b ! and all these return wrong/inconsistent answers.

I see that many of these boil down the core of the gruntz algorithm which is the compare function . For eg

>>> a  = Symbol('a')
>>> x = Symbol('x')
>>> compare(exp(-a*x), x, x)
'='

If we don't have any particular assumption on a then we get this but I am confused as there is no a where an exponential with exponent(a*x) would share a comparability class with x
compare(exp(0*x), x, x)

compare(exp(0*x), x, x)
Out[18]: '<'

compare(exp(5*x), x, x)
Out[19]: '>'

compare(exp(-5*x), x, x)
Out[20]: '>'

compare(exp(-0.5*x), x, x)
Out[21]: '>'

compare(exp(0.5*x), x, x)
Out[22]: '>'

compare(exp(I*x), x, x)
Out[23]: '>'

compare(exp(-I*x), x, x)
Out[24]: '>'

It's either '>' or '<' and this is one of the prominent reasons why we encounter these cases .

Hence whenever a user declared the variable a and calls for limit(expr, x, oo) shouldn't we raise a warning instead of returning the wrong result . The warning should inform them that they should be imposing assumptions on a so that better decisions can be taken and once that is done we can return more consistent and correct answers !
I propose something like this


--- a/sympy/series/gruntz.py
+++ b/sympy/series/gruntz.py
@@ -147,8 +147,13 @@ def compare(a, b, x):
     c = limitinf(la/lb, x)
     if c == 0:
         return "<"
-    elif c.is_infinite:
-        return ">"
+    elif any(_.is_infinite for _ in Mul.make_args(c)):
+        if any(True for _ in Mul.make_args(c) if _.is_zero is None):
+            # raise warning
+        elif any( _.is_zero for _ in Mul.make_args(c)):
+            return "<"
+        else:
+            return ">"
     else:
         return "="

Hence whenever we tackle c = limitinf(-a*x/log(x), x) and get back -oo*sign(a) for c , it goes through the first condition and warns the user to declare somthing like a= Symbol('x', zero = False) this makes sign(a).is_zero return False and hence we could then use the ">" symbol rather the equality symbol as I don't think we encounter any case where exponential with symbolic exponent would be comparable to a linear x .
As I just finished my read on the gruntz thesis I would be glad to hear from your side and also I've implemented this locally and doesn't disturb any of the existing slow/normal tests !

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

No branches or pull requests

3 participants