Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_ca_multi_field_engine.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
58#ifndef TPL_CA_MULTI_FIELD_ENGINE_H
59#define TPL_CA_MULTI_FIELD_ENGINE_H
60
61#include <array>
62#include <cstddef>
63#include <functional>
64#include <span>
65#include <tuple>
66#include <type_traits>
67#include <utility>
68
69#include <ca-traits.H>
70#include <tpl_ca_concepts.H>
73#include <tpl_ca_neighborhood.H>
74
75namespace Aleph {
76namespace CA {
77
78namespace ca_mf_engine_detail {
79
81template <typename Lattice, typename Neighborhood, typename Buffers, std::size_t... I>
82inline auto build_views(const Lattice &lat,
83 const Neighborhood &nh,
84 const typename Lattice::coord_type &center,
86 std::index_sequence<I...>)
87{
88 using Coord = typename Lattice::coord_type;
89 std::size_t neigh_sz = nh.size();
90 if (neigh_sz > std::tuple_size_v<std::tuple_element_t<0, Buffers>>)
91 neigh_sz = std::tuple_size_v<std::tuple_element_t<0, Buffers>>;
92
93 std::size_t cursor = 0;
94 nh.for_each_offset(center, [&](const auto &off)
95 {
96 Coord c = center;
97 for (std::size_t d = 0; d < Lattice::rank; ++d)
98 c[d] = static_cast<ca_index_t>(c[d] + off[d]);
99 if (cursor < neigh_sz)
100 ((std::get<I>(bufs)[cursor] = lat.template at_safe<I>(c)), ...);
101 ++cursor;
102 });
103
104 return std::tuple{
106}
107
108} // namespace ca_mf_engine_detail
109
121template <typename Lattice, typename Rule, typename Neighborhood>
123{
124 static_assert(MultiFieldLatticeLike<Lattice>,
125 "Multi_Field_Engine requires a MultiFieldLatticeLike lattice");
126 static_assert(NeighborhoodLike<Neighborhood>,
127 "Multi_Field_Engine requires a NeighborhoodLike neighbourhood");
128 static_assert(Neighborhood::rank_v == Lattice::rank, "Neighbourhood rank must match lattice rank");
129
130public:
132 using rule_type = Rule;
136 using fields_tuple = typename Lattice::field_types;
137
138 static constexpr std::size_t rank = Lattice::rank;
139 static constexpr std::size_t field_count = Lattice::field_count;
140 static constexpr std::size_t neighbour_count = Neighborhood::size_v;
141
143 using hook_type = std::function<void(std::size_t, const Lattice &)>;
144
145private:
148 Rule rule_;
152 std::size_t step_count_ = 0;
153
154 template <std::size_t... I>
155 static auto make_buffers(std::index_sequence<I...>)
156 {
157 return std::tuple{std::array<typename Lattice::template field_type<I>,
158 (neighbour_count == 0 ? std::size_t{1} : neighbour_count)>{}...};
159 }
160
161 template <std::size_t... I>
162 void write_cell(const coord_type &c, const fields_tuple &v, std::index_sequence<I...>)
163 {
164 ((nxt_.template set<I>(c, std::get<I>(v))), ...);
165 }
166
167public:
179 : cur_(std::move(initial)), nxt_(cur_.extents()), rule_(std::move(r)), nh_(std::move(n))
180 {}
181
184 requires std::default_initializable<Neighborhood>
185 : Multi_Field_Engine(std::move(initial), std::move(r), Neighborhood{})
186 {}
187
190 {
191 return cur_;
192 }
193
196 {
197 return step_count_;
198 }
199
202 {
203 return cur_.extents();
204 }
205
207 template <typename F>
208 void on_pre_step(F &&f)
209 {
210 pre_hook_ = std::forward<F>(f);
211 }
212
214 template <typename F>
215 void on_post_step(F &&f)
216 {
217 post_hook_ = std::forward<F>(f);
218 }
219
232 void step()
233 {
234 if (pre_hook_)
236
237 auto bufs = make_buffers(std::make_index_sequence<field_count>{});
238
239 auto compute_one = [&](const coord_type &c)
240 {
242 std::make_index_sequence<field_count>{});
243 const fields_tuple cur_vals = cur_.at_cell(c);
244 const Cell_Context<rank> ctx{step_count_, c};
247 write_cell(c, new_vals, std::make_index_sequence<field_count>{});
248 };
249
251
252 cur_.swap(nxt_);
253 ++step_count_;
254
255 if (post_hook_)
257 }
258
263 void run(const std::size_t steps)
264 {
265 for (std::size_t i = 0; i < steps; ++i)
266 step();
267 }
268
269private:
270 template <typename F>
272 {
273 coord_type c{};
274 if constexpr (rank == 1)
275 {
276 const auto n0 = static_cast<ca_index_t>(cur_.size(0));
277 for (ca_index_t i = 0; i < n0; ++i)
278 {
279 c[0] = i;
280 f(c);
281 }
282 }
283 else if constexpr (rank == 2)
284 {
285 const auto n0 = static_cast<ca_index_t>(cur_.size(0));
286 const auto n1 = static_cast<ca_index_t>(cur_.size(1));
287 for (ca_index_t i = 0; i < n0; ++i)
288 for (ca_index_t j = 0; j < n1; ++j)
289 {
290 c[0] = i;
291 c[1] = j;
292 f(c);
293 }
294 }
295 else if constexpr (rank == 3)
296 {
297 const auto n0 = static_cast<ca_index_t>(cur_.size(0));
298 const auto n1 = static_cast<ca_index_t>(cur_.size(1));
299 const auto n2 = static_cast<ca_index_t>(cur_.size(2));
300 for (ca_index_t i = 0; i < n0; ++i)
301 for (ca_index_t j = 0; j < n1; ++j)
302 for (ca_index_t k = 0; k < n2; ++k)
303 {
304 c[0] = i;
305 c[1] = j;
306 c[2] = k;
307 f(c);
308 }
309 }
310 else
311 static_assert(rank <= 3, "Multi_Field_Engine currently supports rank <= 3");
312 }
313};
314
315} // namespace CA
316} // namespace Aleph
317
318#endif // TPL_CA_MULTI_FIELD_ENGINE_H
size_t steps
Definition ca-c-api.h:126
Common typedefs and tag types for the Cellular Automata module.
Lattice that adds boundary-aware access on top of a storage.
typename Storage::extents_type extents_type
const extents_type & extents() const noexcept
void swap(Lattice &other) noexcept(noexcept(store_.swap(other.store_)))
O(1) swap.
typename Storage::coord_type coord_type
static constexpr std::size_t rank
ca_size_t size() const noexcept
Synchronous double-buffered engine for multi-field lattices.
void run(const std::size_t steps)
Run several steps.
typename Lattice::coord_type coord_type
Multi_Field_Engine(Lattice initial, Rule r)
Build with a default-constructed neighbourhood.
Multi_Field_Engine(Lattice initial, Rule r, Neighborhood n)
Build a multi-field engine.
void step()
Apply the multi-field rule to every cell once and swap buffers.
void on_pre_step(F &&f)
Register a hook fired before every step().
static constexpr std::size_t rank
void write_cell(const coord_type &c, const fields_tuple &v, std::index_sequence< I... >)
static constexpr std::size_t neighbour_count
const extents_type & extents() const noexcept
static constexpr std::size_t field_count
void on_post_step(F &&f)
Register a hook fired after every step().
typename Lattice::extents_type extents_type
const Lattice & frame() const noexcept
static auto make_buffers(std::index_sequence< I... >)
std::size_t steps_run() const noexcept
std::function< void(std::size_t, const Lattice &)> hook_type
Hook signature: (step_index_just_completed, frame).
typename Lattice::field_types fields_tuple
Shape (per-axis sizes) of an mdspan, mixing compile-time and run-time extents.
Definition ah-mdspan.H:303
A coordinate type with N integral components.
Concept: a lattice that exposes the multi-field interface.
Connectivity pattern around a coordinate.
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
auto build_views(const Lattice &lat, const Neighborhood &nh, const typename Lattice::coord_type &center, Buffers &bufs, std::index_sequence< I... >)
Recurse over the Field_Indices and gather one Neighbor_View per field.
@ I
Infected (and infectious).
std::span< const T > Neighbor_View
Read-only view over a contiguous range of neighbour values.
Definition ca-traits.H:90
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
Definition ca-traits.H:60
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
STL namespace.
Per-cell context handed to rules that need to know "where" and "when" they are firing.
Definition ca-traits.H:106
static int * k
gsl_rng * r
C++20 concepts for the Cellular Automata module.
Phase 14 multi-field cellular automata lattice (AoS / SoA).
Phase 14 multi-field local rules for Aleph::CA.
Neighborhoods catalogue for Aleph::CA.