# EoN module¶

## Introduction¶

**EoN** (Epidemics on Networks) is a Python package for the simulation of
epidemics on networks and solving ODE models of disease spread.

The algorithms are based on the book

Mathematics of Epidemics on Networks: from Exact to Approximate Models by Kiss, Miller & Simon

Please cite the book if using these algorithms

For simulations, we assume that input networks are **NetworkX**
graphs; see https://networkx.github.io/

**EoN** consists of several sets of algorithms.

- The first deals with
**stochastic simulation of epidemics on networks**. The most significant of these are fast_SIS and fast_SIR which usually outperform Gillespie algorithms (also included). These algorithms are discussed in more detail in the appendix of the book. - A significant extension of these simulations is a set of tools
designed to
**visualize and animate simulated epidemics**, and generally help investigate a given stochastic simulation. - Another set deals with
**numerical solution of systems of analytic equations**derived in the book. For these it is possible to either provide the degree distribution, or simply use a network and let the code determine the degree distribution. - There are a few additional algorithms which are not described in the book, but which we believe will be useful. Most notably, related to visualization and generation of animations.

Distributed under MIT license. See `license.txt`

for full details.

## Simulation Toolkit¶

This submodule deals with epidemic simulation. We start with a quick list of the functions with links to the individual functions. A brief description is below.

### Quick list¶

`fast_SIR` (G, tau, gamma[, initial_infecteds, …]) |
fast SIR simulation for exponentially distributed infection and recovery times |

`fast_nonMarkov_SIR` (G[, trans_time_fxn, …]) |
A modification of the algorithm in figure A.3 of Kiss, Miller, & Simon to allow for user-defined rules governing time of transmission. |

`fast_SIS` (G, tau, gamma[, initial_infecteds, …]) |
Fast SIS simulations for epidemics on weighted or unweighted networks, allowing edge and node weights to scale the transmission and recovery rates. |

`fast_nonMarkov_SIS` (G[, trans_time_fxn, …]) |
Similar to fast_nonMarkov_SIR. |

`Gillespie_SIR` (G, tau, gamma[, …]) |
Performs SIR simulations for epidemics. |

`Gillespie_SIS` (G, tau, gamma[, …]) |
Performs SIS simulations for epidemics on networks with or without weighted edges. |

`Gillespie_Arbitrary` (G, …[, tmin, tmax, …]) |
Performs simulations for epidemics, allowing more flexibility than SIR/SIS. |

`basic_discrete_SIR` (G, p[, …]) |
Performs simple discrete SIR simulation assuming constant transmission probability p. |

`basic_discrete_SIS` (G, p[, …]) |
Does a simulation of the simple case of all nodes transmitting with probability p independently to each susceptible neighbor and then recovering. |

`discrete_SIR` (G[, test_transmission, args, …]) |
Simulates an SIR epidemic on G in discrete time, allowing user-specified transmission rules |

`percolate_network` (G, p) |
Performs percolation on a network G with each edge persisting with probability p |

`directed_percolate_network` (G, tau, gamma[, …]) |
performs directed percolation, assuming that transmission and recovery are Markovian |

`nonMarkov_directed_percolate_network_with_timing` (G, …) |
Performs directed percolation on G for user-specified transmission time and recovery time distributions. |

`nonMarkov_directed_percolate_network` (G, xi, …) |
performs directed percolation on a network following user-specified rules. |

`estimate_SIR_prob_size` (G, p) |
Uses percolation to estimate the probability and size of epidemics assuming constant transmission probability p |

`estimate_SIR_prob_size_from_dir_perc` (H) |
Estimates probability and size of SIR epidemics for an input network after directed percolation |

`estimate_directed_SIR_prob_size` (G, tau, gamma) |
Predicts probability and attack rate assuming continuous-time Markovian SIR disease on network G |

`estimate_nonMarkov_SIR_prob_size_with_timing` (G, …) |
estimates probability and size for user-input transmission and recovery time functions. |

`estimate_nonMarkov_SIR_prob_size` (G, xi, …) |
Predicts epidemic probability and size using nonMarkov_directed_percolate_network. |

`get_infected_nodes` (G, tau, gamma[, …]) |
Finds all eventually infected nodes in an SIR simulation, through a percolation approach |

`percolation_based_discrete_SIR` (G, p[, …]) |
perfoms a simple SIR epidemic but using percolation as the underlying method. |

### Short descriptions¶

Event-based algorithms:

These algorithms use an efficient approach to simulate epidemics. fast_SIR and fast_SIS assume constant transmission and recovery rates, while fast_nonMarkov_SIR and fast_nonMarkov_SIS allow the user to specify more detailed rules for transmission.

**fast_SIR****fast_nonMarkov_SIR****fast_SIS****fast_nonMarkov_SIS**

Gillespie Algorithms

These algorithms simulate epidemics assuming constant transmission and recovery rates. They are commonly used, but in many cases are slower than the event driven methods. I do not see evidence that they are ever significantly faster. It is not very practical to get away from the constant rate assumptions so I prefer to avoid them. However, the Gillespie_Arbitrary allows the user to do SEIR, SIRS, or any of a number of other more exotic scenarios that are not currently in the event-driven code.

**Gillespie_SIR****Gillespie_SIS****Gillespie_Arbitrary**

Discrete-time algorithms

These algirthms are appropriate for where we separate infection into generations. We assume infection lasts a single time step. The basic_* algorithms assume that transmission occurs with probability p for all edges. In contrast discrete_SIR allows for very general user-specified transmission rules.

**basic_discrete_SIR****basic_discrete_SIS****discrete_SIR**

Percolation-based approaches

There is a close relation between percolation and SIR disease which is described in Chapter 6 of the book. Many of these algorithms are related to demonstrating the equivalence as outlined in the book, and are not really the most efficient way to simulate an epidemic. However, these algorithms will be useful for estimating probability and size of epidemics.

**percolate_network**(undirected percolation corresponding to fixed transmission probability)**directed_percolate_network**(directed percolation corresponding to constant transmission and recovery rates)**nonMarkov_directed_percolate_network_with_timing**(uses user-generated duration and transmission time distributions)**nonMarkov_directed_percolate_network**(uses user-generated transmission rules)**estimate_SIR_prob_size**(estimates prob/size from an undirected percolated network - only appropriate if constant p)**estimate_SIR_prob_size_from_dir_perc**(estimates epi prob and size from a given percolated network)**estimate_directed_SIR_prob_size**(estimates based on constant transmission and recovery rates)**estimate_nonMarkov_SIR_prob_size_with_timing**(estimates based on user-generated transmission and recovery time distributions)**estimate_nonMarkov_SIR_prob_size**(estimates based on user-generated transmission rules)**get_infected_nodes**(simulates epidemic and returns final infected nodes)**percolation_based_discrete_SIR**

## Simulation Investigation toolkit¶

We can study simulations in detail through the Simulation_Investigation class. This includes automated generation of animations.

This is particularly useful if we want to look at time series or at animations of the network as the disease spreads.

Some examples are provided.

### Quick List¶

`display` (time[, ts_plots, ts_list, nodelist, …]) |
Provides a plot of the network at a specific time and (optionally) some of the time series |

`animate` ([frame_times, ts_plots, ts_list, …]) |
As in display, but this produces an animation. |

`node_history` (node) |
returns the history of a node. |

`node_status` (node, time) |
returns the status of a given node at a given time. |

`get_statuses` ([nodelist, time]) |
returns the status of nodes at a given time. |

`summary` ([nodelist]) |
Provides the population-scale summary of the dynamics: t, S, I, and R |

`t` () |
Returns the times of events Generally better to get these all through summary() |

`S` () |
Returns the number susceptible at each time. |

`I` () |
Returns the number infected at each time Generally better to get these all through summary() |

`R` () |
Returns the number recovered at each time Generally better to get these all through summary() |

`transmissions` () |
Returns a list of tuples (t,u,v) stating that node u infected node v at time t. |

`transmission_tree` () |
Produces a MultiDigraph whose edges correspond to transmission events. |

`add_timeseries` (t, S, I[, R, colordict, label]) |
This allows us to include some additional timeseries for comparision with the simulation. |

`update_ts_kwargs` (ts, **kwargs) |
Allows us to change some of the matplotlib key word arguments for a timeseries object |

`update_ts_label` (ts, label) |
updates the label for time series plots |

`update_ts_colordict` (ts, colordict) |
updates the colordict for time series plots |

`sim_update_kwargs` (**kwargs) |
Allows us to change some of the matplotlib key word arguments for the simulation. |

`sim_update_label` (label) |
updates the label for the simulation in the time series plots |

`sim_update_colordict` (colordict) |
updates the colordict for the simulation |

`set_pos` (pos) |
Set the position of the nodes. |

### Short description¶

Visualizations

There are two main commands for visualization. We can either produce a snapshot at a given time, or produce an animation. In either case we can optionally include plots of S, I, (and R) as functions of time.

**display**(allows us to plot a graph at a specific time- point, and to optionally include the calculated time series)

**animate**(allows us to plot a graph at many time points- We can create a visualization such as mp4, or save each individual frame of an animation. The time series are optional.

Data about simulation

Often we’ll want to be able to check what happened to specific nodes in the network, or we’ll want to know what the time history of the outbreak looked like

**node_history****node_status**returns the status of a node at a given time**get_statuses**returns the status of a collection of nodes at- a given time (in a dict).

**summary**returns t, S, I, (and if SIR R) for the population (or a subset of the population)**t****S****I****R****transmissions**returns a list of 3-tuples of the form (t, u, v) stating that u transmitted to v at time t.**transmission_tree**returns a MultiDiGraph where an edge from u to v with attribute time = t means that u transmitted to v at time t. (For SIR this is a tree or a forest)

Details for plotting

The remaining commands are to do with the specifics of how the plots appear

**update_ts_kwargs****update_ts_label****update_ts_colordict****sim_update_kwargs****sim_update_label****sim_update_colordict****set_pos**

## Analytic Toolkit¶

This submodule deals with solution to systems of equations appearing in the book. The majority of these also have a version that take a graph G. There are additional functions that calculate properties which these need.

### Quick list¶

`SIS_individual_based` (G, tau, gamma[, rho, …]) |
Encodes System (3.7) of Kiss, Miller, & Simon. |

`SIS_individual_based_pure_IC` (G, tau, gamma, …) |
Encodes System (3.7) of Kiss, Miller, & Simon. |

`SIS_pair_based` (G, tau, gamma[, rho, …]) |
Encodes System (3.26) of Kiss, Miller, & Simon. |

`SIS_pair_based_pure_IC` (G, tau, gamma, …[, …]) |
Encodes System (3.26) of Kiss, Miller, & Simon, using a “pure initial condition”. |

`SIR_individual_based` (G, tau, gamma[, rho, …]) |
Encodes System (3.30) of Kiss, Miller, & Simon. |

`SIR_individual_based_pure_IC` (G, tau, gamma, …) |
Encodes System (3.30) of Kiss, Miller, & Simon. |

`SIR_pair_based` (G, tau, gamma[, rho, …]) |
Encodes System (3.39) of Kiss, Miller, & Simon. |

`SIR_pair_based_pure_IC` (G, tau, gamma, …[, …]) |
Encodes System (3.39) of Kiss, Miller, & Simon, using a “pure initial condition”. |

`SIS_homogeneous_meanfield` (S0, I0, n, tau, gamma) |
Encodes System (4.8) of Kiss, Miller, & Simon. |

`SIR_homogeneous_meanfield` (S0, I0, R0, n, …) |
Encodes System (4.9) of Kiss, Miller, & Simon. |

`SIS_homogeneous_pairwise` (S0, I0, SI0, SS0, …) |
Encodes System (4.10) of Kiss, Miller, & Simon. |

`SIS_homogeneous_pairwise_from_graph` (G, tau, …) |
Calls SIS_homogeneous_pairwise after calculating S0, I0, SI0, SS0, n based on the graph G and initial fraction infected rho. |

`SIR_homogeneous_pairwise` (S0, I0, R0, SI0, …) |
Encodes System (4.11) of Kiss, Miller, & Simon. |

`SIR_homogeneous_pairwise_from_graph` (G, tau, …) |
Calls SIR_homogeneous_pairwise after calculating S0, I0, R0, SI0, SS0, n, based on the graph G and initial fraction infected rho. |

`SIS_heterogeneous_meanfield` (Sk0, Ik0, tau, gamma) |
Encodes System (5.10) of Kiss, Miller, & Simon. |

`SIS_heterogeneous_meanfield_from_graph` (G, …) |
Calls SIS_heterogeneous_meanfield after calculating Sk0, Ik0 based on the graph G and random fraction infected rho. |

`SIR_heterogeneous_meanfield` (Sk0, Ik0, Rk0, …) |
Encodes System (5.11) of Kiss, Miller, & Simon. |

`SIR_heterogeneous_meanfield_from_graph` (G, …) |
Calls SIR_heterogeneous_meanfield after calculating Sk0, Ik0, Rk0 based on a graph G and initial fraction infected rho. |

`SIS_heterogeneous_pairwise` (Sk0, Ik0, SkSl0, …) |
Encodes System (5.13) of Kiss, Miller, & Simon. |

`SIS_heterogeneous_pairwise_from_graph` (G, …) |
Calls SIS_heterogeneous_pairwise after calculating Sk0, Ik0, SkSl0, SkIl0, IkIl0 from a graph G and initial fraction infected rho. |

`SIR_heterogeneous_pairwise` (Sk0, Ik0, Rk0, …) |
Encodes System (5.15) of Kiss, Miller, & Simon. |

`SIR_heterogeneous_pairwise_from_graph` (G, …) |
Calls SIR_heterogeneous_pairwise after calculating Sk0, Ik0, Rk0, SkSl0, SkIl0 from a graph G and initial fraction infected rho. |

`SIS_compact_pairwise` (Sk0, Ik0, SI0, SS0, …) |
Encodes system (5.18) of Kiss, Miller, & Simon. |

`SIS_compact_pairwise_from_graph` (G, tau, gamma) |
Calls SIS_compact_pairwise after calculating Sk0, Ik0, SI0, SS0, II0 from the graph G and initial fraction infected rho. |

`SIR_compact_pairwise` (Sk0, I0, R0, SS0, SI0, …) |
Encodes system (5.19) of Kiss, Miller, & Simon. |

`SIR_compact_pairwise_from_graph` (G, tau, gamma) |
Calls SIR_compact_pairwise after calculating Sk0, I0, R0, SS0, SI0 from the graph G and initial fraction infected rho. |

`SIS_super_compact_pairwise` (S0, I0, SS0, SI0, …) |
Encodes system (5.20) of Kiss, Miller, & Simon. |

`SIS_super_compact_pairwise_from_graph` (G, …) |
Calls SIS_super_compact_pairwise after calculating S0, I0, SS0, SI0, II0 from the graph G and initial fraction infected rho |

`SIR_super_compact_pairwise` (R0, SS0, SI0, N, …) |
Encodes system (5.22) of Kiss, Miller, & Simon. |

`SIR_super_compact_pairwise_from_graph` (G, …) |
Calls SIR_super_compact_pairwise after calculating R0, SS0, SI0 from the graph G and initial fraction infected rho |

`SIS_effective_degree` (Ssi0, Isi0, tau, gamma) |
Encodes system (5.36) of Kiss, Miller, & Simon. Please cite the |

`SIS_effective_degree_from_graph` (G, tau, gamma) |
Calls SIS_effective_degree after calculating Ssi0, Isi0 from the graph G and initialf fraction infected rho. |

`SIR_effective_degree` (S_si0, I0, R0, tau, gamma) |
Encodes system (5.38) of Kiss, Miller, & Simon. |

`SIR_effective_degree_from_graph` (G, tau, gamma) |
Calls SIR_effective_degree after calculating S_si0, I0, R0 from the graph G and initial fraction infected rho |

`SIR_compact_effective_degree` (Skappa0, I0, …) |
Encodes system (5.43) of Kiss, Miller, & Simon. |

`SIR_compact_effective_degree_from_graph` (G, …) |
Calls SIR_compact_effective_degree after calculating Skappa0, I0, R0, SI0 from the graph G and initial fraction infected rho. |

`SIS_compact_effective_degree` (Sk0, Ik0, SI0, …) |
Encodes system (5.44) of Kiss, Miller, & Simon. |

`SIS_compact_effective_degree_from_graph` (G, …) |
because the SIS compact effective degree model is identical to the compact pairwise model, simply calls SIS_compact_pairwise_from_graph |

`Epi_Prob_discrete` (Pk, p[, number_its]) |
Encodes System (6.2) of Kiss, Miller, & Simon. |

`Epi_Prob_cts_time` (Pk, tau, gamma[, umin, …]) |
Encodes System (6.3) of Kiss, Miller, & Simon. |

`Epi_Prob_non_Markovian` (Pk, Pxidxi, po[, …]) |
Encodes system (6.5) of Kiss, Miller, & Simon. |

`Attack_rate_discrete` (Pk, p[, rho, Sk0, …]) |
Encodes systems (6.6) and (6.10) of Kiss, Miller, & Simon. |

`Attack_rate_discrete_from_graph` (G, p[, …]) |
if initial_infecteds and initial_recovereds is defined, then it will find Sk0, phiS0, and phiR0 and then call Attack_rate_discrete. |

`Attack_rate_cts_time` (Pk, tau, gamma[, …]) |
Encodes system (6.7) of Kiss, Miller, & Simon. |

`Attack_rate_cts_time_from_graph` (G, tau, gamma) |
Given a graph, predicts the attack rate for Configuration Model networks with the given degree distribution. |

`Attack_rate_non_Markovian` (Pk, Pzetadzeta, pi) |
Encodes system (6.8) of Kiss, Miller, & Simon. |

`Attack_rate_discrete` (Pk, p[, rho, Sk0, …]) |
Encodes systems (6.6) and (6.10) of Kiss, Miller, & Simon. |

`EBCM_discrete` (N, psihat, psihatPrime, p, phiS0) |
Encodes system (6.11) of Kiss, Miller, & Simon. |

`EBCM_discrete_from_graph` (G, p[, …]) |
Takes a given graph, finds the degree distribution (from which it gets psi), assumes a constant proportion of the population is infected at time 0, and then uses the discrete EBCM model. |

`EBCM` (N, psihat, psihatPrime, tau, gamma, phiS0) |
Encodes system (6.12) of Kiss, Miller, & Simon. |

`EBCM_uniform_introduction` (N, psi, psiPrime, …) |
Handles the case that the disease is introduced uniformly as opposed to depending on degree. |

`EBCM_from_graph` (G, tau, gamma[, …]) |
Given network G and rho, calculates N, psihat, psihatPrime, and calls EBCM. |

`EBCM_pref_mix` (N, Pk, Pnk, tau, gamma[, rho, …]) |
Encodes the system derived in exercise 6.21 of Kiss, Miller, & Simon. |

`EBCM_pref_mix_from_graph` (G, tau, gamma[, …]) |
Takes a given graph, finds degree correlations, and calls EBCM_pref_mix |

`EBCM_pref_mix_discrete` (N, Pk, Pnk, p[, rho, …]) |
Encodes the discrete version of exercise 6.21 of Kiss, Miller, & Simon. |

`EBCM_pref_mix_discrete_from_graph` (G, p[, …]) |
Takes a given graph, finds degree correlations, and calls EBCM_pref_mix_discrete |

`get_Pk` (G) |
Used in several places so that we can input a graph and then we can call the methods that depend on the degree distribution |

`get_PGF` (Pk) |
Given a degree distribution (as a dict), returns the probability generating function |

`get_PGFPrime` (Pk) |
Given a degree distribution (as a dict) returns the function \(\psi'(x)\) |

`get_PGFDPrime` (Pk) |
Given a degree distribution (as a dict) returns the function \(\psi''(x)\) |

`estimate_R0` (G[, tau, gamma, transmissibility]) |
provides the estimate of the reproductive number R_0 = T <K^2-K>/<K> |

### Short description¶

These come from the book. The numbers given below are the equation numbers in the book.

Chapter 3

This chapter deals with models assuming we know the full network structure.

System (3.7): SIS model: Closes equations by assuming that knowing the probabilities for nodes to have each status is enough to predict impact of their interactions (ignores temporal correlation between statuses of neighbors).

**SIS_individual_based****SIS_individual_based_pure_IC**

The pure_IC version assumes that some nodes begin infected with probability 1 and the others are susceptible with probability 1.

System (3.26): assumes that tracking pair correlations is enough. Many more equations than individual-based.

**SIS_pair_based****SIS_pair_based_pure_IC**

System (3.30) SIR equivalent of corresponding SIS model.

**SIR_individual_based****SIR_individual_based_pure_IC**

System (3.39) SIR equivalent of corresponding SIS model.

**SIR_pair_based****SIR_pair_based_pure_IC**

Chapter 4

This chapter attempts to approximate the exact dynamics by ignoring heterogeneity in degree.

System (4.8) Assumes dynamics determined by average number of contacts and number of nodes of each status.

**SIS_homogeneous_meanfield**

System (4.9) As for SIS.

**SIR_homogeneous_meanfield**

System (4.10) Assumes dynamics are determined by the average number of contacts, nodes of each status, and pairs of each status.

**SIS_homogeneous_pairwise****SIS_homogeneous_pairwise_from_graph**(reads properties from input graph)

System (4.11)

**SIR_homogeneous_pairwise****SIR_homogeneous_pairwise_from_graph**

Chapter 5

This chapter attempts to approximate the exact dynamics and incorporates heterogeneity in degree (at the cost of more complex models)

System (5.10)

**SIS_heterogeneous_meanfield****SIS_heterogeneous_meanfield_from_graph**

System (5.11)

**SIR_heterogeneous_meanfield****SIR_heterogeneous_meanfield_from_graph**

System (5.13)

**SIS_heterogeneous_pairwise****SIS_heterogeneous_pairwise_from_graph**

System (5.15)

**SIR_heterogeneous_pairwise****SIR_heterogeneous_pairwise_from_graph**

System (5.18)

**SIS_compact_pairwise****SIS_compact_pairwise_from_graph**

System (5.19)

**SIR_compact_pairwise****SIR_compact_pairwise_from_graph**

System (5.20)

**SIS_super_compact_pairwise****SIS_super_compact_pairwise_from_graph**

System (5.22)

**SIR_super_compact_pairwise****SIR_super_compact_pairwise_from_graph**

System (5.36)

**SIS_effective_degree****SIS_effective_degree_from_graph**

System (5.38)

**SIR_effective_degree****SIR_effective_degree_from_graph**

System (5.43)

**SIR_compact_effective_degree****SIR_compact_effective_degree_from_graph**

System (5.44)

**SIS_compact_effective_degree****SIS_compact_effective_degree_from_graph**

Chapter 6

This chapter uses percolation-based techniques to explore epidemic properties.

System (6.2) Given a degree distribution and uniform transmission probability, find epidemic probability.

**Epi_Prob_discrete**

System (6.3) As in 6.2, but assuming constant transmission and recovery rates.

**Epi_Prob_cts_time**

System (6.5) As in 6.2, but with user-specified transmission rules

**Epi_Prob_non_Markovian**

System (6.6) Given a degree distribution, initial proportion infected, and transmission probability, find attack rate. See also System (6.10).

**Attack_rate_discrete****Attack_rate_discrete_from_graph**

System (6.7) as in 6.6, but assuming constant transmission and recovery rates.

**Attack_rate_cts_time****Attack_rate_cts_time_from_graph**

System (6.8) As in 6.6, but with user-specified transmission rules

**Attack_rate_non_Markovian**

System (6.10) See code for System (6.6).

System (6.11) Perform EBCM calculations for discrete-time.

**EBCM_discrete****EBCM_discrete_from_graph**

System (6.12) Perform EBCM calculations for continuous-time.

**EBCM**allows initial status to be degree dependant.**EBCM_uniform_introduction**assumes disease introduced at t=0 uniformly at random**EBCM_from_graph**assumes disease introduced at t=0 uniformly at random in network of given degree distribution.

- exercise 6.21 Deals with the EBCM model assuming preferential mixing.
**EBCM_pref_mix****EBCM_pref_mix_from_graph****EBCM_pref_mix_discrete****EBCM_pref_mix_discrete_from_graph**

## Auxiliary Functions¶

We have a few additional functions which are of value.

### Quick List¶

`get_time_shift` (times, L, threshold) |
Identifies the first time at which list/array L crosses a threshold. |

`subsample` (report_times, times, status1[, …]) |
Given |

### Short Description¶

get_time_shift(allows us to shift plots to eliminate the effect of early-time stochasticity)subsample(allows us to take output given at a stochastic set of times and get output at given times - particularly useful to allow for averaging multiple simulations)