如何将字典作为参数传递给solve_ivp?

问题描述 投票:0回答:2

我在尝试将字典作为参数传递给 Scipy 的solve_ivp 来求解下面给出的 ODE 系统时遇到了困难。问题是我的系统有很多参数(比下面显示的要多)。为了方便起见并避免错误地更改长列表中的各个值,例如 [20,8,2,120,-80,...,30],我想传递一个像这样的字典的参数查找表:

def morris_lecar2_defaults():
    return {
        "C_M" : 20,
        "g_K" : 8,
        "g_L" : 2,
        "V_Ca" : 120,
        "V_K" : -80,
        "V_L" : -60,
        "V_1" : -1.2,
        "V_2" : 18,
        "g_Ca" : 4.0,
        "phi" : 1/15,
        "V_3" : 12,
        "V_4" : 17.4,
        "I_ext" : 30,
    }

def morris_lecar2(t, u, p):
    (V, N) = u
    M_inf = 0.5*(1 + np.tanh((V - p["V_1"])/p["V_2"])) # (2)
    N_inf = 0.5*(1 + np.tanh((V - p["V_3"])/p["V_4"])) # (3)
    tau_N = 1/(p["phi"]*np.cosh((V - p["V_3"])/(2*p["V_4"]))) # (4)
    # (1)
    dVdt = (-p["g_L"]*(V - p["V_L"]) - p["g_Ca"]*M_inf*(V - p["V_Ca"]) - p["g_K"]*N*(V - p["V_K"]) + p["I_ext"])/p["C_M"]
    dNdt = (N_inf - N)/tau_N
    return np.array((dVdt, dNdt)) 

问题是当我将其作为可选 args 参数传递给 Scipy 的solve_ivp 例程时,我收到错误:

Traceback (most recent call last):
  line 159, in <module>
    sol_2 = solve_ivp(Morris_Lecar2,(0, 1000), (-20, 1, 0.001), args= morris_lecar2_defaults)
  File "C:\Anaconda\envs\test\lib\site-packages\scipy\integrate\_ivp\ivp.py", line 542, in solve_ivp
    solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
  File "C:\Anaconda\envs\test\lib\site-packages\scipy\integrate\_ivp\rk.py", line 94, in __init__
    self.f = self.fun(self.t, self.y)
  File "C:\Anaconda\envs\test\lib\site-packages\scipy\integrate\_ivp\base.py", line 138, in fun
    return self.fun_single(t, y)
  File "C:\Anaconda\envs\test\lib\site-packages\scipy\integrate\_ivp\base.py", line 20, in fun_wrapped
    return np.asarray(fun(t, y), dtype=dtype)
  File "C:\Anaconda\envs\test\lib\site-packages\scipy\integrate\_ivp\ivp.py", line 514, in <lambda>
    fun = lambda t, x, fun=fun: fun(t, x, *args)
TypeError: Morris_Lecar2() argument after * must be an iterable, not function

字典仍然被视为函数对象,尽管多次尝试解决这个问题,但我没有运气。解决这个满足solve_ivp的大参数集问题的最Pythonic但用户友好的方法是什么?

python python-3.x scipy
2个回答
2
投票

阅读文档,看来

args
应该是
tuple
。所以,试试这个:

sol_2 = solve_ivp(
    Morris_Lecar2, (0, 1000), (-20, 1, 0.001), args=(morris_lecar2_defaults(),)
)

请注意,此处结尾的逗号

args=(morris_lecar2_defaults(),)
required。另请注意,我正在调用
morris_lecar2_defaults()
函数。

morris_lecar2_defaults
制作为
dict
,然后将其作为单个项目传递
tuple
:

会更有意义
morris_lecar2_defaults = {
    "C_M": 20,
    "g_K": 8,
    "g_L": 2,
    "V_Ca": 120,
    "V_K": -80,
    "V_L": -60,
    "V_1": -1.2,
    "V_2": 18,
    "g_Ca": 4.0,
    "phi": 1 / 15,
    "V_3": 12,
    "V_4": 17.4,
    "I_ext": 30,
}

sol_2 = solve_ivp(
    Morris_Lecar2, (0, 1000), (-20, 1, 0.001), args=(morris_lecar2_defaults,)
)

另外,既然函数定义是小写的,那么

morris_lecar2
不应该是小写吗?

所以:

morris_lecar2_defaults = {
    "C_M": 20,
    "g_K": 8,
    "g_L": 2,
    "V_Ca": 120,
    "V_K": -80,
    "V_L": -60,
    "V_1": -1.2,
    "V_2": 18,
    "g_Ca": 4.0,
    "phi": 1 / 15,
    "V_3": 12,
    "V_4": 17.4,
    "I_ext": 30,
}

sol_2 = solve_ivp(
    morris_lecar2, (0, 1000), (-20, 1, 0.001), args=(morris_lecar2_defaults,)
)

0
投票

最简单的解决方案是将参数传递为:

sol_2 = solve_ivp(Morris_Lecar2,(0, 1000), (-20, 1, 0.001), 
                  args= morris_lecar2_defaults().values())
© www.soinside.com 2019 - 2024. All rights reserved.