Hegselmann-Krause
The HK model [1] describes continuous opinion dynamics. Each node holds an initial opinion \(h \in [-1,1]\) and updates it in discrete rounds. At each step: 1) \(\epsilon\) neighbor identification: find the set \(\Gamma_\epsilon\) of each node, \(d_{i,j}=\left|h_i-h_j\right|\le\epsilon\), \(j\in\Gamma_\epsilon\); 2) update the opinion value: The opinion of node \(i\) at the next time step is updated as follows:
where \(\#\Gamma_\epsilon\) denotes the number of \(\epsilon\) neighbors.
Implementation
Unlike the SIR model with three discrete states, the HK model uses a continuous opinion space. To avoid infinitely many states, we consider only two cases (Figure ref{fig:HK}): if $#Gamma_epsilon=0$, the opinion remains unchanged; otherwise, it is updated to the $epsilon$-neighbors’ average.
For each neighbor \(j \in N(i)\), generate two message terms:
where \(\mathbf{1}(\cdot)\) is the indicator function.
Node \(i\) aggregates received messages by averaging opinions of \(\varepsilon\)-neighbors:
Finally, the opinion of node \(i\) is updated as
Status
During the simulation, a node holds a continuous opinion value:
Status |
Range |
|---|---|
Opinion |
Float in [-1,1] |
HKModel
- class fs_gplib.Opinions.HKModel.HKModel(data, seeds, epsilon, device='cpu', rand_seed=None)[source]
Bases:
DiffusionModelHegselmann-Krause (HK) bounded-confidence opinion dynamics on static graphs.
Each node carries a continuous opinion \(h \in (-1, 1)\) (initialised from seeds or drawn uniformly at random when seeds is
None). At each step, for every node \(i\) the set of confidence neighbors consists of graph neighbors \(j\) with \(|h_i^{(k-1)} - h_j^{(k-1)}| < \varepsilon\). If that set is non-empty, \(h_i^{(k)}\) becomes the average of their opinions; if it is empty, \(h_i\) stays unchanged.Self-loops are removed from the edge index.
- Parameters:
data (torch_geometric.data.Data) -- PyTorch Geometric
Datarepresenting \(G=(V,E)\). Must provideedge_indexandnum_nodes.seeds (list[float] | None) -- Initial opinion per node, length
num_nodes, each strictly between-1and1; orNoneto sample each component independently from \(\mathrm{Uniform}(-1, 1)\) (using rand_seed for the RNG).epsilon (float) -- Confidence bound \(\varepsilon\) in
[0, 1]; only neighbors with opinion separation below this threshold contribute to the update.device (str | int) -- (optional)
'cpu'or a CUDA device index. Defaults to'cpu'.rand_seed (int | None) -- (optional) Seed for the random number generator when seeds is
None. Defaults toNone.
- run_iteration()[source]
Execute a single opinion-update step.
The internal
node_statusis 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_statusis 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