Table Of Contents

Previous topic

Downloading and installing NepidemiX

Next topic

Tutorial

This Page

Documentation

Introduction

There are two ways to use NepidemiX: through a configurable command line program or by writing your won Python programs accessing the NepidemiX classes. Simulations and processes can be specified in a simple configuration file and can be extended using Python or both.

If you are new to NepidemiX it is recommended that you start with the Tutorial. which shows both how to script simulations using config files and how to write them as Python classes.

This page is intended as a very brief documentation outlining some of the features of the NepidemiX package, highlighting some of the features introduced by the tutorial. It lists the different configuration and scripting options, and link to the documentation for the main classes used for programming. A full API documentation is best accessed through the Python docstrings as shown in the Tutorial.

Simulations, processes and networks

At the core of NepidemiX is the Simulation class. This is basically an engine that iterates through a given number of time steps and for each executes some functionality determined by a process on a network. It encapsulates the logic independent of network structure or process functionality. Thus, a simulation takes require a specialized process, as well as a given network to function.

As nepidemix was intended to mainly run simulations and these can be rather complex as well as dependent on the type of process and network used, the Simulation class is initialized using a configuration object. Currently this is a NepidemiXConfigParser object, derived from the python2 standard class ConfigParser.RawConfigParser, but this may come to change in future versions. The configuration will among other things tell the simulation class what type of process to use and what kind of network generating function. Simulation will thereafter create both these objects.

For examples on how to configure and run a simulation see the Tutorial. For a full list of configuration options see the API documentation for the Simulation class.

API-reference: Simulations

Network generation

There is no dedicated network class in nepidemix, instead it relies on the very well developed and efficient NetworkX Graph. In order to tell Simulation what graph to generate the configuration option network_func is set. However, this can not be set directly to a NetworkX Graph generating function. Instead it must be set to a so called wrapper that takes the options destined for the function (as given in the section NetworkParameters) and cast them to the appropriate types. This is due to the fact that there is no native way of determine either type from a raw ini file, nor to query a python function for what types it requires for its parameters.

The current solution is not very elegant, a future update of the software will include type specification possibilities in the ini file instead. Currently, however, wrappers are defined in the nepidemix file networkgenerationwrappers.py . One example is:

grid_2d_graph_networkx = NetworkGenerator(networkx.grid_2d_graph,{'m':int, 'n':int}).create

Note the .create at the end. This line creates a wrapper for the networkx function grid_2d_graph. NetworkGenerator is a class defined in networkgenerationwrappers. As first argument it takes the name of a function, and as second a dictionary mapping between said functions parameter names and python types. networkx.grid_2d_graph takes two parameters m and n, both integers. After this is done we can set:

network_func = grid_2d_graph_networkx

in the config file, and also use m and n as options in the NetworkParameters section.

Thus if you write your own network generator you will need to first write the function and then also wrap it as shown above.

Hopefully you will not have to; wrapper for common functions exist already as given in the table below.

Wrapper name Parameter, type Description reference
barabasi_albert_graph_networkx
  • n, int
  • m, int
NetworkX barabasi_albert_graph
albert_barabasi_prv_quick
  • N, int
  • m, int
  • p, float
  • q, float
NepidemiX-API-networkxtra.albert_barabasi_physrevlett_quick
connected_watts_strogatz_graph_networkx
  • n, int
  • k, int
  • p, float
NetworkX connected_watts_strogatz_graph
powerlaw_cluster_graph_networkx
  • n, int
  • m, int
  • p, float
NetworkX powerlaw_cluster_graph
powerlaw_degree_sequence
  • n, int
  • a, float
NepidemiX-API-networkxtra.powerlaw_degree_sequence
grid_2d_graph_networkx
  • m, int
  • n, int
NetworkX grid_2d_graph
fast_gnp_random_graph_networkx
  • n, int
  • k, int
  • p, float
NetworkX fast_gnp_random_graph
load_network
  • file, str
NepidemiX-API-networkxtra.loadNetwork

The Process class

A process is a set of operations executing on a network each iteration of the simulation. The Simulation class will call methods in a process object representing different stages such as node and edge state updates, network state initialization, et c. Processes are subclasses of the class nepidemix.process.Process. This class defines the interface for all processes, and by overloading the methods of this class different specific processes functionality is created.

Processes operate at network/edge level as well as network level. The node and edge updates look at one entity at a time, but have access to read from the full network. The network update is called for the entire network and can operate on that level. As most processes we are interested in are on the form if node/edge state is x then with some probability move it into state y. Such rules will only write to a single entity (node/edge) at a time and can be fully implemented using local (per-entity) update rules only. The whole network update can later be used if other data/updates are needed, for instance mean field or topology changes.

What is then a state which the rules change? From the view of NepidemiX it is up to the programmer to decide, but must be deduced from a single NetworkX entity (node/edge). Thus in the case of a NetworkX node the update rule cab be triggered by the node ID (usually an integer, but could be anything NetworkX can use) and the associated dictionary - which of course can be any combination of (hash-able) key-attribute values. Thus the ‘true’ state of the node is the information of the node. By convention however, it is usually more practical to consider the state to be defined by the node attributes, or a subset thereof.

For this reason there are two main subclasses of Process: ExplicitStateProcess, and AttributeStateProcess. The first assumes names are given to each possible state that a node/edge can be in. For instance in an SIR-model, the nodes can be in one of three states: S, I, or R. In practice, only a single attribute (naming the state) is associated with each node. While practical for a large class of models, there are times when the number of individual states are so large that explicit enumeration may be prohibiting. In these cases the class AttributeStateProcess may be used instead. This specialization of Process assume instead that the state is a combination of node/edge attributes. The full node attribute dictionary, or a subset thereof.

When talking about processes derived from AttributeStateProcess they all have states in the form of a dictionary (you can think of this as a vector, only with named elements instead of ordered). In this documentation, and in code, we denote the states by a dictionary in python form. E.g. {key1:attribute1, key2:attribute2, ...}.

The easiest way of building a process is probably to script it using ScriptedProcess to build your process. This subclass of AttributeStateProcess will take a rule definition file as input, and may be use for a large class of processes without too much overhead.

For practical examples on how to specify processes see the Tutorial.

API-reference: Processes