Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_ca_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
65#ifndef TPL_CA_RULE_H
66#define TPL_CA_RULE_H
67
68#include <array>
69#include <concepts>
70#include <cstddef>
71#include <cstdint>
72#include <random>
73#include <type_traits>
74#include <tuple>
75#include <utility>
76
77#include <ah-errors.H>
78#include <ca-rng.H>
79#include <ca-traits.H>
80
81namespace Aleph {
82namespace CA {
83
84// -----------------------------------------------------------------------
85// Outer_Totalistic_Rule
86// -----------------------------------------------------------------------
87
97template <typename F>
99{
101
102public:
109 constexpr explicit Outer_Totalistic_Rule(F func) : f_(std::move(func)) {}
110
119 template <typename State>
120 [[nodiscard]] constexpr State operator()(const State &current, Neighbor_View<State> neighbours) const
121 {
122 std::size_t alive = 0;
123 for (const auto &v : neighbours)
124 if (v != State{})
125 ++alive;
126 return f_(current, alive);
127 }
128};
129
130// -----------------------------------------------------------------------
131// Totalistic_Rule
132// -----------------------------------------------------------------------
133
145template <typename F>
147{
149
150public:
156 constexpr explicit Totalistic_Rule(F func) : f_(std::move(func)) {}
157
169 template <typename State>
170 [[nodiscard]] constexpr State operator()(const State &current, Neighbor_View<State> neighbours) const
171 {
172 using sum_type = std::common_type_t<State, std::intmax_t>;
173 sum_type sum = static_cast<sum_type>(current);
174 for (const auto &v : neighbours)
175 sum += static_cast<sum_type>(v);
176 return static_cast<State>(f_(sum));
177 }
178};
179
180// -----------------------------------------------------------------------
181// Lookup_Rule
182// -----------------------------------------------------------------------
183
184namespace ca_rule_detail {
185constexpr std::size_t static_pow_rule(std::size_t base, std::size_t exp) noexcept
186{
187 std::size_t r = 1;
188 for (std::size_t i = 0; i < exp; ++i)
189 r *= base;
190 return r;
191}
192} // namespace ca_rule_detail
193
211template <std::size_t NumStates, std::size_t NumNeighbors>
213{
214public:
216 static constexpr std::size_t num_states_v = NumStates;
217
219 static constexpr std::size_t num_neighbours_v = NumNeighbors;
220
222 static constexpr std::size_t table_size_v
224
226 using table_type = std::array<std::size_t, table_size_v>;
227
228private:
230
231public:
236 constexpr Lookup_Rule() = default;
237
243 constexpr explicit Lookup_Rule(table_type t) : table_(t) {}
244
251 {
252 return table_;
253 }
254
265 template <typename State>
266 [[nodiscard]] State operator()(const State &current, Neighbor_View<State> neighbours) const
267 {
268 ah_length_error_if(neighbours.size() != NumNeighbors)
269 << "Lookup_Rule::operator(): expected " << NumNeighbors << " neighbours, got "
270 << neighbours.size();
271
272 auto validate_state = [](const State &value, const char *label)
273 {
274 if constexpr (std::is_signed_v<State>)
275 ah_domain_error_if(value < State{})
276 << "Lookup_Rule::operator(): " << label << " state is negative";
277
278 const std::size_t idx = static_cast<std::size_t>(value);
279 ah_domain_error_if(idx >= NumStates) << "Lookup_Rule::operator(): " << label << " state "
280 << idx << " outside [0, " << NumStates << ")";
281 return idx;
282 };
283
284 std::size_t idx = validate_state(current, "current");
285 for (const auto &v : neighbours)
286 idx = idx * NumStates + validate_state(v, "neighbour");
287 return static_cast<State>(table_[idx]);
288 }
289};
290
304[[nodiscard]] inline constexpr Lookup_Rule<2, 2> make_wolfram_elementary_rule(std::uint8_t rule_no) noexcept
305{
307 for (std::size_t pattern = 0; pattern < 8; ++pattern)
308 {
309 const std::size_t left = (pattern >> 2) & 1;
310 const std::size_t self = (pattern >> 1) & 1;
311 const std::size_t right = (pattern >> 0) & 1;
312 const std::size_t lookup_idx = (self << 2) | (left << 1) | right;
313 t[lookup_idx] = static_cast<std::uint8_t>((rule_no >> pattern) & 1);
314 }
315 return Lookup_Rule<2, 2>(t);
316}
317
318// -----------------------------------------------------------------------
319// Probabilistic_Rule
320// -----------------------------------------------------------------------
321
347template <typename F, typename Engine = std::mt19937_64>
349{
350 mutable F f_;
351 std::uint64_t master_seed_ = 0;
352
353public:
357
368 constexpr explicit Probabilistic_Rule(F func) : f_(std::move(func)) {}
369
378 constexpr Probabilistic_Rule(F func, std::uint64_t master_seed)
379 : f_(std::move(func)), master_seed_(master_seed)
380 {}
381
383 [[nodiscard]] constexpr std::uint64_t master_seed() const noexcept
384 {
385 return master_seed_;
386 }
387
389 void set_master_seed(std::uint64_t s) noexcept { master_seed_ = s; }
390
399 template <typename State>
400 [[nodiscard]] State operator()(const State &current,
401 Neighbor_View<State> neighbours) const
402 requires std::invocable<F &, const State &, Neighbor_View<State>>
403 {
404 return f_(current, neighbours);
405 }
406
422 template <typename State, std::size_t Rank>
423 [[nodiscard]] State operator()(const State &current,
424 Neighbor_View<State> neighbours,
425 const Cell_Context<Rank> &ctx) const
426 {
427 if constexpr (std::is_invocable_r_v<State, F &, const State &,
429 {
430 Engine eng{static_cast<typename Engine::result_type>(
432 return f_(current, neighbours, eng);
433 }
434 else
435 {
436 return f_(current, neighbours);
437 }
438 }
439};
440
441// -----------------------------------------------------------------------
442// Composite_Rule
443// -----------------------------------------------------------------------
444
454template <typename... Rules>
456{
457 std::tuple<Rules...> rules_;
458
459public:
465 constexpr explicit Composite_Rule(Rules... rs) : rules_(std::move(rs)...) {}
466
475 template <typename State>
476 [[nodiscard]] constexpr State operator()(const State &current, Neighbor_View<State> neighbours) const
477 {
478 State acc = current;
479 std::apply(
480 [&](const auto &...r)
481 {
482 ((acc = r(acc, neighbours)), ...);
483 },
484 rules_);
485 return acc;
486 }
487};
488
489// -----------------------------------------------------------------------
490// Game of Life: B3/S23 — convenience instance
491// -----------------------------------------------------------------------
492
495{
504 template <typename State>
505 [[nodiscard]] constexpr State operator()(const State &current, const std::size_t alive) const noexcept
506 {
507 const bool alive_now = current != State{};
508 const bool alive_next
509 = (alive_now and (alive == 2 or alive == 3)) or (not alive_now and alive == 3);
510 return alive_next ? static_cast<State>(1) : static_cast<State>(0);
511 }
512};
513
516
526
527} // namespace CA
528} // namespace Aleph
529
530#endif // TPL_CA_RULE_H
Exception handling system with formatted messages for Aleph-w.
#define ah_length_error_if(C)
Throws std::length_error if condition holds.
Definition ah-errors.H:703
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
size_t size_t int32_t value
Definition ca-c-api.h:116
Reproducible random-number support for stochastic CA rules (Phase 8).
Common typedefs and tag types for the Cellular Automata module.
Sequential composition of one or more rules.
std::tuple< Rules... > rules_
constexpr Composite_Rule(Rules... rs)
Construct a sequential composition of rules.
constexpr State operator()(const State &current, Neighbor_View< State > neighbours) const
Apply every composed rule to the same neighbour view.
Precomputed transition table for (self, neighbours...).
static constexpr std::size_t num_states_v
Number of distinct cell states accepted by this rule.
State operator()(const State &current, Neighbor_View< State > neighbours) const
Compute the next state using the precomputed table.
static constexpr std::size_t num_neighbours_v
Number of neighbour entries required by operator().
static constexpr std::size_t table_size_v
Number of entries in the transition table.
constexpr const table_type & raw_table() const noexcept
Return the underlying transition table.
constexpr Lookup_Rule()=default
Build a zero-initialised lookup rule.
std::array< std::size_t, table_size_v > table_type
Transition table type storing next states for every input tuple.
constexpr Lookup_Rule(table_type t)
Build a lookup rule from a precomputed transition table.
Rule whose next state depends on (current, alive_count).
Definition tpl_ca_rule.H:99
constexpr State operator()(const State &current, Neighbor_View< State > neighbours) const
Compute the next state from current value and neighbours.
constexpr Outer_Totalistic_Rule(F func)
Construct an outer-totalistic rule from a functor.
Reproducible stochastic rule wrapper (Phase 8).
constexpr std::uint64_t master_seed() const noexcept
constexpr Probabilistic_Rule(F func, std::uint64_t master_seed)
Construct a stochastic wrapper with an explicit master seed.
State operator()(const State &current, Neighbor_View< State > neighbours) const
Legacy invocation: forward (state, neighbours) to F.
constexpr Probabilistic_Rule(F func)
Construct a stochastic wrapper from a functor.
Engine engine_type
Underlying engine type used when the wrapped functor accepts an Engine& reference.
void set_master_seed(std::uint64_t s) noexcept
Replace the master seed without rebuilding the rule.
State operator()(const State &current, Neighbor_View< State > neighbours, const Cell_Context< Rank > &ctx) const
Reproducible invocation with engine context.
Rule whose next state depends on the sum of every cell in the neighbourhood (including the centre).
constexpr State operator()(const State &current, Neighbor_View< State > neighbours) const
Compute the next state from the sum of centre and neighbours.
constexpr Totalistic_Rule(F func)
Construct a totalistic rule from a functor.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_exp_function > > exp(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4077
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 static_pow_rule(std::size_t base, std::size_t exp) noexcept
constexpr Game_Of_Life_Rule make_game_of_life_rule() noexcept
Build the canonical Game of Life rule.
std::span< const T > Neighbor_View
Read-only view over a contiguous range of neighbour values.
Definition ca-traits.H:90
Outer_Totalistic_Rule< Game_Of_Life_Functor > Game_Of_Life_Rule
Outer-totalistic rule type implementing Conway's Game of Life.
constexpr Lookup_Rule< 2, 2 > make_wolfram_elementary_rule(std::uint8_t rule_no) noexcept
Build the elementary 1D Wolfram rule rule_no (0..255) as a Lookup_Rule<2, 2> over neighbourhood {-1,...
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
STL namespace.
Per-cell context handed to rules that need to know "where" and "when" they are firing.
Definition ca-traits.H:106
Functor implementing Conway's Game of Life canonical rule (B3/S23).
constexpr State operator()(const State &current, const std::size_t alive) const noexcept
Evaluate the B3/S23 transition.
gsl_rng * r