deSolve:无法理解如何使用根函数提前停止 ode 求解器
deSolve: Can't understand how to early stop ode solver with root functions
我对如何在满足特定条件时停止求解器感到困惑。我准备了一个虚拟 SIR 模型,一旦 I 隔间达到某个值就应该停止。但在我的代码中,求解器只是继续:
library(deSolve)
library(dplyr)
pars <- c(beta = .1, gamma = .04)
init <- c(S = 100, I = .01, R = 0, trig = 0)
rootFun <- function(t, y, pars) {
r <- 1
if (y['I'] > 10 & y['trig'] == 0) r <- 0
if (y['I'] > 80) r <- 2
if (r == 2) print('should finish')
return(r)
}
eventFun <- function(t, y, pars) {
message('First threshold passed!')
y['trig'] <- 1
y
}
derFun <- function(t, y, pars) {
with(as.list(c(y, pars)), {
dS = -S * I * beta
dI = S * I * beta - I * gamma
dR = I * gamma
list(c(dS, dI, dR, 0))
})
}
ode(y = init, func = derFun, parms = pars, times = 1:100, events = list(func = eventFun, root = TRUE, terminalroot = 2),
rootfun = rootFun) %>% invisible()
如果根的计算结果为 2,求解器应停止,如果计算结果为零,则触发一个事件,并在所有其他情况下继续。但是根是 2 并没有阻止它。
在event(root=>action)机制中,event位于状态连续函数的root处。在您的情况下,根函数将是 y['I']-10
和 y['I']-80
,rootfun
是这些函数的列表(或返回其值列表的函数)。
此函数经常在解曲线的所有部分进行评估,以检测 符号变化(对于某些步进器,如果一个分量是分段常量并且root 函数恰好命中零)。然后使用包围法细化符号变化的间隔。除了提供这些值之外,根函数中不应该也不能进行任何处理。
对状态的操作在 eventfun
中编码,它 returns 事件后的新状态。在内部,集成在根处停止,并以返回的状态作为初始值重新启动。
终止使用 terminalroot
变量编码。它是一个索引,确定哪个根函数提供终止事件。
所以
rootFun <- function(t, y, pars) {
return(c(y['I']-10, y['I']-80))
}
应该可以在所有其他行不变的情况下使用。请注意,触发器组件现在未使用,可以删除。
我对如何在满足特定条件时停止求解器感到困惑。我准备了一个虚拟 SIR 模型,一旦 I 隔间达到某个值就应该停止。但在我的代码中,求解器只是继续:
library(deSolve)
library(dplyr)
pars <- c(beta = .1, gamma = .04)
init <- c(S = 100, I = .01, R = 0, trig = 0)
rootFun <- function(t, y, pars) {
r <- 1
if (y['I'] > 10 & y['trig'] == 0) r <- 0
if (y['I'] > 80) r <- 2
if (r == 2) print('should finish')
return(r)
}
eventFun <- function(t, y, pars) {
message('First threshold passed!')
y['trig'] <- 1
y
}
derFun <- function(t, y, pars) {
with(as.list(c(y, pars)), {
dS = -S * I * beta
dI = S * I * beta - I * gamma
dR = I * gamma
list(c(dS, dI, dR, 0))
})
}
ode(y = init, func = derFun, parms = pars, times = 1:100, events = list(func = eventFun, root = TRUE, terminalroot = 2),
rootfun = rootFun) %>% invisible()
如果根的计算结果为 2,求解器应停止,如果计算结果为零,则触发一个事件,并在所有其他情况下继续。但是根是 2 并没有阻止它。
在event(root=>action)机制中,event位于状态连续函数的root处。在您的情况下,根函数将是 y['I']-10
和 y['I']-80
,rootfun
是这些函数的列表(或返回其值列表的函数)。
此函数经常在解曲线的所有部分进行评估,以检测 符号变化(对于某些步进器,如果一个分量是分段常量并且root 函数恰好命中零)。然后使用包围法细化符号变化的间隔。除了提供这些值之外,根函数中不应该也不能进行任何处理。
对状态的操作在 eventfun
中编码,它 returns 事件后的新状态。在内部,集成在根处停止,并以返回的状态作为初始值重新启动。
终止使用 terminalroot
变量编码。它是一个索引,确定哪个根函数提供终止事件。
所以
rootFun <- function(t, y, pars) {
return(c(y['I']-10, y['I']-80))
}
应该可以在所有其他行不变的情况下使用。请注意,触发器组件现在未使用,可以删除。