SciPyを使用して単純なODEを解くために、私はodeint関数を次の形式で使用していました:
scipy.integrate.odeint(func, y0, t, args=(), Dfun=None, col_deriv=0, full_output=0, ml=None, mu=None, rtol=None, atol=None, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0, mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0)[source]
統合される単純な関数には、次の形式の引数を含めることができます。
def dy_dt(t, y, arg1, arg2):
# processing code here
SciPy 1.0では、odeおよびodeint関数が置き換えられたようです新しいsolve_ivpメソッドによる。
scipy.integrate.solve_ivp(fun, t_span, y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, **options)
ただし、これはargsパラメーターを提供していないようで、argsの受け渡しの実装に関するドキュメントの指示もありません。
したがって、新しいAPIで引数の受け渡しが可能かどうか、これはまだ追加されていない機能ですか? (この機能が意図的に削除されている場合、私には見落としのように思われますか?)
リファレンス: https://docs.scipy.org/doc/scipy/reference/integrate.html
新しい関数にargs
パラメータがあるようには見えません。回避策として、次のようなラッパーを作成できます
def wrapper(t, y):
orig_func(t,y,hardcoded_args)
それを渡します。
比較的最近、同様の質問が scipy's github に出てきました。彼らの解決策はlambda
を使うことです:
solve_ivp(fun=lambda t, y: fun(t, y, *args), ...)
そして、彼らはこれが問題にならないためにすでに十分なオーバーヘッドがあると主張します。
最近 'args'オプションがsolve_ivpに追加されました。ここを参照してください https://github.com/scipy/scipy/issues/8352#issuecomment-535689344
Javier-Acunaの非常に簡潔で非常に便利な回答 によると、あなた(そして私も)が望む機能が最近追加されました。これは Githubで発表された 偉大なウォーレンウェッケサー(彼の Github 、 StackOverflow を参照)自身によるものでした。とにかく、 docstring of solve_ivp 以外のジョークには、それを ` Lotka-Volterra方程式 に使用する例があります。
solve_ivp(fun、t_span、y0、method = 'RK45'、t_eval = None、density_output = False、events = None、vectorized = False、args = None、** options、)
したがって、タプルとしてargsを含めるだけです。あなたの場合
args = (arg1, arg2)
あなたのscipyバージョン> = 1.4でない限り、私の答えを使用しないでください。その下のバージョンのsolve_ivpにはargsパラメーターはありません。私は個人的にバージョン1.2.1で失敗した私の答えを経験しました。
zahabaz による実装は、scipyバージョンが1.4未満の場合でもおそらく正常に動作します
クレブの答えに加えて、これがlambda t,y: fun(t,y,args)
メソッドの使用例です。 2つのパラメーターを持つ2次同次ODEのrhsを返す関数ハンドルを設定します。次に、それをいくつかのオプションとともにソルバーにフィードします。
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
def rhs_2nd_order_ode(t, y, a, b):
"""
2nd order ODE function handle for use with scipy.integrate.solve_ivp
Solves u'' + au'+ bu = 0 after reducing order with y[0]=u and y[1]=u'.
:param t: dependent variable
:param y: independent variables
:param a: a
:param b: b
:return: Returns the rhs of y[0]' = y[1] and y[1]' = -a*y[1] - b*y[0]
"""
return [y[1], -a*y[1] - b*y[0]]
if __name__ == "__main__":
t_span = (0, 10)
t_eval = np.linspace(t_span[0], t_span[1], 100)
y0 = [0, 1]
a = 1
b = 2
sol = integrate.solve_ivp(lambda t,y: rhs_2nd_order_ode(t,y,a,b), t_span, y0,
method='RK45', t_eval=t_eval)
fig, ax = plt.subplots(1, 1)
ax.plot(sol.t, sol.y[0])
ax.set(xlabel='t',ylabel='y')
完全を期すために、これも可能だと思いますが、ここに掲載されている他の2つのオプションが問題なく動作する理由を理解できません。
from functools import partial
fun = partial(dy_dt, arg1=arg1, arg2=arg2)
scipy.integrate.solve_ivp(fun, t_span, y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, **options)