是否可以在ode(包deSolve)中使用rk4和rootfun

是否可以在ode(包deSolve)中使用rk4和rootfun,r,modeling,ode,R,Modeling,Ode,我正试图用基于LV模型的微分方程来模拟一个食饵-捕食者系统。为了精确起见,我需要使用runge-kutta4方法。 但根据这些方程式,一些人口很快就会变成负数 所以我尝试使用ODE的事件/根系统,但似乎rk4和rootfun不兼容 eventFunc <- function(t, y, p){ if (y["N1"] < 0) { y["N1"] = 0 } if (y["N2"] < 0) { y["N2"] = 0 } if (y["P"] < 0) {

我正试图用基于LV模型的微分方程来模拟一个食饵-捕食者系统。为了精确起见,我需要使用runge-kutta4方法。 但根据这些方程式,一些人口很快就会变成负数

所以我尝试使用ODE的事件/根系统,但似乎rk4和rootfun不兼容

eventFunc <- function(t, y, p){
  if (y["N1"] < 0) { y["N1"] = 0 }
  if (y["N2"] < 0) { y["N2"] = 0 }
  if (y["P"] < 0) { y["P"] = 0 }
  return(y)
}

rootFunction <- function(t, y, p){
  if (y["P"] < 0) {y["P"] = 0}
  if (y["N1"] < 0) {y["N1"] = 0}
  if (y["N2"] < 0) {y["N2"] = 0}
  return(y)
}

out <- ode(func=Model_T2.2,
           method="rk4",
           y=state,
           parms=parameters,
           times=times,
           events = list(func = eventFunc,
                         root = TRUE),
           rootfun = rootFunction
           )

eventFunc这是所有显式解算器(如rk4)都会遇到的问题。在一定程度上,缩短时间步长会有所帮助。最好使用隐式方法的解算器,
lsoda
似乎以某种形式普遍可用


另一种显式强制正值的方法是将它们参数化为指数。设置N1=exp(U1)
N2=exp(U2)
,然后ODE函数代码转换为(as
dN=exp(U)*dU=N*dU

N1多亏了,我现在可以运行我的L-V模型了

radau
(而不是您提到的
randau
)函数确实接受根函数,而events ans隐式实现了runge-kutta方法


再次感谢,希望这将对将来的人有所帮助。

状态
参数
时间
在您的“工作示例”(第二个代码段)中缺失。尝试
deSolve
文档中的一些示例确实表明
method=“rk4”
和根事件不兼容。但是如何使用函数
randau
?此函数支持
事件
。我添加了
参数
时间
状态
变量。我将尝试
randau
功能,并在测试后尽快更新此帖子。谢谢您的快速回复。您确定型号正确吗?即使对于
P=0
您也会得到
dP=-Mp
。对于正
P
这意味着与种群大小无关的不断移除/收获,但如果没有种群,就无法再移除任何东西。真是太遗憾了!卢兹尔发现了真正的问题:我数学不好。。。谢谢。
if(!require(ggplot2)) {
  install.packages("ggplot2"); require(ggplot2)}
if(!require(deSolve)) {
  install.packages("deSolve"); require(deSolve)}
Model_T2.2 <- function(t, state, par){
  with(as.list(c(state, par)), {

    response1 <- (a1 * N1)/(1+(a1*h1*N1)+(a2*h2*N2))
    response2 <- (a2 * N2)/(1+(a1*h1*N1)+(a2*h2*N2))

    dN1 = r1*N1 * (1 - ((N1 + A12 * N2)/K1)) - response1 * P
    dN2 = r2*N2 * (1 - ((N1 + A21 * N2)/K2)) - response2 * P
    dP = ((E1 * response1) + (E2 * response2)) * P - Mp

    return(list(c(dN1, dN2, dP)))
  })
}

parameters<-c(
  r1=1.42, r2=0.9,
  A12=0.6, A21=0.5,
  K1=50, K2=50,
  a1=0.77, a2=0.77,
  b1 = 1, b2=1,
  h1=1.04, h2=1.04,
  o1=0, o2=0,
  Mp=0.22,
  E1=0.36, E2=0.36
)

## inital states
state<-c(
  P=10,
  N1=30,
  N2=30
)

times <- seq(0, 30, by=0.5)

out <- ode(func=Model_T2.2,
           method="rk4",
           y=state,
           parms=parameters,
           times=times,
           events = list(func = eventFunc,
                         root = TRUE),
           rootfun = rootFunction
           )

md <- melt(as.data.frame(out), id.vars=1, measure.vars = c("N1", "N2", "P"))
pl <- ggplot(md, aes(x=time, y=value, colour=variable))
pl <- pl + geom_line() + geom_point() + scale_color_discrete(name="Population")
pl
N1 <- exp(U1)
N2 <- exp(U2)
response1 <- (a1)/(1+(a1*h1*N1)+(a2*h2*N2))
response2 <- (a2)/(1+(a1*h1*N1)+(a2*h2*N2))

dU1 = r1 * (1 - ((N1 + A12 * N2)/K1)) - response1 * P
dU2 = r2 * (1 - ((N1 + A21 * N2)/K2)) - response2 * P
dP = ((E1 * response1*N1) + (E2 * response2*N2)) * P - Mp