Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ca_critters_reversible_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
31#include <cstddef>
32#include <cstdint>
33#include <cstdlib>
34#include <iostream>
35#include <limits>
36#include <random>
37#include <stdexcept>
38#include <string>
39
40#include <ca-traits.H>
41#include <tpl_ca_async_engine.H>
42#include <tpl_ca_block_rule.H>
43#include <tpl_ca_lattice.H>
44#include <tpl_ca_storage.H>
46
47using namespace Aleph;
48using namespace Aleph::CA;
49
50namespace
51{
52
54
55void seed(Grid &g, std::uint32_t seed_value, double p_alive)
56{
57 std::mt19937 rng(seed_value);
58 std::uniform_real_distribution<double> u(0.0, 1.0);
59 for (ca_size_t i = 0; i < g.size(0); ++i)
60 for (ca_size_t j = 0; j < g.size(1); ++j)
61 g.set({static_cast<ca_index_t>(i), static_cast<ca_index_t>(j)},
62 u(rng) < p_alive ? 1 : 0);
63}
64
65void render(const Grid &g, std::ostream &os)
66{
67 for (ca_size_t i = 0; i < g.size(0); ++i)
68 {
69 for (ca_size_t j = 0; j < g.size(1); ++j)
70 os << (g.at({static_cast<ca_index_t>(i), static_cast<ca_index_t>(j)})
71 ? "##"
72 : " .");
73 os << '\n';
74 }
75}
76
77bool grids_equal(const Grid &a, const Grid &b)
78{
79 for (ca_size_t i = 0; i < a.size(0); ++i)
80 for (ca_size_t j = 0; j < a.size(1); ++j)
81 if (a.at({static_cast<ca_index_t>(i), static_cast<ca_index_t>(j)})
82 != b.at({static_cast<ca_index_t>(i), static_cast<ca_index_t>(j)}))
83 return false;
84 return true;
85}
86
87std::size_t alive(const Grid &g)
88{
89 std::size_t n = 0;
90 for (ca_size_t i = 0; i < g.size(0); ++i)
91 for (ca_size_t j = 0; j < g.size(1); ++j)
92 if (g.at({static_cast<ca_index_t>(i), static_cast<ca_index_t>(j)}) != 0)
93 ++n;
94 return n;
95}
96
97} // namespace
98
99int main(int argc, char **argv)
100{
101 std::size_t steps = 1000;
102 ca_size_t side = 32;
103 std::uint32_t seed_value = 0xC0DEFEEDu;
104 try
105 {
106 if (argc >= 2)
107 steps = static_cast<std::size_t>(std::stoul(argv[1]));
108 if (argc >= 3)
109 side = static_cast<ca_size_t>(std::stoul(argv[2]));
110 if (argc >= 4)
111 {
112 // Accept hex (0x...) or decimal so the seed survives a
113 // round-trip through the printed banner.
114 const unsigned long long s = std::stoull(argv[3], nullptr, 0);
115 if (s > std::numeric_limits<std::uint32_t>::max())
116 throw std::out_of_range("seed");
117 seed_value = static_cast<std::uint32_t>(s);
118 }
119 }
120 catch (const std::invalid_argument &)
121 {
122 std::cerr << "Invalid argument: expected non-negative integers for "
123 "[steps] [side] [seed]\n";
124 return 1;
125 }
126 catch (const std::out_of_range &)
127 {
128 std::cerr << "Argument out of range for [steps] [side] [seed]\n";
129 return 1;
130 }
131
132 // Margolus reversibility requires a 2D grid whose extents are
133 // both ≥ 2 and even: odd extents leave a one-cell strip that the
134 // alternating partition cannot reach without breaking the
135 // forward(N) ∘ backward(N) = identity property.
136 if (side < 2 or side % 2 != 0)
137 {
138 std::cerr << "Invalid side: " << side
139 << " (must be a positive even integer ≥ 2 for Margolus reversibility)\n";
140 return 1;
141 }
142
143 Grid initial({side, side}, 0);
144 seed(initial, seed_value, 0.45);
145 Grid baseline = initial;
146
147 std::cout << "Critters reversible CA — " << side << "×" << side
148 << ", " << steps << " steps, seed 0x" << std::hex << seed_value
149 << std::dec << "\n\n";
150 std::cout << "Initial frame (" << alive(initial) << " alive):\n";
151 render(initial, std::cout);
152
156 engine.run(steps);
157
158 std::cout << "\nAfter forward(" << steps << ") steps ("
159 << alive(engine.frame()) << " alive):\n";
160 render(engine.frame(), std::cout);
161
162 engine.run_back(steps);
163
164 std::cout << "\nAfter backward(" << steps << ") steps ("
165 << alive(engine.frame()) << " alive):\n";
166 render(engine.frame(), std::cout);
167
168 const bool ok = grids_equal(engine.frame(), baseline);
169 std::cout << "\nReversibility check: "
170 << (ok ? "PASS — bit-exact identity recovered"
171 : "FAIL — recovered frame differs from initial")
172 << "\n";
173 return ok ? 0 : 1;
174}
int main()
size_t steps
Definition ca-c-api.h:126
Common typedefs and tag types for the Cellular Automata module.
Update-scheme aware engine.
Critters reversible CA block rule.
Lattice that adds boundary-aware access on top of a storage.
Placeholder neighbourhood for engines that drive block rules.
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::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
Margolus 2×2 partition update for reversible CAs.
The lattice wraps around on every axis.
Definition ca-traits.H:124
ValueArg< size_t > seed
Definition testHash.C:53
static mt19937 engine
Phase 13 update-scheme aware engine.
Block-based local rules for Aleph::CA (Phase 13).
Cellular automata lattice with pluggable boundary policies.
Dense, contiguous storage for cellular automata cells (1D/2D/3D).
Phase 13 update-scheme strategies for Aleph::CA.