sympy / sympy

A computer algebra system written in pure Python
https://sympy.org/
Other
12.84k stars 4.4k forks source link

limit((log(E + 1/x) - 1)**(1 - sqrt(E + 1/x)), x, oo) returns 0 instead of oo #22982

Closed anutosh491 closed 1 month ago

anutosh491 commented 2 years ago

Originally reported on https://groups.google.com/g/sympy/c/wV0FsQ86ooE/m/TliUrKjMrhkJ I came across an issue which is similar to the one above , I searched whether any similar/related issue has been reported already and found one on the google groups . gruntz is responsible for this .Not too sure about the fix though !

>>> x = Symbol('x', real=True, positive=True)
>>> m = Symbol('m', real=True, positive=True)
>>> limit((log(E + 1/x) - 1)**(1 - sqrt(E + 1/x)), x, oo)
0
>>> gruntz((log(E + 1/x) - 1)**(1 - sqrt(E + 1/x)), x, oo)
0

Close relatives of the expression work fine

>>> limit((log(E + 1/x) )**(1 - sqrt(E + 1/x)), x, oo)
1
>>> limit((log(E + 1/x) - 1)**(- sqrt(E + 1/x)), x, oo)
oo

Pic from wolfram for reference image

As this has already been reported on the google group , it might have been raised before . Though I did a basic check for myself, if found to be reported earlier ...feel free to close . Thanks!

anutosh491 commented 2 years ago

It seems that pow_heuristics method from limits.py can be improved to solve this issue, following steps similar to this image

But we need to take care of both the real and imaginary limits when we would be using exp to raise, otherwise we might encounter wrong results , so something along this lines can should be used and improved

--- a/sympy/series/limits.py
+++ b/sympy/series/limits.py
@@ -181,13 +181,12 @@ def free_symbols(self):
     def pow_heuristics(self, e):
         _, z, z0, _ = self.args
         b1, e1 = e.base, e.exp
-        if not b1.has(z):
-            res = limit(e1*log(b1), z, z0)
-            return exp(res)
-
         ex_lim = limit(e1, z, z0)
         base_lim = limit(b1, z, z0)

+        if not b1.has(z) or base_lim in (S.Zero, S.Infinity, S.NegativeInfinity):
+           from sympy import expand_log, im, re, I
+           log_b1 = expand_log(log(b1), force=True)
+           im_res = I*limit(e1*im(log_b1), z, z0, _)
+           re_res = limit(e1*re(log_b1), z, z0, _)
+           return exp(im_res)*exp(re_res)

         if base_lim is S.One:
arnabnandikgp commented 3 months ago

It seems that the problem stems from the following

In [5]: _p = symbols('_p', positive=True)

In [6]: expr = (log(E + 1/_p) - 1)**(1 - sqrt(E + 1/_p))

In [7]: mrv_leadterm(expr,_p)
Out[7]: (exp(_p - 1 + exp(1/2)), 2 - exp(1/2)) # should have been (exp(-1+exp(1/2)),1-exp(1/2))

initially it seems that rewrite for the expression (log(E + 1/x) - 1)**(1 - sqrt(E + 1/x)) was the problem which in master is givnen by


In [14]: f   #(f is the value when the above expression is rewritten using its mrv)
Out[14]: 
       1/2                          1/2          ________                     
  1 - ℯ                       - _p⋅ℯ    + _p - ╲╱ _w + ℯ ⋅log(log(_w + ℯ) - 1)
_w        ⋅(log(_w + ℯ) - 1)⋅ℯ                                                

I tried to make the calculations for mrv manually and the answers were consistent with that given in master, then i tried to compare the results with diofant and it seems the rewrite in diofant is given by

In [16]: m
Out[16]: 
       1/2       ⎛      1/2⎞   ⎛      ________⎞                     
  1 - ℯ     - _p⋅⎝-1 + ℯ   ⎠ + ⎝1 - ╲╱ _w + ℯ ⎠⋅log(log(_w + ℯ) - 1)
_w        ⋅ℯ                                                        

and interistingly enough both the values are equal as one can see(by observation and also using equals method in sympy)

In [18]: f.equals(m)
Out[18]: True

but while we calcualte leadterm for the both there is an inconsistency as follows

In [19]: f.leadterm(_w, logx= -_p)
Out[19]: 
⎛           1/2          ⎞
⎜ _p - 1 + ℯ          1/2⎟
⎝ℯ             , 2 - ℯ   ⎠

In [21]: m.leadterm(_w, logx=-_p)
Out[21]: 
⎛       1/2          ⎞
⎜ -1 + ℯ          1/2⎟
⎝ℯ         , 1 - ℯ   ⎠
arnabnandikgp commented 2 months ago

I was looking through what is wrong in the above and stumbled upon another similar issue #15323 and I totally agree with the kalevi here as he has rightly pointed out in the comment use of expand is causing problems here by turnig m to f as ponted out in the above comment, also a expand_mul was added later which is causing this same probelm, here https://github.com/sympy/sympy/blob/3a812204052176854bdfc1ea9d12097c3f9307ca/sympy/series/gruntz.py#L690-L691 I tried removing these expand methods but it breaks the following test, https://github.com/sympy/sympy/blob/3a812204052176854bdfc1ea9d12097c3f9307ca/sympy/series/tests/test_limits.py#L836-L838 need to see how we can get this done.