【问题标题】:How can you pass a dictionary as parameters to solve_ivp?如何将字典作为参数传递给solve_ivp?
【发布时间】:2022-01-04 02:44:04
【问题描述】:

我在尝试将字典作为参数传递给 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但用户友好的方法是什么?

【问题讨论】:

  • 虽然我不知道solve_ivp的函数签名是什么,但为什么不把它表达为args=morris_lecar2_defaults()。这样,至少您传递的是该函数的结果,而不是指向该函数的指针。我还在 scipy 的文档中读到“args 必须是长度为 3 的元组”,所以不确定 dict 是否正确......
  • 你错过了如何调用solve_ivp,编辑:我现在看到它被埋在堆栈跟踪中。如果您单独提供,这将是一个更具可读性的问题

标签: python python-3.x scipy


【解决方案1】:

阅读docs,看来args 应该是tuple。所以,试试这个:

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

请注意,args=(morris_lecar2_defaults(),) 后面的逗号是必需的。另外,请注意我正在调用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,)
)

【讨论】:

    猜你喜欢
    • 2021-12-14
    • 2020-10-24
    • 2018-09-14
    • 2010-09-24
    • 1970-01-01
    • 2017-10-01
    • 2023-03-26
    • 2013-10-29
    相关资源
    最近更新 更多