代码之家  ›  专栏  ›  技术社区  ›  requiemman

在scipy的solve_ivp()中实现lambda函数会导致太多的值无法解压缩

  •  0
  • requiemman  · 技术社区  · 2 年前
    from scipy.integrate import solve_ivp
    
    def myfunc(a,b,c,d,e,f,g,h):
      t=a+2
      d=b+3
      return t,d
    
    a=1
    b=2
    c=3
    d=4
    e=5
    f=6
    g=7
    e=8
    
    solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),np.linspace(0,100),3)
    

    这就是我面临的问题类型。Scipy’s solve_ivp() 用语法解决函数 solve_ivp(function,timerange,initial guess,**kwargs)

    我有一个功能(比如 myfunc() )它接收大量的参数,对它们进行一些数学运算,并返回2个变量。我在这里附上了一个样品。我想把这个函数作为 solve_ivp() .我用 lambda 但我遇到了 too many values to unpack (expected 2) 错误

    如何解决此问题?

    2 回复  |  直到 2 年前
        1
  •  1
  •   hpaulj    2 年前

    这是另一种情况,我本应该要求进行完整的回溯,而不是快速猜测问题(请参阅我的评论)。

    运行您的代码:

       ...: integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),np.linspace(0,100),3)
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    Cell In[9], line 15
         12 g=7
         13 e=8
    ---> 15 integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),np.linspace(0,100),3)
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/ivp.py:524, in solve_ivp(fun, t_span, y0, method, t_eval, dense_output, events, vectorized, args, **options)
        519 if method not in METHODS and not (
        520         inspect.isclass(method) and issubclass(method, OdeSolver)):
        521     raise ValueError("`method` must be one of {} or OdeSolver class."
        522                      .format(METHODS))
    --> 524 t0, tf = map(float, t_span)
        526 if args is not None:
        527     # Wrap the user's fun (and jac, if given) in lambdas to hide the
        528     # additional parameters.  Pass in the original fun as a keyword
        529     # argument to keep it in the scope of the lambda.
        530     try:
    
    ValueError: too many values to unpack (expected 2)
    

    这是一个拆包错误,在

    t0, tf = map(float, t_span)
    

    这试图获得2个浮点值 t_span 自变量和它们在2个变量中, t0,tf 。相反,您提供 arange(100) !

    用(0100)运行它:

    In [12]: integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),(0,100),3)
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    Cell In[12], line 1
    ----> 1 integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),(0,100),3)
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/ivp.py:568, in solve_ivp(fun, t_span, y0, method, t_eval, dense_output, events, vectorized, args, **options)
        565 if method in METHODS:
        566     method = METHODS[method]
    --> 568 solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
        570 if t_eval is None:
        571     ts = [t0]
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/rk.py:89, in RungeKutta.__init__(self, fun, t0, y0, t_bound, max_step, rtol, atol, vectorized, first_step, **extraneous)
         85 def __init__(self, fun, t0, y0, t_bound, max_step=np.inf,
         86              rtol=1e-3, atol=1e-6, vectorized=False,
         87              first_step=None, **extraneous):
         88     warn_extraneous(extraneous)
    ---> 89     super().__init__(fun, t0, y0, t_bound, vectorized,
         90                      support_complex=True)
         91     self.y_old = None
         92     self.max_step = validate_max_step(max_step)
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/base.py:135, in OdeSolver.__init__(self, fun, t0, y0, t_bound, vectorized, support_complex)
        133 self.t_old = None
        134 self.t = t0
    --> 135 self._fun, self.y = check_arguments(fun, y0, support_complex)
        136 self.t_bound = t_bound
        137 self.vectorized = vectorized
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/base.py:17, in check_arguments(fun, y0, support_complex)
         14 y0 = y0.astype(dtype, copy=False)
         16 if y0.ndim != 1:
    ---> 17     raise ValueError("`y0` must be 1-dimensional.")
         19 if not np.isfinite(y0).all():
         20     raise ValueError("All components of the initial state `y0` must be finite.")
    
    ValueError: `y0` must be 1-dimensional.
    

    所以现在它不喜欢标量 3 对于 y0 .将其更改为列表 [3] (或等效数组):

    In [13]: integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),(0,100),[3])
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    Cell In[13], line 1
    ----> 1 integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),(0,100),[3])
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/ivp.py:568, in solve_ivp(fun, t_span, y0, method, t_eval, dense_output, events, vectorized, args, **options)
        565 if method in METHODS:
        566     method = METHODS[method]
    --> 568 solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
        570 if t_eval is None:
        571     ts = [t0]
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/rk.py:94, in RungeKutta.__init__(self, fun, t0, y0, t_bound, max_step, rtol, atol, vectorized, first_step, **extraneous)
         92 self.max_step = validate_max_step(max_step)
         93 self.rtol, self.atol = validate_tol(rtol, atol, self.n)
    ---> 94 self.f = self.fun(self.t, self.y)
         95 if first_step is None:
         96     self.h_abs = select_initial_step(
         97         self.fun, self.t, self.y, self.f, self.direction,
         98         self.error_estimator_order, self.rtol, self.atol)
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/base.py:154, in OdeSolver.__init__.<locals>.fun(t, y)
        152 def fun(t, y):
        153     self.nfev += 1
    --> 154     return self.fun_single(t, y)
    
    File ~/.local/lib/python3.10/site-packages/scipy/integrate/_ivp/base.py:23, in check_arguments.<locals>.fun_wrapped(t, y)
         22 def fun_wrapped(t, y):
    ---> 23     return np.asarray(fun(t, y), dtype=dtype)
    
    Cell In[13], line 1, in <lambda>(t, s)
    ----> 1 integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),(0,100),[3])
    
    NameError: name 'h' is not defined
    

    现在我们有一个缺失的变量, h 。那应该是从哪里来的?

    更正全局变量分配:

    In [17]: e=5; h=8
    In [18]: integrate.solve_ivp(lambda t,s:myfunc(a,b,c,d,e,f,g,h),(0,100),[3,3])
    Out[18]: 
      message: The solver successfully reached the end of the integration interval.
      success: True
       status: 0
            t: [ 0.000e+00  9.384e-02  1.032e+00  1.042e+01  1.000e+02]
            y: [[ 3.000e+00  3.282e+00  6.097e+00  3.425e+01  3.030e+02]
                [ 3.000e+00  3.469e+00  8.161e+00  5.508e+01  5.030e+02]]
          sol: None
     t_events: None
     y_events: None
         nfev: 26
         njev: 0
          nlu: 0
    

    现在它运行了,尽管我不确定这有什么好处。函数总是返回(a+2,b+3),即(3,5)。您在(0100)范围内对其进行积分,因此返回 y 是初始值+100*(3,5),即(303503):

    In [20]: 3+_18['t']*3
    Out[20]: 
    array([  3.        ,   3.28153316,   6.09686481,  34.25018124,
           303.        ])
    In [21]: 3+_18['t']*5
    Out[21]: 
    array([  3.        ,   3.46922194,   8.16144135,  55.0836354 ,
           503.        ])
    

    您的函数返回2个值,一个globals函数 a b 所以 y0 也需要是形状(2)。 solve_ivp 将是标量 t ,和2元素 y 价值,尽管你 lambda 把那些扔掉。我试着用 lambda t,s: my_func(t,s,a,b,...) ,但在尝试返回(t,[s+(2,3)])时一直遇到问题,这是一个“不规则数组”。

    我可以用

    integrate.solve_ivp(lambda t,s:myfunc(a,b,t,s,c,d,e,f),(0100),[0,0])

    推杆 t,s 在插槽中 myfunc 将忽略它们。

        2
  •  1
  •   jared    2 年前

    以下是您的代码中的几个问题。

    1. 微分方程函数的前两个自变量应该是时间和因变量。你的 lambda 采用两个论点, t s 但从不使用它们。
    2. 你通过了 linspace 对于时间范围,但应该是2个成员 tuple list 包含开始和停止时间。(如果希望在特定时间得到结果,请将所需时间传递给 t_eval kwarg )
    3. 当它应该是一个数组(或 列表 )形状的 (n,) 哪里 n 是方程式的数目。那个 n 应该与微分方程返回的大小匹配,但微分方程返回两个值,并且只提供一个初始条件。

    您需要解决所有这些问题才能使代码正常工作。