为 solve_ivp 传递参数(新 SciPy ODE API)
Pass args for solve_ivp (new SciPy ODE API)
为了使用 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 是否可以传递 arg,或者这是尚未添加的功能? (如果有意删除此功能,对我来说似乎是一种疏忽?)
参考:
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), ...)
并且他们争辩说已经有足够的开销让这无关紧要。
添加到 Cleb 的回答中,这里有一个使用 lambda t,y: fun(t,y,args)
方法的示例。我们设置函数句柄 returns 具有两个参数的二阶齐次 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')
为了完整起见,我想你也可以这样做,但我不确定你为什么要费心,因为这里发布的其他两个选项都很好。
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)
最近 'args' 选项已添加到 solve_ivp,请参阅此处:https://github.com/scipy/scipy/issues/8352#issuecomment-535689344
据, the feature that you (as well as I) desire has recently been added. This was announced on Github by none other than the great Warren Weckesser (See his Github, Whosebug) 本人说。
无论如何,开个玩笑 docstring of solve_ivp has an example using it in for the `Lotka-Volterra equations
solve_ivp(
fun,
t_span,
y0,
method='RK45',
t_eval=None,
dense_output=False,
events=None,
vectorized=False,
args=None,
**options,
)
因此,只需将 args 作为元组包含在内。你的情况
args = (arg1, arg2)
请不要使用我的回答,除非你的 scipy 版本 >= 1.4。
对于低于它的版本,solve_ivp 中没有 args 参数。我亲身经历过 1.2.1 版本的回答失败。
如果您的 scipy 版本 < 1.4
, 的实施可能仍然可以正常工作
为了使用 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 是否可以传递 arg,或者这是尚未添加的功能? (如果有意删除此功能,对我来说似乎是一种疏忽?)
参考: 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), ...)
并且他们争辩说已经有足够的开销让这无关紧要。
添加到 Cleb 的回答中,这里有一个使用 lambda t,y: fun(t,y,args)
方法的示例。我们设置函数句柄 returns 具有两个参数的二阶齐次 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')
为了完整起见,我想你也可以这样做,但我不确定你为什么要费心,因为这里发布的其他两个选项都很好。
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)
最近 'args' 选项已添加到 solve_ivp,请参阅此处:https://github.com/scipy/scipy/issues/8352#issuecomment-535689344
据
solve_ivp( fun, t_span, y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, args=None, **options, )
因此,只需将 args 作为元组包含在内。你的情况
args = (arg1, arg2)
请不要使用我的回答,除非你的 scipy 版本 >= 1.4。 对于低于它的版本,solve_ivp 中没有 args 参数。我亲身经历过 1.2.1 版本的回答失败。
如果您的 scipy 版本 < 1.4
,