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

UnboundLocalError in nonlinsolve #22413

Open
proy87 opened this issue Nov 3, 2021 · 8 comments
Open

UnboundLocalError in nonlinsolve #22413

proy87 opened this issue Nov 3, 2021 · 8 comments
Labels
solvers.solveset Wrong Result The output produced by SymPy is mathematically incorrect.

Comments

@proy87
Copy link

proy87 commented Nov 3, 2021

nonlinsolve((4*y*(2*x + 2*exp(y) + 1)*exp(2*x), 4*x*exp(2*x) + 4*y*exp(2*x + y) + 4*exp(2*x + y) + 1), x,y)

raises UnboundLocalError: local variable 'exp_invs' referenced before assignment.

@oscargus
Copy link
Contributor

oscargus commented Nov 4, 2021

Do you think that
image
is the correct answer?

@proy87
Copy link
Author

proy87 commented Nov 4, 2021

@oscargus , (x,0) doesn't satisfy the second equation.

@oscargus
Copy link
Contributor

oscargus commented Nov 4, 2021

OK! Then my simple fix didn't work... (I was not sure how to interpret the results...)

@oscargus
Copy link
Contributor

oscargus commented Nov 4, 2021

The problem is that g_ys is EmptySet here:

if isinstance(f, exp) or (f.is_Pow and f.base == S.Exp1):
if isinstance(g_ys, ImageSet):
# can solve upto `(d*exp(exp(...(exp(a*x + b))...) + c)` format.
# Further can be improved to `(d*exp(exp(...(exp(a*x**n + b*x**(n-1) + ... + f))...) + c)`.
g_ys_expr = g_ys.lamda.expr
g_ys_vars = g_ys.lamda.variables
k = Dummy('k{}'.format(len(g_ys_vars)))
g_ys_vars_1 = (k,) + g_ys_vars
exp_invs = Union(*[imageset(Lambda((g_ys_vars_1,), (I*(2*k*pi + arg(g_ys_expr))
+ log(Abs(g_ys_expr)))), S.Integers**(len(g_ys_vars_1)))])
elif isinstance(g_ys, FiniteSet):
exp_invs = Union(*[imageset(Lambda(n, I*(2*n*pi + arg(g_y)) +
log(Abs(g_y))), S.Integers)
for g_y in g_ys if g_y != 0])
return _invert_complex(f.exp, exp_invs, symbol)

Just adding a check for EmptySet here:

if f == symbol:
return (f, g_ys)

is what I tried and it returns the incorrect result.

So something more clever should be returned by an additional if-statement at the end of the first piece of code.

@oscargus
Copy link
Contributor

oscargus commented Nov 4, 2021

I'm tempted to believe that the correct way to get away with the error is to change 326 to:

if f == symbol or g_ys == EmptySet:

and that the incorrect result comes from elsewhere (I seem to recall that nonlinsolve/substitution sometimes give incorrect results).

One should maybe add a corresponding fast exit for _invert_real for performance reasons.

@proy87
Copy link
Author

proy87 commented Nov 4, 2021

@oscargus , if g_ys is EmptySet, shouldn't it return EmptySet, because f(x)=EmptySet is EmptySet?

@oscargus
Copy link
Contributor

oscargus commented Nov 4, 2021

It will since it returns (f, g_ys).

@oscargus
Copy link
Contributor

oscargus commented Nov 4, 2021

I created a PR that avoids the error, but returns the incorrect solution. So this remains to be fixed in the issue. (I am quite sure that I have not introduced the incorrect result by fixing the error.)

@oscargus oscargus added the Wrong Result The output produced by SymPy is mathematically incorrect. label Nov 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
solvers.solveset Wrong Result The output produced by SymPy is mathematically incorrect.
Projects
None yet
Development

No branches or pull requests

3 participants