Voter

The Voter model [1] is a classical binary opinion dynamics model. Each node holds a discrete opinion \(s \in \{0, 1\}\). At each time step: 1) a node \(i\) is selected uniformly at random from the network; 2) node \(i\) adopts the opinion of a randomly chosen neighbor \(j \in N(i)\).

This process is equivalent to computing the fraction of neighbors holding opinion 1, then updating the selected node's opinion by sampling a Bernoulli random variable with that fraction as the success probability:

\[s_i^{(k)} \sim \mathrm{Bernoulli}\!\left( \frac{\sum_{j \in N(i)} s_j^{(k-1)}}{\#N(i)} \right)\]

where \(\#N(i)\) denotes the number of neighbors of node \(i\).

Implementation

The Voter model uses binary opinions, so each node's state is simply 0 or 1. At each iteration a single randomly chosen node updates its opinion via neighbor aggregation. Self-loops are removed to prevent a node from influencing itself.

Voter model diagram
  1. For each neighbor \(j \in N(i)\), generate a message equal to its current opinion:

\[m_{ji}^{(k)} = s_j^{(k-1)}\]
  1. Node \(i\) aggregates received messages by computing the mean opinion of its neighbors:

\[m_i^{(k)} = \frac{\sum_{j \in N(i)} m_{ji}^{(k)}}{\#N(i)}\]
  1. A node index \(i\) is selected uniformly at random. Its opinion is updated by sampling:

\[\begin{split}s_i^{(k)} = \begin{cases} 1, & \text{if } U_i < m_i^{(k)}, \\[6pt] 0, & \text{otherwise}, \end{cases}\end{split}\]

where \(U_i \sim \mathrm{Uniform}(0,1)\) is a random number. All other nodes retain their current opinions.

Status

During the simulation, a node holds a binary opinion value:

Status

Value

Opinion

0 or 1

VoterModel

class fs_gplib.Opinions.VoterModel(data, seeds, device='cpu', rand_seed=None)[source]

Bases: DiffusionModel

Binary Voter opinion dynamics model on static graphs.

Each node holds a binary opinion in {0, 1}. At every step, one node is selected uniformly at random and updates its opinion by copying a randomly chosen neighbor's opinion. In this implementation, that update is realised by computing the fraction of neighbors with opinion 1 and then sampling a Bernoulli random variable with that probability.

Returned node states are encoded as: 0 = opinion 0, 1 = opinion 1.

Self-loops are removed internally so that a node does not influence its own opinion during the update.

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|\)).

  • seeds (list[int] | float | None) -- Initial nodes with opinion 1. Pass a list of node IDs, a float in (0,1) to initialise that fraction of nodes chosen uniformly at random with opinion 1, or None.

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

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

run_iteration()[source]

Execute a single opinion-update step.

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

Returns:

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

Return type:

torch.Tensor

run_iterations(times)[source]

Execute times opinion-update steps sequentially.

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

Parameters:

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

Returns:

Node opinions 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 opinions are re-initialised before the epoch starts.

Parameters:

iterations_times (int) -- Number of opinion-update steps per epoch.

Returns:

Node opinions 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 opinions are re-initialised before the run.

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

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

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

Returns:

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

Return type:

torch.Tensor

References