Opinionet — Opinion Dynamics#

Opinionet is a model of opinion dynamics on a social network. It simulates a network of users (nodes in a network), who update their opinions upon interaction with their social contacts (their neighboring nodes). This model includes a variety of different opinion dynamics models from the literature, including the Hegselmann-Krause (2002) and Deffuant (2000) models. The one-dimensional opinion space can be chosen to be discrete or continuous, and network edge weights can be configured to represent interaction probabilities. The Opinionet model is designed for further expansion and adaptation by researchers of social network opinion dynamics.


Implementation#

Opinion space#

The network consists of nodes (representing users) and edges (representing social links). Each user holds an opinion, a value in the one-dimensional opinion space. In the model, the opinion space can be either continuous or discrete. A continuous opinion space represents views held on a spectrum with two opposing extremes (e.g. ranging from ‘yes’ to ‘no’, ‘agree’ to ‘disagree’, etc.), and is modeled as a real interval \([a, b] \subset \mathbb{R}\); a discrete space holds views on a topic with a countable number of distinct choices (e.g. either ‘yes’ or ‘no’, different preferences for political parties, etc.), and is modeled as a series of integers \(\{0, ..., N\}\).

Hint

You can control the opinion space via the opinion_space key (see below).

Interaction functions#

There are two basic types of interaction functions: the Deffuant type, and the Hegselmann-Krause type. In addition, two parameters are relevant to the opinion interaction: the tolerance \(\epsilon\) and the susceptibility \(\mu\). The tolerance determines which spectrum of opinions a user is willing to engage with. A small tolerance bound means users only interact with opinions very close to their own; a large tolerance means users are rather more ‘broad-minded’. The susceptibility, in general, models how susceptible users are to others’ opinions, that is, to what degree they are willing to shift their own opinion towards that of others.

Hegselmann-Krause (HK) model: In the HK model, users shift their opinions towards the average opinion of all of their neighbors. In a single step, a randomly chosen vertex updates its opinion via

(a) Continuous opinion space:

\[\sigma_i(t+1) = \sigma_i(t) + \mu * (\langle\sigma_k \rangle - \sigma_i(t) ),\]

(b) Discrete opinion space:

\[\sigma_i(t+1) = [\sigma_i(t) + \mu * (\langle\sigma_k \rangle - \sigma_i(t) )],\]

where \([x]\) denotes rounding to the nearest integer.

Here, \(\langle \sigma_k \rangle\) is the average opinion of all neighboring vertices whose opinions fall within the tolerance range, i.e. for whom \(\vert \sigma_i - \sigma_k \vert < \epsilon\).

In a directed network, this average is weighted, meaning the neighbors’ opinions are weighted using the edge weights (see Network) normalised to the number of actually interacting neighbors.

Deffuant model: In the Deffuant model, only pairs of users interact. A random vertex \(i\) and one of its neighbors \(k\) are chosen, and the vertex updates its opinion via

(a) Continuous opinion space:

\[\sigma_i(t+1) = \sigma_i(t) + \mu * (\sigma_k - \sigma_i(t)),\]

(b) Discrete opinion space:

\[\sigma_i(t+1) = \sigma_k\]

with probability \(\mu\).

How the neighbor is chosen depends on the network: in a directed network, the probability is equal to the edge weights (see below). In an undirected network, a neighbor is chosen with uniform probability.

Note

With these implementations, user opinions will always remain in the opinion space, whether discrete or continuous. For \(\mu = 1\), the neighbors’ opinion is always adopted entirely.

Hint

You can control the interaction function, tolerance, and susceptibility through the keys of the same name. Note that the tolerance can be arbitrarily large, though it loses interpretability when negative. The susceptibility must be in \([0, 1]\).

Network#

In each iteration of the model, a single user is chosen at random with uniform probability, and this user’s opinion is updated through its interaction with other users. Which users interact is determined through the network topology. Utopia allows choosing different types of underlying topologies for the network (e.g. small-world or scale-free), or loading your own network from a dataset. The network can be directed or undirected, and edges can be given weights, representing the probability of the end nodes interacting.

Hint

You can control the network topology through the network/model key, and the directedness through the directed key.

Undirected network: In an undirected network, links have no orientation, and (in this model) hold no edge weights. In the Deffuant model of opinion dynamics, only pairs of nodes interact in one time step (see Interaction functions). In an undirected network, all neighbors of a given node have an equal probability of being selected as an interaction partner.

Directed network: In a directed network, edges have an orientation. Imagine a network of Twitter users: person A may follow person B, but person B does not necessarily follow person A back. Vertices therefore have an out-degree (people they follow), and an in-degree (people they are followed by). In the directed network, each link is given an edge weight \(w \in [0, 1]\). This weight plays a role in selecting neighbors for interaction (in the Deffuant model) or in giving weight to neighbors’ opinions (in the Hegselmann-Krause model) – more on that below.

Edge weights: The edge weights are calculated using a softmax function. Let \(\Delta \sigma_{i,j}\) be the opinion difference \(\vert \sigma_i - \sigma_j \vert\) between users \(i\) and \(j\). The weight on edge \(i, j\) is then set to

\[w_{i, j} = \dfrac{e^{-w \Delta \sigma_{i, j}}}{\sum_{k} e^{-w \Delta \sigma_{i, k}}},\]

where the sum over \(k\) ranges over all neighbors of \(i\) (softmax function). The parameter \(w>0\) is the weighting parameter. It controls how sharply the edge weights decrease with the opinion difference. For \(w=0\), the edge weights are all equal to 1/out degree(i).

Hint

You can control the weighting parameter via the network/edges/weighting key. It only has an effect when the network is directed.

Warning

Extremely large weighting parameters (\(w \gg 10\)) can lead to memory underflow, and weights will be written as zero.

Note

When the network is directed, edge weights are saved to an edge_weights dataset. You can use the edge weights in the graph plotting function, for instance to define the width of the links (see Plotting).

Rewiring: The topology of the network does not have to be static. You can let users cut links and rewire to new neighbors via the rewiring key. If activated, a randomly selected link between users whose opinions are further apart than the tolerance \(\epsilon\) is rewired to a new, randomly chosen neighbor.

How to run the model#

Model parameters#

See the model config
opinion_space:
  type: !param
    default: continuous
    is_any_of: [continuous, discrete]
    dtype: str

  # for continuous
  interval: [0, 1]

  # for discrete
  num_opinions: !is-positive-int 4

tolerance: !is-positive 0.3

susceptibility: !is-in-unit-interval 0.3

interaction_function: !param
  default: Deffuant
  is_any_of: [Deffuant, HegselmannKrause]
  dtype: str

network:
  # if directed, interaction probabilities are given by the edge weights, which
  # are set as the (normalized) distance in opinion space.
  # for undirected, interaction probability is constant for all neighbors
  directed: !is-bool true

  # network model
  model: KlemmEguiluz
  # can be:
  #   - WattsStrogatz (scale-free)
  #   - ErdosRenyi (random)
  #   - regular
  #   - complete
  #   - BollobasRiordan (small-world, directed)
  #   - BarabasiAlbert (small-world, undirected)
  #   - load_from_file (load a custom graph)

  num_vertices: !is-unsigned 200
  mean_degree: !is-positive-or-zero 4

  ErdosRenyi:
    parallel: false
    self_edges: false

  WattsStrogatz:
    p_rewire: 0.2
    oriented: false

  BollobasRiordan:
    alpha: 0.4
    beta: 0.6
    gamma: 0.
    del_in: 1.
    del_out: 0.

  regular:
    oriented: false

  KlemmEguiluz:
    mu: 0.2

  edges:
    weighting: !param
      default: 1
      limits: [0, 10]
      dtype: double
    rewiring: !is-bool true

The following keys in the model configuration allow you to control the model:

  • opinion_space:

    • type: whether the opinion space is continuous or discrete.

    • interval: if the opinion space is continuous: a real, closed interval.

    • num_opinions: if the opinion space is discrete: the number of discrete opinions.

  • tolerance: a real, positive value representing the confidence bound.

  • susceptibility: a real, positive value in \([0, 1]\).

  • network:

    • directed: whether or not the network should be directed. If directed, the network edges will be given weights (see above).

    • Model: the network topology: can be KlemmEguiluz (small-world, highly clustered, scale-free network, defualt), regular (a regular network), ErdosRenyi (random), WattsStrogatz (small-world, default), BarabasiAlbert (scale-free undirected), BollobasRiordan (scale-free directed), complete, or load_from_file (see here).

    • edges:

      • weighting: the weighting parameter used in the softmax function to set the edge weights (see above). Must be a postive real.

      • rewiring: whether or not edges between users with large opinion differences are rewired.

Plotting#

Opinionet comes with several default plots:

Graph plots:

  • graph: plots a single snapshot of the network at time time_idx. Node and edge properties can be plotted; by default, the node size is the (out-)degree, the node color its opinion. For directed graphs, the edge widths can be configured to match the edge weights.

  • graph_animation: animated plot of the network over time.

Universe plots:

  • opinion_animated: an animated histogram of the opinion distribution over time. The plot can also output the distribution at a single timeframe using the time_idx key.

  • opinion_time_series: plots the temporal development of the opinion density, as well as the final opinion distribution, as well as some representative trajectories of users in the largest opinion groups in the final distribution. This can be controlled from the configuration, e.g. by specifying the number of representatives (max_reps).

Multiverse plots:

Various data analytical parameters can be plotted for multiverse runs, e.g. as a 1d errorbar, or a 2d heatmap. These plots use the DAG framework. Current parameter options are:

  • op_number_of_peaks: calculate the number of opinion peaks

  • op_localization: yields a measure of how condensed the opinion distribution is

  • op_polarization: the polarization (in analogy with the physical definition) of the opinion distribution

In each case, the time of the opinion distribution in question can be specified.

See the default plot configuration
# -- Universe plots -----------------------------------------------------------
# .. Graph plots ..............................................................
graph:
  based_on: graph

graph_animation:
  based_on: graph_animation
  enabled: false

# .. Opinion plots ............................................................

opinion_animated:
  based_on: opinion_animated

opinion_time_series:
  based_on: opinion_time_series



# -- Multiverse plots ---------------------------------------------------------
localization_over_tolerance:
  based_on: localization_over_tolerance
  enabled: false  # needs tolerance dimension

localization_2d:
  based_on: localization_2d
  enabled: false
See the base plot configuration
.variables:
  base_path: &base_path data/Opinionet





# =============================================================================
#  ╔╦╗╔═╗╔╦╗╔═╗╦  ╔═╗╔╦╗╔═╗╔═╗
#   ║ ║╣ ║║║╠═╝║  ╠═╣ ║ ║╣ ╚═╗
#   ╩ ╚═╝╩ ╩╩  ╩═╝╩ ╩ ╩ ╚═╝╚═╝
# =============================================================================
# -- Overloads ----------------------------------------------------------------
# Overload some configs to insert model-specific settings

# Model-specific defaults
.defaults:
  based_on: .defaults

  # Can define something here ...


# .. Creators .................................................................
.creator.universe:
  based_on:
    - .creator.universe
    - .defaults

  dag_options:
    select_path_prefix: *base_path

.creator.multiverse:
  based_on:
    - .creator.multiverse
    - .defaults

  select_and_combine:
    base_path: *base_path




# .. Plot functions ...........................................................
.plot.errorbars:
  based_on:
    - .plot.facet_grid.errorbars

  expected_multiverse_ndim: [1,2,3,4,5]


.plot.sweep2d:
  module: model_plots.Opinionet
  plot_func: sweep2d

  expected_multiverse_ndim: [2,3,4,5]




# =============================================================================
#  ╔═╗╦  ╔═╗╔╦╗╔═╗
#  ╠═╝║  ║ ║ ║ ╚═╗
#  ╩  ╩═╝╚═╝ ╩ ╚═╝
# =============================================================================
# -- Graph plots --------------------------------------------------------------
graph:
  based_on:
    - .creator.universe
    - .plot.graph

  select:
    graph_group: nw

  graph_creation:
    at_time_idx: -1
    node_props: ['opinion']
    # edge_props: ['edge_weight']

  graph_drawing: &graph_drawing
    positions:
      model: spring
      k: 1
    nodes:
      node_color:
        from_property: opinion
      node_size:
        from_property: degree
        scale_to_interval: [10, 200]
    edges:
      width: 0.2

  helpers:
    set_title:
      title: Graph at time

graph_animation:
  based_on:
    - graph
    - .animation.ffmpeg

  graph_creation:
    at_time_idx: ~

  graph_animation:
    sel:
      time:
        from_property: opinion


# -- Opinion plots ------------------------------------------------------------

opinion_animated:
  based_on:
    - .animation.ffmpeg

  creator: universe
  universes: all
  module: model_plots.Opinionet
  plot_func: opinion_animated

  num_bins: 100
  time_idx: ~ # if given, will plot one specific time only

  animation:
    animation_update_kwargs:
      stepsize: 1

  color: dodgerblue

  helpers:
    set_title:
      title: Opinion distribution
    set_labels:
        x: User opinion
        y: Group size

opinion_time_series:
  creator: universe
  universes: all
  module: model_plots.Opinionet
  plot_func: opinion_time_series

  select:
    opinion: data/Opinionet/nw/opinion
    opinion_space:
      path: cfg/Opinionet
      with_previous_result: true
      transform:
        - getitem: opinion_space

  helpers:
    setup_figure:
      ncols: 2
      sharey: True
      gridspec_kw:
        width_ratios: [4, 1]
        wspace: 0.05

    axis_specific:
      density_development:
        axis: [0, 0]
        set_labels:
          x: Time
          y: User opinion
      final_histogram:
        axis: [1, 0]
        set_title:
          title: Final
        set_labels:
          x: Group size

  density_kwargs:
    origin: lower
    aspect: auto
    cmap: bone_r
    vmin: 0
    vmax: 25

  hist_kwargs:
    color: mediumseagreen
    orientation: horizontal

  representatives:
    enabled: True
    max_reps: 5
    rep_threshold: 10



# -- Multiverse plots ---------------------------------------------------------

# evaluating a parameter sweep over the tolerance and the seed
localization_over_tolerance:
  based_on:
    - .creator.multiverse
    - .plot.errorbars  # overloaded, see above

  select_and_combine:
    fields:
      tolerances:
        path: cfg/Opinionet
        transform:
          - getitem: [!dag_prev , tolerance]
      localization:
        path: data/Opinionet/nw/opinion
        transform:
          - operation: .isel
            args: [!dag_prev ]
            kwargs:
              time: -1
          - operation: Opinionet.op_localization
            args: [!dag_prev ]
            kwargs:
              along_dim: vertex_idx
              bins: 100
              interval: [0., 1.]
  transform:
    - operation: .isel
      args: [!dag_tag tolerances]
      kwargs:
        seed: 0
      tag: tolerance
    - operation: .mean
      args: [!dag_tag localization]
      kwargs:
        dim: seed
      tag: localization_mean
    - operation: .std
      args: [!dag_tag localization]
      kwargs:
        dim: seed
        ddof: 1
      tag: localization_std
    - operation: xr.Dataset
      kwargs:
        data_vars:
          tolerance: !dag_tag tolerance
          L: !dag_tag localization_mean
          dL: !dag_tag localization_std
      tag: data

  x: tolerance
  y: L
  yerr: dL
  capsize: 2
  marker: o
  helpers:
    set_title:
      title: Peak localization
    set_labels:
      x: Tolerance
      y: Localization

# evaluating a parameter sweep over the tolerance and susceptibility
localization_2d:
  based_on:
    - .creator.multiverse
    - .plot.sweep2d  # overloaded, see above

  select_and_combine:
    fields:
      tolerances:
        path: cfg/Opinionet
        transform:
          - getitem: [!dag_prev , tolerance]
      susceptibilities:
        path: cfg/Opinionet
        transform:
          - getitem: [!dag_prev , susceptibility]
      localization:
        path: data/Opinionet/nw/opinion
        transform:
          - operation: .isel
            args: [!dag_prev ]
            kwargs:
              time: -1
          - operation: Opinionet.op_localization
            args: [!dag_prev ]
            kwargs:
              along_dim: vertex_idx
              bins: 100
              interval: [0., 1.]

  transform:
    - operation: .isel
      args: [!dag_tag tolerances]
      kwargs:
        susceptibility: 0
      tag: tolerance
    - operation: .isel
      args: [!dag_tag susceptibilities]
      kwargs:
        tolerance: 0
      tag: susceptibility
    - operation: xr.Dataset
      kwargs:
        data_vars:
          tolerance: !dag_tag tolerance
          susceptibility: !dag_tag susceptibility
          L: !dag_tag localization
      tag: data

  x: tolerance
  y: susceptibility
  z: L

  helpers:
    set_title:
      title: Peak localization
    set_labels:
      x: Tolerance
      y: Susceptibility

For available base plots, see Base Plot Configuration Pool.

Literature#

  • Deffuant G. et al: Mixing beliefs among interating agents. Adv Complex Syst. (2000) 3:87-98.

  • Hegselmann, R. & Krause, U. (2002). Opinion Dynamics and Bounded Confidence Models, Analysis and Simulation. J. Artificial Societies and Soc. Simulation 5 3: 1–33.

  • Gaskin, Thomas (2020). Master’s thesis: Modelling Homophily and Discrimination in Selective Exposure Opinion Dynamics. Heidelberg University. Download here.

  • Traub, Jeremias (2019). Bachelor’s thesis: Modelling Opinion Dynamics – Selective Exposure in Adaptive Social Networks. Heidelberg University.

Further reading:

  • Arendt, D. L. & Blaha, L. M. (2015). Opinions, influence, and zealotry: a computational study on stubbornness. Comp. Math. Organization Theory 21 2: 184–209.

  • Axelrod, R. (1997). The dissemination of culture: a model with local convergence and global polarization. J. Conflict Resolution 41: 203–226.

  • Baumann, F. et al. (2020b). Emergence of polarized ideological opinions in multidimensional topic spaces. arXiv:2007.00601 [physics.soc-ph].

  • Carro, A. et al. (2013). The Role of Noise and Initial Conditions in the Asymptotic Solution of a Bounded Confidence, Continuous-Opinion Model. J. Stat. Phys. 151: 131–149.

  • Castellano, C. et al. (2009). Statistical physics of social dynamics. Reviews of Modern Physics 81 2: 591–646.

  • Del Vicario, M. et al. (2016). The spreading of misinformation online. Proc. Nat. Acad. Sc. USA. 113 3: 554–559.

  • Flache, A. et al. (2017). Models of Social Influence: Towards the Next Frontiers. J. Artifical Societies and Soc. Simulation 20 4.

  • Guerra, P. H. C. et al. (2013). A measure of polarization on social media networks based on community boundaries. Proc. Int. AAAI Conf. Web and Social Media (ICWSM’13).

  • Kozma, B. & Barrat, A. (2008). Consensus formation on adaptive networks. Phys. Rev. E 77, 016102.

  • Mäs, M., Flache, A., & Helbing, D. (2010) Individualization as Driving Force of Clustering Phenomena in Humans. PLoS Comput. Biol. 6 10: e1000959.

  • Perra, N. & Rocha, L. E. C. (2019). Modelling opinion dynamics in the age of algorithmic personalisation. Sci. Rep. 9 7261.

  • Sobkowicz, P. (2012). Discrete Model of Opinion Changes Using Knowledge and Emotions as Control Variables. PLoS ONE 7 9: e44489.

  • Sznajd-Weron, K. (2005). Sznajd model and its applications. Acta Physica Polonica B 36 8: 2537–2547.