我在deSolve的R中解决了ode求解器问题。
我发现求解器为应该始终等于零的变量提供非零中间值。在我开始尝试使用if(R> 0){browser()}之类的测试进行调试之前,这看起来并不是一个问题。
我的代码如下。提前谢谢!
埃伦
library(deSolve)
simpleSIR <- function(t,states,par){
with(as.list(c(states,par)),{
S=states[1]
I=states[2]
R=states[3]
newinfections = beta*I*S
dS <- -newinfections
dI <- newinfections - gamma*I
dR <- gamma*I
if(R>0)
{
print(paste("why is this not zero?",R))
}
return(list(c(dS,dI,dR)))
})}
par=list(beta=0.3,gamma=0.0)
init=c(0.99,0.01,0)
times <- seq(0,500,by = 1)
out <- as.data.frame(ode(y = init, times = times, func = simpleSIR, parms = par,maxsteps=2000))
plot(out[,2],type="l")
lines(out[,3],type="l",col="red")
lines(out[,4],type="l",col="blue")
答案 0 :(得分:1)
我认为您的问题在于ode()
中数值整合的默认方法是lsoda
。这种方法可以在求解器之间切换刚性和非刚性问题。如果您有切换到刚性求解器,则jacobian将以数字方式进行评估,这可能会导致您看到的数字错误。
您可以看到这可能是以下代码中的原因:
out <- deSolve::ode(y = init, times = times, func = simpleSIR, parms = par,maxsteps=2000)
deSolve::diagnostics.deSolve(out)
“[...] 14到目前为止雅可比评估和LU分解的数量:23 [...]”
,它对应于原始代码生成的打印消息数(23)。 您将通过使用像RK4这样的非刚性求解器来解决问题:
out.rk4 <- deSolve::ode(y = init, times = times, func = simpleSIR,method = "rk4", parms = par,maxsteps=2000)
如果您坚持使用lsoda
,您可能想尝试使用您分析计算的雅可比提供lsoda。
答案 1 :(得分:0)
首先,我不知道你是否理解状态变量和参数之间的差异。
R
(在您的情况下)是状态变量。这意味着,在模拟开始时(t = 0)R = 0
。但随着时间的推移,这可能会改变。看你的状态变量S!
您的参数beta和gamma,它们在计算过程中不会改变。
然后您可以简化代码。请使用此行而不是您对par
和init
:
par <- c(beta = 0.3, gamma = 0.0)
init <- c(S = 0.99, I = 0.01, R = 0)
现在您可以删除以下行,因为with(as.list(c(states, par))
可以使用名称S,I和R来获取参数和状态参数的名称。
S = states[1]
I = states[2]
R = states[3]
你也可以简化你的情节:
matplot(out[,1], out[,2:4], type = "l", col = c("black", "red", "blue"))
此致
J_F