springle
springle

Reputation: 11

Trouble interpretting R code for Lotka-Volterra

I was given this code to create a Lotka Volterra predator-prey model. This code runs fine and produces the type of graph I am hoping to get, however, I don't understand what some of the code is doing and therefore don't know what I need to modify when using it on other data at other scales.

The two portions I don't understand are:

    for (n1 in seq((0.1*k[1]),(1.2*k[1]),100)){
  for (n2 in seq(.1*k[2],1.2*k[2],.1*k[2])){

and the if statement in this line:

    (n1==100&n2==100){plot(y[,2],y[,3],type="l",xlim=c(0,1000)

Any help interpreting this so I have a better understanding of how the code works would be greatly appreciated!

    library(deSolve)
    r<<-matrix(c(1,1),ncol=1)
    k<<-matrix(c(1000,1000),ncol=1)
    alpha<<-matrix(c(1,1.5,.5,1),ncol=2)
    t_stop<-100
    color="blue"
    for (n1 in seq((0.1*k[1]),(1.2*k[1]),100)){
      for (n2 in seq(.1*k[2],1.2*k[2],.1*k[2])){
    lvcomp2<-function(t,n,params){ w=n[1]; z=n[2]
    return(list(c(r[1]*n[1]*(k[1]-n[1]-alpha[1,2]*n[2])/k[1],r[2]*n[2]*(k[2]-n[2]- 
    alpha[2,1]*n[1])/k[2])))}
    y<-lsoda(c(n1,n2),c(seq(0,t_stop,1)),lvcomp2,NA)
    if (n1==100&n2==100){plot(y[,2],y[,3],type="l",xlim=c(0,1000), 
    ylim=c(0,1000),col=color,xlab="Abundance of species 1",ylab="Abundance of species 2")}
    if (n2==1200) {lines(y[,2],y[,3], col=color)}
    if (n1==1200){lines(y[,2],y[,3], col=color)}
    if (n2==100) {lines(y[,2],y[,3], col=color)}
    if (n1==100) {lines(y[,2],y[,3], col=color)}}} 

Upvotes: 1

Views: 89

Answers (1)

Donald Seinen
Donald Seinen

Reputation: 4419

That code does a good job of obfuscating the process. Some questionable practices in it, such as superassignment <<-, unnecessary actions in loop, et cetera. Here is a simplified version of the code, which we can get by going step-by-step and taking things outside of the loop, filling in constant values where they don't change, and applying a style guide.

library(deSolve)

# in the sample code, both loops iterate over the same thing:
s <- seq(from = 100, to = 1200, by = 100)
lsoda_times <- seq(0, 100, 1)

# all combinations of s to solve an Ordinary Differential Equation for
grid <- expand.grid(s, s)
grid <- subset(grid, Var1 %in% c(1200, 100) | Var2 %in% c(1200, 100))

lvcomp2 <- function(t, n, parms, ...) { # use lsoda convention ..., see ?lsoda
  list(c( # list output to satisfy lsoda requirements
    n[1] * (1000-n[1] - 0.5*n[2]) / 1000, # derivatives
    n[2] * (1000-n[2] - 1.5*n[1]) / 1000
  ))
}

y <- lsoda(c(100, 100), seq(0, 100, 1), lvcomp2, NA)
# make base plot
plot(y[, 2], y[, 3], type = "l", xlim = c(0, 1000), ylim = c(0, 1000),
     col = "blue", xlab = "Abundance of species 1", ylab = "Abundance of species 2"
)

# add lines to the plot
for (i in 1:nrow(grid)) {
  y <- lsoda(c(grid[i, 1], grid[i, 2]), lsoda_times, lvcomp2, NA)
  lines(y[, 2], y[, 3], col = "blue")
}

per @tpetzoldt comment - updated to a more efficient approach first removing 100 unnecessary calls to lsoda

Upvotes: 2

Related Questions