Source code for graph_utils
"""Graph analysis utilities for the MAIS simulation.
This module provides helper functions for computing structural properties of
the contact graph used in the simulation, such as node degree statistics
derived from edge-probability data.
"""
import numpy as np
from scipy.sparse import csr_matrix, lil_matrix
[docs]
def compute_mean_degree(graph, nodes):
"""Compute the mean expected number of contacts (degree) for a set of nodes.
For each pair of nodes in the graph, the function aggregates all edges
connecting them to compute the probability that *at least one* contact
occurs on any layer. This probability is stored in a dense sparse matrix,
and the expected degree of each node in ``nodes`` is the row sum of that
matrix. The mean is then taken over all nodes in ``nodes``.
The computation iterates over all node pairs, so it is suited for analysis
rather than performance-critical simulation paths.
Args:
graph (LightGraph): The contact graph object. Must expose:
- ``graph.num_nodes`` (int): Total number of nodes.
- ``graph.nodes`` (iterable): All node indices.
- ``graph.A`` (array-like): Adjacency structure mapping a node
pair ``(n1, n2)`` to an index into ``graph.edges_repo``
(``0`` means no edge).
- ``graph.edges_repo`` (list): Repository of edge collections
keyed by the index returned from ``graph.A``.
- ``graph.get_edges_probs(edges)`` (callable): Returns an array
of transmission probabilities for the given edges.
nodes (iterable): Subset of node indices for which the mean degree is
computed.
Returns:
float: Mean expected number of contacts per node over the given
``nodes``.
"""
# first create matrix of all probs of contacts
# (can be optimised, I do not care about time now - so for all nodes)
graph_matrix = lil_matrix((graph.num_nodes, graph.num_nodes), dtype=float)
for n1 in graph.nodes:
for n2 in graph.nodes:
index = graph.A[n1, n2]
if index == 0: # no edge
continue
edges_repo = graph.edges_repo[index]
probs = graph.get_edges_probs(np.array(edges_repo))
probs = 1 - probs
graph_matrix[n1, n2] = 1 - probs.prod()
graph_matrix = csr_matrix(graph_matrix)
def node_degree(node):
return graph_matrix[node].sum()
degrees = [node_degree(node) for node in nodes]
return sum(degrees)/len(degrees)