我在尝试将字典作为参数传递给 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但用户友好的方法是什么?
阅读文档,看来
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,)
)
最简单的解决方案是将参数传递为:
sol_2 = solve_ivp(Morris_Lecar2,(0, 1000), (-20, 1, 0.001),
args= morris_lecar2_defaults().values())