sympy icon indicating copy to clipboard operation
sympy copied to clipboard

Nonlinsolve wrong solution

Open aliceesiee opened this issue 2 years ago • 5 comments

Hello,

I would like to automatise the resolution of this kind of equations (and increase litle by litle the number of variables) :

a*exp(-b*90)=33
a*exp(-b*92)=66

I first tried this with one equation and it worked:

import sympy as sym
from sympy import solveset, S
from sympy.abc import x
from sympy import Symbol

a = symbols('a')
eq=sym.Eq(sym.exp(a*90),33)
solveset(eq,a,domain=S.Reals)

Then I tried this but it didn’t work :

a,b = symbols('a,b')
eq1 = sym.Eq(a*sym.exp(-b*90),33)
eq2 = sym.Eq(a*sym.exp(-b*92),66)
result=sym.solveset([eq1,eq2],(a,b),domain=S.Reals)

I get the following error, I guess the exponential is the problem?

ValueError                                Traceback (most recent call last)
Input In [59], in <cell line: 9>()
      7 eq1 = sym.Eq(a*sym.exp(-b*90),33)
      8 eq2 = sym.Eq(a*sym.exp(-b*92),66)
----> 9 result=sym.solveset([eq1,eq2],(a,b),domain=S.Reals)

File C:\ProgramData\Anaconda\lib\site-packages\sympy\solvers\solveset.py:2178, in solveset(f, symbol, domain)
   2175     return S.EmptySet
   2177 if not isinstance(f, (Expr, Relational, Number)):
-> 2178     raise ValueError("%s is not a valid SymPy expression" % f)
   2180 if not isinstance(symbol, (Expr, Relational)) and  symbol is not None:
   2181     raise ValueError("%s is not a valid SymPy symbol" % (symbol,))

ValueError: [Eq(a*exp(-90*b), 33), Eq(a*exp(-92*b), 66)] is not a valid SymPy expression

Then I tried :

import sympy as sym
from sympy import symbols, nonlinsolve

a, b = symbols('a, b', real=True)
eq1 = sym.Eq(a*sym.exp(-b*90),33)
eq2 = sym.Eq(a*sym.exp(-b*92),66)

sol = nonlinsolve([eq1,eq2],[a,b])
print(sol)

I get

{(NaN, NaN),(33𝑒90𝑖(2𝑛𝜋+𝜋)35184372088832, {𝑖(2𝑛𝜋+𝜋)+log(2⎯⎯√2)|||||𝑛∈ℤ}),(33𝑒180𝑛𝑖𝜋35184372088832, {2𝑛𝑖𝜋+log(2⎯⎯√2)|||||𝑛∈ℤ})}

However I want real solutions and if I solve if by hand, i get a= 33*2**(-45) and b= -ln(2)/2. I don't understand why I don't get this solution when computed.

I checked if the manual solution belongs to the computed solution but I get false.

sol_byhand=(33*2**(-45),-sym.log(2)/2)
sol_byhand in sol

Is it normal? It was suggested here to raise an issue.

Thanks for reading

aliceesiee avatar Sep 15 '22 08:09 aliceesiee

An answer was suggested at the issue. Note that

  • on your second attempt you misused solveset.
  • The output of nonlinsolve is probably fine but you have to select values of n that give you the real solution.

smichr avatar Sep 15 '22 18:09 smichr

  • Thank you for your answer. But by indicating real=True in the definition of a and b, shouldn't lead to only the real solutions?
  • I am sorry but I am not sure of what is wrong in my second attempt of solveset? that I wrote sym.solveset wheareas I could only write solveset?

I tried 2 ways to extract the real solution from the set :

  1. sol=nonlinsolve([eq1,eq2],[a,b]) & sym.Reals**2 but it leads to EmptySet.
  2. sol_real=[(a,b) for (a,b) in sol if (np.imag(a)==0 and np.imag(b)==0)] print (f"only real solution : {sol_real}") but I get only real solution : []

So it seams that the real solution that I fond manually is not inside the set?

aliceesiee avatar Sep 16 '22 08:09 aliceesiee

  • not sure of what is wrong in my second attempt of solveset

You passed a list ([eq1,eq2]), not an expression or relational, for f:

image

smichr avatar Sep 16 '22 18:09 smichr

I do not know how to work well with the sets/imagesets. But here is one way:

image

smichr avatar Sep 16 '22 19:09 smichr

I do not know how to work well with the sets/imagesets. But here is one way:

image

Thank you for that, I will keep that as I keep on working with my problem

aliceesiee avatar Sep 20 '22 12:09 aliceesiee

For at least the parts of the solution which are ImageSets, you can also get the real solutions by finding the intersection of the ImageSet with S.Reals (with evaluate =True). The evaluation of the intersection doesn't seem to always work, but it works for the ImageSets in this case:

>>> from sympy import *
>>> a, b = symbols('a, b', real=True)
>>> eq1 = Eq(a*exp(-b*90),33)
>>> eq2 = Eq(a*exp(-b*92),66)
>>> result = nonlinsolve([eq1, eq2], [a, b])
>>> sol1 = result.args[1] # ignore the NaN solution
>>> b_sol = sol1[1]
>>> b_sol
ImageSet(Lambda(_n, 2*_n*I*pi + log(sqrt(2)/2)), Integers)
>>> real_sol = Intersection(b_sol, S.Reals, evaluate=True)
>>> real_sol
{log(sqrt(2)/2)}

NikhilSDate avatar Sep 29 '22 15:09 NikhilSDate

@NikhilSDate thank you !

aliceesiee avatar Oct 04 '22 12:10 aliceesiee