Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_ca_triangular_lattice_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
44#include <set>
45#include <string>
46
47#include <gtest/gtest.h>
48
49#include <ca-traits.H>
50#include <tpl_ca_concepts.H>
51#include <tpl_ca_engine.H>
52#include <tpl_ca_neighborhood.H>
53#include <tpl_ca_rule.H>
54#include <tpl_ca_storage.H>
56
57using namespace Aleph;
58using namespace Aleph::CA;
59
61static_assert(LatticeLike<Tri_2D>);
62
63// ---------------------------------------------------------------------------
64// Parity helpers.
65// ---------------------------------------------------------------------------
66
68{
73 for (ca_index_t i = -3; i <= 3; ++i)
74 for (ca_index_t j = -3; j <= 3; ++j)
76 static_cast<int>(((i + j) % 2 + 2) % 2));
77}
78
80{
81 std::set<std::pair<long long, long long>> seen;
82 for (ca_index_t i = 0; i < 6; ++i)
83 for (ca_index_t j = 0; j < 6; ++j)
84 {
85 const auto px = tri_pixel_centre(Tri_Coord{i, j}, 1.0);
86 const auto key = std::pair<long long, long long>(
87 static_cast<long long>(px[0] * 1e6),
88 static_cast<long long>(px[1] * 1e6));
89 EXPECT_TRUE(seen.insert(key).second)
90 << "duplicate pixel for (i=" << i << ", j=" << j << ")";
91 }
92}
93
94// ---------------------------------------------------------------------------
95// Lattice accessors.
96// ---------------------------------------------------------------------------
97
99{
100 Tri_2D lat({3, 4}, 0);
101 for (ca_index_t i = 0; i < 3; ++i)
102 for (ca_index_t j = 0; j < 4; ++j)
103 lat.set_tri(Tri_Coord{i, j}, static_cast<int>(i * 10 + j));
104 for (ca_index_t i = 0; i < 3; ++i)
105 for (ca_index_t j = 0; j < 4; ++j)
106 EXPECT_EQ(lat.at_tri(Tri_Coord{i, j}), i * 10 + j);
107}
108
110{
111 Tri_2D lat({3, 3}, 9);
112 EXPECT_EQ(lat.at_tri_safe(Tri_Coord{-1, 0}), 0);
113 EXPECT_EQ(lat.at_tri_safe(Tri_Coord{0, 3}), 0);
114 EXPECT_EQ(lat.at_tri_safe(Tri_Coord{1, 1}), 9);
115}
116
117// ---------------------------------------------------------------------------
118// Engine integration.
119// ---------------------------------------------------------------------------
120
121namespace {
122
123// Toy rule: cell becomes alive iff it has *at least one* alive
124// neighbour (parity-aware via `Triangular_Neighborhood`). Once alive
125// it stays alive. This is enough to verify that the engine routes
126// through the parity-dependent neighbourhood correctly.
127struct Spread_Once_Functor
128{
129 template <typename State>
130 [[nodiscard]] constexpr State operator()(const State &current,
131 const std::size_t alive) const noexcept
132 {
133 return (current != State{} or alive >= 1) ? static_cast<State>(1)
134 : static_cast<State>(0);
135 }
136};
137
138} // namespace
139
141{
143 L seed({3, 3}, 0);
144 // Place the seed at an "up" triangle.
145 seed.set_tri(Tri_Coord{1, 1}, 1);
146
149 seed, Rule{Spread_Once_Functor{}}, Triangular_Neighborhood{});
150 eng.run(1);
151
152 // Expected three alive neighbours of (1, 1) under the up triangle
153 // parity rule of `Triangular_Neighborhood`: (1,0), (1,2), (2,1).
154 EXPECT_EQ(eng.frame().at_tri(Tri_Coord{1, 0}), 1);
155 EXPECT_EQ(eng.frame().at_tri(Tri_Coord{1, 2}), 1);
156 EXPECT_EQ(eng.frame().at_tri(Tri_Coord{2, 1}), 1);
157 // The seed itself stays alive.
158 EXPECT_EQ(eng.frame().at_tri(Tri_Coord{1, 1}), 1);
159 // A non-edge-neighbour (different parity, no shared edge) stays dead.
160 EXPECT_EQ(eng.frame().at_tri(Tri_Coord{0, 0}), 0);
161}
162
164{
166 L seed({4, 4}, 0);
167 seed.set_tri(Tri_Coord{0, 0}, 1);
168
171 seed, Rule{Spread_Once_Functor{}}, Triangular_Neighborhood{});
172 eng.run(20); // ample to saturate a 4x4 connected lattice
173
174 for (ca_index_t i = 0; i < 4; ++i)
175 for (ca_index_t j = 0; j < 4; ++j)
176 EXPECT_EQ(eng.frame().at_tri(Tri_Coord{i, j}), 1);
177}
178
179// ---------------------------------------------------------------------------
180// TikZ sanity.
181// ---------------------------------------------------------------------------
182
184{
185 Tri_2D lat({2, 2}, 0);
186 lat.set_tri(Tri_Coord{0, 1}, 1);
187 const std::string out = render_triangular_lattice_tikz(
188 lat, [](int v) { return v != 0 ? std::string("blue") : std::string("white"); });
189 EXPECT_NE(out.find("regular polygon sides=3"), std::string::npos);
190 EXPECT_NE(out.find("fill=blue"), std::string::npos);
191 EXPECT_NE(out.find("rotate=180"), std::string::npos); // down triangle
192 EXPECT_NE(out.find("rotate=0"), std::string::npos); // up triangle
193}
size_t size_t int32_t * out
Definition ca-c-api.h:120
Common typedefs and tag types for the Cellular Automata module.
Rule whose next state depends on (current, alive_count).
Definition tpl_ca_rule.H:99
Synchronous double-buffered engine.
void run(const std::size_t steps)
Run several synchronous steps.
Triangular lattice with parity helpers over a 2D storage.
void set_tri(Tri_Coord c, const state_type &v)
Write cell value at triangular coords (i, j) (strict).
Three edge-neighbours over a 2D lattice with parity coupling.
#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
constexpr int tri_parity(const Tri_Coord &c) noexcept
std::array< double, 2 > tri_pixel_centre(const Tri_Coord &c, const double side) noexcept
Cartesian centre of a triangle in (i, j) units.
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
Definition ca-traits.H:60
constexpr bool tri_is_down(const Tri_Coord &c) noexcept
constexpr bool tri_is_up(const Tri_Coord &c) noexcept
void render_triangular_lattice_tikz(std::ostream &os, const Lattice &lat, Palette &&palette, const double side=1.0)
Render a triangular frame as a TikZ picture.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Out-of-range neighbours behave as if the lattice ended.
Definition ca-traits.H:119
Coordinates of a triangular cell as (i, j) integers.
ValueArg< size_t > seed
Definition testHash.C:53
C++20 concepts for the Cellular Automata module.
Synchronous double-buffered engine for cellular automata.
Neighborhoods catalogue for Aleph::CA.
Rule mechanisms for Aleph::CA.
Dense, contiguous storage for cellular automata cells (1D/2D/3D).
Triangular lattice with up/down parity helpers and pixel mapping suitable for visualisation.