The Gill algorithm (space constrained Gillespie with multiple species) is presented in Algo- rithm B.1. In addition to tmax and A, it takes as arguments a setS of species, two vectors
containing the per capita birth and death rate for each species br and dr, and a vector N
containing the total number of organisms of each species currently inhabiting the grid. The algorithm iterates until the maximum time is reached (outer while loop) and has three main sections: lines 5-9 compute the relevant population level rates, lines 10-23 compute the next event and lines 24-25 compute the elapsed time. In lines 5-9 the population level birth and death rates (Br and Dr) are computed for each species by multiplying per capita rates by the number of organisms of that species, and the total event rate λ is computed as the sum of all event rates (over all species). In lines 10-23, species are considered in turn and the probability δ ∈ [0, 1) that the next event is a death of the current species is computed by normalising the species death rate; the probability β ∈ [0, 1) that the next event is a birth of the current species is calculated analogously. The algorithm then compares δ and β to the
B.1. Algorithms 164
Table B.1: Symbols used in algorithms
Symbol Description Algorithms
i Species identifier All
t, tmax Time, maximum time All
A, B Habitat occupancy; index gives site and entry contains species identifier i
All
br
i, dri Per capitabirth and death rate for species
i
Gill
Br
i, Dri Total population birth and death rate
summed over individuals of species i
Gill
Ni, N Number of individuals of species i, total
number of organisms
Gill
τ Time until the next event under Gill Gill
λ Total event rate Gill
S Set of species Gill
β, δ Probability that the next event is a birth, death (summed over all species)
Gill
bpi, dpi Per capita probability of birth and death within a given timestep
RFd2S, RFd2M ,
RR1S
∆t Size of a timestep (fixed value) RFd2S, RFd2M ,
RR1S
E List of (site, eventT ype) pairs RR1S
C List of (species, site) pairs for occupied sites
B.1. Algorithms 165
Algorithm B.1 Gill algorithm for multiple species. 1: Gill(tmax, A,S, br, dr, N )
2: t← 0.0
3: while t < tmax do I Keep simulating until tmaxreached
4: λ ← 0.0, lwb ← 0.0, p ← rand()
5: for i∈ S do I Set up rates
6: Br
i ← briNi 7: Dri ← driNi 8: λ ← λ + Bir+ Dri
9: end for
10: for i∈ S do I Simulate next event; loop over species, exiting on event
11: δ ← Dr
i/λ 12: β ← Bri/λ
13: if p ≤ δ + lwb then
14: doDeath(i, A, N ) I Kill random member of species i
15: break I Exit for loop
16: end if
17: lwb← lwb + δ
18: if p ≤ β + lwb then
19: doBirth(i, A, N ) I Random member of species i attempts birth
20: break I Exit for loop
21: end if
22: lwb← lwb + β
23: end for
24: τ ← −ln(rand())/λ I Simulate elapsed time
25: t ← t + τ I Update time
B.1. Algorithms 166
uniformly random number p ∈ [0, 1) (generated in line 4), executing a single event if this value plus the current lower bound lwb is greater than or equal to p (a death at line 14 or a birth at line 19). When an event takes place the for loop is exited via a call to break (ensuring that exactly one event is executed per iteration of the while loop). The time to the next event τ is then computed by drawing from an exponential distribution with mean λ (line 24) and time t increased by this amount (line 25).
The call to doDeath(i, A, N ) (line 14) randomly selects a site in A occupied by an organism of species i, sets this site to be empty and decrements the population count Ni. Similarly, the
call to doBirth(i, A, N ) (line 19) randomly selects a site in A occupied by an organism of species i and chooses with uniform probability between neighbouring sites; if the chosen site is unoccupied a birth takes place into this site and the population count Ni is incremented.
Note that if the site into which a birth is due to take place is already occupied, the birth event does not take place. The same is true of all the algorithms presented here.
This algorithm is based upon the Direct Method (DM) (Gillespie, 1977). However, be- cause different organisms have different birth rates as a function of the occupancy of their neighbourhood, the original DM method would have required computing the birth and death event rate for every organism on the grid (i.e. 2× N rates where N is the total number of organisms). The birth rate of each organism also depends upon the occupancy of its neigh- bourhood, and with the Moore Neighbourhood, computing these rates entails assessing the occupancy of the 8 neighbouring cells. These would then need to be updated after an event took place (Potential ways of avoiding the need to update all event rates, since only those of organisms in the direct neighbourhood of an event would be affected, are reviewed in Slepoy et al., 2008; Sanassy et al., 2014). The main innovations in the algorithm that we employ are based on the following reasoning. Firstly, all organisms of the same species have the same death rate. This means that it is not necessary to compute or store the rates for each organism individually. Instead, we can store and compute only m species-level death rates and choose the organism to which a death applies in two steps: firstly, we select a species according to the species-level death rates, and then we choose the organism to which it applies uniform randomly within the organisms of this species. When a death occurs, we update the count of the number of organisms of that species and the overall species-level death rate. Secondly, all organisms of the same species have the same constitutional birth propensity, and their ac- tualised birth rate depends only on the probability of a potential birth occurring into a vacant cell. Focusing on a single individual, the rate at which that individual tries to give birth (its constitutional birth propensity) multiplied by its probability of actually achieving a success- ful birth, is equivalent to the rate at which it gives birth successfully. Since all organisms of the same species have the same birth propensity, we can first select a species according to the species-level birth propensity (given by the product of the number of organisms of that species and the constitutional birth propensity of the species), select an organism of that
B.1. Algorithms 167
species uniform randomly, select its birth site uniform randomly from those in its neighbour- hood and only implement birth should that site prove to be unoccupied. This means that we never have to compute (or store) birth rates as a function of the occupancy of the neighbour- hood, and in fact requires us to keep track of only the number of organisms of each species (a vector of length m) and the site at which each resides (a vector of length N , where N is the total number of organisms in the system).
As a result, the space complexity of the algorithm scales as O(n2) in the size of the lattice
(where n is the number of sites per side) and O(m) in the number of species. The number of operations required per (actualised) event depends on the overall occupancy: at high occu- pancy, birth events are generated but not effected as births are due to take place into occupied sites. However, these probabilities are independent of the size of the lattice n, so are constant in n per actualised event. The number of operations per proposed event scales as O(m) in the number of species (species selection), as O(n2) in the size of the lattice (in the worst case of a single species and full grid, we have to loop over all organisms of that species, i.e. all sites), but is constant in the number of sites in the neighbourhood as occupancy is only computed for the site into which birth is due to take place.
Algorithm B.2 RFd2S algorithm for multiple species. 1: RFd2S(tmax, A, ∆t, bp, dp)
2: t← 0.0
3: while t < tmax do I Keep simulating until tmaxreached
4: B ← A
5: C ← getSites(A)
6: shuffle(C)
7: for (i, site) ∈ C do I Consider sites for death
8: if dpi ≥ rand() then
9: doDeath(B, site)
10: end if
11: end for
12: for (i, site) ∈ C do I Consider sites for birth
13: if bpi ≥ rand() then
14: doBirth(i, B, B, site)
15: end if
16: end for
17: t ← t + ∆t I Update time
18: A ← B I Update array for next generation
B.1. Algorithms 168