Implementation details of epiworldR

George Vega Yon

Derek Meyer

2023-06-20

Introduction

The following vignette provides detailed information about the implementation of epiworldR. The package is a wrapper of the C++ package epiworld, a framework for building agent-based models.1

General flow of the models

The core function of epiworldR is the run() function. This function executes the model and saves the results in a database part of the underlying C++ object. The package implements a discrete-time ABM, meaning the model is executed in discrete steps (e.g., days). The run() function executes the following steps:

  1. The model is reset(), which involves: (a) resetting the agents, or if available, restoring the population backup2, (b) resetting the database, (c) distributing viruses and tools, (d) and setting the initial state of agents. All these steps fixing current_date = 0.
  1. The model’s state is recorded in the database, and the current_date is incremented by 1.

  2. After resetting the model, we start an iterative process repeating the following steps:

    1. The state of each agent is updated. States are updated according to their corresponding update_state function.

      Since the model is discrete-time, state changes are stored as promises, meaning that agents’ states are not updated immediately. Instead, the state is updated at the end of the updates. This is done to avoid updating the state of an agent and then using the updated state to update the state of another agent. For example, if agent \(i\) infects agent \(j\), then agent \(j\) should not be able to infect agent \(i\) in the same step.

    2. Once the update schedule is laid out, the changes are made effective, so, for instance, individuals who became infected during the update will start the next step in the infected state.

    3. Global actions are executed. These could also change agents’ states, so just like in the previous step, these changes are stored as promises and made effective once all actions have been evaluated.

    4. The model’s state is recorded in the database, and the current_date is incremented by 1.

    5. The model checks whether the simulation should stop. If the simulation should stop, the model stops. Otherwise, the model goes back to step a.

Other steps included in epiworld but not in epiworldR are the network rewiring and mutation of viruses. These will be implemented in future versions of epiworldR.

Computing probabilities

Transmission probability

Generally, epiworldR assumes that at each step of the simulation, susceptible agents can acquire the disease from at most one infected agent. The probability of transmission from \(i\) to \(j\) is given by the following formula:

\[ P(i\to j| \mbox{at most one}) = \frac{p_{ij} \times \prod_{k\neq i}\left(1 - p_{kj}\right)}{\prod_k\left(1 - p_{kj}\right) + \sum_k p_{kj} \times \prod_{l\neq k}\left(1 - p_{lj}\right)} \]

The adjusted probabilities \(p_{ij}\) are computed as a function of \(i\), \(j\), and the virus. The following section describes how these probabilities are computed.

Adjusted probabilities

Viruses and tools provide a way to adjust how agents move between states. Viruses in epiworldR contain various baseline probabilities used across models, including transmission, recovery, and death. On the other hand, tools alter these probabilities by reducing/increasing them. Furthermore, tools alter agents’ susceptibility, infectiousness, recovery, and death probabilities. Currently, tools alter these probabilities by a constant factor,

\[ p_{ij} = p_{v} \times \left(1 - factor_{host}\right) \times \left(1 - factor_{target}\right) \]

Where \(p_{v}\) is the raw transmission probability of the virus \(v\), and \(factor_{t}\) are the increasing/reducing factors tools have over the process. For example, if p_v was 0.9, the host was wearing a mask, so \(factor_{\mbox{mask host}} = 0.3\) and the target was vaccinated, so \(factor_{\mbox{vaccinated target}} = 0.5\), then the adjusted probability \(p_{ij}\) would be \(0.9 \times (1 - 0.3) \times (1 - 0.5) = 0.27\).

When agents have more than one tool, factors are combined as follows:

\[ factor_{agent} = 1 - \prod_{t\in tools_{agent}}\left(1 - factor_{t}\right) \]

Therefore, for example, a vaccinated agent wearing a mask would have a factor of \(1 - (1 - 0.30) \times (1 - 0.5) = 0.65\). The adjusted probabilities principle also applies to recovery rates in the SIR and SEIR models.

Transmission in connected models3

The “connected” models provide a version where agents live in a fully connected network. This means that each agent can infect any other agent, making this version similar to typical compartmental models. In these models, the transmission probability depends on the contact rate. For each susceptible agent, the transmission process is simulated as follows:

  1. The number of contacts \(c\) is drawn from a binomial distribution with parameters \(n\) and \(p\), where \(n\) is the number of agents and \(p =\)contact_rate\(/ n\).

  2. Then, \(c\) agents are randomly selected from the population. Transmission can then occur from any of these agents to the susceptible agent.

  3. The probability of transmission from each of the \(c\) agents is calculated as described in the previous section.


  1. The C++ package is available at https://github.com/UofUEpiBio/epiworld.↩︎

  2. Population backups are created on the fly the first time the model is run. Generally, backups are relevant for undoing changes in the network structure. Although epiworld (C++) provides a way to change network structure, the current version of epiworldR does not.↩︎

  3. The following section applies to the ModelSIRCONN and ModelSEIRCONN models. The ModelSIR and ModelSEIR models are similar but do not use a connected network.↩︎