我在scipy cookbook中使用Zombie Apocalypse example来学习如何在python中解决ODE系统 .
在这个模型中,有一个方程式,根据出生率,死亡率和初始人口,提供每天的人口 . 然后根据人口数量计算出有多少僵尸被创造和杀死 .
我有兴趣用一系列数据替换人口微分方程,这些数据告诉我们每个时间步的人口数量 . 我收到以下错误:
TypeError: can't multiply sequence by non-int of type 'float'
正如人们所指出的那样,这是因为将个别数字乘以列表是没有意义的 . 我不知道如何在每个时间T从列表中提供一个数字到微分方程 .
这是两次尝试的代码
# solve the system dy/dt = f(y, t)
def f(y, t):
Si = [345, 299, 933, 444, 265, 322] # replaced an equation with list
Zi = y[0]
Ri = y[1]
# the model equations (see Munz et al. 2009)
f0 = B*Si*Zi + G*Ri - A*Si*Zi
f1 = d*Si + A*Si*Zi - G*Ri
return [f0, f1]
我也试过了
numbers = [345, 299, 933, 444, 265, 322]
for t in [0, 5]:
Si = numbers
# solve the system dy/dt = f(y, t)
def f(y, t):
Zi = y[0]
Ri = y[1]
# the model equations (see Munz et al. 2009)
f0 = B*Si*Zi + G*Ri - A*Si*Zi
f1 = d*Si + A*Si*Zi - G*Ri
return [f0, f1]
两次尝试都有同样的问题,即将整个列表提供给 f0
和 f1
而不是从列表中迭代地提供1个数字 .
3 回答
据我从您的问题下面的评论中了解到,您尝试合并可能有噪音的测量数据 . 您可以使用这些数据来适应您的时间课程,而不是直接插入数据 . 在这里,我显示变量
S
的结果:green dots
是从您提供的ODE系统的解决方案中采样的 . 为了模拟测量误差,我在这些数据中添加了一些噪声(blue dots
) . 然后,您可以适合您的ODE系统,以尽可能好地再现这些数据(red line
) .对于这些任务,您可以使用lmfit . 重现绘图的代码如下所示(可以在内联注释中找到一些解释):
您无法在数值积分器评估ODE函数的哪些点知道先验 . 积分器(
odeint
和其他非明确的"fixed step-size")动态生成一个内部点列表,这些点可能比给定的采样点列表具有更小或有时更大的步长 . 输出的值从内部列表中插入 .如果要用函数替换ODE的一部分,则必须将样本数据转换为函数 . 这可以通过插值来完成 . 使用scipy.interpolate.interp1函数生成函数对象,然后可以像任何其他标量函数一样使用它们 .
要专门做我在问题中提出的问题,即使用值代替其中一个ODES你将需要使用一个循环,你使用odesolver来解决你的系统1秒,然后将输出作为下一次循环迭代的初始条件 . 这种方法的代码如下 . 然而正如许多人所指出的那样,在大多数情况下,如Cleb和其他人所描述的那样使用插值会更好