Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ca_schelling_async_vs_sync_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
32#include <cstddef>
33#include <cstdint>
34#include <iostream>
35#include <random>
36#include <string>
37
38#include <ca-rng.H>
39#include <ca-traits.H>
40#include <tpl_ca_async_engine.H>
41#include <tpl_ca_lattice.H>
42#include <tpl_ca_neighborhood.H>
43#include <tpl_ca_storage.H>
46
47using namespace Aleph;
48using namespace Aleph::CA;
49
50namespace
51{
52
55
56void seed_grid(Grid &g, std::uint32_t seed_value)
57{
58 std::mt19937 rng(seed_value);
59 std::discrete_distribution<int> pick({0.20, 0.40, 0.40});
60 for (ca_size_t i = 0; i < g.size(0); ++i)
61 for (ca_size_t j = 0; j < g.size(1); ++j)
62 g.set({static_cast<ca_index_t>(i), static_cast<ca_index_t>(j)},
63 pick(rng));
64}
65
67double segregation_index(const Grid &g)
68{
69 double accum = 0.0;
70 std::size_t agents = 0;
71 for (ca_size_t i = 0; i < g.size(0); ++i)
72 for (ca_size_t j = 0; j < g.size(1); ++j)
73 {
74 const auto self = g.at({static_cast<ca_index_t>(i),
75 static_cast<ca_index_t>(j)});
76 if (self == 0)
77 continue;
78 std::size_t same = 0;
79 std::size_t other = 0;
80 for (ca_index_t di = -1; di <= 1; ++di)
81 for (ca_index_t dj = -1; dj <= 1; ++dj)
82 {
83 if (di == 0 and dj == 0)
84 continue;
85 const auto v = g.at_safe({static_cast<ca_index_t>(i) + di,
86 static_cast<ca_index_t>(j) + dj});
87 if (v == 0)
88 continue;
89 if (v == self)
90 ++same;
91 else
92 ++other;
93 }
94 const std::size_t total = same + other;
95 if (total > 0)
96 {
97 accum += static_cast<double>(same) / static_cast<double>(total);
98 ++agents;
99 }
100 }
101 return agents == 0 ? 0.0 : accum / static_cast<double>(agents);
102}
103
105void render(const Grid &g, std::ostream &os)
106{
107 for (ca_size_t i = 0; i < g.size(0); ++i)
108 {
109 for (ca_size_t j = 0; j < g.size(1); ++j)
110 {
111 const auto v = g.at({static_cast<ca_index_t>(i),
112 static_cast<ca_index_t>(j)});
113 os << (v == 0 ? " " : v == 1 ? "AA" : "BB");
114 }
115 os << '\n';
116 }
117}
118
119} // namespace
120
121int main(int argc, char **argv)
122{
123 std::size_t steps = 30;
124 ca_size_t side = 16;
125 std::uint32_t seed_value = 0xBADC0DEu;
126 if (argc >= 2) steps = static_cast<std::size_t>(std::stoul(argv[1]));
127 if (argc >= 3) side = static_cast<ca_size_t>(std::stoul(argv[2]));
128 if (argc >= 4) seed_value = static_cast<std::uint32_t>(std::stoul(argv[3]));
129
130 Grid initial({side, side}, 0);
132
133 std::cout << "Schelling segregation: same rule, three schemes\n";
134 std::cout << " side = " << side << ", steps = " << steps
135 << ", seed = 0x" << std::hex << seed_value << std::dec << "\n\n";
136 std::cout << "Initial frame (segregation index "
137 << segregation_index(initial) << "):\n";
138 render(initial, std::cout);
139 std::cout << "\n";
140
141 // --- Synchronous double-buffer ---------------------------------------
143 sync(initial, Schelling{0.5, 1.0, 1.0, 1u}, Moore<2, 1>{});
144 sync.run(steps);
145 std::cout << "Synchronous_Update (double-buffer) — segregation "
146 << segregation_index(sync.frame()) << ":\n";
147 render(sync.frame(), std::cout);
148 std::cout << "\n";
149
150 // --- Sequential in-place ---------------------------------------------
152 seq(initial, Schelling{0.5, 1.0, 1.0, 2u}, Moore<2, 1>{});
153 seq.run(steps);
154 std::cout << "Sequential_Update (in-place) — segregation "
155 << segregation_index(seq.frame()) << ":\n";
156 render(seq.frame(), std::cout);
157 std::cout << "\n";
158
159 // --- Random asynchronous ---------------------------------------------
162 async(std::move(initial), Schelling{0.5, 1.0, 1.0, 3u}, Moore<2, 1>{},
164 static_cast<std::size_t>(side * side)});
165 async.run(steps);
166 std::cout << "Random_Asynchronous_Update — segregation "
167 << segregation_index(async.frame()) << ":\n";
168 render(async.frame(), std::cout);
169 std::cout << "\n";
170
171 std::cout
172 << "Compare segregation indices: typically the asynchronous schemes\n"
173 << "converge more smoothly to higher segregation than synchronous\n"
174 << "ones, because synchronous updates can swap occupants in lockstep\n"
175 << "and oscillate.\n";
176 return 0;
177}
int main()
size_t steps
Definition ca-c-api.h:126
Reproducible random-number support for stochastic CA rules (Phase 8).
Common typedefs and tag types for the Cellular Automata module.
Update-scheme aware engine.
Lattice that adds boundary-aware access on top of a storage.
Moore (Chebyshev) neighborhood of radius R in N dimensions.
Local approximation of the Schelling segregation model.
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::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
Definition ca-traits.H:60
std::size_t ca_size_t
Unsigned size component used for extents and counts.
Definition ca-traits.H:63
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Pick one cell at random per sub-step, update it in place.
In-place sequential update (no double buffer).
Classical double-buffer synchronous update.
The lattice wraps around on every axis.
Definition ca-traits.H:124
Phase 13 update-scheme aware engine.
Cellular automata lattice with pluggable boundary policies.
Neighborhoods catalogue for Aleph::CA.
Reproducible stochastic CA rules (Phase 8).
Dense, contiguous storage for cellular automata cells (1D/2D/3D).
Phase 13 update-scheme strategies for Aleph::CA.