如何用Python求解一对非线性方程?
用Python解决一对非线性方程的(最佳)方法是什么?(可以用Numpy、Scipy或Sympy)
比如:
- x+y^2 = 4
- e^x+ xy = 3
如果能提供一个解决上述方程组的代码示例就太好了。
9 个回答
31
如果你喜欢使用sympy这个库,可以用nsolve这个功能。
>>> nsolve([x+y**2-4, exp(x)+x*y-3], [x, y], [1, 1])
[0.620344523485226]
[1.83838393066159]
第一个参数是一个方程的列表,第二个参数是一个变量的列表,第三个参数是一个初始猜测值。
34
简短回答:使用 fsolve
正如其他回答所提到的,解决你提出的这个问题最简单的方法就是使用类似 fsolve
的工具:
from scipy.optimize import fsolve
from math import exp
def equations(vars):
x, y = vars
eq1 = x+y**2-4
eq2 = exp(x) + x*y - 3
return [eq1, eq2]
x, y = fsolve(equations, (1, 1))
print(x, y)
输出:
0.6203445234801195 1.8383839306750887
解析解?
你提到如何“解决”这个问题,但其实有不同类型的解决方案。既然你提到了 SymPy,我应该指出一个重要的区别,那就是 解析解 和 数值解 之间的差别。你给出的这个例子没有(简单的)解析解,但其他一些非线性方程组可能有。当有现成的解析解时,SymPy 通常可以帮你找到:
from sympy import *
x, y = symbols('x, y')
eq1 = Eq(x+y**2, 4)
eq2 = Eq(x**2 + y, 4)
sol = solve([eq1, eq2], [x, y])
输出:
⎡⎛ ⎛ 5 √17⎞ ⎛3 √17⎞ √17 1⎞ ⎛ ⎛ 5 √17⎞ ⎛3 √17⎞ 1 √17⎞ ⎛ ⎛ 3 √13⎞ ⎛√13 5⎞ 1 √13⎞ ⎛ ⎛5 √13⎞ ⎛ √13 3⎞ 1 √13⎞⎤
⎢⎜-⎜- ─ - ───⎟⋅⎜─ - ───⎟, - ─── - ─⎟, ⎜-⎜- ─ + ───⎟⋅⎜─ + ───⎟, - ─ + ───⎟, ⎜-⎜- ─ + ───⎟⋅⎜─── + ─⎟, ─ + ───⎟, ⎜-⎜─ - ───⎟⋅⎜- ─── - ─⎟, ─ - ───⎟⎥
⎣⎝ ⎝ 2 2 ⎠ ⎝2 2 ⎠ 2 2⎠ ⎝ ⎝ 2 2 ⎠ ⎝2 2 ⎠ 2 2 ⎠ ⎝ ⎝ 2 2 ⎠ ⎝ 2 2⎠ 2 2 ⎠ ⎝ ⎝2 2 ⎠ ⎝ 2 2⎠ 2 2 ⎠⎦
注意,在这个例子中,SymPy 找到了所有的解,并且不需要你提供初始估计。
你可以用 evalf
来对这些解进行数值评估:
soln = [tuple(v.evalf() for v in s) for s in sol]
[(-2.56155281280883, -2.56155281280883), (1.56155281280883, 1.56155281280883), (-1.30277563773199, 2.30277563773199), (2.30277563773199, -1.30277563773199)]
数值解的精度
不过,大多数非线性方程组并没有合适的解析解,所以像上面那样使用 SymPy 是很棒的,但并不总是适用。这就是为什么我们最终会寻找数值解,尽管使用数值解时会有以下问题: 1) 我们不能保证找到所有解或“正确”的解,特别是当有很多解的时候。 2) 我们必须提供一个初始猜测,而这并不总是容易。
既然我们接受了想要数值解的事实,像 fsolve
这样的工具通常能满足你的需求。对于这类问题,SymPy 可能会慢很多,但它可以提供另一种好处,就是更精确地找到(数值)解:
from sympy import *
x, y = symbols('x, y')
nsolve([Eq(x+y**2, 4), Eq(exp(x)+x*y, 3)], [x, y], [1, 1])
⎡0.620344523485226⎤
⎢ ⎥
⎣1.83838393066159 ⎦
更高的精度:
nsolve([Eq(x+y**2, 4), Eq(exp(x)+x*y, 3)], [x, y], [1, 1], prec=50)
⎡0.62034452348522585617392716579154399314071550594401⎤
⎢ ⎥
⎣ 1.838383930661594459049793153371142549403114879699 ⎦
98
对于数值解法,你可以使用 fsolve:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fsolve.html#scipy.optimize.fsolve
from scipy.optimize import fsolve
import math
def equations(p):
x, y = p
return (x+y**2-4, math.exp(x) + x*y - 3)
x, y = fsolve(equations, (1, 1))
print equations((x, y))