首页 > 解决方案 > 如何遍历一个元组或函数列表并对它们的返回值进行操作?

问题描述

我一直在研究据称接受耦合方程的通用元组的模块,该模块吐出解决方案。最初,我在我感兴趣的特定方程组上对其进行了测试,并且效果非常好。但后来我在一个更简单的系统上对其进行了测试,只是为了看看我是否真的实现了一个通用的功能。

似乎在有效的实例中,我能够从列表中提取每个函数,插入参数,并对返回值进行操作。

在它不起作用的情况下,看起来 Python 正在将我的函数归类为“生成器”,这是我无法对...进行算术运算的东西。

这段代码也是我第一次尝试使用*argsand **kwargs,这很令人兴奋,但也许那里也有一些错误......

我是一个相对较新的程序员,他主要从文档和论坛的复制和粘贴中学习,直到我的代码工作。请善待。如果我的问题格式不正确,请告诉我如何提出更好的问题。如果您回答,请在我的知识水平范围内回答(如果我需要研究某些内容以理解您的回答,请提供文档链接)

第一个片段是解决问题的原始函数:

# Below is the standard representation of RK4, generalized to any system
# ** init is the solution vector y_(n-1) from the previous step
#    used to solve for the solution at the next step, y_n.
# ** t is the previous time step
# ** dfuncs is the vector field dy/dt = f(t,y)

def RK4(init, t, dfuncs, h):
    k1 = [ h*f(*init,t) for f in dfuncs ]
    args = [ r+0.5*kr for r,kr in zip((*init,t),(*k1, h)) ]
    k2 = [ h*f(*args) for f in dfuncs ]
    args = [ r+0.5*kr for r,kr in zip((*init,t),(*k2, h)) ]
    k3 = [ h*f(*args) for f in dfuncs ]
    args = [ r+kr for r,kr in zip((*init,t),(*k3, h)) ]
    k4 =[ h*f(*args) for f in dfuncs ]
    return (r+(k1r+2*k2r+2*k3r+k4r)/6 for r,k1r,k2r,k3r,k4r in
            zip(init,k1, k2, k3, k4))

这是该函数运行良好的代码:

 #The following three functions represent the three ODEs in question
    # dB/Dt =
    def fx(B, S, E, t):
        return (r_b*B*(1 -  (B*(pow(T, 2)
                        + pow(E, 2)))/(K*S*pow(E, 2)))
                        - (beta*pow(B, 2))/(pow((alpha*S),2)
                        + pow(B, 2)))
    #dS/dt =
    def fy(B, S, E, t):
        return r_s*S*(1 - (S*K_e) / (E*K_s))

    # dE/dt =
    def fz(B, S, E, t):
        return r_e*E*(1 - E/K_e) - (P*B*pow(E, 2))/(S*(pow(T,2) + pow(E, 2)))

    # set parameter values from Ludwig paper
    r_b = 1.52
    r_s = 0.095
    r_e = 0.92
    alpha = 1.11
    beta = 43200
    K = 355
    K_s = 25440
    K_e = 1
    P = 0.00195
    T = 0.1
    t_0 = 0.
    t_n = 50.
    Dt = .5
    steps=int(np.floor((t_n - t_0) / Dt))

    # initialize solution vectors
    t = steps * [0.0]
    B = steps * [0.0]
    S = steps * [0.0]
    E = steps * [0.0]

    #Set initial conditions
    B[0],S[0],E[0],t[0] = 1e-16, .075*K_s, 1., 0.

    # Solve the system using RK4
    for i in range(1, steps):
        B[i],S[i],E[i] = RK4((B[i - 1], S[i - 1], E[i - 1]), t[i - 1], (fx, fy, fz), Dt)

这是失败的更简单的系统:

def dy(y, z, t):
    return y
def dz(y, z, t):
    return pow(z, 2)

t0 = 0
tn = 10
y0 = 1
z0 = 0
Dt = 0.01
steps = int(np.floor((tn - t0) / Dt))

y = steps * [0.0]
z = steps * [0.0]
t = steps * [0.0]

y[0] = y0
z[0] = z0
t[0] = t0

for i in range(1, steps):
    y[i] = RK4((y[i-1], z[i-1]), t[i-1], (dy, dz), Dt)

带回溯:

Traceback (most recent call last):
  File "C:/Users/wesle/PycharmProjects/Budworms/basic.py", line 27, in <module>
    y[i] = RK4((y[i-1], z[i-1]), t[i-1], (dy, dz), Dt)
  File "C:\Users\wesle\PycharmProjects\Budworms\RK4.py", line 23, in RK4
    k1 = [ h*f(*init,t) for f in dfuncs ]
  File "C:\Users\wesle\PycharmProjects\Budworms\RK4.py", line 23, in <listcomp>
    k1 = [ h*f(*init,t) for f in dfuncs ]
TypeError: unsupported operand type(s) for *: 'float' and 'generator'

标签: pythoniterable

解决方案


在非工作示例中,您没有分配z[i]. 这导致y[i]分配了整个输出,即生成器。在以后的迭代中,这y[i]是在浮点乘法的上下文中评估的,这就是错误所说的。我相信您需要做的就是添加z[i]

y[i], z[i] = RK4((y[i - 1], z[i - 1]), t[i - 1], (dy, dz), Dt)

推荐阅读