R中的deSolve给出了不正确的中间值

时间:2016-06-06 10:45:55

标签: r ode

我在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")

2 个答案:

答案 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,它们在计算过程中不会改变。

然后您可以简化代码。请使用此行而不是您对parinit

的定义
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