Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ca_voter_model_example.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
45#include <array>
46#include <cmath>
47#include <cstdint>
48#include <cstdio>
49#include <random>
50#include <sstream>
51#include <string>
52#include <vector>
53
55
56using namespace Aleph;
57using namespace Aleph::CA;
58
59namespace {
60
61// Voter rule with a unique sub-seed per call — deterministic given
62// the engine schedule (which itself is deterministic).
63class Voter_Rule
64{
65 std::uint64_t seed_;
66 mutable std::uint64_t calls_ = 0;
67
68public:
69 explicit Voter_Rule(std::uint64_t seed) noexcept : seed_(seed) {}
70
71 [[nodiscard]] int operator()(int current, Neighbor_View<int> neigh) const noexcept
72 {
73 if (neigh.empty())
74 return current;
75 std::uint64_t key = seed_;
76 key = (key * 1099511628211ull) ^ (calls_ + 1);
77 ++calls_;
78 std::mt19937_64 rng(key);
79 std::uniform_int_distribution<std::size_t> pick(0, neigh.size() - 1);
80 return neigh[pick(rng)];
81 }
82};
83
84// Build a "bowtie": three triangles glued at node 0.
86{
87 // Nodes: 0 (hub), then three triangles {1,2}, {3,4}, {5,6}, each
88 // forming a triangle with node 0.
90 auto edge = [&](std::size_t a, std::size_t b)
91 {
92 adj[a].append(b);
93 adj[b].append(a);
94 };
95 // Triangle 1
96 edge(0, 1); edge(0, 2); edge(1, 2);
97 // Triangle 2
98 edge(0, 3); edge(0, 4); edge(3, 4);
99 // Triangle 3
100 edge(0, 5); edge(0, 6); edge(5, 6);
101 return adj;
102}
103
104void print_state(const Graph_Lattice<int> &lat, std::size_t step)
105{
106 std::printf("Step %4zu :", step);
107 for (std::size_t n = 0; n < lat.size(); ++n)
108 std::printf(" %d", lat.at_node(n));
109 std::putchar('\n');
110}
111
112std::string render_tikz(const Graph_Lattice<int> &lat)
113{
114 // Hard-coded layout: the hub at (0,0), the three triangles around
115 // it at 120-degree increments.
116 std::ostringstream os;
117 os << "% Aleph::CA voter model bowtie\n";
118 os << "\\begin{tikzpicture}[node distance=1.5cm]\n";
119 const double radius = 2.0;
120 const double pi = 3.14159265358979323846;
121 std::array<std::array<double, 2>, 7> pos{};
122 pos[0] = {0.0, 0.0};
123 for (int t = 0; t < 3; ++t)
124 {
125 const double theta0 = (2 * pi / 3.0) * static_cast<double>(t);
126 pos[1 + 2 * t] = {radius * std::cos(theta0 - 0.3),
127 radius * std::sin(theta0 - 0.3)};
128 pos[2 + 2 * t] = {radius * std::cos(theta0 + 0.3),
129 radius * std::sin(theta0 + 0.3)};
130 }
131
132 for (std::size_t n = 0; n < 7; ++n)
133 {
134 const char *colour = lat.at_node(n) != 0 ? "red!60" : "blue!60";
135 os << " \\node[circle, draw, fill=" << colour
136 << ", inner sep=2pt, minimum size=6mm] (n" << n << ") at (" << pos[n][0]
137 << ", " << pos[n][1] << ") {" << n << "};\n";
138 }
139 // Edges (deduplicated by always going low->high).
140 for (std::size_t a = 0; a < 7; ++a)
141 for (std::size_t b : lat.neighbours(a))
142 if (b > a)
143 os << " \\draw (n" << a << ") -- (n" << b << ");\n";
144 os << "\\end{tikzpicture}\n";
145 return os.str();
146}
147
148} // namespace
149
150int main()
151{
153 // Polarise: hub at 0, alternate triangles biased.
154 seed.set_node(0, 0);
155 seed.set_node(1, 1); seed.set_node(2, 1);
156 seed.set_node(3, 0); seed.set_node(4, 0);
157 seed.set_node(5, 1); seed.set_node(6, 1);
158
159 std::printf("Aleph::CA Phase-6 example: voter model on a 7-node bowtie graph\n");
160 print_state(seed, 0);
161
162 Graph_Synchronous_Engine<Graph_Lattice<int>, Voter_Rule> eng(seed, Voter_Rule{2026});
163
164 // Run, sampling the state every 50 steps and stopping when we
165 // detect consensus.
166 bool consensus = false;
167 for (std::size_t s = 1; s <= 5000; ++s)
168 {
169 eng.step();
170 if ((s % 200) == 0 or s == 1)
171 print_state(eng.frame(), s);
172 bool all_eq = true;
173 const int v0 = eng.frame().at_node(0);
174 for (std::size_t n = 1; n < eng.frame().size(); ++n)
175 if (eng.frame().at_node(n) != v0)
176 {
177 all_eq = false;
178 break;
179 }
180 if (all_eq)
181 {
182 consensus = true;
183 std::printf("Consensus on value %d reached at step %zu\n", v0, s);
184 print_state(eng.frame(), s);
185 break;
186 }
187 }
188 if (not consensus)
189 {
190 std::printf("Did not reach consensus within 5000 steps; final state:\n");
191 print_state(eng.frame(), 5000);
192 }
193
194 std::printf("\n--- TikZ render of final state ---\n");
195 std::fputs(render_tikz(eng.frame()).c_str(), stdout);
196 return 0;
197}
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:250
Graph lattice: one cell per node + precomputed adjacency.
Synchronous double-buffered engine for graph CAs.
void step()
Apply the rule to every node once and swap buffers.
static mt19937 rng
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
std::span< const T > Neighbor_View
Read-only view over a contiguous range of neighbour values.
Definition ca-traits.H:90
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
size_t size(Node *root) noexcept
ValueArg< size_t > seed
Definition testHash.C:53
CA whose underlying topology is an arbitrary undirected graph.