Utopia  2
Framework for studying models of complex & adaptive systems.
revision.hh
Go to the documentation of this file.
1 #ifndef UTOPIA_MODELS_OPINIONET_REVISION
2 #define UTOPIA_MODELS_OPINIONET_REVISION
3 
4 #include <cmath>
5 
6 #include "modes.hh"
7 #include "utils.hh"
8 
9 
11 
14 using Modes::Rewiring;
15 
16 // .. Opinion update functions ................................................
17 
19 template<typename NWType, typename VertexDescType>
21  const VertexDescType v,
22  NWType& nw,
23  const double susceptibility,
24  const double tolerance,
25  const Opinion_space_type opinion_space)
26 {
27  double expectation = 0;
28  size_t num_interaction_partners = 0;
29 
30  // Directed case: Calculate the expectation based on the probability
31  // distribution given by the weights.
32  if constexpr (Utils::is_directed<NWType>()) {
33  VertexDescType nb;
34  for (const auto e : range<IterateOver::out_edges>(v, nw)) {
35  nb = target(e, nw);
36  if (Utils::opinion_difference(v, nb, nw) <= tolerance) {
37  expectation += nw[nb].opinion * nw[e].weight;
38  ++num_interaction_partners;
39  }
40  }
41 
42  // If interaction partners found: normalize weighted opinion average to
43  // number of interaction partners participating in interaction.
44  if (num_interaction_partners != 0) {
45  expectation *= static_cast<double>(boost::out_degree(v, nw)) /
46  num_interaction_partners;
47  }
48  else {
49  expectation = nw[v].opinion;
50  }
51  }
52 
53  // Undirected case: Calculate the opinion average
54  else {
55  for (const auto e : range<IterateOver::out_edges>(v, nw)) {
56  auto nb = boost::target(e, nw);
57  if (Utils::opinion_difference(v, nb, nw) <= tolerance) {
58  expectation += nw[nb].opinion;
59  ++num_interaction_partners;
60  }
61  }
62 
63  // If interaction partners found: normalize opinion average to
64  // number of interaction partners
65  if (num_interaction_partners != 0) {
66  expectation /= num_interaction_partners;
67  }
68  else {
69  expectation = nw[v].opinion;
70  }
71  }
72 
73  // Update opinion
74  nw[v].opinion += susceptibility * (expectation - nw[v].opinion);
75 
76  if (opinion_space == Opinion_space_type::discrete) {
77  nw[v].opinion = round(nw[v].opinion);
78  }
79 }
80 
82 template<typename NWType, typename RNGType, typename VertexDescType>
84  const VertexDescType v,
85  NWType& nw,
86  const double susceptibility,
87  const double tolerance,
88  const Opinion_space_type opinion_space,
89  std::uniform_real_distribution<double>& prob_distr,
90  RNGType& rng)
91 {
92  // Get neighbor
93  const VertexDescType nb = Utils::select_neighbor(v, nw, prob_distr, rng);
94 
95  // Discrete case: adopt nb opinion with probability = susceptibility
96  if (opinion_space == Opinion_space_type::discrete) {
97  if (Utils::opinion_difference(v, nb, nw) <= tolerance) {
98  const double interaction_probability = prob_distr(rng);
99  if (interaction_probability < susceptibility) {
100  nw[v].opinion = nw[nb].opinion;
101  }
102  }
103  }
104 
105  // Continuous case: move towards nb opinion proportional to susceptibility
106  else {
107  if (Utils::opinion_difference(v, nb, nw) <= tolerance) {
108  nw[v].opinion += susceptibility * (nw[nb].opinion - nw[v].opinion);
109  }
110  }
111 }
112 
113 // .. Rewiring ................................................................
114 
117 template<typename NWType, typename RNGType>
119  NWType& nw,
120  const double tolerance,
121  const double weighting,
122  RNGType& rng)
123 {
124  using namespace boost;
125 
126  // Choose random edge for rewiring
127  const auto e = random_edge(nw, rng);
128  const auto s = source(e, nw);
129 
130  if (Utils::opinion_difference(s, target(e, nw), nw) > tolerance) {
131  const auto new_target = random_vertex(nw, rng);
132 
133  if (new_target != s and not edge(s, new_target, nw).second)
134  {
135  remove_edge(e, nw);
136  add_edge(s, new_target, nw);
137 
138  if constexpr (Utils::is_directed<NWType>()) {
139  Utils::set_and_normalize_weights(s, nw, weighting);
140  }
141  }
142  }
143 }
144 
145 // .. Revision ................................................................
146 
148 template<typename NWType, typename RNGType>
149 void revision(
150  NWType& nw,
151  const double susceptibility,
152  const double tolerance,
153  const double weighting,
154  const Interaction_type interaction,
155  const Opinion_space_type opinion_space,
156  const Rewiring rewire,
157  std::uniform_real_distribution<double>& prob_distr,
158  RNGType& rng)
159 {
160  // Choose random vertex for revision
161  const auto v = boost::random_vertex(nw, rng);
162 
163  if (boost::out_degree(v, nw) != 0) {
164 
165  if (interaction == Interaction_type::HegselmannKrause) {
167  v, nw, susceptibility, tolerance, opinion_space
168  );
169  }
170 
171  else if (interaction == Interaction_type::Deffuant) {
173  v, nw, susceptibility, tolerance, opinion_space,
174  prob_distr, rng
175  );
176  }
177 
178  if constexpr (Utils::is_directed<NWType>()) {
179  Utils::set_and_normalize_weights(v, nw, weighting);
180  }
181  }
182 
183  if (rewire == Rewiring::RewiringOn) {
184  rewire_random_edge(nw, tolerance, weighting, rng);
185  }
186 }
187 
188 } // namespace Utopia::Models::Opinionet::Revision
189 
190 #endif // UTOPIA_MODELS_OPINIONET_REVISION
Opinion_space_type
Definition: modes.hh:13
@ discrete
Definition: modes.hh:15
Interaction_type
Definition: modes.hh:8
@ Deffuant
Definition: modes.hh:9
@ HegselmannKrause
Definition: modes.hh:10
Rewiring
Definition: modes.hh:18
@ RewiringOn
Definition: modes.hh:19
Definition: revision.hh:10
std::uniform_real_distribution< double > prob_distr
Definition: test_revision.cc:18
void rewire_random_edge(NWType &nw, const double tolerance, const double weighting, RNGType &rng)
Definition: revision.hh:118
void update_opinion_HK(const VertexDescType v, NWType &nw, const double susceptibility, const double tolerance, const Opinion_space_type opinion_space)
Hegselmann-Krause opinion update function.
Definition: revision.hh:20
void revision(NWType &nw, const double susceptibility, const double tolerance, const double weighting, const Interaction_type interaction, const Opinion_space_type opinion_space, const Rewiring rewire, std::uniform_real_distribution< double > &prob_distr, RNGType &rng)
Performs an opinion update and edge rewiring (if enabled).
Definition: revision.hh:149
void update_opinion_Deffuant(const VertexDescType v, NWType &nw, const double susceptibility, const double tolerance, const Opinion_space_type opinion_space, std::uniform_real_distribution< double > &prob_distr, RNGType &rng)
Deffuant opinion update function.
Definition: revision.hh:83
std::mt19937 rng
– Type definitions ----------------------------------------------------—
Definition: test_revision.cc:17
double opinion_difference(VertexDescType v, VertexDescType w, NWType &nw)
Calculate the absolute opinion difference of two vertices.
Definition: utils.hh:87
VertexDescType select_neighbor(const VertexDescType v, NWType &nw, std::uniform_real_distribution< double > &prob_distr, RNGType &rng)
Definition: utils.hh:57
void set_and_normalize_weights(const VertexDescType v, NWType &nw, const double weighting)
Set and normalize weights according to opinion difference.
Definition: utils.hh:102