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

nsimplify with tolerance doesn’t work with functions with numerical arguments #15589

Open
Wrzlprmft opened this issue Dec 5, 2018 · 8 comments

Comments

@Wrzlprmft
Copy link

Wrzlprmft commented Dec 5, 2018

Consider the following example:

import sympy
f = sympy.Function("f")
x = sympy.Symbol("x")
assert sympy.nsimplify(1e-16*x   ,tolerance=1e-10) == 0
assert sympy.nsimplify(1e-16*f(x),tolerance=1e-10) == 0
assert sympy.nsimplify(1e-16*f(0),tolerance=1e-10) == 0

Only the last assertion fails – which it shouldn’t unless I am completely mistaken.

@oscarbenjamin
Copy link
Contributor

oscarbenjamin commented Dec 5, 2018

The doc for nsimplify says:

Find a simple representation for a number or, if there are free symbols
 or if rational=True, then replace Floats with their Rational equivalents.
If no change is made and rational is not False then Floats will at least be
converted to Rationals.

I'm not really sure what the rationale for that behaviour is but does match what you see.

Your two cases differ because 1e-16*f(x) has the free symbol x whereas 1e-16*f(0) has no free symbols:

In [17]: (1e-16*f(x)).free_symbols
Out[17]: {x}

In [18]: (1e-16*f(0)).free_symbols
Out[18]: set()

Per the doc-string you can get the same effect in the no free symbols case by setting rational=True:

In [19]: nsimplify(1e-16*f(0), tolerance=1e-10, rational=True)
Out[19]: 0

@Wrzlprmft
Copy link
Author

I'm not really sure what the rationale for that behaviour is but does match what you see.

Indeed. I read this but misunderstood it (or my brain autocorrected it to something more intuitive). In this case, I would make this a feature request for a more intuitive behaviour.

@oscarbenjamin
Copy link
Contributor

What exactly would the feature request be? Does rational=True do what you want?

Can you explain what you're using nsimplify for and why your suggestion makes sense? (I personally have never used it - that's why I looked up the docstring!)

@Wrzlprmft
Copy link
Author

What exactly would the feature request be? Does rational=True do what you want?

The dependence on the presence of free symbols is not what I expected. Thinking about it, I think the idea is that if you have no free symbols, you most likely want the entire expression to be represented by a number, but that does not make sense in the presence of undefined functions.

Can you explain what you're using nsimplify for and why your suggestion makes sense? (I personally have never used it - that's why I looked up the docstring!)

I am using it to check terms for identity whose composition involves floats and thus floating-point inaccuracies.

@oscarbenjamin
Copy link
Contributor

I also wouldn't have expected it to depend on free symbols. I read https://en.wikipedia.org/wiki/Free_variables_and_bound_variables and from there I'm not sure why f is not a free symbol in these expressions.

@asmeurer
Copy link
Member

asmeurer commented Dec 7, 2018

SymPy doesn't consider functions to be symbols for the purposes of free symbols. But the check really should be is_number, which takes into account things like f(0) which don't have free symbols but can't be numerically evaluated.

@oscarbenjamin
Copy link
Contributor

Would you consider making that change to nsimplify to be reasonable?

@oscarbenjamin
Copy link
Contributor

This and #14761 are duplicate issues

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

3 participants