Since , consider only the infected. To simulate as DTMC, consider a random walk on ( Gambler's ruin problem)
Denote , and
Transition matrix
# Make the transition matrix
T = mat.or.vec(nr = (Pop+1), nc = (Pop+1))
for (row in 2:Pop) {
I = row-1
mv_right = gamma*I*Delta_t # Recoveries
mv_left = beta*I*(Pop-I)*Delta_t # Infections
T[row,(row-1)] = mv_right
T[row,(row+1)] = mv_left
}
# Last row only has move left
T[(Pop+1),Pop] = gamma*(Pop)*Delta_t
# Check that we don't have too large values
if (max(rowSums(T))>1) {
T = T/max(rowSums(T))
}
diag(T) = 1-rowSums(T)
Simulating a DTMC
library(DTMCPack)
sol = MultDTMC(nchains = 20, tmat = T, io = IC, n = t_f)
gives 20 realisations of a DTMC with transition matrix T, initial conditions IC (a vector of initial probabilities of being in the different states) and final time t_f
Recall that the inter-event time is exponentially distributed
Critical step of the Gillespie algorithm:
weight of all possible events (propensity)
Draw from
So the inter-event time if becomes very large for some
This can cause the simulation to grind to a halt
Example: a birth and death process
Individuals born at per capita rate
Individuals die at per capita rate
Let's implement this using classic Gillespie
Gillespie's algorithm (birth-death model)
set and
while {}
Draw from
Draw from
Find such that
switch {}
1: Birth,
2: Death,
b = 0.01 # Birth rate
d = 0.01 # Death rate
t_0 = 0 # Initial time
N_0 = 100 # Initial population
# Vectors to store time and state. Initialise with initial condition.
t = t_0
N = N_0
t_f = 1000 # Final time
# We'll track the current time and state (could also just check last entry in t
# and N, but will take more operations)
t_curr = t_0
N_curr = N_0
while (t_curr<=t_f) {
xi_t = (b+d)*N_curr
# The exponential number generator does not like a rate of 0 (when the
# population crashes), so we check if we need to quit
if (N_curr == 0) {
break
}
tau_t = rexp(1, rate = xi_t)
t_curr = t_curr+tau_t
v = c(b*N_curr, xi_t)/xi_t
zeta_t = runif(n = 1)
pos = findInterval(zeta_t, v)+1
switch(pos,
{
# Birth
N_curr = N_curr+1
},
{
# Death
N_curr = N_curr-1
})
N = c(N, N_curr)
t = c(t, t_curr)
}
Drawing at random from an exponential distribution
If you do not have an exponential distribution random number generator.. We want from , i.e., has probability density function
Use cumulative distribution function
which has values in . So draw from and solve for
Last one did not go well
Wanted 1000 time units (days?)
Interrupted around 500 () because I lost patience
(Slide before: the sim stopped because the population went extinct, I did not stop it!)