具有多个参数的ODEINT(与时间相关)

时间:2017-01-25 19:52:59

标签: python-2.7 scipy odeint

我正在尝试使用ODEINT解决单个一阶ODE。以下是代码。我期望在3个时间点获得3个y值。我正在努力解决的问题是能够传递 mt nt 的第n个值来计算 dydt 。我认为ODEINT传递 mt nt 的所有3个值,而不是第0个,第1个或第2个,具体取决于迭代。因此,我收到了这个错误:

  

RuntimeError:func(4)返回的数组大小与y0(1)的大小不匹配。

有趣的是,如果我将初始条件替换为(并且应该)单个值为:a0 = [2] * 4,代码可以工作,但是给我一个4X4矩阵作为解决方案,这似乎是不正确的。

mt = np.array([3,7,4,2]) # Array of constants
nt = np.array([5,1,9,3]) # Array of constants
c1,c2,c3 = [-0.3,1.4,-0.5] # co-efficients
para = [mt,nt] # Packing parameters

#Test ODE function
def test (y,t,extra):
    m,n = extra
    dydt = c1*c2*m - c1*y - c3*n
    return dydt

a0= [2]  # Initial Condition
tspan = range(len(mt)) # Define tspan

#Solving the ODE
yt= odeint(test, a0,tspan,args=(para,)) 
#Plotting the ODE
plt.plot(tspan,yt,'g')
plt.title('Multiple Parameters Test')
plt.xlabel('Time')
plt.ylabel('Magnitude')

一阶微分方程是:

  

dy / dt = c1 *(c2 * mt-y(t)) - c3 * nt

这个等式代表小鼠内分泌系统的一部分,我试图建模。该系统类似于双罐系统,其中第一罐接收特定激素[以未知速率],但我们的传感器将在特定时间间隔(1秒)检测到该水平(mt)。然后该罐进入第二个罐,其中该激素(y)的水平被另一个传感器检测到。我使用单独的变量标记了级别,因为检测级别的传感器彼此独立并且没有相互校准。 'c2'可以被认为是显示两个水平之间相关性的系数。而且,这种激素从罐1到罐2的转移是扩散驱动的。这种激素通过生化过程进一步消耗(类似于第二个水箱的排水阀)。目前尚不清楚哪些参数会影响消费;然而,另一个传感器可以检测到特定时间间隔消耗的激素(nt)的量(1秒,在这种情况下也是如此)。

因此,mtnt是特定时间点激素的浓度/水平。虽然代码中只有4个元素,但我的研究中这些数组的长度要长得多。所有传感器都以1秒的间隔报告浓度 - 因此tspan由相隔1秒的时间点组成。

目标是在数学上确定第二个罐中的这种激素的浓度(y),然后根据实验数据优化这些系数的值。我能够将这些数组mtnt传递给定义的ODE,并在MATLAB中使用ODE45进行求解,没有任何问题。我一直在遇到这个RunTimeError,同时试图用Python复制代码。

1 个答案:

答案 0 :(得分:0)

正如我在评论中提到的,如果您想使用常微分方程对此系统进行建模,则必须在采样时间之间对mn的值进行假设。一种可能的模型是使用线性插值。这是一个使用scipy.interpolate.interp1d基于样本mfunc(t)nfunc(t)创建函数mtnt的脚本。

import numpy as np
from scipy.integrate import odeint
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

mt = np.array([3,7,4,2])  # Array of constants
nt = np.array([5,1,9,3])  # Array of constants

c1, c2, c3 = [-0.3, 1.4, -0.5] # co-efficients

# Create linear interpolators for m(t) and n(t).
sample_times = np.arange(len(mt))
mfunc = interp1d(sample_times, mt, bounds_error=False, fill_value="extrapolate")
nfunc = interp1d(sample_times, nt, bounds_error=False, fill_value="extrapolate")

# Test ODE function
def test (y, t):
    dydt = c1*c2*mfunc(t) - c1*y - c3*nfunc(t)
    return dydt

a0 = [2]  # Initial Condition
tspan = np.linspace(0, sample_times.max(), 8*len(sample_times)+1)
#tspan = sample_times

# Solving the ODE
yt = odeint(test, a0, tspan)

# Plotting the ODE
plt.plot(tspan, yt, 'g')
plt.title('Multiple Parameters Test')
plt.xlabel('Time')
plt.ylabel('Magnitude')
plt.show()

以下是剧本创建的情节:

plot

请注意,我不是仅在sample_times生成解决方案(即在0,1,2和3时),而是将tspan设置为更密集的点集。这显示了模型在采样时间之间的行为。