如何用Python求解一对非线性方程?

93 投票
9 回答
176316 浏览
提问于 2025-04-17 09:35

用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))

撰写回答