SEIR

The SEIR Model [1] assumes that infection spreads only through links between neighboring nodes in a graph \(G=(V,E)\). Each node is in one of four states: \(S\) (susceptible), \(E\) (exposed/incubating), \(I\) (infected), or \(R\) (recovered). A susceptible node \(i\) becomes exposed by its infected neighbors \(j \in N(i)\) with rate \(\beta\), exposed nodes become infectious with rate \(\alpha\), and infected nodes recover with rate \(\gamma\):

\[\begin{split}\begin{aligned} \frac{dS_i}{dt} &= -\beta \sum_{j\in N(i)} S_i I_j, \\ \frac{dE_i}{dt} &= \beta \sum_{j\in N(i)} S_i I_j - \alpha E_i, \\ \frac{dI_i}{dt} &= \alpha E_i - \gamma I_i, \\ \frac{dR_i}{dt} &= \gamma I_i . \end{aligned}\end{split}\]

Implementation

Node transitions follow three rules: 1) if a \(S\) state node has \(I\) state neighbors, each \(I\) state neighbor exposes the \(S\) state node with probability \(\beta\) (S→E); 2) the \(E\) state node becomes \(I\) with probability \(\alpha\) (E→I); 3) the \(I\) state node is recovered to the \(R\) state with probability \(\gamma\) (I→R).

SEIR model diagram

Node states are represented by three Boolean indicator vectors \(h, e, r \in \{0,1\}^N\), where \(h_i=1\) denotes infected or exposed, \(h_i=0\) denotes recovered or susceptible, and \((h_i,e_i,r_i)=(1,0,0)\) denotes infected, \((h_i,e_i,r_i)=(1,1,0)\) denotes exposed, \((h_i,e_i,r_i)=(0,0,1)\) denotes recovered, \((h_i,e_i,r_i)=(0,0,0)\) denotes susceptible. The update of the system at step \(k\) is decomposed into three stages:

  1. Each infected neighbor \(j\) of node \(i\) transmits a log-probability contribution for exposure (S→E)

\[m_{ji}^{(k)} = \mathbf{1}\!\left(h_j^{(k-1)}=1 \land e_j^{(k-1)}=0\right)\,\log(1-\beta)\]
  1. Node \(i\) collects contributions from all neighbors \(N(i)\) to compute its exposure probability

\[m_i^{(k)} = 1 - \exp\!\left( \sum_{j \in N(i)} m_{ji}^{(k)} \right)\]
  1. The indicator variables are updated with independent uniform random variables \(U_i^{\mathrm{exp}}, U_i^{\mathrm{inf}}, U_i^{\mathrm{rec}} \sim \mathrm{Uniform}(0,1)\)

\[\begin{split}\begin{aligned} h_i^{(k)} &= \begin{cases} 1, & \text{if } (U_i^{\mathrm{exp}} < m_i^{(k)}) \land (h_i^{(k-1)}=0 \land r_i^{(k-1)}=0), \\[4pt] 0, & \text{if } (U_i^{\mathrm{rec}} < \gamma) \land (h_i^{(k-1)}=1 \land e_i^{(k-1)}=0), \\[4pt] h_i^{(k-1)}, & \text{otherwise}, \end{cases} \\[6pt] e_i^{(k)} &= \begin{cases} 1, & \text{if } (U_i^{\mathrm{exp}} < m_i^{(k)}) \land (h_i^{(k-1)}=0 \land r_i^{(k-1)}=0), \\[4pt] 0, & \text{if } (U_i^{\mathrm{inf}} < \alpha) \land e_i^{(k-1)}=1 , \\[4pt] e_i^{(k-1)}, & \text{otherwise}, \end{cases} \\[6pt] r_i^{(k)} &= \begin{cases} 1, & \text{if } (U_i^{\mathrm{rec}} < \gamma) \land (h_i^{(k-1)}=1 \land e_i^{(k-1)}=0), \\[4pt] r_i^{(k-1)}, & \text{otherwise}. \end{cases} \end{aligned}\end{split}\]

Status

During the simulation, a node can be in one of the following states:

Status

Code

Susceptible

0

Infected

1

Exposed

2

Recovered

3

SEIRModel

class fs_gplib.Epidemics.SEIRModel(data, seeds, infection_beta: float, removal_gamma: float, latent_alpha: float, device='cpu', use_weight: bool = False, rand_seed=None)[source]

Bases: DiffusionModel

SEIR (Susceptible-Exposed-Infected-Recovered) diffusion model on static graphs.

Each node starts as susceptible or infected (seed). At every step each infected neighbor independently exposes a susceptible node with probability \(\beta\) (S→E), exposed nodes become infectious with probability \(\alpha\) (E→I), and infected nodes recover with probability \(\gamma\) (I→R) and become permanently immune.

Returned node states are encoded as: 0 = susceptible, 1 = infected, 2 = exposed, 3 = recovered.

Parameters:
  • data (torch_geometric.data.Data) -- PyTorch Geometric Data object representing graph \(G=(V,E)\). Must contain edge_index (the edge set \(E\)) and num_nodes (\(|V|\)). When use_weight is True, edge_attr supplies per-edge weights \(w_{ji}\).

  • seeds (list[int] | float) -- Nodes whose initial state is Infected. Pass a list of node IDs, or a float in (0, 1) to infect that fraction of nodes chosen uniformly at random.

  • infection_beta (float) -- Per-contact exposure probability \(\beta \in [0,1]\) (S→E).

  • removal_gamma (float) -- Per-step recovery probability \(\gamma \in [0,1]\) (I→R).

  • latent_alpha (float) -- Per-step incubation/progression probability \(\alpha \in [0,1]\) (E→I).

  • device (str | int) -- (optional) 'cpu' or a CUDA device index. Defaults to 'cpu'.

  • use_weight (bool) -- (optional) If True, each edge \((j,i)\) carries a weight \(w_{ji}\) from data.edge_attr and the exposure probability becomes \(\beta w_{ji}\). If False all weights default to 1 (i.e. \(w_{ji}=1\)). Defaults to False.

  • rand_seed (int | None) -- (optional) Random seed used when seeds is a float. Defaults to None.

run_iteration()[source]

Execute a single simulation step.

The internal node_status is updated so that subsequent calls continue from the latest state.

Returns:

Node states after one step, shape (1, N).

Return type:

torch.Tensor

run_iterations(times)[source]

Execute times simulation steps sequentially.

The internal node_status is updated in-place so that subsequent calls continue from the latest state.

Parameters:

times (int) -- Number of steps to run.

Returns:

Node states at final step, shape (1, N).

Return type:

torch.Tensor

run_epoch(iterations_times)[source]

Run a single Monte-Carlo epoch (one independent realisation).

Node states are re-initialised before the epoch starts.

Parameters:

iterations_times (int) -- Number of simulation steps per epoch.

Returns:

Node states at final step of the epoch, shape (1, N).

Return type:

torch.Tensor

run_epochs(epochs, iterations_times, batch_size=200)[source]

Run multiple independent Monte-Carlo epochs in batches.

Node states are re-initialised before the run.

Parameters:
  • epochs (int) -- Total number of independent realisations.

  • iterations_times (int) -- Number of simulation steps per epoch.

  • batch_size (int) -- (optional) Number of epochs processed in parallel per batch. Defaults to 200.

Returns:

Node states at final step of all epochs, shape (epochs, N).

Return type:

torch.Tensor

References