Agent Based Model

Background

The agent based model implementation of SIR divides the population in three components — as in the continuous model — Susceptible, Infected, and Recovered. In the agent based model the component is represented as the Agent.state.

Each individual is represented as an agent and the state of each agent changes over time based on the interactions between agents:

Outline of core classes Agent and Model

Agent class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Agent(mesa.Agent):

    SUSCEPTIBLE = 0
    INFECTED = 1
    RECOVERED = 2

    def __init__(self, model):
        super().__init__(model)

    def get_neighborhood(self): ...

    def step(self): ...

The Model class

The Model class stores the model parameters, the model geometry (space/grid), and the agents in the model.

The basic structure of this class is

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Model(mesa.Model):

    def __init__(self, seed=None):
        super().__init__(seed=seed)

        # store model parameters

        # create the model space/grid

        # create agents in the model

        # setup data collection

        # start simulation

    def step(self): ...   

Implementing the SIR Model

Agent class

The get_neighborhood method:

The step method has the following rules:

We could implement these rules fully, but instead we will implement them step by step and examine progress.

The Model class

This is implemented along similar lines to the Fire Model or the Schelling Model:

In Model.__init__:

In Model.step:

Visualisation

To start, the function draw_model is near identical to the Schelling Model function. use colours and labels:

1
2
    colors = ['green', 'red', 'yellow']
    labels = ['Susceptible', 'Infected', 'Recovered']

Then creating a model and displaying it using

1
2
3
model = Model(20, 10, seed=666)
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(6,2))
draw_model(model, ax)

should result in the following

This is OK, but what happens when multiple agents are in the same grid location? How can we see multiple agents since we will only see the last one drawn.

There are a number of fixes for this. The easiest of these is to draw smaller agents and give each agent a random offset (from the centre). This works, but we want to be careful of two things:

There is a solution to both of these issues:

1
    self.rng = default_rng(666)
1
    self.offset = model.rng.uniform(0.2, 0.8, size=2)
1
    pos = agent.pos + np.array([0.5,0.5])

to

1
    pos = agent.pos + agent.offset

This results in the following

Implementing Agent update rules in separate versions

Version 1 — INFECTED agent movement

Add movement to the agent that is INFECTED only. Use grid method move_agent.

By moving just the single INFECTED agent it is easier to verify that the correct behaviour is implemented.

TEST: When you run simulation only the INFECTED agent show move and only move from grid location to neighbouring grid location.

Version 2 — all agent movement

Now modify the agent.step method so that all agents move.

TEST: Now all agents should be moving. Lower density value so easier to track each agent to verify movement.

Version 3 — disease spread

When updating an INFECTED agent we need to see if they infect any SUSCEPTIBLE agents who are sharing their current grid location. To do this:

TEST: Now infection should spread as agents move around the grid.

Version 4 — recover from disease

An infected agent recovers with probability pr_recover, changing state from INFECTED to RECOVERED.

TEST: Now infection should spread but over time the infected are replaced by recovered.

NOTE: Finally check the order of your actions in agent.step we want the move to be the last action carried out.

Data Collection

Next add the data collection (similar to Fire Model and Schelling Model). And generate plots similar to the fire model to investigate the impact of the model parameters pr_infect and pr_recover. These parameters play a similar role to the Fire model parameters pr_spread and pr_burnout, and play a similar role to the continuous SIR model parameters beta and gamma.

Task 2

Generate generate plots similar to the fire model to investigate the impact of the model parameters.

Task 3

Modify the model so that it includes state DEAD. This gives use the SIRD model and is implemented using:

Task 4

One advantage of the agent based model approach for disease spread is that it is easy to add effects of social distancing. One approach is to add another parameter, say pr_isolate, which when state is INFECTED the agent does not move with probability pr_isolate. This probability check is applied inside the probability check self.random.random()<self.model.pr_move.

Then using data collector and batch runner generate plots to show the impact of pr_isolate.