简体   繁体   中英

Solving nonlinear systems of equations using Python's fsolve function

I am using scipy.optimize's function fsolve to solve for two unknowns in two equations. The equations that I am trying to solve in the end are (much) more complex but I already struggle understanding the following basic example.

import scipy.optimize as scopt

def fun(variables) :
    (x,y) = variables
    eqn_1 = x ** 2 + y - 4
    eqn_2 = x + y ** 2 +3
    return [eqn_1, eqn_2]

result = scopt.fsolve(fun, (0.1, 1)) 
print(result)

This gives the result [-2.08470396 -0.12127194] , however when I plug those numbers back into the function (one time assuming the first is meant as x, one time assuming the first is y), I get results very different from zero.

print((-2.08470396)**2 - 0.12127194 - 4)
print((-2.08470396) + (- 0.12127194) ** 2 + 3)

Result 0.22 and 0.93.

print((-0.12127194)**2 -2.08470396 - 4)
print((-0.12127194) + (-2.08470396) ** 2 + 3)

Result -6.06 and 7.22.

What am I missing here?

Did you notice the warning that is generated when you run result = scopt.fsolve(fun, (0.1, 1)) ? That warning tells you that something failed:

In [35]: result = scopt.fsolve(fun, (0.1, 1))
/Users/warren/a202111/lib/python3.9/site-packages/scipy/optimize/minpack.py:175: RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last ten iterations.
  warnings.warn(msg, RuntimeWarning)

The problem is that there is no solution to fun(variables) = (0, 0) . The first equation gives y = 4-x**2 , and then the second equation can be written x + (4-x**2)**2 + 3 = 0 , which has no real solution (you can plot the left side or do some algebra to convince yourself of that).

If you use, say, eqn_2 = x + y ** 2 - 3 , fsolve gives a valid numerical solution:

In [36]: def fun(variables) :
    ...:     (x,y) = variables
    ...:     eqn_1 = x ** 2 + y - 4
    ...:     eqn_2 = x + y ** 2 - 3
    ...:     return [eqn_1, eqn_2]
    ...: 

In [37]: result = scopt.fsolve(fun, (0.1, 1))

In [38]: result
Out[38]: array([-1.38091841,  2.09306436])

In [39]: fun(result)
Out[39]: [0.0, 0.0]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM