deSolve ODE不适用于微分方程(计算NA)

时间:2020-11-01 23:23:41

标签: r ode differential-equations

我一直在使用方法deSolve::ode45,该方法一直有效,直到对方程式做了一些必要的更改。有谁知道为什么ODE求解器不起作用?我尝试使用ode45和默认的ode方法运行,但都无法正常工作。请让我知道是否有进一步的解释会有所帮助。

我已经检查了微分方程,我相信它们是正确的。

使用的公式如下:

CCHFModel = function(t,x,params)
{
  # get SIR values
  SH <- x[1]
  EH <- x[2]
  IA <- x[3]
  IS <- x[4]
  RH <- x[5]
  ST <- x[6]
  IT <- x[7]
  SC <- x[9]
  IC <- x[10]
  RC <- x[11]
  
  # Load values ----
  
  # Beta values
  betaHHA = params["betaHHA"]
  betaHHS = params["betaHHS"]
  betaTH = params["betaTH"]
  betaCH = params["betaCH"]
  betaTC = params["betaTC"]
  betaCT = params["betaCT"]
  betaTT = params["betaTT"]
  
  # Gamma value
  gamma = params["gamma"]
  
  # death rates
  muH = params["muH"]
  muT = params["muT"]
  muC = params["muC"]
  
  # birth rates
  piH  = params["piH"]
  piT = params["piT"]
  piC = params["piC"]
  
  # incubation
  deltaHS = params["deltaHS"]
  deltaHA = params["deltaHA"]
  
  # recovery rate
  alphaA = params["alphaA"]
  alphaS = params["alphaS"]
  alphaC = params["alphaC"]
  
  
  # total population
  NH = (SH + IA + IS + EH + RH) + (piH * SH) - (muH * SH)
  NT = (ST + IT) +  (piT * ST) - (muT * ST)
  NC = (SC + IC + RC) +  (piC * SC) - (muH * SC)
  
  # tick carrying Capacity 
  # KT = NC * 130 # 130 ticks per carrier max
  
  #computations ----
  dSHdt <- (piH * NH) - (betaHHA * IA + betaHHS * IS + betaCH * IC + betaTH * IT)*(SH/NH) - (muH * SH)
  dEHdt <- (betaHHA * IA + betaHHS * IS + betaCH * IC + betaTH * IT)*(SH/NH) - ((deltaHA + muH)*EH)
  dIAdt <- (deltaHA * EH) - ((alphaA + muH + deltaHS) * IA)
  dISdt <- (deltaHS * IA) - ((alphaS + muH + gamma) * IS)
  dRHdt <- alphaA * IA + alphaS * IS - muH*RH
  dSTdt <- (piT * NT) - (betaTT *  IT + betaCT * IC)*(ST/NT) - (muT * ST)
  dITdt <- (betaTT * IT + betaCT *  IC)*(ST/NT) - (muT * IT)
  dSCdt <- (piC * NC) - (betaTC * IT)*(SC/NC) - (muC * SC)
  dICdt <- (betaTC * IT)*(SC/NC) - ((alphaC +muC) * IC)
  dRCdt <- (alphaC * IC) - (muC * RC)
  
  # return results
  list(c(dSHdt, dEHdt, dIAdt, dISdt, dRHdt, dSTdt, dITdt, dSCdt, dICdt, dRCdt))
}

我使用以下命令运行ODE求解器:

defaultParms = c(betaHHA = .0413,  
                 betaHHS = .0413,
                 betaTH = .2891, 
                 betaCH = .0826, 
                 betaTC = (1/365), 
                 betaCT = 59/365, 
                 betaTT = ((1/(365 * 2)) * .04) * 280,
                 gamma = 1/10, 
                 muH = (1/(365 * 73)), 
                 muT = (1/(365 * 2)),
                 muC = (1/(11 * 365)), 
                 piH = 1.25/(73 * 365), 
                 piT =  4.5/730,
                 piC = 1/(11 * 365),
                 deltaHS = 1/3, 
                 deltaHA = 1/2, 
                 alphaA = 1/17, 
                 alphaS = 1/17, 
                 alphaC = 1/7) 
# time to start solution 
t = seq(from = 0, to = 365, by = 0.1)

#initialize initial conditions
initialConditions = c(SH = 10000, EH = 5, IA = 5, IS = 10, RH = 2, ST = 80000, IT = 50, SC = 30000, IC = 5, RC = 1)

dataSet = ode(y = initialConditions, times = t, func = CCHFModel, parms = defaultParms)%>%
  as.data.frame()

运行此命令后,所有符合初始条件的输出均为NA。

1 个答案:

答案 0 :(得分:3)

这是由于输入错误造成的-您在代码的第一部分中对输入值的转换输入了错误的编号(即,您跳过了x[8]。我将进行两次(希望如此)有用的练习,首先说明如何调试此功能,然后显示如何重写函数以使其不那么容易出错...

调试

  1. 尝试为t=0x=<initial conditions>运行梯度函数:
CCHFModel(0,initialConditions, defaultParms)
##          piH      betaHHA      deltaHA      deltaHS       alphaA          piT 
## -15.02882327  12.62349834   0.53902803   0.07805607   0.88227788 385.31052332 
##       betaTT          piC       betaTC       alphaC 
##   0.85526763           NA           NA           NA 

嗯,我们已经看到了问题。为什么计算得出的梯度的最后三个元素为NA

  1. 在函数末尾(在browser()行之前)添加dsCdt <- ...,以便我们仔细看一下。重新定义函数,然后尝试再次计算梯度。

  2. 当我们到达那里并打印出一些计算量时,我们发现NCRC都是NA……我们还可以看到NA的{​​{1}}值将导致RCNC,所以让我们检查NA的定义...

  3. 啊哈! RC被定义为RC,但是x[11]只有10...。仔细观察表明,我们错过了length(initialConditions)。重新定义适当地会始终给出非{x[8]的值(我不知道它们是否正确,但至少它们不是NA)。

防错(1)

尽管使用NA[]提取向量元素通常会给出相同的答案,但当要提取单个元素(标量)时,应始终使用[[]]来自矢量。原因如下:

[[]]

如果您使用initialConditions[11] ## NA initialConditions[[11]] ## Error in x[[11]] : subscript out of bounds ,则[]会在您的代码中传播,因此您必须寻找原始源代码。如果您使用NA,则R会立即失败并告诉您问题出在哪里。另一个好处是[[]]以通常没有意义的方式传播矢量元素的名称(看一下上面“ debugging / 1”中输出的名称...)

防错(2)

通过用以下代码代替拆包代码(计算总人口之前的所有内容),可以避免对参数和状态向量进行所有繁琐且容易出错的拆包

[]

提供了正确的参数和状态向量名称(它们之间没有名称重叠),这将创建一个命名列表,并允许在函数中按名称查找元素; comb <- c(as.list(x), as.list(params)) attach(comb) on.exit(detach(comb)) 确保最后一切都正确清理。 (您会看到建议使用on.exit(detach(comb))来执行此操作;在这里我更喜欢这种策略,因为它使[如有必要]在函数中的调试更加容易。但是正如@tpetzoldt在注释中指出的,您应该始终with()attach(...)配对;否则情况会变得非常混乱和混乱……)

在函数结尾处我将使用

on.exit(detach(...))

确保正确标记了梯度矢量,这使故障排除更加容易。