Skip to content

Example 8: SIR Model with contact network

Bui Thi Mai Anh edited this page Jul 3, 2018 · 2 revisions

The SIR with a contact network

We consider here a simple SIR model (with two transitions, S-->I with rate: beta*I/N and I-->R with rate gamma). In a mixing population, each individual has the same probability to contact all others. If we consider a contact network between individuals of the population, an individual may contact a few other individuals.

The contact network

A network is a graph with nodes and edges. In the individual contact network model, a node represents an individual and an edge indicates a contact between two individuals. In the general case, we consider a node is a sub-population (the population is divided by the equivalence relation R: aRb = (a.node == b.node)). In each node, we consider an individual contacts all others of the same node (so a node is homogeneously mixed).

The probability of infection (or the force of infection) of a susceptible in a contact network model is formulated by the number of infectious individuals having contact with itself.

There are several commonly considered topology for a network of contacts: #random (Erdos Renyi random graph), #scalefree (Barabasi Albert graph), #smallworld (Watts and Strogatz model)

The Kendrick script of the SIR contact network model:

The network of contacts is studied at individual-level, each node is corresponding to an individual in the population. We specify the model by composing two concerns: a spatial concern and a SIR concern. The probability of infection (lambda) that should take into account the number of infectious contacts of each individual is specified through functional transition rate. The code below is used the Kendrick API. We consider further developping a DSL targeted to network models in order to simplify the specification and make it more accessible for epidemiologists.

|model network spatialConcern sirConcern simulator db f|
model := KEModel new population: (KEPopulation size: 100).

sirConcern := KEModelPart new.
sirConcern addAttribute: #status value: #(S I R).
sirConcern addParameters: { #beta. #gamma. #lambda }.
sirConcern addTransitionFrom: { #status->#S } to: { #status->#I } probability: 'lambda'.
sirConcern addTransitionFrom: { #status->#I } to: { #status->#R } probability: 'gamma'.

spatialConcern := KEModelPart new.
network := KEContactNetwork nodes: 100 topology: { #random. #p->0.02 }.
spatialConcern addParameter: #network value: network.
spatialConcern addAttribute: #node value: network allContacts.

model integrate: sirConcern.
model integrate: spatialConcern.

model atParameter: #lambda assignValue: [ :aModel||node|
	node := aModel currentCompartment at: #node.
	((aModel atParameter: #network) 
            contactsOf: {aModel. #node->node. #status->#I})
        *(aModel atParameter: #beta)/(aModel atParameter: #N)
	 ].
model atParameter: #beta assignValue: 100.
model atParameter: #gamma assignValue: 0.1.

1 to: 99 do: [:i| model atCompartment: {#status->#S. #node->i asString asSymbol} put: 1].
model atCompartment: { #status->#I. #node->#'100' } put: 1.

simulator := KESimulator new: #IBM from: 0.0 to: 50 by: 0.1.
simulator executeOn: model.
f := [:name| |d tmp|
		tmp := (simulator allTimesSeriesContaining: name) collect: [ :e| e value ].
		d := OrderedCollection new.
		1 to: tmp first data size do: [ :k| d add: (tmp collect: [:e| e data at: k]) sum ].
		(KETimeSeries from: d withIndex: tmp first index) compartment: (STON fromString: name)
		].
db := KEDiagramBuilder new data: { (f value: '{#status:#I}') }.
db open.
db := KENetworkBuilder new
	data: simulator timeSeries;
        network: (model atParameter: #network);
	status: #(#S #I #R);
	colors: #(#green #red #blue);
	viewDataAtTime: 12.5;
	legend: 'random network, p = 0.02'.
db open

Infectious dynamics obtained by applying the individual-based simulation on the model

The network of contacts

Node of the contact network as a spatial subpopulation

We study each node of the network as a spatial subpopulation. In a node, an individual contacts all others (a node is supposed to be homogeneous).

|model network spatialConcern sirConcern simulator db|
model := KEModel new population: (KEPopulation size: 1000).

sirConcern := KEModelPart new.
sirConcern addAttribute: #status value: #(S I R).
sirConcern addParameters: { #beta. #gamma. #lambda }.
sirConcern addTransitionFrom: { #status->#S } to: { #status->#I } probability: 'lambda'.
sirConcern addTransitionFrom: { #status->#I } to: { #status->#R } probability: 'gamma'.

spatialConcern := KEModelPart new.
network := KEContactNetwork nodes: 10 topology: { #random. #p->0.2 }.
spatialConcern addParameter: #network value: network.
spatialConcern addAttribute: #node value: network allContacts.

model integrate: sirConcern.
model integrate: spatialConcern.

model atParameter: #lambda assignValue: [ :aModel||node|
	node := aModel currentCompartment at: #node.
	((aModel atParameter: #network) contactsOf: {aModel. #node->node. #status->#I})*(aModel atParameter: #beta)/(aModel atParameter: #N)
	 ].
model atParameter: #beta assignValue: 1.
model atParameter: #gamma assignValue: 0.1.

2 to: 10 do: [:i| model atCompartment: {#status->#S. #node->i asString asSymbol} put: 100].
model atCompartment: { #status->#I. #node->#'1' } put: 1.
model atCompartment: { #status->#S. #node->#'1' } put: 99.

simulator := KESimulator new: #IBM from: 0.0 to: 50 by: 0.1.
simulator executeOn: model.
db := KENetworkBuilder new 
	data: simulator timeSeries; 
	network: (model atParameter: #network);
 	status: #(I); viewDataAtTime: 50.
db open

Visualising the infectious prevalence in each node of the network:

Network of 10 nodes

Custom sidebar of the Kendrick Wiki

Basic-SIR

SIR---Metapopulation

Clone this wiki locally