CompartmentedModel: Compartmented models of disease

class epydemic.CompartmentedModel

Bases: Process

The base class a compartmented model of disease, which represents a disease as a collection of discrete compartments with each compartment specifying some facet of the disease’s progression. Nodes transition between compartments with some probability, so the disease’s progression forms a stochastic process in which nodes typically move through several compartments according to the probabilities defined.

When run, a compartmented model generates results consisting of the size of each compartment at the end of the experiment. This can be changed by overriding the results() method.

Compartmented models are designed so that their specification is independent of the process dynamics used to simulate them: they can be run in discrete time using synchronous dynamics, or in continuous time using stochastic dynamics.

CompartmentedModel is an abstract class that must be sub-classed to define actual disease models. epydemic provides implementations of the three “reference” compartmented models, SIR, SIS, and SEIR, as well as several variants of them: Hethcote [Het00] provides a survey of a huge range of others.

Model state variables

These are used as tags for attributes on nodes and edges that store the model state.

CompartmentedModel.COMPARTMENT: str = None

State variable holding a node’s compartment.

CompartmentedModel.OCCUPIED: str = None

State variable that’s True for occupied edges.

CompartmentedModel.T_OCCUPIED: str = None

State variable holding the occupation time of an edge.

CompartmentedModel.T_HITTING: str = None

State variable holding the infection time of a node.

Model setup

Immediately before being run, the model is set up by placing all the nodes into compartments. All edges are also marked as unoccupied.

CompartmentedModel.reset()

Reset the model ready to be built.

CompartmentedModel.build(params)

Build the process model. This should be overridden by sub-classes, and should create the various elements of the model.

Parameters:

params (Dict[str, Any]) – the model parameters

CompartmentedModel.setUp(params)

Set up the initial population of nodes into compartments.

Parameters:

params (Dict[str, Any]) – the simulation parameters

CompartmentedModel.initialCompartmentDistribution()

Return the initial distribution of nodes to compartments. The result should be a valid distribution, with probabilities summing to one. (A ValueError exception is raised if not.) The distribution is used by initialCompartments() to set the initial compartment of each node.

Return type:

List[Tuple[str, float]]

Returns:

a list of (compartment, probability) pairs

CompartmentedModel.initialCompartments()

Place each node in the network into its initial compartment. The default initialises the nodes into a random compartment according to the initial compartment distribution returned by initialCompartmentDistribution(). This method may be overridden to, for example, structure the initial population non-randomly.

CompartmentedModel.changeInitialCompartment(n, c)

Change the initial compartment of a node. This is called only from initialCompartments(), and by default simply calls changeCompartment(). Overriding this method changes the behaviour of assigning initial compartments independently of the behaviour of later changes.

Parameters:
  • n (Any) – the node

  • c (str) – the new compartment for the node

Building and querying the model

Building a model (within CompartmentedModel.build()) means specifying the various compartments, loci, and events, and their associated probabilities. The initial occupancy of compartments can be set to allow for random initialisation, and the occupancy of existing components changed to allow better sub-classing.

CompartmentedModel.addCompartment(c, p=0.0)

Add a compartment to the model. A node is assigned to the compartment initially with the given probability. The probabilities for all compartments in the model must sum to 1.

Parameters:
  • c (str) – the compartment name

  • p (float) – the initial occupancy probability (defaults to 0.0)

. automethod:: CompartmentedModel.changeCompartmentInitialOccupancy

CompartmentedModel.trackNodesInCompartment(c, name=None)

Add a locus tracking nodes in a given compartment.

Parameters:
  • c (str) – the compartment to track

  • name (Optional[str]) – (optional) the name of the locus (defaults to the compartment name)

Returns:

the locus used to track the nodes

CompartmentedModel.trackEdgesBetweenCompartments(l, r, name=None)

Add a locus to track edges with endpoint nodes in the given compartments.

Parameters:
  • l (str) – the compartment of the left node

  • r (str) – the compartment of the right node

  • name (Optional[str]) – (optional) the name of the locus (defaults to a combination of the two compartment names)

Returns:

the locus used to track the nodes

We can also query the model, which is especially useful within event functions and when generating results in CompartmentedModel.results()

CompartmentedModel.compartments()

Return the set of compartments for this model.

Return type:

List[str]

Returns:

the compartments

CompartmentedModel.compartment(c)

Return all the nodes currently in a particular compartment in a network. This works for all compartments, not just those that are loci for dynamics – but is a lot slower, so it’s better to create a locus is you’re going to access a compartment frequently.

Parameters:

c (str) – the compartment

Return type:

List[Any]

Returns:

a collection of nodes

Evolving the network

Events in compartmented models need an interface to change the compartment of nodes, to mark edges used in transmitting the epidemic, and to record the hitting time of nodes.

CompartmentedModel.setCompartment(n, c)

Set the compartment of a node. This assumes that the node doesn’t already have a compartment set, and so should be used only for initialising new nodes: in all other cases, use changeCompartment().

Parameters:
  • n (Any) – the node

  • c (str) – the new compartment for the node

CompartmentedModel.getCompartment(n)

Return the compartment of a node.

Parameters:

n (Any) – the node

Return type:

str

Returns:

its compartment

CompartmentedModel.changeCompartment(n, c)

Change the compartment of a node.

Parameters:
  • n (Any) – the node

  • c (str) – the new compartment for the node

CompartmentedModel.markOccupied(e, t, firstOnly=True)

Mark the given edge as having been occupied by the dynamics, i.e., to have been traversed in transmitting the disease, at time t. By default the time of first occupation is recorded: if firstOnly is False then subsequent occupations overwrite the ealier ones.

Parameters:
  • e (Tuple[Any, Any]) – the edge

  • t (float) – the simulation time at which it was occupied

  • firstOnly (bool) – (optional) only record the first occupation time (defaults to True)

CompartmentedModel.markHit(n, t, firstOnly=True)

Mark the node as “hit”, which happens when the epidemic first reaches the node. By default the first hitting time is recorded: if firstOnly is False then subsequent infections overwrite the ealier ones.

For SIR the hitting time is the time of infection; for SIS the time of first infection; for SEIR the time of exposure.

Parameters:
  • n (Any) – the node

  • t (float) – the simulation time

  • firstOnly (bool) – (optional) only record the first hitting time (defaults to True)

The network access interface of Process is extended with methods that understand the mappings between nodes, edges, and compartments.

CompartmentedModel.addNode(n, c=None, **kwds)

Add a node to the working network, adding it to the appropriate compartment if one is provided].

Parameters:
  • n (Any) – the new node

  • c (Optional[str]) – (optional) compartment for the node

  • kwds – (optional) node attributes

CompartmentedModel.removeNode(n)

Remove a node from the working network, updating any affected compartments.

Parameters:

n (Any) – the node

CompartmentedModel.addEdge(n, m, **kwds)

Add an edge between nodes, adding the edge to any appropriate compartments.

Parameters:
  • n (Any) – the start node

  • m (Any) – the end node

  • kwds – (optional) edge attributes

CompartmentedModel.removeEdge(n, m)

Remove an edge from the working network and from any compartments.

Parameters:
  • n (Any) – the start node

  • m (Any) – the end node

Generating results

The experiment needs to define a results dict to return when it completes.

CompartmentedModel.results()

Create a dict of experimental results for the experiment, consisting of the final sizes of all the compartments.

Return type:

Dict[str, Any]

Returns:

a dict of experimental results

CompartmentedModel.skeletonise()

Remove unoccupied edges from the network. This leaves the network consisting of only “occupied” edges that were used to transmit the infection between nodes, also known as the contact tree. Note that this process means that further dynamics over the network probably don’t make sense, unless you’re actually wanting to run on the residual network post-infection.

Return type:

Graph

Returns:

the network with unoccupied edges removed