<- 8900 # population size
N <- 20 # time steps
t <- 0.0004 # transmission probability
beta <- 0.5 # recovery probability (corresponding to a duration of 1/0.5=2 time steps) alpha
SIR model
Different implementations of the basic SIR model
The classical SIR model is a useful example to understand how disease transmission models are constructed. The SIR model defines three states — susceptible, infectious, and recovered, and assumes that the only possible transitions are from susceptible to infectious, and from infectious to recovered.
Here we implement the SIR model using three different approaches, to show the similarities between these approaches.
Markov chain, discrete
Parameter values
Set up data frame
<-
pop data.frame(
DAY = seq(0, t),
S = numeric(t+1),
I = numeric(t+1),
R = numeric(t+1))
$S[1] <- N - 1 # there needs to be 1 infectious person to start
pop$I[1] <- 1
pop$R[1] <- 0 pop
Run model
for (i in seq(t)) {
$S[i+1] <-
pop$S[i] - pop$S[i] * (1 - (1 - beta)^pop$I[i])
pop$I[i+1] <-
pop$I[i] + pop$S[i] * (1 - (1 - beta)^pop$I[i]) - pop$I[i] * alpha
pop$R[i+1] <-
pop$R[i] + pop$I[i] * alpha
pop }
Plot results
matplot(
-1],
pop[, type = "l",
col = c("green", "red", "blue"),
las = 1)
Markov model, continuous
Settings
## load deSolve package
library(deSolve)
Warning: package 'deSolve' was built under R version 4.2.2
## create SIR function
<- function(time, state, parameters) {
sir
with(as.list(c(state, parameters)), {
<- -beta * S * I
dS <- beta * S * I - alpha * I
dI <- alpha * I
dR
return(list(c(dS, dI, dR)))
}) }
Initialisation
## proportion in each compartment
<- c(S = 8699/8700, I = 1/8700, R = 0.0)
init
## beta: infection parameter; alpha: recovery parameter
<- c(beta = 1.5, alpha = 0.2)
parameters
## time frame
<- seq(0, 20, by = 0.1) times
Solve using ode (General Solver for Ordinary Differential Equations)
<- ode(y = init, times = times, func = sir, parms = parameters) out
Plot results
## change to data frame
<- as.data.frame(out[, -1])
out
## plot matrix
matplot(
x = times, y = out, type = "l", las = 1,
xlab = "Time", ylab = "Proportion of population", main = "SIR Model",
lwd = 1, lty = 1, bty = "l", col = c("green", "red", "blue"))
## add legend
legend(
"topright", c("Susceptible", "Infected", "Recovered"),
pch = 1, col = c("green", "red", "blue"))
Agent-based model, one run
Parameter values
<- 8900 # population size
N <- 20 # iterations
t <- 0.0004 # transmission probability
beta <- 0.5 # recovery probability (corresponding to a duration of 1/0.5=2 time steps) alpha
Set up data frame
<- matrix(nrow = N, ncol = t+1)
pop 1] <- c("I", rep("S", N-1)) pop[,
Run model
for (i in seq(t)) {
# identify S/I/R
<- pop[, i] == "S"
is_S <- pop[, i] == "I"
is_I <- pop[, i] == "R"
is_R
# calculate transition probability
<- 1 - (1 - beta)^sum(is_I)
beta_t
# S may become I or stay S
+1] <-
pop[is_S, isample(
x = c("I", "S"),
size = sum(is_S),
prob = c(beta_t, 1-beta_t),
replace = TRUE)
# I may become R or stay I
+1] <-
pop[is_I, isample(
x = c("R", "I"),
size = sum(is_I),
prob = c(alpha, 1-alpha),
replace = TRUE)
# R stays R
+1] <- pop[is_R, i]
pop[is_R, i }
Plot
<- apply(pop, 2, function(x) table(factor(x, c("S", "I", "R"))))
pop_tab matplot(
t(pop_tab),
type = "l",
col = c("green", "red", "blue"),
las = 1)
Agent-based model, multiple runs
Parameter values
<- 8900 # population size
N <- 20 # iterations
t <- 0.0004 # transmission probability
beta <- 0.5 # recovery probability (corresponding to a duration of 1/0.5=2 time steps) alpha
Set up function
<-
run function() {
# set up population
<- matrix(nrow = N, ncol = t+1)
pop 1] <- c("I", rep("S", N-1))
pop[,
# run chains
for (i in seq(t)) {
# identify S/I/R
<- pop[, i] == "S"
is_S <- pop[, i] == "I"
is_I <- pop[, i] == "R"
is_R
# calculate transition probability
<- 1 - (1 - beta)^sum(is_I)
beta_t
# S may become I or stay S
+1] <-
pop[is_S, isample(
x = c("I", "S"),
size = sum(is_S),
prob = c(beta_t, 1-beta_t),
replace = TRUE)
# I may become R or stay I
+1] <-
pop[is_I, isample(
x = c("R", "I"),
size = sum(is_I),
prob = c(alpha, 1-alpha),
replace = TRUE)
# R stays R
+1] <- pop[is_R, i]
pop[is_R, i
}
# summarize results
<-
pop_tab t(apply(pop, 2, function(x) table(factor(x, c("S", "I", "R")))))
# return results
return(pop_tab)
}
Run model
<- replicate(10, run()) runs
Plot
matplot(
1],
runs[, , type = "l",
col = c("green", "red", "blue"),
las = 1)
for (i in seq(2, 10))
matplot(
runs[, , i],type = "l",
col = c("green", "red", "blue"),
las = 1,
add = TRUE)
R session info
sessionInfo()
R version 4.2.1 (2022-06-23 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)
Matrix products: default
locale:
[1] LC_COLLATE=English_Belgium.utf8 LC_CTYPE=English_Belgium.utf8
[3] LC_MONETARY=English_Belgium.utf8 LC_NUMERIC=C
[5] LC_TIME=English_Belgium.utf8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] deSolve_1.34
loaded via a namespace (and not attached):
[1] htmlwidgets_1.5.4 compiler_4.2.1 fastmap_1.1.0 cli_3.6.1
[5] tools_4.2.1 htmltools_0.5.4 rstudioapi_0.14 yaml_2.3.5
[9] rmarkdown_2.26 knitr_1.46 jsonlite_1.8.8 xfun_0.43
[13] digest_0.6.34 rlang_1.1.1 evaluate_0.23