Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_ca_block_rule.H
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
61#ifndef TPL_CA_BLOCK_RULE_H
62#define TPL_CA_BLOCK_RULE_H
63
64#include <array>
65#include <concepts>
66#include <cstddef>
67#include <type_traits>
68#include <utility>
69
70namespace Aleph {
71namespace CA {
72
81template <typename State>
82using Block_2x2 = std::array<State, 4>;
83
89template <typename R, typename State>
90concept Block_Rule_2x2 = requires(const R &r, Block_2x2<State> b) {
91 { r(b) } -> std::convertible_to<Block_2x2<State>>;
92};
93
94namespace ca_block_rule_detail {
95
98template <typename State>
99[[nodiscard]] inline constexpr State invert(const State &s) noexcept
100{
101 if constexpr (std::is_same_v<State, bool>)
102 return not s;
103 else if constexpr (std::is_integral_v<State>)
104 return s == State{0} ? State{1} : State{0};
105 else
106 return s == State{} ? State{1} : State{};
107}
108
110template <typename State>
111[[nodiscard]] inline constexpr std::size_t popcount(const Block_2x2<State> &b) noexcept
112{
113 std::size_t n = 0;
114 for (const auto &v : b)
115 if (v != State{})
116 ++n;
117 return n;
118}
119
120} // namespace ca_block_rule_detail
121
122// =======================================================================
123// Critters
124// =======================================================================
125
141{
142public:
150 template <typename State>
151 [[nodiscard]] constexpr Block_2x2<State> operator()(const Block_2x2<State> &in) const noexcept
152 {
153 using namespace ca_block_rule_detail;
154 if (popcount(in) == 2)
155 return in;
156 // Invert each cell, then rotate 180°: NW ↔ SE, NE ↔ SW.
158 out[0] = invert(in[3]);
159 out[1] = invert(in[2]);
160 out[2] = invert(in[1]);
161 out[3] = invert(in[0]);
162 return out;
163 }
164};
165
166// =======================================================================
167// Billiard Ball Machine (BBM)
168// =======================================================================
169
186{
187public:
194 template <typename State>
195 [[nodiscard]] constexpr Block_2x2<State> operator()(const Block_2x2<State> &in) const noexcept
196 {
197 using namespace ca_block_rule_detail;
198 const std::size_t n = popcount(in);
199
200 if (n == 1)
201 {
202 // Ball moves to the diagonally-opposite corner.
204 out[0] = in[3];
205 out[1] = in[2];
206 out[2] = in[1];
207 out[3] = in[0];
208 return out;
209 }
210 if (n == 2)
211 {
212 // Diagonal swap only on the two "head-on" patterns.
213 const bool main_diag
214 = (in[0] != State{}) and (in[3] != State{}) and (in[1] == State{}) and (in[2] == State{});
215 const bool anti_diag
216 = (in[1] != State{}) and (in[2] != State{}) and (in[0] == State{}) and (in[3] == State{});
218 {
220 out[0] = in[3];
221 out[1] = in[2];
222 out[2] = in[1];
223 out[3] = in[0];
224 return out;
225 }
226 }
227 return in;
228 }
229};
230
231// =======================================================================
232// Toffoli–Margolus lattice gas
233// =======================================================================
234
255{
256public:
263 template <typename State>
264 [[nodiscard]] constexpr Block_2x2<State> operator()(const Block_2x2<State> &in) const noexcept
265 {
266 using namespace ca_block_rule_detail;
267 const std::size_t n = popcount(in);
268
269 if (n == 1 or n == 3)
270 {
271 // Horizontal swap: NW ↔ NE, SW ↔ SE.
273 out[0] = in[1];
274 out[1] = in[0];
275 out[2] = in[3];
276 out[3] = in[2];
277 return out;
278 }
279 if (n == 2)
280 {
281 const bool top_row
282 = (in[0] != State{}) and (in[1] != State{}) and (in[2] == State{}) and (in[3] == State{});
283 const bool bottom_row
284 = (in[2] != State{}) and (in[3] != State{}) and (in[0] == State{}) and (in[1] == State{});
286 {
287 // Vertical swap: top row ↔ bottom row.
289 out[0] = in[2];
290 out[1] = in[3];
291 out[2] = in[0];
292 out[3] = in[1];
293 return out;
294 }
295
296 const bool left_col
297 = (in[0] != State{}) and (in[2] != State{}) and (in[1] == State{}) and (in[3] == State{});
298 const bool right_col
299 = (in[1] != State{}) and (in[3] != State{}) and (in[0] == State{}) and (in[2] == State{});
301 {
302 // Horizontal swap: left column ↔ right column.
304 out[0] = in[1];
305 out[1] = in[0];
306 out[2] = in[3];
307 out[3] = in[2];
308 return out;
309 }
310
311 const bool main_diag
312 = (in[0] != State{}) and (in[3] != State{}) and (in[1] == State{}) and (in[2] == State{});
313 const bool anti_diag
314 = (in[1] != State{}) and (in[2] != State{}) and (in[0] == State{}) and (in[3] == State{});
316 {
317 // Diagonal swap.
319 out[0] = in[3];
320 out[1] = in[2];
321 out[2] = in[1];
322 out[3] = in[0];
323 return out;
324 }
325 }
326 return in;
327 }
328};
329
330// =======================================================================
331// Cell_Rule_As_Block_Rule
332// =======================================================================
333
346template <typename Cell_Rule>
348{
350
351public:
356 constexpr explicit Cell_Rule_As_Block_Rule(Cell_Rule cr) : cell_(std::move(cr)) {}
357
364 template <typename State>
366 {
368 for (std::size_t i = 0; i < 4; ++i)
369 out[i] = cell_(in[i]);
370 return out;
371 }
372};
373
374} // namespace CA
375} // namespace Aleph
376
377#endif // TPL_CA_BLOCK_RULE_H
size_t size_t int32_t * out
Definition ca-c-api.h:120
Fredkin–Toffoli Billiard Ball Machine block rule.
constexpr Block_2x2< State > operator()(const Block_2x2< State > &in) const noexcept
Apply the BBM block rule.
Adapt a regular cell rule (with empty neighborhood) to a block rule.
constexpr Block_2x2< State > operator()(const Block_2x2< State > &in) const
Apply the wrapped rule to every cell of the 2×2 block.
constexpr Cell_Rule_As_Block_Rule(Cell_Rule cr)
Wrap cr as a block rule.
Critters reversible CA block rule.
constexpr Block_2x2< State > operator()(const Block_2x2< State > &in) const noexcept
Apply the Critters block rule.
Toffoli–Margolus (TM) lattice-gas block rule.
constexpr Block_2x2< State > operator()(const Block_2x2< State > &in) const noexcept
Apply the TM lattice-gas block rule.
A rule that maps a 2×2 block to a 2×2 block.
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
constexpr std::size_t popcount(const Block_2x2< State > &b) noexcept
Population count of a 2×2 block: number of non-zero cells.
constexpr State invert(const State &s) noexcept
Toggle a cell value between its zero and a non-zero counterpart.
@ R
Recovered (and immune).
std::array< State, 4 > Block_2x2
Fixed-size 2×2 block of cell values used by Margolus rules.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
STL namespace.
gsl_rng * r