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

AIB*_*AIB 60 python numpy sympy scipy

使用Python解决一对非线性方程的最佳方法是什么?(Numpy,Scipy或Sympy)

例如:

  • x + y ^ 2 = 4
  • e ^ x + xy = 3

解决上述配对的代码片段会很棒

HYR*_*YRY 68

对于数值解,你可以使用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))
Run Code Online (Sandbox Code Playgroud)


Kra*_*nov 27

如果您更喜欢同情,可以使用nsolve.

>>> nsolve([x+y**2-4, exp(x)+x*y-3], [x, y], [1, 1])
[0.620344523485226]
[1.83838393066159]
Run Code Online (Sandbox Code Playgroud)

第一个参数是方程列表,第二个是变量列表,第三个是初始猜测.

  • 我收到此答案中的代码错误“名称 y 未定义”。 (2认同)

Osc*_*min 12

简短回答:使用 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)
Run Code Online (Sandbox Code Playgroud)

输出:

0.6203445234801195 1.8383839306750887
Run Code Online (Sandbox Code Playgroud)

解析解?

你说如何“解决”,但有不同种类的解决方案。既然你提到了 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])
Run Code Online (Sandbox Code Playgroud)

输出:

?? ?  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 ??
Run Code Online (Sandbox Code Playgroud)

请注意,在此示例中,SymPy 会找到所有解决方案,并且不需要给出初始估计值。

您可以使用以下方法对这些解决方案进行数值评估evalf

soln = [tuple(v.evalf() for v in s) for s in sol]
Run Code Online (Sandbox Code Playgroud)
[(-2.56155281280883, -2.56155281280883), (1.56155281280883, 1.56155281280883), (-1.30277563773199, 2.30277563773199), (2.30277563773199, -1.30277563773199)]
Run Code Online (Sandbox Code Playgroud)

数值解的精度

然而,大多数非线性方程组都没有合适的解析解,因此使用上面的 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])
Run Code Online (Sandbox Code Playgroud)
?0.620344523485226?
?                 ?
?1.83838393066159 ?
Run Code Online (Sandbox Code Playgroud)

精度更高:

nsolve([Eq(x+y**2, 4), Eq(exp(x)+x*y, 3)], [x, y], [1, 1], prec=50)
Run Code Online (Sandbox Code Playgroud)
?0.62034452348522585617392716579154399314071550594401?
?                                                    ?
? 1.838383930661594459049793153371142549403114879699 ?
Run Code Online (Sandbox Code Playgroud)

  • 不知道为什么这不是投票最多的答案,但是,有没有办法将 SymPy 给出的解析解转换为近似数值列表?据我了解,找到所有解决方案的唯一方法是通过分析方法,但转换这些解决方案可能非常有用。 (2认同)
  • 我添加了一个 evalf 的示例 (2认同)

Cle*_*leb 5

替代方案fsolveroot

import numpy as np
from scipy.optimize import root    

def your_funcs(X):

    x, y = X
    # all RHS have to be 0
    f = [x + y**2 - 4,
         np.exp(x) + x * y - 3]

    return f

sol = root(your_funcs, [1.0, 1.0])
print(sol.x)
Run Code Online (Sandbox Code Playgroud)

这将打印

[0.62034452 1.83838393]
Run Code Online (Sandbox Code Playgroud)

如果您随后检查

print(your_funcs(sol.x))
Run Code Online (Sandbox Code Playgroud)

你得到

[4.4508396968012676e-11, -1.0512035686360832e-11]
Run Code Online (Sandbox Code Playgroud)

确认解决方案是正确的。

  • “root”相对于“fsolve”的优点是能够轻松指定解析方法和容差。 (2认同)