Source code for info_spreader
"""Information-spreader seeding policy for the MAIS simulation.
This module defines the :class:`Spreader` policy, which uses PageRank
centrality to seed a highly-connected node into state ``I`` at the
start of the simulation. It is intended for use with information-
diffusion models rather than epidemic models.
"""
import numpy as np
import graph_tool.all as gt
import logging
from policies.policy import Policy
from models.agent_info_models import STATES
[docs]
class Spreader(Policy):
"""Policy that seeds the most central node into the infectious state.
On the first simulation day, a ``graph-tool`` graph is built from
the contact network, PageRank centrality is computed (weighted by
edge probability, intensity, and layer weight), and the node at the
requested quantile of centrality is moved to state ``I``.
Args:
graph: The contact network graph object. Must expose
``e_source``, ``e_dest``, ``e_probs``, ``e_intensities``,
``e_types``, ``layer_weights``, and ``num_nodes``.
model: The epidemic model instance (must support
``change_states`` and ``nodes``).
quantile (float): Quantile in [0, 1] of the centrality
distribution used to select the seed node.
Defaults to 0.9.
"""
[docs]
def __init__(self, graph, model, quantile=0.9):
"""Initialise the spreader policy.
Args:
graph: The contact network graph object.
model: The epidemic model instance.
quantile (float): Centrality quantile for seed node
selection. Defaults to 0.9.
"""
super().__init__(graph, model)
self.quantile = quantile
[docs]
def first_day_setup(self):
"""Build the weighted graph, compute PageRank, and seed the central node.
Constructs an undirected ``graph-tool`` graph with edge weights
equal to ``prob * intensity * layer_weight``, runs PageRank,
and changes the state of the node at ``self.quantile`` of the
centrality distribution to ``STATES.I``.
"""
print("Spreader policy: first day setup")
# create graph_tool graph
g = gt.Graph(directed=False)
e_weight = g.new_edge_property("float")
g.add_vertex(self.graph.num_nodes)
for i, (source, dest) in enumerate(zip(self.graph.e_source, self.graph.e_dest)):
e = g.add_edge(source, dest)
e_weight[e] = self.graph.e_probs[i] * self.graph.e_intensities[i] * self.graph.layer_weights[self.graph.e_types[i]]
# get nodes centralities
nodes_centralities = gt.pagerank(g, weight=e_weight)
nodes_centralities = nodes_centralities.get_array()
print(nodes_centralities.shape)
print(len(nodes_centralities))
indexes = sorted(range(len(nodes_centralities)), key=lambda k: nodes_centralities[k])
idx = indexes[int(len(nodes_centralities) * self.quantile) - 1]
logging.info(f"Spreader policy: first day setup, node {idx} is selected with centrality {nodes_centralities[idx]}")
self.model.change_states(self.model.nodes == idx, target_state=STATES.I)