In this lecture we will look at another way of modelling infectious diseases: the agent-based model (ABM).
We will also focus on ABMs and NetLogo in workshop 3.
We focussed on compartmental models, which think in terms of the population as a whole. We will now look at agent based models (ABMs), which model complex systems in terms of the interactions and behaviour of many many agents. Three useful and interesting papers on this topic are Auchincloss and Diez Roux (2008), Hunter, Mac Namee, and Kelleher (2017) and Badham et al. (2018). Jen Badham has also written a fantistically helpful guide to NetLogo, which you can find here.
ABMs are a relatively new, but widely used, class of models that attempt to understand the macro-effects arising from micro-behaviour. They simulate the behaviour and interactions of individuals, according to a set of pre-defined rules, and are particularly suited to situations where the general theoretical models don’t account for human behaviour (see Buchanan 2008 for an economics example), and for situations where place / proximity / relationship is important.
To quote Auchincloss and Diez Roux (2008), “Agent-based models are computer represenations of systems consisting of a collection of discrete microentities [agents] interacting and changing over discrete time steps that give rise to macrosystems.”
An agent in an ABM is anything that changes how it behaves in response to input from the other agents and the environment. In the ABMs we study and develop, the agents will usually be people. Agents are given rules that determine their behaviour and their response to what is happening in the system. At each time step, the agents all re-evaluate their decisions/behaviour according to the state of all the other agents, and the environment they find themselves in. One of the big advantages of ABMs is that they can encode things like social norms or memes.
We will use NetLogo to simulate ABMs. You can either download this here and run it locally, or use the web version, or load it through AppsAnywhere on a university machine.
Typically, an ABM has three elements:
For example, in a simple epidemiological model, agents might be labelled with attributes such as ‘susceptible’, ‘infectious’ or ‘recovered’/‘removed’. If a susceptible agent comes into close contact (what this means will need to be defined in the model) with an infectious agent, they may become infected.
In a more detailed model, different agents can have different behaviours such a whether (or to what extent) they will self-isolate, whether they will wear a mask, or how much they move around. These factors would affect things like how often an agent comes into contact with other agents, or how likely they are to become infected if in contact with an infectious agent. They can also be influenced by the behaviour and decisions of those around them. This gives modellers a lot of functionality that is not easily replicable in a compartmental model.
When we discussed the limitations of SIR models in lectures 1 and 2, one of the things we thought about was the assumption of mass action, that is that each person in the system has a uniform influence on every other person. In an ABM, the agents are arranged in space, and so it is natural that the extent to which to agents influence one another depends in some way on the distance between them. We will explore this idea now.
During this lecture and the following workshop, we will see several different types of plot. One of these is of the agents arranged in 2D space.
Figure 3.1: Agents arranged at random in 2D space. One is infectious.
In Figure 3.1 we see 100 points (representing 100 agents) arranged randomly in 2D space. This represents the first time point in our model, where we have one infectious person (or agent) in a population of otherwise susceptible people (or agents). In this model the
Assuming mass action, every other person in the grid has an equal probability of being infected by this one person at time point 2 (let’s say this is 1/50). At time step 2, our plot will therefore look something like Figure 3.2.
Figure 3.2: The same agents, at the following time step.
We see that another person has become infected by the initial infectious person. In line with the mass action assumption of the SIR models, every person (or agent) has an equal effect on every other person, and so the people who are newly infected were chosen (by the computer) at random. Note that in this model the agents aren’t moving at all, so that we can easily see which agent is which. When we go on to look at ABMs in NetLogo, we will explore different types of movement.
Now that there are two infectious people, the probability of each susceptible person becoming infected is higher, and indeed in Figure ??} we now have five infectious people, and fourteen at time point 4.Figure 3.3: The same agents, at the following time step.
Figure 3.4: The same agents, at the following time step.
We can plot the time series of Susceptible, Infectious and Recovered people through the epidemic as we did in lectures 1 and 2 with the SIR model, and we find the pattern to be similar.
Figure 3.5: The populations of the three States over the course of the epidemic
You can see that this looks very similar to the SIR model plots we saw in Lecture 1. Because the ABM relies on random choices (eg. an agent has a probability of being infected) and the model works in whole numbers of agents, the lines are somewhat ‘wibbly’.
In many ways this example was rather silly - people aren’t randomly spaced on a 2D plane, and they don’t have equal probability of being infected by anyone else in that space. However, this has highlighted some of the shortfalls of the compartmental models that treat the population as one homogeneous mass, and some of the modelling opportunities that agent-based models can introduce. By starting from the ground up, with individual people as agents, we can incorporate some much more realistic behaviour.
The first things we’ll tackle are movement and proximity:
This model will start in the same way as before, with 100 people randomly spaced on a grid. However this time, people can move a little at each time step, and can only be infected if there is someone infectious nearby.
From now on we will run our models in NetLogo (which is what we’ll use in our workshop), so the plots will look a little different, but in principle they are the same as those we’ve been using so far - agents in 2D space, coloured according to their state.
Turtles: for historical reasons, the agents in NetLogo models are called “turtles”. So when you see this in these notes, or in NetLogo code or interface, you can interpret it as “agents” or “person/people”.
In this lecture, we will briefly look at a simple and then a more complex model, and then in the workshops you will have time to explore NetLogo and to experiment with the models.
The first model we’ll look at in NetLogo is “Epidemic_ABM_RHO.nlogo”. You can download this file from the module webpage, save it to somewhere on your computer and open it in NetLogo (using ‘File -> Open’).
Figure 4.1 shows the main NetLogo window, with ‘Epidemic_ABM_RHO
.nlogo’ open. This is also after the setup
button has been pressed.
Figure 4.1: The main NetLogo window.
The beige buttons and windows show monitors and plots that NetLogo will calculate and update as the model runs. The green buttons show variables that the user can change. In this model, these are:
We will look through the code in chunks, to understand the logic of the model. Two things to note:
This model is a replication of the basic SIR model we studied in Lecture 1. There are three states, Susceptible
, Infectious
and Recovered
, and the system is closed (no people are lost or introduced). We will use this to demontrate how NetLogo models are set up and run.
First of all, we set up some global variables (only one in this example). These are properties of the system as a whole (rather than of individual turtles), and will be monitored as the system evolves. Note that in NetLogo code, comments are preceded by a semi-colon.
globals
[ effective-R-recovered ; R_n estimated using newly recovered turtles
]
We then create some turtles_own variables, which keep track of each turtle:
turtles-own
[ status
my-transmissions
]
The ‘status’ variable tracks whether the turtle is susceptible, infectious or recovered. The variable ‘my-transmissions’ keeps track of how many other turtles each turtle has directly infected.
Having established these variables, we can now set up the model. Note that some of the variable names in the following code (initial-people, infection-chance etc) are variables set by the user.
to setup
clear-all
ask patches [ set pcolor white ]
create-turtles num-people ; Create num-people turtles
[ setxy random-xcor random-ycor ; Randomly spaced on a grid
set status "S" ; Set all as Susceptible (for now)
set size 0.5
set my-transmissions 0
]
ask n-of initial-I turtles ; Choose initial-I turtles at random
[ set status "I" ; to be infectious
]
update-colours
reset-ticks
end
The chunk of code essentially repeats the following steps for the required number of turtles (num-people
):
Some (initial-I
) turtles are then chosen at random to be labelled as Infectious. The colours are updated (in this model, blue is susceptible, red is infectious and green is removed).
Having set up the model in this way, NetLogo performs a number of tasks at each time step:
to go
if not any? turtles with [status = "I"] [stop] ; If there are no infectious turtles left, stop
move-all
recover
transmit
update-colours
tick
end
In summary, at each time-step (‘tick’):
The code for moving, infecting other turtles and recovering can be seen in the ‘code’ tab in NetLogo. We won’t go into writing NetLogo code, but if you want to ask about it then feel free to in the workshop.
In this model, there are three possible modes of movement:
The probability of moving can also be set using prob-move
, so that if there is movement, turtles will move with that probability.
The code that achieves this is
to move-all
ask turtles
[ if random-float 1 < prob-move ; determine whether the turtle will move at all
[ ( ifelse
movement = "none" [ ]
movement = "local"
[ set heading random 360
forward 1 ; Move one space in some random direction
]
movement = "anywhere" [ setxy random-xcor random-ycor ] ; move to a random new point
)
]
]
end
In NetLogo, random numbers are generated often.
The command random-float 1
generates a random number from Unif[0,1], with as many decimal places as are used by the system. In the code above, this is used to achieve an event with probability prob-move
.
The command random 360
generates a random integer between 0 and 360, and is used in the code above to randomly generate an angle for the turtle’s direction of movement.
The local
mode of movement allows the turtle to move one unit in any direction.
The anywhere
mode of movement allows the turtle to ‘teleport’ to a new randomly generated point in the space. The coordinates for this point is generated using random-xcor
and random-ycor
.
Having moved, all infectious turtles have the chance to recover.
to recover
let count-new-R 0
let count-infected-by-new-R 0
ask turtles with [status = "I"] ; For each infectious turtle
[ if random-float 1 < 1 / infectious-period ; Recover if a random Unif[0,1] is less than 1/recovery rate
[ set status "R"
set count-new-R count-new-R + 1 ; Number of newly recovered turtles
set count-infected-by-new-R count-infected-by-new-R + my-transmissions ; Total number of other turtles directly infected by these newly recovered turtles
]
]
if count-new-R > 0 [ set effective-R-recovered count-infected-by-new-R / count-new-R ] ; estimate R_n - average number of direct secondary infections by these newly recovered turtles
end
In this model, we model this in a similar way to the compartmental models we studied, using a recovery rate. The parameter chosen by the user is infectious-period
(in ticks), and then at each tick, each infectious turtle recovers with probability 1/infectious-period
.
This portion of the code also contains the estimation of the effective reproduction number, \(R_n\).
The two counts that are set up are
count-new-R
: A count of the turtles newly recovered at this tickcount-infected-by-new-R
: The total number of turtles directly infected by those newly recovered turtlesThus once all the turtles have been looked at, we will have the number of turtles who have recovered at that time step, and the total number of turtles directly infected by those turtles. To estimate \(R_n\) we can therefore do \[ R_n\approx\frac{\texttt{count-infected-by-new-R}}{\texttt{count-new-R}}, \] that is, the average number of secondary infections per newly recovered turtle.
The final modelling step at each tick is to allow each infectious turtle to infect others. There are two versions of this, chosen using the transmit-to
selector in the main window. To understand how these work, we need to introduce patches.
In NetLogo, the world is modelled as a grid of patches. By default this is a \(33\times{33}\) grid, so there are 1089 patches. Patches can be used to model or monitor differences in the environment. For example different patches could have different population densities, or the prevaling attitude to mask-wearing in each patch could be monitored.
The transmission code uses patches by choosing a patch in the model to be exposed to an infectious turtle. Note that in this section we use the word ‘exposed’ not in the pre-infectious SEIR sense, but to mean those in effective contact with an infectious turtle.
to transmit
let targets no-turtles ; creates empty turtle set for exposed
ask turtles with [status = "I"] ; For each infectious turtle
[ ; randomly select turtles to expose depending on model settings
; expose everyone on same patch
if transmit-to = "patch" ;; targets other turtles on same patch
[ set targets other turtles-here
]
; expose turtles on random other patch
if transmit-to = "anyone" ;; targets any other turtle
[ let opportunities count turtles-on one-of patches - 1 ; ensures same number of exposed turtles
if opportunities >= 1
[ set targets n-of opportunities other turtles
]
]
; check whether the exposure results in transmission
ask targets with [status = "S"] ; Finds target turtles who are Susceptible
[ if random-float 1 < prob-transmission-pp ; and infects them with probability prob-transmission-pp
[ set status "I"
ask myself [ set my-transmissions my-transmissions + 1 ] ; Increases transmission count for that turtle
]
]
]
end
First of all, we create an empty turtle set called targets
. This will hold our exposed turtles, once we have found them. We then find all the Infectious turtles, and transmit the disease one at a time. If transmit-to
is set to ‘patch’, then the exposed turtles (the targets
) are those (if any) on the same patch. If transmit-to
is set to ‘anyone’, a patch is chosen at random and the number of turtles on that patch is counted. The variable opportunities
is then set to that count minus one. This ensures the same expected number of exposed turtles as for the ‘patch’ option, with the minus one taking the place of the infectious turtle who would be on that patch. That number (opportunities
) of turtles is then chosen at random from all the other turtles, and these are the targets
.
Now that we have our targets
for this particular Infectious turtle, we find all the ones who are susceptible. We cycle through these, randomly infecting them with probability prob-transmission-pp
. Each time a turtle is infected, we increase my-transmission
by one (remember that this variable belongs to the Infectious turtle). Remember that once a turtle recovers, its my-transmission
count will be used to estimate \(R_n\).
Open the model file, click the ‘setup’ button. You will see the desired number of turtles appear, a few of which are red. These are the initially infected ones. If you press ‘Go’ you will see the turtles begin to move around (if movement is enabled), and sometimes become infected. The Effective R plot shows \(R_n\) as it is estimated at each tick. The Epidemic plot shows the Infected (red) and Recovered (green) populations.
The plot shows the number of susceptible (blue), infectious (red) and recovered (green) turtles as time progresses.
There are also three counters: Density, R0 and Spread.
Density shows the average number of turtles per patch.
Spread monitors the proportion of the population that is either Infected or Recovered, ie. the proportion that has been affected by the disease. Once the epidemic has died out, Spread will represent the final epidemic size as a proportion of the population.
R0 is an estimate of the basic reproduction number \(R_0\), calculated from the model parameters. The formula used is
\[R_0 \approx{\frac{\texttt{infectious-period}\times{\texttt{prob-transmission-pp}\times{\texttt{num-people}}}}{\texttt{number-of-patches}}} \]
Exercise 4.1 Think back to our compartmental SIR model, where we had \(R_0 = \frac{\beta}{\gamma}\). How do these ABM parameters relate to \(\beta\) and \(\gamma\)?
One feature of agent-based models as we have described them is that they are stochastic.
Definition 5.1 A stochastic model is one which, due to inherent uncertainty, will not always return the same output given the same input variables.
This is because many of the stages of the model are performed using random number generation.
Exercise 5.1 List the parts of the ABM described above that are subject to randomness.
Some of the events that are subject to random chance in the model we have looked at are:
Thus, running the model with the same input values (by which we mean those chosen using the sliders on the ‘Interface’ panel) many times will result in different outcomes.
NetLogo provides a way for us to do this, in ‘Tools -> BehaviourSpace’. Here, we can specify the value(s) for each parameter, and how many repetitions we would like of each. We can also specify the variables we wish to monitor.
Figure 5.1: The BehaviourSpace window.
For the experiment set up in Figure 5.1, where we are running the experiment for the same input values 30 times, and monitoring the number of Infected
and Recovered
turtles, we find the following.
Figure 5.2: The count of infected turtles over time for 50 ABM runs with the same input values.
As you can see in Figure 5.2, there is some variation in the height and location of the peak of infections, as well as the point at which the epidemic dies out (you can see these locations by the small ticks on the x-axis as the lines reach zero). This variation is due entirely to the randomness inherent in the model, since each of these 50 runs had the same input parameter values. We can also plot the number of recovered turtles, as in 5.3.
Figure 5.3: The count of recovered turtles over time for 50 ABM runs with the same input values.
Exercise 5.2 Which of these plots do you think would be the most useful in a public health setting?
In this lecture we have
In the workshop you will have the opportunity to look into ABMs in more detail, and to experiment with the parameters.