Pythonを使用して非線形方程式のペアを解くための(最良の)方法は何ですか(Numpy、ScipyまたはSympy)
例えば:
- x + y ^ 2 = 4
- e ^ x + xy = 3
上記のペアを解決するコードスニペットは素晴らしいでしょう
数値解法には、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))
Sympyを好むなら nsolve を使用できます。
>>> nsolve([x+y**2-4, exp(x)+x*y-3], [x, y], [1, 1])
[0.620344523485226]
[1.83838393066159]
最初の引数は方程式のリスト、2番目は変数のリスト、3番目は初期推測です。
これを試してください。完璧に機能することを保証します。
import scipy.optimize as opt
from numpy import exp
import timeit
st1 = timeit.default_timer()
def f(variables) :
(x,y) = variables
first_eq = x + y**2 -4
second_eq = exp(x) + x*y - 3
return [first_eq, second_eq]
solution = opt.fsolve(f, (0.1,1) )
print(solution)
st2 = timeit.default_timer()
print("RUN TIME : {0}".format(st2-st1))
->
[ 0.62034452 1.83838393]
RUN TIME : 0.0009331008900937708
ご参考までに。上記のように、「fsolve」を「broyden1」に置き換えることにより、「Broydenの近似」を使用することもできます。できます。やったよ。
Broydenの近似がどのように機能するかは正確にはわかりませんが、0.02秒かかりました。
また、Sympyの機能を使用しないことをお勧めします<-確かに便利ですが、速度の点では非常に遅いです。表示されます。
from scipy.optimize import fsolve
def double_solve(f1,f2,x0,y0):
func = lambda x: [f1(x[0], x[1]), f2(x[0], x[1])]
return fsolve(func,[x0,y0])
def n_solve(functions,variables):
func = lambda x: [ f(*x) for f in functions]
return fsolve(func, variables)
f1 = lambda x,y : x**2+y**2-1
f2 = lambda x,y : x-y
res = double_solve(f1,f2,1,0)
res = n_solve([f1,f2],[1.0,0.0])
IDLで結合された非線形方程式(通常は多項式と指数関数を含む)で動作するようにBroydenの方法を取得しましたが、Pythonで試していません。
scipy.optimize.broyden1
scipy.optimize.broyden1(F, xin, iter=None, alpha=None, reduction_method='restart', max_rank=None, verbose=False, maxiter=None, f_tol=None, f_rtol=None, x_tol=None, x_rtol=None, tol_norm=None, line_search='armijo', callback=None, **kw)[source]
Broydenの最初のヤコビアン近似を使用して、関数の根を見つけます。
この方法は「ブロイデンの良い方法」としても知られています。
fsolve
の代替は root
です。
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)
これは印刷されます
[0.62034452 1.83838393]
確認したら
print(your_funcs(sol.x))
あなたが得る
[4.4508396968012676e-11, -1.0512035686360832e-11]
ソリューションが正しいことを確認します。