Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_ca_neighborhood_test.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 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
36# include <array>
37# include <cstdint>
38# include <set>
39# include <span>
40# include <stdexcept>
41
42# include <gtest/gtest.h>
43
44# include <ca-traits.H>
45# include <tpl_ca_concepts.H>
46# include <tpl_ca_storage.H>
47# include <tpl_ca_lattice.H>
48# include <tpl_ca_neighborhood.H>
49
50using namespace Aleph;
51using namespace Aleph::CA;
52
53// ---------------------------------------------------------------------------
54// Compile-time concept conformance.
55// ---------------------------------------------------------------------------
56
57static_assert(NeighborhoodLike<Moore<2, 1>>);
58static_assert(NeighborhoodLike<Moore<2, 2>>);
59static_assert(NeighborhoodLike<Moore<3, 1>>);
66
67// ---------------------------------------------------------------------------
68// Compile-time count checks.
69// ---------------------------------------------------------------------------
70
71static_assert(Moore<1, 1>::size_v == 2);
72static_assert(Moore<1, 2>::size_v == 4);
73static_assert(Moore<2, 1>::size_v == 8);
74static_assert(Moore<2, 2>::size_v == 24);
75static_assert(Moore<3, 1>::size_v == 26);
76
77static_assert(Von_Neumann<1, 1>::size_v == 2);
78static_assert(Von_Neumann<2, 1>::size_v == 4);
79static_assert(Von_Neumann<2, 2>::size_v == 12);
80static_assert(Von_Neumann<3, 1>::size_v == 6);
81static_assert(Von_Neumann<3, 2>::size_v == 24);
82
83static_assert(Hex_Neighborhood::size_v == 6);
84static_assert(Triangular_Neighborhood::size_v == 3);
85
86// ---------------------------------------------------------------------------
87// Moore — every offset must be unique, non-zero, and inside the radius.
88// ---------------------------------------------------------------------------
89
91{
93 EXPECT_EQ(nh.size(), 8u);
94 EXPECT_EQ(nh.radius(), 1u);
95
96 std::set<std::pair<int, int>> seen;
97 std::size_t calls = 0;
98 nh.for_each_offset({ 0, 0 }, [&](const auto & o)
99 {
100 ++calls;
101 EXPECT_FALSE(o[0] == 0 and o[1] == 0);
102 EXPECT_GE(o[0], -1); EXPECT_LE(o[0], 1);
103 EXPECT_GE(o[1], -1); EXPECT_LE(o[1], 1);
104 seen.emplace(static_cast<int>(o[0]), static_cast<int>(o[1]));
105 });
106 EXPECT_EQ(calls, 8u);
107 EXPECT_EQ(seen.size(), 8u);
108}
109
111{
113 std::size_t calls = 0;
114 nh.for_each_offset({ 0, 0 }, [&](const auto & o) {
115 ++calls;
116 EXPECT_FALSE(o[0] == 0 and o[1] == 0);
117 EXPECT_LE(std::max(std::abs((int)o[0]), std::abs((int)o[1])), 2);
118 });
119 EXPECT_EQ(calls, 24u);
120}
121
122// ---------------------------------------------------------------------------
123// Von Neumann — offsets satisfy L1 ≤ R and ≥ 1.
124// ---------------------------------------------------------------------------
125
127{
129 EXPECT_EQ(nh.size(), 4u);
130
131 std::set<std::pair<int, int>> seen;
132 nh.for_each_offset({ 0, 0 }, [&](const auto & o) {
133 seen.emplace(static_cast<int>(o[0]), static_cast<int>(o[1]));
134 });
135 EXPECT_EQ(seen.count({ -1, 0 }), 1u);
136 EXPECT_EQ(seen.count({ 1, 0 }), 1u);
137 EXPECT_EQ(seen.count({ 0, -1 }), 1u);
138 EXPECT_EQ(seen.count({ 0, 1 }), 1u);
139}
140
142{
144 std::size_t calls = 0;
145 nh.for_each_offset({ 0, 0 }, [&](const auto & o) {
146 ++calls;
147 const int s = std::abs((int)o[0]) + std::abs((int)o[1]);
148 EXPECT_GE(s, 1); EXPECT_LE(s, 2);
149 });
150 EXPECT_EQ(calls, 12u);
151}
152
153// ---------------------------------------------------------------------------
154// Hex
155// ---------------------------------------------------------------------------
156
158{
160 EXPECT_EQ(nh.size(), 6u);
161
162 std::set<std::pair<int, int>> seen;
163 nh.for_each_offset({ 0, 0 }, [&](const auto & o) {
164 seen.emplace(static_cast<int>(o[0]), static_cast<int>(o[1]));
165 });
166 EXPECT_EQ(seen.size(), 6u);
167 EXPECT_EQ(seen.count({ 1, 0 }), 1u);
168 EXPECT_EQ(seen.count({ -1, 0 }), 1u);
169 EXPECT_EQ(seen.count({ 0, 1 }), 1u);
170 EXPECT_EQ(seen.count({ 0, -1 }), 1u);
171 EXPECT_EQ(seen.count({ 1, -1 }), 1u);
172 EXPECT_EQ(seen.count({ -1, 1 }), 1u);
173}
174
175// ---------------------------------------------------------------------------
176// Triangular — third offset is parity-dependent.
177// ---------------------------------------------------------------------------
178
180{
182 EXPECT_EQ(nh.size(), 3u);
183
184 // Even parity (i+j even) → third offset is (1, 0).
185 std::set<std::pair<int, int>> seen_even;
186 nh.for_each_offset({ 0, 0 }, [&](const auto & o) {
187 seen_even.emplace(static_cast<int>(o[0]), static_cast<int>(o[1]));
188 });
189 EXPECT_EQ(seen_even.count({ 0, -1 }), 1u);
190 EXPECT_EQ(seen_even.count({ 0, 1 }), 1u);
191 EXPECT_EQ(seen_even.count({ 1, 0 }), 1u);
192
193 // Odd parity → third offset is (-1, 0).
194 std::set<std::pair<int, int>> seen_odd;
195 nh.for_each_offset({ 0, 1 }, [&](const auto & o) {
196 seen_odd.emplace(static_cast<int>(o[0]), static_cast<int>(o[1]));
197 });
198 EXPECT_EQ(seen_odd.count({ 0, -1 }), 1u);
199 EXPECT_EQ(seen_odd.count({ 0, 1 }), 1u);
200 EXPECT_EQ(seen_odd.count({ -1, 0 }), 1u);
201}
202
203// ---------------------------------------------------------------------------
204// Custom
205// ---------------------------------------------------------------------------
206
208{
210 Offset_Vec<2>{ 0, 2 },
211 Offset_Vec<2>{ -3, 1 } });
212 EXPECT_EQ(nh.size(), 3u);
213 EXPECT_EQ(nh.radius(), 3u); // largest |component| is 3
214
215 std::vector<std::pair<int, int>> seen;
216 nh.for_each_offset({ 0, 0 }, [&](const auto & o) {
217 seen.emplace_back(static_cast<int>(o[0]), static_cast<int>(o[1]));
218 });
219 ASSERT_EQ(seen.size(), 3u);
220 EXPECT_EQ(seen[0].first, 2); EXPECT_EQ(seen[0].second, 0);
221 EXPECT_EQ(seen[1].first, 0); EXPECT_EQ(seen[1].second, 2);
222 EXPECT_EQ(seen[2].first, -3); EXPECT_EQ(seen[2].second, 1);
223}
224
225// ---------------------------------------------------------------------------
226// gather_neighbors — boundary policy is honoured via at_safe.
227// ---------------------------------------------------------------------------
228
230{
232 for (ca_index_t i = 0; i < 3; ++i)
233 for (ca_index_t j = 0; j < 3; ++j)
234 lat.set({ i, j }, static_cast<int>(i * 10 + j));
235
237 std::array<int, Moore<2, 1>::size_v> buf { };
239 std::span<int>(buf.data(), buf.size()));
240
241 // Sum of all 8 neighbours of (0,0) under toroidal wrap on a 3x3
242 // lattice equals (sum of all cells) - cell(0,0). All cells: 0+1+2+
243 // 10+11+12+20+21+22 = 99. Minus cell(0,0) = 99.
244 int total = 0;
245 for (int v : buf) total += v;
246 EXPECT_EQ(total, 99);
247}
248
250{
253 std::array<int, Moore<2, 1>::size_v> buf { };
255 std::span<int>(buf.data(), buf.size()));
256
257 // (0,0) has only 3 in-range neighbours: (0,1), (1,0), (1,1). The
258 // remaining 5 read as 0 (open boundary).
259 int alive = 0;
260 for (int v : buf) if (v != 0) ++alive;
261 EXPECT_EQ(alive, 3);
262}
263
265{
268 std::array<int, 2> buf { };
270 std::span<int>(buf.data(), buf.size())),
271 std::length_error);
272}
Common typedefs and tag types for the Cellular Automata module.
User-supplied list of offsets for arbitrary connectivity.
Six-neighbour hex pattern in axial coordinates over a 2D lattice.
static constexpr std::size_t size_v
Number of neighbours (always 6).
Lattice that adds boundary-aware access on top of a storage.
Moore (Chebyshev) neighborhood of radius R in N dimensions.
constexpr void for_each_offset(const Coord_Vec< N > &center, F &&f) const
Apply a functor to each offset in the neighborhood.
Three edge-neighbours over a 2D lattice with parity coupling.
static constexpr std::size_t size_v
Number of neighbours (always 3).
Von Neumann (L1) neighborhood of radius R in N dimensions.
constexpr void for_each_offset(const Coord_Vec< N > &center, F &&f) const
Apply a functor to each offset in the neighborhood.
#define TEST(name)
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::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
Definition ca-traits.H:60
std::array< ca_index_t, N > Coord_Vec
Default coordinate vector.
Definition ca-traits.H:69
void gather_neighbors(const Nbh &nh, const L &lat, const typename L::coord_type &center, std::span< T > out)
Populate out[0..nh.size()) with neighbour values of center.
Coord_Vec< N > Offset_Vec
Default offset vector (aliases Coord_Vec).
Definition ca-traits.H:79
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Out-of-range neighbours behave as if the lattice ended.
Definition ca-traits.H:119
The lattice wraps around on every axis.
Definition ca-traits.H:124
C++20 concepts for the Cellular Automata module.
Cellular automata lattice with pluggable boundary policies.
Neighborhoods catalogue for Aleph::CA.
Dense, contiguous storage for cellular automata cells (1D/2D/3D).