传递args for solve_ivp(新的SciPy ODE API)

时间:2018-01-14 00:53:14

标签: python numpy scipy ode odeint

为了使用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 func已被更新的 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

5 个答案:

答案 0 :(得分:6)

新功能似乎没有args参数。作为一种解决方法,您可以创建一个像

这样的包装器
def wrapper(t, y):
    orig_func(t,y,hardcoded_args)

并将其传递给。

答案 1 :(得分:1)

最近,'args'选项已添加到solve_ivp,请参见此处:https://github.com/scipy/scipy/issues/8352#issuecomment-535689344

答案 2 :(得分:1)

根据Javier-Acuna's ultra-brief, ultra-useful answer,您(以及我)最近都希望添加该功能。这就是伟大的沃伦·韦克瑟(Warren Weckesser)(见他的announced on GithubGithub)自己的StackOverflow。 无论如何,开玩笑docstring of solve_ivp旁有一个示例将其用于`Lotka-Volterra equations

solve_ivp( 好玩 t_span, y0, method ='RK45', t_eval = None, density_output = False, 事件=无, vectorized = False, args = None, **选项, )

因此,只需将args作为元组包含在内。就您而言

args = (arg1, arg2)

除非您的科学版本> = 1.4,否则请不要使用我的答案。 下面的版本在resolve_ivp中没有args参数。对于版本1.2.1,我个人经历了我的回答失败的问题。

在您的科学版本<1.4

的情况下,zahabaz的实现可能仍然可以正常工作

答案 3 :(得分:0)

这是克莱布(Cleb)的答案,下面是使用lambda t,y: fun(t,y,args)方法的示例。我们设置了函数句柄,该函数句柄返回带有两个参数的二阶齐次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')

答案 4 :(得分:0)

出于完整性考虑,我认为您也可以这样做,但是我不确定为什么您会打扰这里发布的其他两个看起来很不错的选项。

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)