Skip to content

Conversation

@sachin-4099
Copy link
Contributor

@sachin-4099 sachin-4099 commented Mar 27, 2020

Fixes: #14811

First of all, it no longer raises any exception as mentioned in the issue.
But, the actual issue is that it is returned unevaluated due to a ValueError.

Brief description of what is fixed or changed

Previously:

In[1]: limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) 
Out[1]: Unevaluated, returned as it is

A bit of simplification was missing in limitinf() function of gruntz.py which was causing ValueError and thus, the result was an unevaluated form.

Now this evaluates correctly:

In[1]: limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) 
Out[1]: oo

Other Comments

Regression Test has been added.

Release Notes

  • series
    • Adds simplification to limitinf() function of gruntz.py resolving ValueError

@sympy-bot
Copy link

sympy-bot commented Mar 27, 2020

Hi, I am the SymPy bot (v158). 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:

  • series
    • Adds simplification to limitinf() function of gruntz.py resolving ValueError (#18978 by @sachin-4099)

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.6.

Note: This comment will be updated with the latest check if you edit the pull request. You need to reload the page to see it.

Click here to see the pull request description that was parsed.

Fixes: #14811 

First of all, it no longer raises any exception as mentioned in the issue.
But, the actual issue is that it is `returned unevaluated due to a ValueError.`

#### Brief description of what is fixed or changed
**Previously:**
```
In[1]: limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) 
Out[1]: Unevaluated, returned as it is
```
A bit of simplification was missing in `limitinf() function of gruntz.py` which was causing `ValueError `and thus, the result was an unevaluated form.

**Now this evaluates correctly:**
```
In[1]: limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) 
Out[1]: oo
```



#### Other Comments
Regression Test has been added.


#### Release Notes


<!-- BEGIN RELEASE NOTES -->
* series
  * Adds simplification to `limitinf() function of gruntz.py` resolving `ValueError` 
<!-- END RELEASE NOTES -->

Update

The release notes on the wiki have been updated.

@sachin-4099
Copy link
Contributor Author

sachin-4099 commented Mar 28, 2020

This is not timing out on my machine.

Co-Authored-By: Kalevi Suominen <jksuom@gmail.com>
@codecov
Copy link

codecov bot commented Mar 28, 2020

Codecov Report

Merging #18978 into master will increase coverage by 11.43%.
The diff coverage is 100%.

@@             Coverage Diff              @@
##           master    #18978       +/-   ##
============================================
+ Coverage   64.32%   75.751%   +11.43%     
============================================
  Files         647       647               
  Lines      168592    168615       +23     
  Branches    39725     39732        +7     
============================================
+ Hits       108439    127728    +19289     
+ Misses      53996     35326    -18670     
+ Partials     6157      5561      -596

@sachin-4099 sachin-4099 requested a review from jksuom March 28, 2020 09:21
@jksuom
Copy link
Member

jksuom commented Mar 28, 2020

Thanks, looks good.

@jksuom jksuom merged commit d731113 into sympy:master Mar 28, 2020
@oscarbenjamin
Copy link
Collaborator

The test added here hangs intermittently on Python 3.5:

$ cat t.py 
from sympy import *
from sympy.abc import x

assert limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) == oo

$ for x in `seq 1 100`; do time python t.py; done

real	0m5.210s
user	0m5.084s
sys	0m0.097s

real	0m7.380s
user	0m7.051s
sys	0m0.142s

real	0m6.112s
user	0m5.949s
sys	0m0.101s
^CTraceback (most recent call last):
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 260, in getit
    return self._assumptions[fact]
KeyError: 'zero'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 260, in getit
    return self._assumptions[fact]
KeyError: 'hermitian'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "t.py", line 4, in <module>
    assert limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) == oo
  File "/Users/enojb/current/sympy/sympy/sympy/series/limits.py", line 70, in limit
    return Limit(e, z, z0, dir).doit(deep=False)
  File "/Users/enojb/current/sympy/sympy/sympy/series/limits.py", line 260, in doit
    r = gruntz(e, z, z0, dir)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 669, in gruntz
    r = limitinf(e0, z)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 432, in limitinf
    c0, e0 = mrv_leadterm(e, x)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 521, in mrv_leadterm
    f, logw = rewrite(exps, Omega, x, w)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 600, in rewrite
    c = limitinf(f.args[0]/g.args[0], x)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 448, in limitinf
    return limitinf(c0, x, leadsimp)  # e0=0: lim f = lim c0
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 448, in limitinf
    return limitinf(c0, x, leadsimp)  # e0=0: lim f = lim c0
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 432, in limitinf
    c0, e0 = mrv_leadterm(e, x)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 522, in mrv_leadterm
    series = calculate_series(f, w, logx=logw)
  File "/Users/enojb/current/sympy/sympy/sympy/series/gruntz.py", line 475, in calculate_series
    for t in e.lseries(x, logx=logx):
  File "/Users/enojb/current/sympy/sympy/sympy/core/expr.py", line 2927, in yield_lseries
    for si in s:
  File "/Users/enojb/current/sympy/sympy/sympy/core/expr.py", line 3149, in _eval_lseries
    series = self._eval_nseries(x, n=n, logx=logx)
  File "/Users/enojb/current/sympy/sympy/sympy/core/mul.py", line 1749, in _eval_nseries
    terms = [t.nseries(x, n=n, logx=logx) for t in self.args]
  File "/Users/enojb/current/sympy/sympy/sympy/core/mul.py", line 1749, in <listcomp>
    terms = [t.nseries(x, n=n, logx=logx) for t in self.args]
  File "/Users/enojb/current/sympy/sympy/sympy/core/expr.py", line 3226, in nseries
    return self._eval_nseries(x, n=n, logx=logx)
  File "/Users/enojb/current/sympy/sympy/sympy/functions/elementary/exponential.py", line 451, in _eval_nseries
    r += Order((arg_series - arg0)**n, x)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/series/order.py", line 224, in __new__
    expr = expr.as_leading_term(*args)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/core/expr.py", line 3305, in as_leading_term
    obj = self._eval_as_leading_term(x)
  File "/Users/enojb/current/sympy/sympy/sympy/core/power.py", line 1665, in _eval_as_leading_term
    return self.func(self.base.as_leading_term(x), self.exp)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/core/power.py", line 319, in __new__
    obj = b._eval_power(e)
  File "/Users/enojb/current/sympy/sympy/sympy/core/mul.py", line 641, in _eval_power
    Pow(Mul._from_args(nc), e, evaluate=False)
  File "/Users/enojb/current/sympy/sympy/sympy/core/decorators.py", line 253, in _func
    return func(self, other)
  File "/Users/enojb/current/sympy/sympy/sympy/core/decorators.py", line 129, in binary_op_wrapper
    return func(self, other)
  File "/Users/enojb/current/sympy/sympy/sympy/core/expr.py", line 200, in __mul__
    return Mul(self, other)
  File "/Users/enojb/current/sympy/sympy/sympy/core/cache.py", line 95, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/Users/enojb/current/sympy/sympy/sympy/core/operations.py", line 54, in __new__
    c_part, nc_part, order_symbols = cls.flatten(args)
  File "/Users/enojb/current/sympy/sympy/sympy/core/mul.py", line 199, in flatten
    if not a.is_zero and a.is_Rational:
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 264, in getit
    return _ask(fact, self)
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 319, in _ask
    _ask(pk, obj)
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 307, in _ask
    a = evaluate(obj)
  File "/Users/enojb/current/sympy/sympy/sympy/core/mul.py", line 1324, in _eval_is_hermitian
    return self._eval_herm_antiherm(True)
  File "/Users/enojb/current/sympy/sympy/sympy/core/mul.py", line 1337, in _eval_herm_antiherm
    elif t.is_hermitian:
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 264, in getit
    return _ask(fact, self)
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 319, in _ask
    _ask(pk, obj)
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 319, in _ask
    _ask(pk, obj)
  File "/Users/enojb/current/sympy/sympy/sympy/core/assumptions.py", line 309, in _ask
    assumptions.deduce_all_facts(((fact, a),))
  File "/Users/enojb/current/sympy/sympy/sympy/core/facts.py", line 534, in deduce_all_facts
    if all(self.get(k) is v for k, v in bcond):
KeyboardInterrupt

real	0m32.485s
user	0m32.046s
sys	0m0.170s

This leads to sporadic Travis failures.

I can only reproduce this on 3.5 and it only failed on Travis for 3.5. That would suggest that dict ordering plays a role in the non-determinism.

@oscarbenjamin
Copy link
Collaborator

If the cause of the hang can not be identified quickly then it would be better to xfail the test on Python 3.5 as it will interfere with other PRs.

@Smit-create
Copy link
Member

Smit-create commented Mar 28, 2020

During the Travis build of #18754 there was a failing test related to the issue resolved. See : https://travis-ci.org/github/sympy/sympy/jobs/668013022?utm_medium=notification&utm_source=github_status

@sachin-4099
Copy link
Contributor Author

sachin-4099 commented Mar 28, 2020

Can you please elaborate on the issue a bit more? Why is this hanging on python 3.5?

@oscarbenjamin
Copy link
Collaborator

It is the same failure as seen on Travis in the first commit of this PR.

Python 3.5 has non-deterministic dict-ordering so somewhere there is likely to be a code-path that iterates over a dict and hangs depending on the order of the items from the dict.

@sachin-4099
Copy link
Contributor Author

Okay, so what could be a possible solution.

@oscarbenjamin
Copy link
Collaborator

Okay, so what could be a possible solution.

Identify and fix the cause of the hang or xfail/skip the test

oscarbenjamin added a commit to oscarbenjamin/sympy that referenced this pull request Mar 28, 2020
The test added in sympy#18978 hangs
intermittently on Python 3.5. This commit XFAILS that test until the
cause of the hang can be identified because it is causing many failed
builds on master.
@oscarbenjamin
Copy link
Collaborator

I've opened #18990 to XFAIL the test that was added here. I don't know whether this means that the issue closed by this PR should be reopened or whether a new issue should be opened instead.

@sachin-4099
Copy link
Contributor Author


(py3) -- python 3.5:

In [1]: limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo)
Out[1]: oo

(base) -- python 3.7:

In [1]: limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo)
Out[1]:
     /                         / x\\
     |     x - 1               \2 /|
     | -4/3      /   x + 1    \    |
 lim \2         *\2/3      + 1/    /
x->oo

@sachin-4099
Copy link
Contributor Author

This is the problem, without any added simplification, the limit is evaluated properly on python 3.5, but not on python 3.7

@oscarbenjamin
Copy link
Collaborator

I think it's best to either comment on the re-opened issue or close that and open a new issue.

@sachin-4099
Copy link
Contributor Author

okay will comment on the re-opened issue

@jksuom
Copy link
Member

jksuom commented Mar 28, 2020

It seems that there is a non-deterministic element even without cancel. These are the results of two independent runs of python t.py with e0 = e0.cancel() replaced by if eo.has(log): print(e0).
t1.txt
t2.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exception during evaluation of limit (only locally, not in the live version)

6 participants