Running a process
The easiest way to understand how epydemic works is to use one of
the in-built disease processes to perform a simulation. After that
we’ll look at how to run large-scale simulations
and how to build disease models from scratch.
We first need to import the basic classes.
from epydemic import SIR, StochasticDynamics, ERNetwork
Creating a model
Let’s start with a disaese process. For simplicity we’ll using the
builtin SIR process.
# create a model
m = SIR() # the model (process) to simulate
Providing parameters
All epydemic’s processes take a range of parameters and
use them when building the model. These are provided as a dict, with
the contents depending on the model we’ll be building. Continuing with
the SIR process, we need to provide three paremeters for the infection
probability, the removal probability, and the initial seeding
probability.
param = dict()
m.setParameters(param, {SIR.P_INFECT: 0.1, # the probability of infection
SIR.P_REMOVE: 0.5, # the probability of removal
SIR.P_INFECTED: 0.01}) # the fraction of nodes initially infected
Note
We set the parameters relating to the process using
Process.setParameters(). You can also put the parameters into
the dict directly, but this way is more flexible for more
complicated cases involving multiple processes.
Providing a network
We can run the simulation over any appropriate network. A network whose degree distribution followed a powerlaw with cutoff would probably be most realistic, but for now we’ll just use an ER random graph model.
param[ERNetwork.N] = 10000 # order (number of nodes) of the network
param[ERNetwork.KMEAN]= 5 # mean node degree
Running the simulation
We can now perform a single run of the simulation, using stochastic dynamics.
# create a network and tie it together with the model using a dynamics
g = ERNetwork() # network generator for ER networks
e = StochasticDynamics(m, g) # use stochastic (Gillespie) dynamics
# set the parameters we want and run the simulation
rc = e.set(param).run()
If for some reason we wanted to use synchronous dynamics, we’d simply replace the simulation dynamics framework: the same models work under both frameworks.
f = SynchronousDynamics(m, g)
rc = f.set(param).run()
We can re-run the simulation, with or without changing the parameters.
# re-run with the same parameters
e.run()
# change something and re-run
m.setParameters(param, {SIR.P_REMOVE: 1.0})
rc = e.set(param).run()
Retrieving results
The run method returns a dict of results. The structure of this
dict is defined by epyc, and is described here: for our purposes, we will simply see a
nested dict with the results of the experiment appearing in a dict
under the epyc.Experiment.RESULTS key. Or you can simply use
Process.getResults():
[nS, nI, nR] = m.getResults(rc, [SIR.S, SIR.I, SIR.R])
The experimental resuilts are constructed by the
Process.results() method. This is overridden by
CompartmentedModel.results() to contain a mapping from
compartments to the number of nodes in that compartment at the end of
the simulation. Sub-classes can override the method further to add
more results.
This is all that’s needed to define a run individual simulations of networked processes. There are additional methods and event types that can be used in other circumstances, which we explore in Advanced topics. It is also common to want to run simulations that explore the ways in which a process changes across a range of parameters, which we discuss under Running a simulation at scale.