# Times for evaluating the model
<- seq(0, 20, by = 1)
time_sir
# Storage for S, I, R at times time_sir
<- matrix(data = NA,
y_sir nrow = length(time_sir),
ncol = 3)
# Function to return our update vector with three elements:
<- function(t, y, parms)
update_sir
{# Get parameter values from parms vector
<- parms["beta"]
beta <- parms["gamma"]
gamma
# Get current state variables from y vector
<- y[1]
S <- y[2]
I <- y[3]
R
# Numeric vector with updates to add to S, I, and R respectively
<- c(-beta * S * I,
out * S * I - gamma * I,
beta * I)
gamma
return (out)
}
# Set parameter values
<- c(beta = 1.3, gamma = 0.23)
parms_sir
# Set initial values for time zero
1, ] <- c(0.99, 0.01, 0)
y_sir[
# Run each step of the model from the second time step onward
for (i in 2:nrow(y_sir))
{# Assign new value to y_sir[i, ] using the update_sir function
<- y_sir[i - 1, ] +
y_sir[i, ] update_sir(time_sir[i],
- 1, ],
y_sir[i
parms_sir)
}
# Plot the number of infectious individuals over time
# type = "s" makes a "stair-step" line plot suitable for difference equations
plot(x = time_sir, y = y_sir[, 2], type = "s")
03. Discrete-time deterministic models: Solutions
Practical 1. A simple SIR model
Questions 1-6 ask:
- At approximately what time does the peak in infectious population occur and what proportion of the population is infectious? and
- Approximately what proportion of the population gets infected?
for three different sets of beta
(transmission rate) and gamma
(recovery rate) in the model. The solutions are summarized in the table and figure below:
Parameters | Peak in infectious population | Total proportion infected |
---|---|---|
beta = 1.3, gamma = 0.23 |
(1) t = 7, I = 0.60 | (2) 0.9997 |
beta = 1.3, gamma = 0.5 |
(3) t = 8, I = 0.30 | (4) 0.943 |
beta = 0.65, gamma = 0.23 |
(5) t = 14, I = 0.31 | (6) 0.943 |
When we start with \(\beta=1.3, \gamma=0.23\) the peak occurs on day 7 with 60% of the population infectious. Almost everyone in the population is infected by the end of the simulation.
When we increase gamma
from \(\gamma=0.23\) to \(\gamma=0.5\), this increase in the recovery rate corresponds to a shorter infectious period (2 days instead of 4.35 days). This means people spend less time in the \(I\) compartment, which decreases the reproduction number by around \(1/2\), and so the peak proportion of the population who are infectious is smaller (by around \(1/2\)). But since the generation interval is also shorter by around \(1/2\), the peak doesn’t happen substantially later.
When instead we decrease beta
from \(\beta=1.3\) to \(\beta=0.65\), this decrease in the transmission rate reduces the reproduction number, but does not change the generation interval. The peak proportion of the population who are infectious is smaller relative to when \(\beta=1.3, \gamma=0.23\). This time, the peak is also shifted later, because the lower reproduction number is not “compensated” in this regard by a shorter generation interval.
For questions (4) and (6), the reproduction number is lower by around the same amount relative to question (2), so the total proportion infected is lower by a similar amount in both (4) and (6).
Practical 2. Extending the SIR model
Incorporating births and deaths
# Times for evaluating the model
<- seq(0, 20, by = 1)
time_sir
# Storage for S, I, R at times time_sir
<- matrix(data = NA,
y_sir nrow = length(time_sir),
ncol = 3)
# Function to return our update vector with three elements:
<- function(t, y, parms)
update_sir
{# Get parameter values from parms vector
<- parms["beta"]
beta <- parms["gamma"]
gamma <- parms["delta"] ## NEW: delta parameter
delta
# Get current state variables from y vector
<- y[1]
S <- y[2]
I <- y[3]
R <- S + I + R ## NEW: calculation of N
N
# Numeric vector with updates to add to S, I, and R respectively
## NEW: transitions for birth and death with parameter delta
<- c(-S * delta - beta * S * I + N * delta,
out -I * delta + beta * S * I - gamma * I,
-R * delta + gamma * I)
return (out)
}
# Set parameter values
## NEW: parameter delta
<- c(beta = 1.3, gamma = 0.23, delta = 0.01)
parms_sir
# Set initial values for time zero
1, ] <- c(0.99, 0.01, 0)
y_sir[
# Run each step of the model from the second time step onward
for (i in 2:nrow(y_sir))
{# Assign new value to y_sir[i, ] using the update_sir function
<- y_sir[i - 1, ] +
y_sir[i, ] update_sir(time_sir[i],
- 1, ],
y_sir[i
parms_sir)
}
# Plot the number of infectious individuals over time
# type = "s" makes a "stair-step" line plot suitable for difference equations
plot(x = time_sir, y = y_sir[, 2], type = "s")
Visualising for the whole population
Calculate \(N(t) = S(t) + I(t) + R(t)\) the total number of individuals.
- Make a plot of \(S(t)\), \(I(t)\), \(R(t)\) and \(N(t)\). Your function \(N(t)\) should be constant at 1 for all values of \(t\). If this is not the case, ensure the model contains births of new S proportional to N, and deaths of each of S, I, and R.
Answer. Here is one possible method:
# Add total population N(t) to y_sir matrix
<- cbind(y_sir, rowSums(y_sir))
y_sir
# Plot each model component
par(mfrow = c(2, 2))
= c("S", "I", "R", "N")
components
for (i in 1:ncol(y_sir)) {
plot(y_sir[, i] ~ time_sir, type = "s", xlab = "Time (years)", ylab = components[i])
}
par(mfrow = c(1, 1))
- Change the code so the model runs for 100 time steps instead of 20. Compare the number of infectious people over time when
delta = 0
(no births and deaths, as before) versus whendelta = 0.01
. What explains the difference?
Answer. When the birth rate is 0.01, we eventually see a second outbreak occur around year 50. This is because new susceptibles enter the population via birth, which eventually furnishes enough susceptibles to make the effective reproduction number \(R_t>1\) and allow a new outbreak to occur.
Here is one way of plotting infectious individuals over time for delta = 0
versus delta = 0.01
, assuming that the solution y_sir
for delta = 0
is stored in the new variable y_sir_00
, and y_sir
for delta = 0.01
is stored in the new variable y_sir_01
:
plot(time_sir, y_sir_00[, 2], col = "black", type = "s", xlab = "Time (years)", ylab = "I(t)")
lines(time_sir, y_sir_01[, 2], col = "red", type = "s", xlab = "Time (years)")
legend("topright", c("delta = 0", "delta = 0.01"), col = c("black", "red"), lty = 1, title = "Birth rate")
- Describe the parameters of the model, what they represent, and whether the assumptions they represent are realistic.
Answer:
The transmission rate beta
represents the rate at which an individual makes “effective contact” with another individual, where effective contact results in a new infection if the contacted individual is infectious and the contacting individual is susceptible.
The recovery rate gamma
represents the recovery rate, such that 1/gamma
is the infectious period.
The birth rate delta
captures the rate of new births and also the rate of deaths.
There’s an implicit assumption in the model that transmission is not passed to newborns, i.e., only susceptibles are born. This is likely a reasonable assumption to make for many diseases.
As we are dealing with proportions of the total population, it’s reasonable to keep N(t) constant, but the birth and death rates may not be reasonable.
Additionally, we assume that the birth rate is proportional to the entire population, rather than restricting our attention to individuals of reproductive age. We also assume that the disease itself does not cause a loss of life expectancy.
Click here to return to the practical.