library(deSolve)
04. Ordinary differential equations (ODEs): SI model
Practical 1: Susceptible-Infectious model implementation
Step-by-step
We will be using the deSolve
package for this, so first we need to load the package.
If the deSolve
package is not installed, first install it using:
install.packages("deSolve")
and then re-run the library(deSolve)
line.
Now, we need to put together our initial conditions as a named numeric vector. The names in the vector should correspond to the names of each compartment in our ODE system, i.e. S and I.
<- c(S = 99, I = 1) y
This gives us 99 susceptibles and one infectious individual. Alternatively we can define S
in terms of the total population size and the number of initially infectious people:
<- 100
N <- 1
I_0 <- N - I_0
S_0 <- c(S = S_0, I = I_0) y
We also need to define which times we want the solution to be evaluated at. For this practical we are solving from 0 to 50 days in steps of 1 day:
<- seq(from = 0, to = 50, by = 1) times
Now we should define the parameters. There is just one parameter, the transmission rate beta
:
<- c(beta = 0.4) parms
Now let’s code up the (ordinary differential) equations themselves in an R function:
<- function(times, state, parms)
SI_model
{# Get variables
<- state["S"]
S <- state["I"]
I <- S + I
N # Get parameters
<- parms["beta"]
beta # Define differential equations
<- -(beta * I / N) * S
dS <- (beta * I / N) * S
dI <- list(c(dS, dI))
res return (res)
}
Make sure you understand what is happening in the function above before you continue.
Having assembled all the “ingredients”, we can now solve the ODE model and plot it:
# Solve equations
<- ode(y = y, times = times, func = SI_model, parms = parms)
output_raw
# Convert matrix to data frame for easier manipulation
<- as.data.frame(output_raw)
output
# Plot model output
plot(output$time, output$S, type = "l", col = "blue", lwd = 2, ylim = c(0, N),
xlab = "Time", ylab = "Number")
lines(output$time, output$I, lwd = 2, col = "red", type = "l")
legend("topright", legend = c("Susceptible", "Infectious"),
col = c("blue", "red"), lwd = 2, bty = "n")
All together
Bringing all the above pieces together looks something like the following. Note that we have defined the SI model function at the top and the parms
, times
, and y
vectors below so that it is easier to change the parameters or initial conditions and re-run the model without having to scroll up past the model function.
library(deSolve) # For solving systems of ODEs
# Define model function
<- function(times, state, parms)
SI_model
{# Get variables
<- state["S"]
S <- state["I"]
I <- S + I
N # Get parameters
<- parms["beta"]
beta # Define differential equations
<- -(beta * I / N) * S
dS <- (beta * I / N) * S
dI <- list(c(dS, dI))
res return (res)
}
# Define parameter values
<- c(beta = 0.4)
parms
# Define time to solve equations
<- seq(from = 0, to = 50, by = 1)
times
# Define initial conditions
<- 100
N <- 1
I_0 <- N - I_0
S_0 <- c(S = S_0, I = I_0)
y
# Solve equations
<- ode(y = y, times = times, func = SI_model, parms = parms)
output_raw
# Convert matrix to data frame for easier manipulation
<- as.data.frame(output_raw)
output
# Plot model output
plot(output$time, output$S, type = "l", col = "blue", lwd = 2, ylim = c(0, N),
xlab = "Time", ylab = "Number")
lines(output$time, output$I, lwd = 2, col = "red", type = "l")
legend("topright", legend = c("Susceptible", "Infectious"),
col = c("blue", "red"), lwd = 2, bty = "n")