CDT++ 1.0.0
Causal Dynamical Triangulations in C++
Loading...
Searching...
No Matches
Move_command.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 Causal Dynamical Triangulations in C++ using CGAL
3
4 Copyright © 2018 Adam Getchell
5 ******************************************************************************/
6
10
11#ifndef CDT_PLUSPLUS_MOVECOMMAND_HPP
12#define CDT_PLUSPLUS_MOVECOMMAND_HPP
13
14#include <spdlog/spdlog.h>
15
16#include "Ergodic_moves_3.hpp"
17#include "Random.hpp"
18
19namespace cdt
20{
23 template <typename ManifoldType>
24 requires(ManifoldType::dimension == 3)
26 {
27 using Queue = std::deque<move_tracker::MoveType>;
28 using Counter = move_tracker::MoveTracker;
30
34 ManifoldType m_manifold;
35
39 Queue m_moves;
40
44 Counter m_attempted;
45
49 Counter m_succeeded;
50
54 Counter m_failed;
55
56 public:
60 MoveCommand() = delete;
61
69 explicit MoveCommand(ManifoldType t_manifold)
70 : m_manifold{std::move(t_manifold)}
71 {}
72
77 [[nodiscard]] auto result() & noexcept -> ManifoldType&
78 { return m_manifold; }
79
84 [[nodiscard]] auto result() const& noexcept -> ManifoldType const&
85 { return m_manifold; }
86
91 [[nodiscard]] auto result() && noexcept -> ManifoldType
92 { return std::move(m_manifold); }
93
94 auto result() const&& -> ManifoldType = delete;
95
100 [[nodiscard]] auto attempted() const noexcept -> Counter const&
101 { return m_attempted; }
102
107 [[nodiscard]] auto succeeded() const noexcept -> Counter const&
108 { return m_succeeded; }
109
114 [[nodiscard]] auto failed() const noexcept -> Counter const&
115 { return m_failed; }
116
121 {
122 m_attempted.reset();
123 m_succeeded.reset();
124 m_failed.reset();
125 }
126
132 { m_moves.push_front(t_move); }
133
138 [[nodiscard]] auto size() const noexcept { return m_moves.size(); }
139
149 template <std::uniform_random_bit_generator Generator>
150 void execute(Generator& generator)
151 {
152 while (!m_moves.empty())
153 {
154 auto const move = m_moves.back();
155 // Record attempted move
156 ++m_attempted[move];
157 auto result =
158 apply_random_move(std::as_const(m_manifold), move, generator);
161 if (result &&
162 !ergodic_moves::detail::check_move(m_manifold, *result, move))
163 {
165 spdlog::warn(
166 "Move violated a manifold invariant or geometry delta.\n");
167 }
168
170 {
171 swap(result.value(), m_manifold);
172 ++m_succeeded[move];
173 }
174 else
175 {
176 ++m_failed[move];
177 }
178 // Remove move from queue
179 m_moves.pop_back();
180 }
181 } // execute
182
189 template <std::uniform_random_bit_generator Generator>
190 [[nodiscard]] static auto apply_random_move(
191 ManifoldType const& manifold, move_tracker::MoveType const move,
192 Generator& generator) -> MoveResult
193 {
194 using enum move_tracker::MoveType;
195 switch (move)
196 {
197 case TWO_THREE: return ergodic_moves::do_23_move(manifold, generator);
198 case THREE_TWO: return ergodic_moves::do_32_move(manifold, generator);
199 case TWO_SIX: return ergodic_moves::do_26_move(manifold, generator);
200 case SIX_TWO: return ergodic_moves::do_62_move(manifold, generator);
201 case FOUR_FOUR: return ergodic_moves::do_44_move(manifold, generator);
202 }
203 return std::unexpected{
206 .requested_move = move}
207 };
208 }
209
213 void print_attempts() const
214 {
215 fmt::print(
216 "There were {} attempted (2,3) moves and {} attempted (3,2) moves "
217 "and {} "
218 "attempted (2,6) moves and {} attempted (6,2) moves and {} attempted "
219 "(4,4) "
220 "moves.\n",
221 m_attempted.two_three_moves(), m_attempted.three_two_moves(),
222 m_attempted.two_six_moves(), m_attempted.six_two_moves(),
223 m_attempted.four_four_moves());
224 }
225
229 void print_successful() const
230 {
231 fmt::print(
232 "There were {} successful (2,3) moves and {} successful (3,2) moves "
233 "and {} "
234 "successful (2,6) moves and {} successful (6,2) moves and {} "
235 "successful "
236 "(4,4) "
237 "moves.\n",
238 m_succeeded.two_three_moves(), m_succeeded.three_two_moves(),
239 m_succeeded.two_six_moves(), m_succeeded.six_two_moves(),
240 m_succeeded.four_four_moves());
241 }
242
246 void print_errors() const
247 {
248 if (std::all_of(m_failed.moves_view().begin(),
249 m_failed.moves_view().end(),
250 [](auto const& value) { return value == 0; }))
251 {
252 fmt::print("There were no failed moves.\n");
253 }
254 else
255 {
256 fmt::print(
257 "There were {} failed (2,3) moves and {} failed (3,2) moves and {} "
258 "failed (2,6) moves and {} failed (6,2) moves and {} failed (4,4) "
259 "moves.\n",
260 m_failed.two_three_moves(), m_failed.three_two_moves(),
261 m_failed.two_six_moves(), m_failed.six_two_moves(),
262 m_failed.four_four_moves());
263 }
264 }
265 };
266} // namespace cdt
267
268#endif // CDT_PLUSPLUS_MOVECOMMAND_HPP
Pachner moves on 2+1 dimensional foliated Delaunay triangulations.
auto do_26_move(Manifold const &t_manifold, Generator &generator) -> Expected
Perform a (2,6) move.
auto do_32_move(Manifold const &t_manifold, Generator &generator) -> Expected
Perform a (3,2) move.
auto check_move(Manifold const &before, Manifold const &after, move_tracker::MoveType const &move) -> bool
Check tracked move deltas and essential CDT manifold invariants.
auto do_44_move(Manifold const &t_manifold, Generator &generator) -> Expected
Perform a (4,4) move.
auto do_62_move(Manifold const &t_manifold, Generator &generator) -> Expected
Perform a (6,2) move.
auto do_23_move(Manifold const &t_manifold, Generator &generator) -> Expected
Perform a (2,3) move.
constexpr auto outcome_from(MoveError const error) noexcept -> MoveOutcome
Classify a structured move error for counter accounting.
std::expected< ManifoldType, MoveError > MoveResult
Value returned by a fallible Pachner-move transformation.
@ EXECUTION_FAILED
Mutation failed after proposal preparation.
@ SUCCEEDED
The requested transition completed.
@ UNKNOWN_MOVE
The requested move kind is unsupported.
MoveType
The types of 3D ergodic moves.
Run-owned random-number generation and reproducible stream splitting.
auto result() const &noexcept -> ManifoldType const &
Access the result manifold without transferring ownership.
auto attempted() const noexcept -> Counter const &
Attempted moves by MoveCommand.
auto result() &&noexcept -> ManifoldType
Consume the result manifold.
void execute(Generator &generator)
Execute all moves in the queue on the manifold.
auto failed() const noexcept -> Counter const &
Failed moves by MoveCommand.
static auto apply_random_move(ManifoldType const &manifold, move_tracker::MoveType const move, Generator &generator) -> MoveResult
Apply one queued move using the caller-owned random stream.
void print_errors() const
Print move errors.
auto succeeded() const noexcept -> Counter const &
Successful moves by MoveCommand.
MoveCommand(ManifoldType t_manifold)
MoveCommand ctor.
void reset_counters()
Reset counters.
auto size() const noexcept
The number of moves on the queue.
void enqueue(move_tracker::MoveType const t_move)
Push a Pachner move onto the move queue.
MoveCommand()=delete
Remove default ctor.
void print_attempts() const
Print attempted moves.
void print_successful() const
Print successful moves.
auto result() &noexcept -> ManifoldType &
Access the result manifold without transferring ownership.
The data and methods to track ergodic moves.
clang-15 does not support std::format
Typed error returned by move preparation or private execution.