Dynamic Network Models
In many real-world systems — such as face-to-face contact networks, mobile communication networks, and transportation systems — the connections between individuals are not fixed but evolve over time. Dynamic network models capture this by operating on a sequence of graph snapshots \(\{G^{(k)}=(V,E^{(k)})\}_{k=1}^{T}\), where the node set \(V\) remains constant while the edge set \(E^{(k)}\) may change at each discrete time step \(k\).
Each dynamic model in FS_GPlib extends a corresponding static model from the
Epidemic Models category to time-varying topologies. The propagation rules at each step are
identical to their static counterparts, but the neighbor set and (optionally) edge weights
are drawn from the current snapshot rather than a fixed graph.
This enables the study of how temporal connectivity patterns affect spreading outcomes.
All dynamic network models support directed and undirected graphs with optional time-varying edge weights. They can be executed on both CPU and GPU, and are compatible with the batch-parallel acceleration described in the Tutorial.
Base Class & Common API
Every dynamic network model inherits from
DiffusionModel,
which provides the shared initialisation pipeline and a uniform simulation
interface. Understanding the base class helps you leverage the full API of
any concrete model.
Unlike the static-graph base classes, dynamic models take a node tensor x
and a list of per-snapshot edge indices edge_index_list (instead of a
single PyG Data object). The maximum number of simulation steps is
bounded by the number of snapshots \(T =\) len(edge_index_list).
- class fs_gplib.Dynamic.base.DiffusionModel(x, edge_index_list, seeds: float | List[int] | None, rand_seed=None, device='cpu', edge_attr_list=None, **kwargs)[source]
Base class for all dynamic-network diffusion models.
DiffusionModel(in the Dynamic package) provides the shared initialisation logic and a uniform simulation interface that every concrete dynamic model (DySI, DySIR, DySEIR, DyThreshold, …) inherits. Users typically do not instantiate this class directly; instead they create a subclass such asDySIRModel.Unlike the static-graph base classes in the Epidemics and Opinions packages, dynamic models operate on a snapshot sequence \(\{G^{(k)}=(V,E^{(k)})\}_{k=1}^{T}\) where the edge set changes at every step while the node set \(V\) remains fixed. The input is therefore a node tensor x and a list of per-snapshot edge indices edge_index_list (with optional edge_attr_list for time-varying weights).
Initialisation pipeline (executed in
__init__):Validate the input graph data via
_validate_graph().Initialise seed nodes via
_initialize_seeds().Validate and store model-specific parameters via
_validate_parameters().Transfer the model to the target device via
_set_device().
Simulation interface – four progressively higher-level entry points:
Method
Description
run_iteration()Advance one snapshot step from the current state.
run_iterations(times)Advance times snapshot steps from the current state.
run_epoch()Reset state, then run through all snapshots (one independent realisation).
run_epochs(epochs, batch_size)Run epochs independent realisations in batches (Monte-Carlo simulation over all snapshots).
- Parameters:
x (torch.Tensor) -- Node feature tensor of shape
(N, 1). The leading dimension defines the node count \(N\).edge_index_list (list[torch.Tensor]) -- A list of
edge_indextensors, one per snapshot. The list length \(T\) determines the maximum number of simulation steps.seeds (float | list[int] | None) -- Initial infected (or activated) node set. A list of node IDs or a float in [0, 1) representing the fraction of nodes to infect uniformly at random.
Noneis accepted for models that do not require seeds.rand_seed (int | None) -- Random seed for NumPy, used when seeds is a float to make the random selection reproducible. Defaults to
None.device (str | int) --
'cpu'or a CUDA device index (e.g.0). Defaults to'cpu'.edge_attr_list (list[torch.Tensor] | None) -- (optional) A list of per-snapshot edge-weight tensors aligned with edge_index_list. If
None, all edge weights default to1.kwargs -- Model-specific parameters (e.g.
infection_beta,recovery_lambda). Each key-value pair is validated to lie in [0, 1] and stored as an instance attribute.
Utility Methods
The following utility methods can be called on any dynamic model instance to re-configure the model after construction:
- DiffusionModel._set_seed(seeds)[source]
Replace the current seed set and refresh node states.
This is the recommended way to change seed nodes after construction. It calls
_initialize_seeds()to parse and store the new seeds, then (if the model is fully initialised)_init_node_status()to rebuild the node-state tensors on the current device.- Parameters:
seeds (float | list[int] | None) -- New seed specification – same format as the constructor parameter seeds (a float fraction, a list of node IDs, or
None).
Example
model = DySIRModel(x, edge_index_list, seeds=[0, 1], ...) # switch to a random 10 % seed set model._set_seed(0.1)
- DiffusionModel._init_node_status()[source]
Reset all node states to the initial configuration.
This method rebuilds the internal
node_statustensor(s) so that only the seed nodes are in the Infected (or Activated) state and all other nodes are Susceptible.Subclasses must override this method to create the status tensors appropriate for their compartmental structure.
Calling this method is useful when you want to rerun a simulation from scratch without reconstructing the model object.
Example
result1 = model.run_iterations(5) model._init_node_status() # reset result2 = model.run_iterations(5)
- DiffusionModel._set_device(device)[source]
Set (or switch) the computation device for the model.
When called during initialisation the internal tensors are moved to the target device. Subclasses override this method to also move the message-passing process module to the device.
- Parameters:
device (str | int) --
'cpu'or a CUDA device index (e.g.0).- Raises:
Exception -- If a GPU is requested but CUDA is not available.
Example
model = DySIRModel(x, edge_index_list, seeds, ...) model._set_device(0) # switch to GPU 0
Simulation Interface
All dynamic models expose four progressively higher-level simulation methods.
Note that run_epoch / run_epochs always iterate through the entire
snapshot sequence and therefore do not accept an iterations_times
parameter (unlike the static-graph models).
Method |
Description |
Resets state? |
|---|---|---|
|
Advance one snapshot step from the current state. |
No |
|
Advance times snapshot steps from the current state. |
No |
|
Reset to initial state, then run through all snapshots (one independent realisation). |
Yes |
|
Run epochs independent realisations in batches, each covering all snapshots (Monte-Carlo simulation). |
Yes |
Tip
run_iteration / run_iterations do not reset node states or the
snapshot counter, so they can be used to inspect intermediate states or
implement early-stopping logic. run_epoch / run_epochs always
start from snapshot 0 with the initial seed configuration and are the
recommended entry points for Monte-Carlo studies.
Available Models
The following models are available: