---
title: "Implementation details of epiworldR"
author:
  - George Vega Yon
  - Derek Meyer
date: "2023-06-20"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Implementation details of epiworldR}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

# 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.[^where-cpp]

[^where-cpp]: The C++ package is available at [https://github.com/UofUEpiBio/epiworld](https://github.com/UofUEpiBio/epiworld).

# 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 backup[^backup], (b) resetting the database, (c) distributing viruses and tools, (d) and setting the initial state of agents. All these steps fixing `current_date = 0`.

[^backup]: 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 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:

    a.  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.

    b. 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.

    c. 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.

    d. The model's state is recorded in the database, and the `current_date` is incremented by 1.

    e. 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 models[^models]

[^models]: The following section applies to the `ModelSIRCONN` and `ModelSEIRCONN` models. The `ModelSIR` and `ModelSEIR` models are similar but do not use a connected network.

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.
