This is an Agent Based model of a disease propagation through a population. The model is designed to simulate the long-time effects of randomly recurrent introduction of a disease in an isolation population. There are data available for over 100 years of epidemics in the Faroe Islands. Here we show that our simulation predicts a powerlaw in the distribution of epidemic sizes given conditions similar to Faroe Islands. We then show that the power law breaks down as we gradually reduce variability in the system.
You can read our paper here: paper
We present an agent-based model for simulating the spread of an infectious disease through a population. The simulation allows for great amount of control over custom variables present in the system, such as the spatial distribution of people and their motion through space and time. We show the simulation is capable of reproducing the results of existing models in the literature such as SIR when stochastic effects of the model are ignored and the agents posses identical properties so they behave identically. However, the real usefulness of the model is in simulating complexity that is not possible to capture using conventional methods. We show our model produces a power-law probability distribution of epidemic sizes that is consistent with the distribution of infectious-disease epidemic sizes recorded at Faroe Island over a 100 year period. In an analysis similar to a parameter sweep, we show that starting with the simple case (approximating SIR), we can approach power law behavior as we add variability to the system.
The simulation is written in C++. The object oriented aspect of the language is used heavily. OpenGL together with GLFW is used for visualization of the data. GLFW is a library for managing windows and interaction with the user written in C. See http://www.glfw.org for more information. The code is maintained publicly on www.github.com/sahandha/SIR.
In view of the model described in our paper, the code design is pretty intuitive. We start out by defining a number of classes to capture the various aspects of the simulation. First we consider four categories: model, controller, view, and storage. Each class in the simulation belongs to a category. These categories follow the standard MVC (model-view-controller) design with the additional storage category which we use for storing data generated by the simulation.
The model consists of various classes. First and foremost, we need to define the geometry of the problem. This is achieved by using the two classes Domain and Place. We then define a class, Person, to represent people. Each instance of this class is one person with certain properties to be discussed below. Next is the InHostDynamics class. This class handles the spread of the disease within an individual as described previously. Finally there is a class named Disease, which implements properties of the disease that is being considered for the simulation. Note that this allows for more than one disease to be active during a simulation, but for now we only consider a single disease spreading through the population.
This class is responsible for creating an overall context for the simulation. In the example used in this paper, the Domain is the geographic area wherein all the islands are located.
We will skip listing the properties and methods as they are trivial.
An instance of this class is a location with a type, e.g., island. Depending on the type of location, individuals can enter and exit this location. The class is always aware of its occupants at any given time.
In a way, this class is the most important in the simulation. Instances of this class are people (agents) who participate in the simulation. Some of the properties of these objects are set during initialization, and some are injected by the controller (discussed later) during the simulation. Here is a listing of some of the most important properties of this class.
Various methods are used to define the behavior of each person. Two methods are the most important, move() and updatedisease(). At each time step of the simulation these two methods are called. Depending on the location, state of the person, the neighbors and their states, and etc., these methods determine the properties of the individual at the next time step.
This class handles the spread of disease in an individual's body. It injects the relevant values into class Person at each time step, as regulated by the Architect (discussed later). There are three important methods in this class, Flow(), Update(), Simulate().
This class is trivial in many ways. It only acts as a container for holding values for a given disease such as the average incubation period, average recovery period, etc.
Controller is a portion of the program that handles the timing and Communication among various components. In essence, it is the central control that makes sure all the right functions are called at the right time and on the right objects.
In our code, there is one class, Architect, that handles all the responsibilities of the controller. It manages time, calls update functions on each person, computes populations, passes values to the visualization class, and sends data to storage.
As mentioned, this class manages the program.
This is the portion of the code that handles visualization of the data as well as the user interaction while the simulation is running. It is handled by one class, namely Visualization.h. In order for this to work, one needs to have access to OpenGL framework, and include the GLFW library. This simulation was developed in a Mac environment, and XCode was used for compiling. OpenGL framework is included in XCode, but one needs to download GLFW and include the appropriate header file and library file paths.
Once the working environment is set up, we can get into the details of implementation. First we list the properties and methods, and then discuss how the class works.
The property, window, is essentially a window where we can draw all the OpenGL elements. During initialization, the size of this window can be chosen. It can also be set to full screen, as it is in our example here. The original coordinates on the screen for from -1 to 1, left to right, and -1 to 1 bottom to top. We therefore need to have transformation functions that map the coordinates of our model into these coordinates on the screen. We also factor in the reduction factors. The reduction factors are there to create extra space on the side and button of the simulation screen for providing extra information.
There are a number of callback functions that return a value of void. These callback functions handle events such as motion of the mouse on the screen, clicking of the mouse, and key strokes from the keyboard. At each time step, these events are polled, and an action is assigned to each one. For example, hitting the Esc button on the keyboard will close the window. Clicking inside a location will return the coordinates of that point, create a new agent, and add that agent into the simulation at the specified position.
Each of the draw and plot methods uses OpenGL for drawing the appropriate primitives. For example DrawPeople uses GL_POINTS to draw points for each person. DrawPlaces uses GL_POLYGON, and PlotSIR uses GL_LINE_STRIP.
Even though we visualize the data in real-time, all the data are saved for further analysis.
Stores data in text files in appropriate folders. This has been deprecated in favor of SQL storage.
Stores data in a MYSQL database. This mathod is preferred, because it allows random access of data by multiple users. Table \ref{tab:sql}.
In order for this to work, one needs to have access to a MYSQLSERVER. In our case, we have the server installed on the local machine, and access it using localhost. We then need to tell C++ where to find the "mysql.h" file, and include it in the header of our code.