简体   繁体   English

将事件/根 function 应用于大型方程组 R deSolve

[英]Apply event/root function to large set of equations R deSolve

TLDR: My main challenge is just how do I write the root function that checks an arbitrary number of state variables, x , and then apply the event function such that all state variables n that have a value less than the threshold ( n <= x ) are acted upon by the event function? TLDR:我的主要挑战是如何编写根 function 检查任意数量的 state 变量x ,然后应用事件 function 使得所有 state 变量n的值小于阈值( n <= x ) 被事件 function 所影响?

I'm trying to use deSolve for a set of Lotka-Volterra equations, but with many state variables (ie not just a predator and prey but 20 interacting organisms).我正在尝试将deSolve用于一组 Lotka-Volterra 方程,但有许多 state 个变量(即不仅仅是捕食者和猎物,还有 20 个相互作用的生物)。

I want to use a root function and event function to be constantly checking if any state variable values dip below a threshold value (eg 1.0) and if they do, use the event function to make that particular state variable 0. I've been messing around with a simple minimal example, but can't quite understand how to extend this to check all the state variables and just apply to the one(s) that is/are below the threshold.我想使用根 function 和事件 function 不断检查是否有任何 state 变量值低于阈值(例如 1.0),如果低于阈值(例如 1.0),则使用事件 function 使特定的 state 变量为 0。我一直在搞乱围绕一个简单的最小示例,但不太了解如何扩展它以检查所有 state 变量并仅应用于低于阈值的变量。

The LV example from the deSolve package vi.nette deSolve package vi.nette 中的LV 示例

LVmod <- function(Time, State, Pars) {
  with(as.list(c(State, Pars)), {
    Ingestion    <- rIng  * Prey * Predator
    GrowthPrey   <- rGrow * Prey * (1 - Prey/K)
    MortPredator <- rMort * Predator
    
    dPrey        <- GrowthPrey - Ingestion
    dPredator    <- Ingestion * assEff - MortPredator
    
    return(list(c(dPrey, dPredator)))
  })
}

pars  <- c(rIng   = 0.2,    # /day, rate of ingestion
           rGrow  = 1.0,    # /day, growth rate of prey
           rMort  = 0.2 ,   # /day, mortality rate of predator
           assEff = 0.5,    # -, assimilation efficiency
           K      = 10)     # mmol/m3, carrying capacity

yini  <- c(Prey = 10, Predator = 2)
times <- seq(0, 50, by = 1)

I can apply my root and event functions to check for just the prey's values:我可以应用我的根函数和事件函数来检查猎物的值:

## event triggered if state variable less than 1
rootfun <- function (Time, State, Pars) {
  return(State[1] - 1)
}

## sets state variable = 1                                                  
eventfun <- function(Time, State, Pars) {
  return(c(State[1] <- 0, State[2]))
}
out   <- lsode(yini, times, LVmod, pars, 
               rootfunc = rootfun, 
               events = list(func = eventfun, root = TRUE))


## User specified plotting
matplot(out[ , 1], out[ , 2:3], type = "l", xlab = "time", ylab = "Conc",
        main = "Lotka-Volterra", lwd = 2)
legend("topright", c("prey", "predator"), col = 1:2, lty = 1:2)

And the result is this:结果是这样的:

低压结果

But now I want to extend this so that it checks all the state variables (in this case just the 2), but ideally in a way that is flexible to different numbers of state variables.但现在我想扩展它,以便它检查所有 state 个变量(在本例中只是 2),但理想情况下,它可以灵活地处理不同数量的 state 个变量。 I have tried messing around with doing this in some sort of loop but can't seem to figure it out.我试过在某种循环中乱搞这个,但似乎无法弄清楚。 My main challenge is just how do I write the root function that checks an arbitrary number of state variables, x , and then apply the event function such that all state variables n that have a value less than the threshold ( n <= x ) are acted upon by the event function?我的主要挑战是如何编写根 function 检查任意数量的 state 变量x ,然后应用事件 function 使得所有 state 变量n的值小于阈值 ( n <= x )由事件 function 采取行动?

Perhaps useful information is at some point I would like to implement a separate (not root-based) event function to change a parameter at some pre-set times, so ideally the solution to this problem could interface with additional event function implementation.也许有用的信息是在某些时候我想实现一个单独的(不是基于根的)事件 function 以在某些预设时间更改参数,因此理想情况下,这个问题的解决方案可以与附加事件 function 实现接口。

Help much appreciated as always!!一如既往地帮助感谢!!

One can use a vectorized version of the LV model and then write rootfun and eventfun also in vectorized style:可以使用LV model的矢量化版本,然后也以矢量化样式编写rootfuneventfun

library(deSolve)

model <- function(t, y, parms) {
  with(parms, {
    dy <- r * y  + y * (A %*% y)
    list(dy)
  })
}

## int6eraction matrix
parms <- list(
  r = c(r1 = 0.1, r2 = 0.1, r3 = -0.1, r4 = -0.1),
  A = matrix(c(
    0.0, 0.0, -0.2, 0.0, # prey 1
    0.0, 0.0, 0.0, -0.1, # prey 2
    0.2, 0.0, 0.0, 0.0,  # predator 1; eats prey 1
    0.0, 0.1, 0.0, 0.0), # predator 2; eats prey 2
    nrow = 4, ncol = 4, byrow = TRUE)
)

times = seq(0, 150, 1)
y0  = c(n1 = 1, n2 = 1, n3 = 2, n4 = 2)

out <- ode(y0, times, model, parms)
plot(out)

## defined as global variables for simplicity, can also be put into parms
threshold <- 0.2  # can be a vector of length(y0)
y_new     <- 1.0  # can be a vector of length(y0)

## uncomment the 'cat' lines to see what's going on
rootfun <- function (t, y, p) {
  #cat("root at t=", t, "\n")
  #cat("y old =", y, "\n")
  return(y - threshold)
}

eventfun <- function(t, y, p) {
  #cat("y old =", y, "\n")
  y <- ifelse(y <= threshold, y_new, y)
  #cat("y new =", y, "\n")
  return(y)
}

out <- ode(y0, times, model, parms, 
           events = list(func = eventfun, root = TRUE), rootfunc=rootfun)
plot(out)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM