Model#

class epiworldpy.Model(self: epiworldpy._core.Model)#

Bases: pybind11_object

An agent-based model: a population, its states, viruses, and tools.

Model is the base class of every model in epiworldpy.epimodels. Those come with their states, parameters, and virus already set up, so a typical workflow only needs a population and a call to run():

from epiworldpy import epimodels

covid = epimodels.ModelSIR("COVID-19", prevalence=0.01,
                           transmission_rate=0.9, recovery_rate=0.1)
covid.agents_smallworld(n=1000, k=5, d=False, p=0.01)
covid.run(ndays=100, seed=1912)
covid.get_db().get_hist_total()

An empty Model() can be used to build a custom model with add_state(), add_virus(), and add_tool().

Create an empty model with no states, agents, viruses, or tools.

Methods

add_edge

Tie two agents.

add_entity

Add an entity to the model.

add_globalevent

Add a global event: a function called at the end of a simulation day.

add_param

Add a named parameter, or get it if it already exists.

add_state

Overloaded function.

add_tool

Add a tool to the model.

add_virus

Add a virus to the model.

agents_bernoulli

Create the population as a Bernoulli (Erdos-Renyi) random graph.

agents_empty_graph

Create a population with no ties.

agents_from_edgelist

Create the population from an edge list.

agents_sbm

Create the population from a stochastic block model (SBM).

agents_smallworld

Create the population as a Watts-Strogatz small-world network.

get_agent

Get an agent by ID.

get_agents

Get the population.

get_agents_in_state

Get the agents currently in a state.

get_agents_states

Get the current state of every agent.

get_db

Get the database with the results of the last run.

get_elapsed

Get the time the simulations took.

get_entity

Get an entity by ID.

get_last_transmission_mode

Get the transmission mode used in the most recent step.

get_n_entities

Get the number of entities in the model.

get_n_globalevents

Get the number of global events.

get_n_replicates

Get the number of replicates run so far.

get_n_states

Get the number of states.

get_n_tools

Get the number of tools in the model.

get_n_viruses

Get the number of viruses in the model.

get_name

Get the name of the model type (for example, "Susceptible-Infected-Recovered (SIR)").

get_ndays

Get the number of days the model was last run for.

get_param

Get the value of a named parameter.

get_rewire_prop

Get the proportion of ties rewired at each step.

get_sim_id

Get the ID of the current simulation.

get_states

Get the labels of the model's states.

get_transmission_kappa

Get the threshold used by the "auto" transmission mode.

get_transmission_mode

Get the transmission mode set with set_transmission_mode().

get_verbose

Check whether verbose output is on.

has_edge

Check whether two agents are tied.

has_globalevent

Check whether the model has a global event.

has_param

Check whether the model has a named parameter.

initial_states

Set the initial distribution of agents across states.

is_directed

Check whether the network is directed.

is_queuing_on

Check whether the queuing system is on.

make_save_run

Create a run_multiple() callback that writes each run's results to files.

par

Get the value of a named parameter (alias of get_param()).

params

Get the model's parameters.

print

Print a summary of the model and its last run.

print_state_codes

Print the index and label of each state.

queuing_off

Turn off the queuing system, so every agent is updated at every step.

queuing_on

Turn on the queuing system (the default).

reset

Reset the model to its initial state.

rewire

Rewire the network with the model's rewiring function, if it has one.

rm_edge

Remove the tie between two agents.

rm_globalevent

Remove a global event.

run

Run the model.

run_globalevents

Run the global events scheduled for today.

run_multiple

Run the model several times.

seed

Seed the model's random number generator.

set_name

Set the name of the model.

set_param

Set the value of a named parameter.

set_rewire_prop

Set the proportion of ties rewired at each step.

set_state_function

Overloaded function.

set_transmission_mode

Set how network transmission is computed.

size

Get the number of agents.

state_of

Get the index of a state from its label.

today

Get the current simulation day.

verbose_off

Turn off verbose output.

verbose_on

Turn on verbose output (progress bars and messages).

write_data

Write the results of the last run to files.

write_edgelist

Write the network to a file as an edge list.

add_edge(self: epiworldpy._core.Model, i: SupportsInt | SupportsIndex, j: SupportsInt | SupportsIndex) → bool#

Tie two agents.

Safe to call during a run, for example from a global event. Only works on undirected networks.

Parameters:
  • i (int) – ID of the first agent.

  • j (int) – ID of the second agent.

Returns:

True if the tie was created, False if the agents were already tied.

Return type:

bool

add_entity(self: epiworldpy._core.Model, entity: epiworldpy._core.Entity) → None#

Add an entity to the model.

Agents are assigned to the entity when the model is run (see Entity.set_distribution()).

Parameters:

entity (Entity) – The entity to add.

add_globalevent(self: epiworldpy._core.Model, fun: collections.abc.Callable[[epiworldpy._core.Model], None], name: str = 'global event', date: SupportsInt | SupportsIndex = -99) → None#

Add a global event: a function called at the end of a simulation day.

Global events can, for example, implement interventions that change the network (see add_edge()) or model parameters.

Parameters:
  • fun (callable) – Function fun(model) -> None.

  • name (str, default "global event") – Name of the event, used by rm_globalevent().

  • date (int, default -99) – Day on which to call fun. A negative value calls it every day.

add_param(self: epiworldpy._core.Model, initial_val: SupportsFloat | SupportsIndex, pname: str, overwrite: bool = False) → float#

Add a named parameter, or get it if it already exists.

Viruses and tools can read parameters by name (see, for example, Virus.set_prob_infecting()), so changing a parameter changes every object that uses it.

Parameters:
  • initial_val (float) – Value of the new parameter.

  • pname (str) – Name of the parameter. It cannot contain a colon.

  • overwrite (bool, default False) – If the parameter exists, whether to replace its value with initial_val.

Returns:

The parameter’s current value.

Return type:

float

add_state(*args, **kwargs)#

Overloaded function.

  1. add_state(self: epiworldpy._core.Model, lab: str, fun: epiworldpy._core.NativeUpdateFun) -> int

Add a state updated by a built-in epiworld function.

Parameters:
Returns:

Index of the new state.

Return type:

int

  1. add_state(self: epiworldpy._core.Model, lab: str, fun: collections.abc.Callable[[epiworldpy._core.Agent, epiworldpy._core.Model], None] = None) -> int

Add a state to the model.

Parameters:
  • lab (str) – Label of the new state.

  • fun (callable or None, default None) – Update function fun(agent, model) -> None called on every agent in this state at each step, or None for a state agents only leave through events (for example, recovery). See also UpdateFun for epiworld’s built-in update functions, which are much faster than Python callbacks.

Returns:

Index of the new state.

Return type:

int

add_tool(self: epiworldpy._core.Model, tool: epiworldpy._core.Tool) → None#

Add a tool to the model.

The model keeps a copy of tool and distributes it to agents when the model is run (see Tool.set_distribution()).

Parameters:

tool (Tool) – The tool to add.

add_virus(self: epiworldpy._core.Model, virus: epiworldpy._core.Virus) → None#

Add a virus to the model.

The model keeps a copy of virus and distributes it to agents when the model is run (see Virus.set_distribution()).

Parameters:

virus (Virus) – The virus to add.

agents_bernoulli(self: epiworldpy._core.Model, n: SupportsInt | SupportsIndex, p: SupportsFloat | SupportsIndex, d: bool = False) → epiworldpy._core.Model#

Create the population as a Bernoulli (Erdos-Renyi) random graph.

Parameters:
  • n (int) – Number of agents.

  • p (float) – Probability that any two agents are tied.

  • d (bool, default False) – Whether the network is directed.

Returns:

The model itself.

Return type:

Model

agents_empty_graph(self: epiworldpy._core.Model, n: SupportsInt | SupportsIndex = 1000) → None#

Create a population with no ties.

Useful for models that do not use a network, such as the *CONN and *Mixing models.

Parameters:

n (int, default 1000) – Number of agents.

agents_from_edgelist(self: epiworldpy._core.Model, source: collections.abc.Sequence[SupportsInt | SupportsIndex], target: collections.abc.Sequence[SupportsInt | SupportsIndex], size: SupportsInt | SupportsIndex, directed: bool) → None#

Create the population from an edge list.

Parameters:
  • source (list of int) – Source agent of each tie.

  • target (list of int) – Target agent of each tie, of the same length as source.

  • size (int) – Number of agents. Agent IDs must be in [0, size).

  • directed (bool) – Whether ties are directed. A directed tie source -> target makes target a neighbor of source only, so target can infect source but not the other way around.

agents_sbm(self: epiworldpy._core.Model, block_sizes: collections.abc.Sequence[SupportsInt | SupportsIndex], mixing_matrix: collections.abc.Sequence[SupportsFloat | SupportsIndex], row_major: bool = True) → epiworldpy._core.Model#

Create the population from a stochastic block model (SBM).

Parameters:
  • block_sizes (list of int) – Number of agents in each of the K blocks (groups).

  • mixing_matrix (list of float) – Flattened K x K matrix; entry (g, h) is the expected number of ties an agent in block g has with agents in block h, so the row sums are the expected degrees.

  • row_major (bool, default True) – Whether mixing_matrix is flattened by rows (NumPy’s default order="C") or by columns (order="F").

Returns:

The model itself.

Return type:

Model

agents_smallworld(self: epiworldpy._core.Model, n: SupportsInt | SupportsIndex, k: SupportsInt | SupportsIndex, d: bool, p: SupportsFloat | SupportsIndex) → epiworldpy._core.Model#

Create the population as a Watts-Strogatz small-world network.

Agents are first placed on a ring and tied to their k nearest neighbors; then a proportion p of the ties are rewired at random.

Parameters:
  • n (int) – Number of agents.

  • k (int) – Number of neighbors of each agent in the ring (half on each side if the network is undirected).

  • d (bool) – Whether the network is directed.

  • p (float) – Proportion of ties to rewire, between 0 and 1.

Returns:

The model itself.

Return type:

Model

get_agent(self: epiworldpy._core.Model, i: SupportsInt | SupportsIndex) → epiworldpy._core.Agent#

Get an agent by ID.

Parameters:

i (int) – ID of the agent.

Returns:

The agent.

Return type:

Agent

get_agents(self: epiworldpy._core.Model) → list[epiworldpy._core.Agent]#

Get the population.

Returns:

Every agent in the model, in ID order.

Return type:

list of Agent

get_agents_in_state(self: epiworldpy._core.Model, state: SupportsInt | SupportsIndex) → numpy.typing.NDArray[numpy.uint64]#

Get the agents currently in a state.

Only available once the model has been run.

Parameters:

state (int) – Index of the state.

Returns:

IDs of the agents in that state.

Return type:

numpy.ndarray

get_agents_states(self: epiworldpy._core.Model) → list[int]#

Get the current state of every agent.

Returns:

State index of each agent, in ID order.

Return type:

list of int

get_db(self: epiworldpy._core.Model) → epiworldpy._core.DataBase#

Get the database with the results of the last run.

Returns:

The model’s database.

Return type:

DataBase

get_elapsed(self: epiworldpy._core.Model, unit: str = 'auto') → dict#

Get the time the simulations took.

Parameters:

unit (str, default "auto") – Time unit: "auto" (chosen from the magnitude), "nanoseconds", "microseconds", "milliseconds", "seconds", "minutes", or "hours".

Returns:

"last": duration of the last run; "total": duration of all runs; "unit": abbreviation of the unit used.

Return type:

dict

get_entity(self: epiworldpy._core.Model, entity_id: SupportsInt | SupportsIndex) → epiworldpy._core.Entity#

Get an entity by ID.

Parameters:

entity_id (int) – ID of the entity.

Returns:

The entity.

Return type:

Entity

get_last_transmission_mode(self: epiworldpy._core.Model) → str#

Get the transmission mode used in the most recent step.

Returns:

"push" or "pull".

Return type:

str

get_n_entities(self: epiworldpy._core.Model) → int#

Get the number of entities in the model.

Returns:

Number of entities.

Return type:

int

get_n_globalevents(self: epiworldpy._core.Model) → int#

Get the number of global events.

Returns:

Number of global events.

Return type:

int

get_n_replicates(self: epiworldpy._core.Model) → int#

Get the number of replicates run so far.

Returns:

Number of calls to run(), including those made by run_multiple().

Return type:

int

get_n_states(self: epiworldpy._core.Model) → int#

Get the number of states.

Returns:

Number of states.

Return type:

int

get_n_tools(self: epiworldpy._core.Model) → int#

Get the number of tools in the model.

Returns:

Number of tools.

Return type:

int

get_n_viruses(self: epiworldpy._core.Model) → int#

Get the number of viruses in the model.

Returns:

Number of viruses.

Return type:

int

get_name(self: epiworldpy._core.Model) → str#

Get the name of the model type (for example, "Susceptible-Infected-Recovered (SIR)").

Returns:

Name of the model.

Return type:

str

get_ndays(self: epiworldpy._core.Model) → int#

Get the number of days the model was last run for.

Returns:

Number of days (steps).

Return type:

int

get_param(self: epiworldpy._core.Model, pname: str) → float#

Get the value of a named parameter.

Parameters:

pname (str) – Name of the parameter.

Returns:

The parameter’s value.

Return type:

float

get_rewire_prop(self: epiworldpy._core.Model) → float#

Get the proportion of ties rewired at each step.

Returns:

Proportion between 0 and 1.

Return type:

float

get_sim_id(self: epiworldpy._core.Model) → int#

Get the ID of the current simulation.

Useful inside a run_multiple() callback.

Returns:

ID of the simulation.

Return type:

int

get_states(self: epiworldpy._core.Model) → list[str]#

Get the labels of the model’s states.

Returns:

State labels, in index order.

Return type:

list of str

get_transmission_kappa(self: epiworldpy._core.Model) → float#

Get the threshold used by the "auto" transmission mode.

Returns:

The kappa threshold (see set_transmission_mode()).

Return type:

float

get_transmission_mode(self: epiworldpy._core.Model) → str#

Get the transmission mode set with set_transmission_mode().

Returns:

"auto", "push", or "pull".

Return type:

str

get_verbose(self: epiworldpy._core.Model) → bool#

Check whether verbose output is on.

Returns:

True if verbose output is on.

Return type:

bool

has_edge(self: epiworldpy._core.Model, i: SupportsInt | SupportsIndex, j: SupportsInt | SupportsIndex) → bool#

Check whether two agents are tied.

Parameters:
  • i (int) – ID of the first agent.

  • j (int) – ID of the second agent.

Returns:

True if the agents are tied (i -> j in a directed network).

Return type:

bool

has_globalevent(self: epiworldpy._core.Model, name: str) → bool#

Check whether the model has a global event.

Parameters:

name (str) – Name of the event.

Returns:

True if the event exists.

Return type:

bool

has_param(self: epiworldpy._core.Model, pname: str) → bool#

Check whether the model has a named parameter.

Parameters:

pname (str) – Name of the parameter.

Returns:

True if the parameter exists.

Return type:

bool

initial_states(self: epiworldpy._core.Model, proportions: collections.abc.Sequence[SupportsFloat | SupportsIndex], queue: collections.abc.Sequence[SupportsInt | SupportsIndex] = []) → epiworldpy._core.Model#

Set the initial distribution of agents across states.

The meaning of proportions is model specific. For the SEIR family, for example, proportions[0] is the share of the initially infected agents placed in Infected rather than Exposed, and proportions[1] is the share of the remaining agents placed in Recovered. The distribution is applied when the model is reset, which happens at the start of every run. Models without a state-based initializer ignore the call.

Parameters:
  • proportions (list of float) – Proportions used by the model’s initializer.

  • queue (list of int, default []) – Queuing flags used by the model’s initializer. Leave empty for the default.

Returns:

The model itself.

Return type:

Model

is_directed(self: epiworldpy._core.Model) → bool#

Check whether the network is directed.

Returns:

True if the network is directed.

Return type:

bool

is_queuing_on(self: epiworldpy._core.Model) → bool#

Check whether the queuing system is on.

Returns:

True if queuing is on.

Return type:

bool

static make_save_run(fmt: str = '%03lu-episimulation.csv', total_hist: bool = True, virus_info: bool = False, virus_hist: bool = False, tool_info: bool = False, tool_hist: bool = False, transmission: bool = False, transition: bool = False, reproductive: bool = False, generation: bool = False, active_cases: bool = False, outbreak_size: bool = False, hospitalizations: bool = False) → collections.abc.Callable[[SupportsInt | SupportsIndex, epiworldpy._core.Model], None]#

Create a run_multiple() callback that writes each run’s results to files.

Parameters:
Returns:

A function fun(sim_id, model) -> None to pass to run_multiple().

Return type:

callable

par(self: epiworldpy._core.Model, pname: str) → float#

Get the value of a named parameter (alias of get_param()).

Parameters:

pname (str) – Name of the parameter.

Returns:

The parameter’s value.

Return type:

float

params(self: epiworldpy._core.Model) → dict[str, float]#

Get the model’s parameters.

Returns:

Parameter values by name.

Return type:

dict of str to float

print(self: epiworldpy._core.Model, lite: bool = False) → None#

Print a summary of the model and its last run.

Parameters:

lite (bool, default False) – If True, print a shorter summary.

print_state_codes(self: epiworldpy._core.Model) → None#

Print the index and label of each state.

queuing_off(self: epiworldpy._core.Model) → epiworldpy._core.Model#

Turn off the queuing system, so every agent is updated at every step.

Needed when an update function may change the state of agents that have no infected neighbors.

Returns:

The model itself.

Return type:

Model

queuing_on(self: epiworldpy._core.Model) → None#

Turn on the queuing system (the default).

With queuing, each step only updates agents that may change state (for example, susceptible agents with an infected neighbor), which is much faster in large populations. It does not change the results.

reset(self: epiworldpy._core.Model) → None#

Reset the model to its initial state.

Restores the population, clears the database, and redistributes viruses, tools, and entities. run() calls it before each simulation.

rewire(self: epiworldpy._core.Model) → None#

Rewire the network with the model’s rewiring function, if it has one.

rm_edge(self: epiworldpy._core.Model, i: SupportsInt | SupportsIndex, j: SupportsInt | SupportsIndex) → bool#

Remove the tie between two agents.

Safe to call during a run, for example from a global event. Only works on undirected networks.

Parameters:
  • i (int) – ID of the first agent.

  • j (int) – ID of the second agent.

Returns:

True if a tie was removed, False if there was none.

Return type:

bool

rm_globalevent(self: epiworldpy._core.Model, name: str) → None#

Remove a global event.

Parameters:

name (str) – Name of the event (see add_globalevent()).

run(self: epiworldpy._core.Model, ndays: SupportsInt | SupportsIndex, seed: SupportsInt | SupportsIndex = -1) → epiworldpy._core.Model#

Run the model.

Parameters:
  • ndays (int) – Number of days (steps) to simulate.

  • seed (int, default -1) – Seed for the random number generator. A negative value keeps the current generator state.

Returns:

The model itself.

Return type:

Model

run_globalevents(self: epiworldpy._core.Model) → None#

Run the global events scheduled for today.

run_multiple(self: epiworldpy._core.Model, ndays: SupportsInt | SupportsIndex, nexperiments: SupportsInt | SupportsIndex, seed_: SupportsInt | SupportsIndex = -1, fun: object = None, reset: bool = True, verbose: bool = True, nthreads: SupportsInt | SupportsIndex = 1) → None#

Run the model several times.

Each experiment resets the model (if reset is True), runs it for ndays days, and then calls fun.

Parameters:
  • ndays (int) – Number of days (steps) of each experiment.

  • nexperiments (int) – Number of experiments.

  • seed (int, default -1) – Seed for the random number generator. A negative value keeps the current generator state.

  • fun (callable or None, default None) – Function fun(sim_id, model) -> None called after each experiment, for example to collect results. With None, the results are saved with make_save_run()’s defaults.

  • reset (bool, default True) – Whether to reset the model before each experiment.

  • verbose (bool, default True) – Whether to show a progress bar.

  • nthreads (int, default 1) – Number of threads. With more than one, experiments run in parallel on copies of the model, so fun must not rely on shared state.

seed(self: epiworldpy._core.Model, s: SupportsInt | SupportsIndex) → None#

Seed the model’s random number generator.

Parameters:

s (int) – Seed.

set_name(self: epiworldpy._core.Model, name: str) → None#

Set the name of the model.

Parameters:

name (str) – New name.

set_param(self: epiworldpy._core.Model, pname: str, val: SupportsFloat | SupportsIndex) → None#

Set the value of a named parameter.

Parameters:
  • pname (str) – Name of the parameter.

  • val (float) – New value.

set_rewire_prop(self: epiworldpy._core.Model, prop: SupportsFloat | SupportsIndex) → None#

Set the proportion of ties rewired at each step.

Only used if the model has a rewiring function.

Parameters:

prop (float) – Proportion between 0 and 1.

set_state_function(*args, **kwargs)#

Overloaded function.

  1. set_state_function(self: epiworldpy._core.Model, state: typing.SupportsInt | typing.SupportsIndex, fun: epiworldpy._core.NativeUpdateFun) -> epiworldpy._core.Model

Replace a state’s update function with a built-in epiworld function.

Parameters:
Returns:

The model itself.

Return type:

Model

  1. set_state_function(self: epiworldpy._core.Model, name: str, fun: epiworldpy._core.NativeUpdateFun) -> epiworldpy._core.Model

Replace a state’s update function with a built-in epiworld function.

Parameters:
Returns:

The model itself.

Return type:

Model

  1. set_state_function(self: epiworldpy._core.Model, state: typing.SupportsInt | typing.SupportsIndex, fun: collections.abc.Callable[[epiworldpy._core.Agent, epiworldpy._core.Model], None]) -> epiworldpy._core.Model

Replace a state’s update function.

Parameters:
  • state (int) – Index of the state.

  • fun (callable or None) – New update function fun(agent, model) -> None, or None to remove it.

Returns:

The model itself.

Return type:

Model

  1. set_state_function(self: epiworldpy._core.Model, name: str, fun: collections.abc.Callable[[epiworldpy._core.Agent, epiworldpy._core.Model], None]) -> epiworldpy._core.Model

Replace a state’s update function.

Parameters:
  • name (str) – Label of the state.

  • fun (callable or None) – New update function fun(agent, model) -> None, or None to remove it.

Returns:

The model itself.

Return type:

Model

set_transmission_mode(self: epiworldpy._core.Model, mode: str, kappa: SupportsFloat | SupportsIndex = 0.5) → epiworldpy._core.Model#

Set how network transmission is computed.

In a pull step, each susceptible agent looks at its infected neighbors; in a push step, each infected agent adds its infection odds to its susceptible neighbors. Both give the same distribution of infections and differ only in speed and in the random numbers drawn. Directed networks always pull.

Parameters:
  • mode ({"auto", "push", "pull"}) – "auto" (the default) chooses each day from the cost of each step: it pushes when D_c + 4 N_c <= kappa (D_s + 4 N_s), where D is the sum of degrees and N the number of agents, over the infected agents that can transmit (c) and the susceptible ones (s), and pulls otherwise. "pull" reproduces the random streams of epiworld 0.15 and earlier.

  • kappa (float, default 0.5) – Threshold used by "auto"; a finite, non-negative number. Smaller values pull more often.

Returns:

The model itself.

Return type:

Model

size(self: epiworldpy._core.Model) → int#

Get the number of agents.

Returns:

Population size.

Return type:

int

state_of(self: epiworldpy._core.Model, name: str) → int#

Get the index of a state from its label.

Parameters:

name (str) – Label of the state.

Returns:

Index of the state.

Return type:

int

Raises:

RuntimeError – If the model has no state with that label.

today(self: epiworldpy._core.Model) → int#

Get the current simulation day.

Returns:

Current day (step), starting at 0.

Return type:

int

verbose_off(self: epiworldpy._core.Model) → epiworldpy._core.Model#

Turn off verbose output.

Returns:

The model itself.

Return type:

Model

verbose_on(self: epiworldpy._core.Model) → epiworldpy._core.Model#

Turn on verbose output (progress bars and messages).

Returns:

The model itself.

Return type:

Model

write_data(self: epiworldpy._core.Model, fn_virus_info: str = '', fn_virus_hist: str = '', fn_tool_info: str = '', fn_tool_hist: str = '', fn_total_hist: str = '', fn_transmission: str = '', fn_transition: str = '', fn_reproductive_number: str = '', fn_generation_time: str = '', fn_active_cases: str = '', fn_outbreak_size: str = '', fn_hospitalizations: str = '') → None#

Write the results of the last run to files.

Each argument is the path of a file to write; files with an empty path are skipped.

Parameters:
write_edgelist(self: epiworldpy._core.Model, fn: str) → None#

Write the network to a file as an edge list.

Parameters:

fn (str) – Path of the output file.