Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ca_sir_epidemic_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
37#include <algorithm>
38#include <array>
39#include <cstddef>
40#include <cstdint>
41#include <iomanip>
42#include <iostream>
43#include <string>
44
45#include <ca-rng.H>
46#include <ca-traits.H>
47#include <tpl_ca_engine.H>
48#include <tpl_ca_lattice.H>
49#include <tpl_ca_neighborhood.H>
50#include <tpl_ca_storage.H>
52
53using namespace Aleph;
54using namespace Aleph::CA;
55
56namespace
57{
58
60
61struct Tally
62{
63 std::size_t s = 0;
64 std::size_t i = 0;
65 std::size_t r = 0;
66};
67
68Tally count(const SIR_Lattice &lat)
69{
70 Tally t;
71 for (ca_size_t i = 0; i < lat.size(0); ++i)
72 for (ca_size_t j = 0; j < lat.size(1); ++j)
73 {
74 const int v = lat.at({static_cast<ca_index_t>(i),
75 static_cast<ca_index_t>(j)});
76 if (v == static_cast<int>(SIR_Cell::S)) ++t.s;
77 else if (v == static_cast<int>(SIR_Cell::I)) ++t.i;
78 else ++t.r;
79 }
80 return t;
81}
82
83char glyph_for(int v)
84{
85 switch (static_cast<SIR_Cell>(v))
86 {
87 case SIR_Cell::S: return '.';
88 case SIR_Cell::I: return '*';
89 case SIR_Cell::R: return '#';
90 }
91 return '?';
92}
93
94void render(const SIR_Lattice &lat, std::ostream &os)
95{
96 for (ca_size_t i = 0; i < lat.size(0); ++i)
97 {
98 for (ca_size_t j = 0; j < lat.size(1); ++j)
99 os << glyph_for(lat.at({static_cast<ca_index_t>(i),
100 static_cast<ca_index_t>(j)}));
101 os << '\n';
102 }
103}
104
105std::string bar(std::size_t v, std::size_t total, std::size_t width = 40)
106{
107 if (total == 0) return std::string(width, ' ');
108 const std::size_t k
109 = std::min(width, static_cast<std::size_t>(
110 (static_cast<double>(v) / static_cast<double>(total))
111 * static_cast<double>(width)));
112 return std::string(k, '|') + std::string(width - k, ' ');
113}
114
115void run_scenario(const char *name, double beta, double gamma,
116 std::uint64_t master_seed,
117 std::size_t total_steps,
118 std::size_t snapshot_every)
119{
120 constexpr ca_size_t rows = 64;
121 constexpr ca_size_t cols = 64;
122
123 // Moore radius 1 has degree 8 ⇒ R0 estimate = beta * 8 / gamma.
124 const double R0 = beta * 8.0 / gamma;
125
126 std::cout << "\n========================================\n";
127 std::cout << " Scenario: " << name << "\n";
128 std::cout << " size=" << rows << "x" << cols
129 << " beta=" << beta << " gamma=" << gamma
130 << " R0~" << std::fixed << std::setprecision(2) << R0
131 << std::defaultfloat
132 << " seed=0x" << std::hex << master_seed << std::dec << '\n';
133 std::cout << "========================================\n";
134
135 SIR_Lattice lat({rows, cols}, static_cast<int>(SIR_Cell::S));
136 lat.set({rows / 2, cols / 2}, static_cast<int>(SIR_Cell::I));
137
138 SIR_Rule<> rule(beta, gamma, master_seed);
140
141 const std::size_t total = rows * cols;
142 std::size_t peak_I = 1;
143 std::size_t peak_step = 0;
144
145 std::cout << "\n--- step 0 (initial) ---\n";
146 render(engine.frame(), std::cout);
147 Tally t = count(engine.frame());
148 std::cout << "S=" << t.s << " I=" << t.i << " R=" << t.r
149 << " [" << bar(t.i, total) << "]\n";
150
151 for (std::size_t step = 1; step <= total_steps; ++step)
152 {
153 engine.step();
154 t = count(engine.frame());
155 if (t.i > peak_I) { peak_I = t.i; peak_step = step; }
156 if (step % snapshot_every == 0 or step == total_steps or t.i == 0)
157 {
158 std::cout << "\n--- step " << step << " ---\n";
159 render(engine.frame(), std::cout);
160 std::cout << "S=" << t.s << " I=" << t.i << " R=" << t.r
161 << " [" << bar(t.i, total) << "]\n";
162 }
163 if (t.i == 0)
164 {
165 std::cout << "\n[epidemic extinct at step " << step << "]\n";
166 break;
167 }
168 }
169
170 std::cout << "\nSummary: peak prevalence I=" << peak_I
171 << " at step " << peak_step
172 << " (final attack rate R="
173 << std::fixed << std::setprecision(3)
174 << (static_cast<double>(t.r) / static_cast<double>(total))
175 << std::defaultfloat << ")\n";
176}
177
178} // namespace
179
180int main()
181{
182 std::cout << "SIR epidemic on a 2-D toroidal lattice (Moore radius 1)\n";
183 std::cout << "Glyphs: '.' susceptible '*' infected '#' recovered\n";
184
185 // R0 ~ 0.05 * 8 / 0.5 = 0.8 < 1 ⇒ epidemic dies out.
186 run_scenario("Subcritical (R0 < 1)",
187 /*beta=*/0.05, /*gamma=*/0.5,
188 /*seed=*/0x5EEDA1Cull, /*steps=*/120, /*every=*/30);
189
190 // R0 ~ 0.20 * 8 / 0.5 = 3.2 > 1 ⇒ wavefront propagation.
191 run_scenario("Supercritical (R0 > 1)",
192 /*beta=*/0.20, /*gamma=*/0.5,
193 /*seed=*/0x5EEDA1Cull, /*steps=*/40, /*every=*/8);
194
195 std::cout << "\nNote: master_seed is identical across runs, so the\n"
196 " trace is bit-for-bit reproducible regardless of\n"
197 " the build mode and the number of worker threads.\n";
198 return 0;
199}
size_t * rows
Definition ca-c-api.h:112
size_t cols
Definition ca-c-api.h:105
Reproducible random-number support for stochastic CA rules (Phase 8).
Common typedefs and tag types for the Cellular Automata module.
Lattice that adds boundary-aware access on top of a storage.
Moore (Chebyshev) neighborhood of radius R in N dimensions.
SIR epidemic transition rule.
Synchronous double-buffered engine.
static void bar(int val, int scale=1)
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_gamma_function > > gamma(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4103
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
SIR_Cell
Discrete states of the SIR automaton.
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
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
The lattice wraps around on every axis.
Definition ca-traits.H:124
static int * k
static mt19937 engine
gsl_rng * r
Synchronous double-buffered engine for cellular automata.
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).