Dynamics: Process dynamics over networks

class epydemic.Dynamics(g=None)

Bases: epyc.experiment.Experiment, object

A dynamical process over a network. This is the abstract base class for implementing different kinds of dynamics as computational experiments suitable for running under. Sub-classes provide synchronous and stochastic (Gillespie) simulation dynamics.

A Dynamics object is an instance of epyc.Experiment, and hence can be run either stand-alone or as part of a larger planned experimental protocol. Each simulation is parameterised by a dict providing the parameters used to condition the simulation, typically providing event probabilities for the various events that may happen.

In stand-alone mode, a simulation is run by calling the run() method (inherited from epyc.Experiment), providing a dict of parameters. The network dynamics then performs a single simulation according to the following process:

  • The simulation makes a copy of the prototype network it was supplied with at creation time or using Dynamics.setNetworkPrototype()
  • The Dynamics.setUp() method initialises this network, typically setting values at each node and edge
  • The Dynamics.do() method is called to perform the simulation, returning a dict of experimental results
  • The Dynamics.tearDown() method is called to clean-up the simulation class, typically destroying the working copy of the prototype network

Running the experiment performs an event-based simulation where events are drawn from two possible sources: probabilistic events generated according to a user-specified discrete probability distribution returned by Dynamics.eventDistribution(); and posted events posted by calls to Dynamics.postEvent() and occurring at a fixed simulation time. run() returns the dict of experimental results generated by Dynamics.do() plus other metadata.

Creating a dynamics class

Dynamics.__init__(g=None)

Create a dynamics, optionally initialised to run on the given network. The network (if provided) is treated as a prototype that is copied before each individual simulation experiment.

Parameters:g – prototype network (optional)

Attributes

Dynamics.TIME = ‘simulation_time’

Metadata element holding the logical simulation end-time.

Dynamics.EVENTS = ‘simulation_events’

Metadata element holding the number of events that happened.

Dynamics.DEFAULT_MAX_TIME = 20000

Default maximum simulation time.

Setting the network

A Dynamics object runs the process it describes over a network. The network is treated as a prototype that is copied before the start of each experiment, so that any manipulations or labelling the experiment caries out are torn down before the next run.

Dynamics.network()

Return the network this dynamics is running over.

Returns:the network
Dynamics.setNetworkPrototype(g)

Set the network the dynamics will run over. This will be copied for each run of an individual experiment.

Parameters:g – the network

Equilibrium

There are two ways of deciding whether a simulation has reached equilibrium: by running the simulation for a fixed (long) time, or by providing an explicit decision procedure.

Dynamics.setMaximumTime(t)

Set the maximum default simulation time. The default is given by DEFAULT_MAX_TIME.

param: t: the maximum time

Dynamics.at_equilibrium(t)

Test whether the model is an equilibrium. Override this method to provide alternative and/or faster simulations.

Parameters:t – the current simulation timestep
Returns:True if we’re done

Running the experiment

A simulation takes the form of an epyc experiment which has set-up, execution, and tear-down phases.

Dynamics.setUp(params)

Before each experiment, create a working copy of the prototype network.

Parameters:params – parameters of the experiment
Dynamics.tearDown()

At the end of each experiment, throw away the copy.

Probabilistic events

To fire events probabilistically, a dynamics makes use of an event distribution provided by a sub-class.

Dynamics.eventDistribution(t)

Return the event distribution, a sequence of (l, p, f) triples where l is the locus of the event, p is the probability of an event occurring, and f is the event function called to make it happen. This method must be overridden in sub-classes.

It is perfectly fine for an event to have a zero probability.

Parameters:t – current time
Returns:the event distribution

Posted events

Posted events are fired at a fixed simulation time. Typically these are used to provide fixed-time behaviours interspersed with probabilistic events.

Dynamics.postEvent(t, g, e, ef)

Post an event to happen at time t. The event function should take the simulation time, network, and element for the event. At time t it is called with the given network and element.

Parameters:
  • t – the current time
  • g – the network
  • e – the element (node or edge) on which the event occurs
  • ef – the event function
Dynamics.pendingEvents(t)

Retrieve any posted event pending to be executed at or before time t. The pending events are returned in the form of zero-argument functions that can simply be called to execute the events. The events are returned as a list, with the earliest-posted event first.

Be aware that running the returned events in order may not be enough to accurately run the simulation in the case where firing an event causes another event to be posted before t. It may be easier to use runPendingEvents() to run all pending events, which handles this case automatically.

Parameters:t – the current time
Returns:a (possibly empty) list of pending event functions
Dynamics.runPendingEvents(t)

Retrieve and fire any pending events at time t. This method handles the case where firing an event posts another event that needs to be run before other already-posted events coming before time t: in other words, it ensures that the simulation order is respected.

Parameters:t – the current time
Returns:the number of events fired