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

Evaluating limits when substuting an expression with infinity. #2599

Closed
wants to merge 6 commits into from

Conversation

hargup
Copy link
Contributor

@hargup hargup commented Nov 15, 2013

Using subs with oo leads to wrong results.
For example

>>> (exp(x)/exp(x*x)).subs(x,oo)
nan

https://code.google.com/p/sympy/issues/detail?id=1769#c9

This attempts to fix this by adding a special case in the _subs function to evaluate limit when expression being substituted with is infinity.

@asmeurer
Copy link
Member

My feeling is that it shouldn't do this. Anyway, why is infinity so special. You can get nan by substituting any number to the right expression.

@skirpichev
Copy link
Contributor

Using subs with oo leads to wrong results.

Sometimes (and sometimes - not). And these things happens not just with oo. Your example is easy to translate to:

In [8]: (exp(1/x)/exp(1/x**2)).limit(x, 0)
Out[8]: 0

In [9]: (exp(1/x)/exp(1/x**2)).subs(x, 0)
Out[9]: nan

Another example:

In [10]: (sin(x)/x).subs(x, 0)
Out[10]: nan

In [11]: (sin(x - 1)/(1 - x)).subs(x, 1)
Out[11]: nan

Nothing unusual, see the Wolfram's Mathematica:

In[2]:= Sin[x]/x/.x->0
                                 1
Power::infy: Infinite expression - encountered.
                                 0
Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.
Out[2]= 
Indeterminate

So, it's not the infinity is special, it's subs. Just stupid (literal) substitutions, no any fancy math and no limits! If that's not clear from docs, we should fix the docstring for subs.

Otherwise, -1.

@hargup
Copy link
Contributor Author

hargup commented Nov 15, 2013

Infinity is special because substituting with infinity is not well define. We cannot simply multiply, divide, subtract or add infinity to something. We must calculate the limit at infinity to keep things consistent.

>>> oo/(oo*oo)
nan

but

>>> (x/(x*x)).subs(x,oo)
0

Other way can be returning nan when every we encounter oo/oo or oo - oo or oo*0 in subs. Anyway, we have to add special case for infinity.

@smichr
Copy link
Member

smichr commented Nov 15, 2013

Yes...substitution is about evaluation at a point. And you might not be
able to evaeluate at that point. The limit tells us what value a function
has arbitrarily close to a point as we approach that point from a given
direction.

@skirpichev
Copy link
Contributor

On Fri, Nov 15, 2013 at 12:31:51PM -0800, Harsh Gupta wrote:

Infinity is special because substituting with infinity is not well define.

??

(x/(x*x)).subs(x, oo) means just: 1) perform some canonicalization of
the expresson, 2) then substitute oo for x, 3) then apply operations
according to priorities.

We cannot simply multiply, divide, subtract or add infinity to something.

In general, we can (but yes, there are some restrictions).

We must calculate the limit at infinity to keep things consistent.

oo/(oo*oo)
nan

But (evaluate=False!):

  >>> Mul(x, Pow(Mul(x, x, evaluate=False), -1, evaluate=False))
  x/x**2
  >>> _.subs(x, oo)
  nan
  >>> (x/(x*x)).subs(x, oo)
  0
  >>> (x/(x*x)).subs(x, 0)
  oo

Where is inconsistency? Sometimes, subs gives nan, it's fine.

Other way can be returning nan when every we encounter oo/oo or oo - oo or
oo*0 in subs.

There are many ways to get nan with subs. There is nothing
special with infinity here in this sense. And there is no reason
to break whole idea of (plain, stupid, literal) substitution
just for this case.

If you want limits - use limit method, not subs.

@hargup
Copy link
Contributor Author

hargup commented Nov 16, 2013

I get it. I did this after reading comment of asmeurer at https://code.google.com/p/sympy/issues/detail?id=1769#c9. Where he said

This comes up with a bunch of functions, actually. If evaluation at oo is not specifically defined in eval(), it is left alone. This leads to a lot of wrong results if people use subs instead of limit

In [76]: factorial(oo)
Out[76]: (∞)!

In [77]: limit(exp(x)/factorial(x),x, oo)
Out[77]: 0

In [78]: (exp(x)/factorial(x)).subs(x, oo)
Out[78]: ∞

Should we special case functions evaluated at oo in Mul and Pow (Function._eval_power)? How would that affect performance?

So, I thought (exp(x)/factorial(x)).subs(x, oo) is expected to return 0. Also it is not very clear from the doc what subs do when it encounter expressions like this. I thought evaluating limit might be a good idea.

Shall I edit the docs, to make it more explicit what sympy does with subs?

@hargup hargup closed this Nov 16, 2013
@skirpichev
Copy link
Contributor

Also it is not very clear from the doc what subs do when it encounter expressions like this.

As I said, if that's not clear - we should fix the documentation. But not to abuse substitution with limits.

@hargup
Copy link
Contributor Author

hargup commented Nov 16, 2013

Forgive me I'm new to sympy and open-source development in general. So I'm still getting familiar with the way things are done here. I guess I should discussed before sending a pull request.

@asmeurer
Copy link
Member

So a few things:

  • I never intended to do this in my comment. Aside from limit being a potentially very expensive thing, I think it's being too smart for subs, which is better left to be relatively dumb. And anyway, as @smichr notes, mathematically f(a) and lim_{x -> a} f(x) are different things. They coincide only if f is continuous at a.
  • Don't worry that this pull request has been rejected. Generally things like this are welcome, but in this case, we decided it's not something we want to do. It happens.
  • I agree that documentation can be improved. Neither the docstring of subs nor the tutorial mention this issue.
  • It seems the real bug here has been fixed, namely, that oo/factorial(oo) doesn't automatically evaluate to oo, i.e., oo doesn't absorb the 1/factorial(oo) because the latter's finiteness is unknown. That should make it impossible, at least using this trick, to rig up examples of subs giving wrong finite results (wrong infinite and especially wrong nan results are unavoidable without the full power of limit).
  • If you still want to contribute, there's an obvious bug here, which is that factorial(oo) should return oo.

@hargup
Copy link
Contributor Author

hargup commented Dec 3, 2013

I edited the docstring for subs.
#2649

@hargup hargup mentioned this pull request Dec 5, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants