Python中的延迟微分方程

时间:2019-04-04 23:51:44

标签: python ode differential-equations

我有这个控制问题,我的目标是选择D的值以使Hb(t)保持在一定范围内,请参见方程式here(如果它有助于尝试重现此paper中讨论的模拟。

我对解决此问题的尝试没有信心-特别是需要使用EP的过去状态值的术语。我的工作是手动计算它们,并将其作为参数传递给集成函数。但是这种方法:

  • 具有重复的代码,很难理解
  • 我认为
  • 是不正确的,因为在解决之后,即使更改了许多参数值,我仍然得到了Hb(t)值。

有没有更好的方法来解决这些具有时间相关状态的微分方程?

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

def erythropoiesis_func(s, t, d, term1, term2, term3, term4):
    """
    Inputs
    d     = drug dose (ug/kg per week)
    term1 = avg of past Tp days
    term2 = E_{tot}(t - (Tp + Tm))
    term3 = P(t - (Tp + Tm))
    term4 = sum of past Tj days times normal
    """

    """
    States of model s(E,P,R):

    E: exogenous plasma concentration of EPO
    P: bone marrow concentration of progenitor cells and precursor cells
    R: concentration of red blood cells (RDCs)

    """
    E = s[0]                
    P = s[1]                
    R = s[2]

    # Parameters to vary by each trajectory (patient) but constant for now
    Ep = .36  #np.random.normal(.3588, .0753, 1)
    Cr = .14 #np.random.normal(.1372, .0520, 1)
    Cp = .21 #np.random.normal(.2014, .0640, 1)

    # Constants:
    Vd  = 52.4            # Volume distribution
    E50 = 100 / Vd        # half-maximal effective concentration (drug potency)
    Tp  = 9               # P cell life in days
    Tm  = 4               # Delay from P compartment to R compartment in days
    Tr  = 70              # R cell life in days


    Etot = (d / Vd) + Ep

    Spmr = np.random.normal(Tr , 30, size=Tr).sum()


    # Compute sdot:
    dsdt = np.empty(len(s))
    dsdt[0] = (24/25)*np.log(2)*Etot                      # E'(t)
    dsdt[1] = Cp*(Etot/(E50 + Etot))*P - Cp*term1         # P'(t)
    dsdt[2] = Cr*(term2/(E50 + term2))*term3 - (Cr/Spmr)*term4

    return dsdt

# Initial Condition for the Control
d0 = .5

# Initial Conditions for the States (E, P, R)
s0 = np.array([(d0/52.4), 1., 1.])

# Constants
Tp  = 9
Tm  = 4               
Tr  = 70
E50 = 100 / 52.4
MCH = 2.4

# Time Interval (days)
tt = np.array(range(Tp+Tm+Tr))

# Pre fill vectors
E = np.ones(len(tt)) * s0[0]
P = np.ones(len(tt)) * s0[1]
R = np.ones(len(tt)) * s0[2]
H = MCH * R

d = np.random.uniform(low=0.0, high=1.0, size=len(tt))

# Simulate
term1_vals = []
term4_vals = []
for t in range(len(tt)-1):
    # time to feed to solver
    ts = [tt[t],tt[t+1]]

    # generating term1
    temp1 = []
    for tj in range(Tp):
        if tj <= t:
            temp1.append( (E[t - tj] / (E50 + E[t - tj] )) * P[t - tj] )
    term1_vals.append(np.mean(temp1))

    # collecting term2 and term3 if they exist
    if (Tp + Tm) <= t:
        term2 = E[t-(Tp + Tm)]
        term3 = P[t-(Tp + Tm)]
    else:
        term2 = 0
        term3 = 0

    # generating term4
    temp4 = []
    for tj in range((Tp+Tm),(Tp+Tm+Tr)):
        if tj <= t:
            temp4.append( np.random.normal(Tr , 30, size=1) * (E[t - tj] / (E50 + E[t - tj] )) * P[t - tj] )
    term4_vals.append(np.sum(temp4))

    # calling solver
    s = odeint(erythropoiesis_func,s0,ts,args=(d[t+1],term1_vals[t],term2,term3,term4_vals[t]))

    #storing values
    E[t+1] = s[-1][0]
    P[t+1] = s[-1][1]
    R[t+1] = s[-1][2]
    H[t+1] = MCH * s[-1][2]
    s0 = s[-1]

0 个答案:

没有答案