【问题标题】:Adding an if then statement to condition initial value in ODE system; deSolve在 ODE 系统中添加 if then 语句来条件初始值;解解
【发布时间】:2021-06-15 11:04:48
【问题描述】:

我正在尝试添加一个 if then 语句来调节我的状态变量之一的初始值,并且正在使用 deSolve。本质上,我想在模拟开始后引入第 3 个 ODE(在本例中是第 3 个物种)。

以下是没有条件的代码:

Antia_3sp_Model <- function(t,y,p1){
  # Parms
  ri <- p1[1]; rj <- p1[2]; k <- p1[3]; p <- p1[4]; o <- p1[5] 
  # State vars
  Pi <- y[1]; Pj <- y[2]; I <- y[3]
  # ODEs
  dPi = ri*Pi - k*Pi*I
  dPj = rj*Pj - k*Pj*I
  dI = p*I*(Pi/(Pi + o) + Pj/(Pj + o))
  list(c(dPi,dPj,dI))
}
# Parm vals
ri <- 0.3; rj <- 0.2; k <- 0.001; p <- 1; o <- 1000 # Note that r can range btw 0.1 and 10 in this model
parms <- c(ri,rj,k,p,o)
# Inits
Pi0 <- 1; Pj0 <- 1; I0 <- 1
N0 <- c(Pi0,Pj0,I0)
# Time pt. sol'ns
TT <- seq(0.1,200,0.1)
# Sim
results <- lsoda(N0,TT,Antia_3sp_Model,parms,verbose = TRUE)

这是我到目前为止所拥有的,在尝试添加 if then 语句之后,说在 time = 50 之前,第三个状态变量的初始值将为 0,并且在 time = 50 或以上时,初始值第三个状态变量的值为 1。

Antia_3sp_Model <- function(t,y,p1){
  # Parms
  ri <- p1[1]; rj <- p1[2]; k <- p1[3]; p <- p1[4]; o <- p1[5] 
  # State vars
  Pi <- y[1]; Pj <- y[2]; I <- y[3]
  
  if (t[i] < t[50]){
    Pj0 = 0
  }
  else if (t[i] >= t[50]){
    Pj0 = 1
  }
  
  # ODEs
  dPi = ri*Pi - k*Pi*I
  dPj = rj*Pj - k*Pj*I 
  dI = p*I*(Pi/(Pi + o) + Pj/(Pj + o))
  list(c(dPi,dPj,dI))
}
# Parm vals
ri <- 0.3; rj <- 0.2; k <- 0.001; p <- 1; o <- 1000 # Note that r can range btw 0.1 and 10 in this model
parms <- c(ri,rj,k,p,o)
# Inits
Pi0 <- 1; Pj0 <- 1; I0 <- 1
N0 <- c(Pi0,Pj0,I0)
# Time pt. sol'ns
TT <- seq(0.1,200,0.1)
# Sim
results <- lsoda(N0,TT,Antia_3sp_Model,parms,verbose = TRUE)

有什么建议吗?

如果我应该添加任何其他信息,请告诉我,非常感谢您的阅读! :)

【问题讨论】:

  • 你有if(t[i] &lt; t[50]),你没有一个变量i。我想你想要ifelse 而不是对矢量Pj0 &lt;- ifelse(t&lt;t[50], 0, 1) 起作用。
  • @pdb 非常感谢!这很有意义!我已经尝试过你的建议,我没有收到任何错误消息,但是在初始时间点之后输出都是 NA——考虑到模型的其余部分可以在什么时候运行,我不确定为什么会发生这种情况Pj=0。有什么想法吗?
  • @pdb 哎呀——发现一个错字——我应该写 TT 而不是 t。修复此问题后,我收到一条奇怪的错误消息:' checkFunc(Func2, times, y, rho) 中的错误:func() (3) 返回的导数数量必须等于初始条件向量的长度 (2002 )'...该函数应该返回相同数量的导数,即使在时间序列的一部分更改了初始条件...有什么想法吗?
  • 这毫无意义。如果t 超过值5(那里没有可用的数组t),t=0.1 的初始值是过去的历史,它们很久以前就处于非活动状态。即使可以更改它们,也不会影响进一步的集成。不过,可以通过这种方式实现外部输入,但是您还需要使用该输入,例如打开交互。
  • 要在某个时间点引入状态的突然变化,您可以通过强制或事件来做到这一点。请参阅?events 帮助页面或以下short tutorial

标签: r if-statement ode desolve


【解决方案1】:

对我来说,“第 3 个状态变量的初始值”应为 1 且 t >= 50 的语句的含义并不完全清楚。初始值定义状态变量的开始,然后由微分方程演化。在下文中,我展示了以下方法:

  1. 状态变量 Pj 初始化t = 50 处的给定值。这可以通过事件来处理。
  2. 状态变量 Pj 在 t >= 50 接收额外的外部输入。这可以通过外部信号进行处理,也称为强制函数

第一个示例显示了事件机制,实现为数据帧eventdat。它也可以通过事件函数以更灵活的形式实现。

在这里,我将 t=50 时的“初始”状态值增加到 100,以使效果更加明显。对时间向量TT 进行舍入以避免出现警告(如果您想知道原因,请询问)。

library("deSolve")

Antia_3sp_Model <- function(t, y, p1){
  # Parms
  ri <- p1[1]; rj <- p1[2]; k <- p1[3]; p <- p1[4]; o <- p1[5]
  # State vars
  Pi <- y[1]; Pj <- y[2]; I <- y[3]

  # ODEs
  dPi <- ri*Pi - k*Pi*I
  dPj <- rj*Pj - k*Pj*I
  dI <- p*I*(Pi/(Pi + o) + Pj/(Pj + o))
  list(c(dPi, dPj, dI))
}

parms <- c(ri = 0.3, rj = 0.2, k = 0.001, p = 1, o = 1000)
N0 <- c(Pi = 1, Pj = 1, I = 1)
TT <- round(seq(0.1, 200, 0.1), 1)

## An "initial value" is the value at the beginning. We call the value during
## simulation the "state". If it is meant that the state should be changed at
## a certain point of time, it can be done with an event

# tp: initial value at t=50 set to 100 to improve visibility of effect (was 1)
eventdat <- data.frame(var = "Pj", time = 50, value = 100, method = "rep")

results <- lsoda(N0, TT, Antia_3sp_Model, parms, events=list(data=eventdat), verbose = TRUE)
plot(results, mfcol=c(1, 3))

强制函数可用于实现与时间相关的参数,或将常数值连续添加到状态。还要注意 ODE 模型的紧凑风格。是否使用with 函数是个人喜好问题。两者各有利弊。

但是,使用事件还是强制函数有很大的不同。


Antia_3sp_Model <- function(t, y, p, import){
  with(as.list(c(y, p)), {
    dPi <- ri*Pi - k*Pi*I
    dPj <- rj*Pj - k*Pj*I + import(t)
    dI <- p*I*(Pi/(Pi + o) + Pj/(Pj + o))
    list(c(dPi, dPj, dI))
  })
}

signal <- approxfun(x=c(0, 50, max(TT)), y=c(0, 1, 1), method="constant", rule=2)

results <- lsoda(N0, TT, Antia_3sp_Model, parms, import=signal, verbose = TRUE)
plot(results, mfcol=c(1, 3))

【讨论】:

  • 哇,非常感谢您如此详细的回复!你说的对我来说很有意义——我现在就去实现它!
  • 抱歉回复太晚了!我最终使用了您提供的第一个解决方案!效果非常好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多