CDT++ 1.0.0
Causal Dynamical Triangulations in C++
Loading...
Searching...
No Matches
Move_run.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 Causal Dynamical Triangulations in C++ using CGAL
3
4 Copyright © 2026 Adam Getchell
5 ******************************************************************************/
6
9
10#ifndef CDT_PLUSPLUS_MOVE_RUN_HPP
11#define CDT_PLUSPLUS_MOVE_RUN_HPP
12
13#include <fmt/format.h>
14
15#include <expected>
16#include <functional>
17#include <limits>
18#include <stdexcept>
19#include <string_view>
20#include <utility>
21
22#include "Move_tracker.hpp"
23#include "Random.hpp"
24
25namespace cdt
26{
33
37 class MoveRunCadence
38 {
39 struct Parsed
40 {};
41
42 Int_precision m_passes{1};
43 Int_precision m_checkpoint{1};
44
46 Parsed /*proof*/) noexcept
47 : m_passes{passes}, m_checkpoint{checkpoint}
48 {}
49
50 public:
52 MoveRunCadence() = default;
53
62 [[nodiscard]] static auto parse(Int_precision const passes,
63 Int_precision const checkpoint) noexcept
64 -> std::expected<MoveRunCadence, MoveRunCadenceError>
65 {
66 if (passes <= 0)
67 {
68 return std::unexpected{MoveRunCadenceError::NONPOSITIVE_PASSES};
69 }
70 if (checkpoint <= 0)
71 {
72 return std::unexpected{MoveRunCadenceError::NONPOSITIVE_CHECKPOINT};
73 }
74 return MoveRunCadence{passes, checkpoint, Parsed{}};
75 }
76
78 [[nodiscard]] constexpr auto passes() const noexcept { return m_passes; }
79
81 [[nodiscard]] constexpr auto checkpoint() const noexcept
82 { return m_checkpoint; }
83 };
84
85 namespace detail
86 {
89 [[nodiscard]] inline auto parse_move_run_cadence(
90 Int_precision const passes, Int_precision const checkpoint,
91 std::string_view const strategy_name) -> MoveRunCadence
92 {
93 auto cadence = MoveRunCadence::parse(passes, checkpoint);
94 if (cadence) { return *cadence; }
95
96 switch (cadence.error())
97 {
99 throw std::invalid_argument{
100 fmt::format("{} passes must be positive", strategy_name)};
102 throw std::invalid_argument{fmt::format(
103 "{} checkpoint interval must be positive", strategy_name)};
104 }
105 throw std::logic_error{"Unknown move-run cadence error"};
106 }
107
109 template <typename ManifoldType>
110 requires(ManifoldType::dimension == 3)
111 struct MoveCommandResults
112 {
113 using Counter = move_tracker::MoveTracker;
114
115 Counter attempted;
116 Counter succeeded;
117 Counter failed;
118 };
119
121 template <typename ManifoldType>
122 [[nodiscard]] auto accumulate_command_results(
123 MoveCommandResults<ManifoldType> totals,
124 MoveCommandResults<ManifoldType> const& delta)
125 -> MoveCommandResults<ManifoldType>
126 {
127 totals.attempted += delta.attempted;
128 totals.succeeded += delta.succeeded;
129 totals.failed += delta.failed;
130 return totals;
131 }
132
134 template <typename ManifoldType, typename Command>
135 [[nodiscard]] auto consume_command_results(Command& command)
136 -> MoveCommandResults<ManifoldType>
137 {
138 MoveCommandResults<ManifoldType> result{.attempted = command.attempted(),
139 .succeeded = command.succeeded(),
140 .failed = command.failed()};
141 command.reset_counters();
142 return result;
143 }
144
146 template <typename ManifoldType, typename StrategyState>
147 struct MovePassResult
148 {
149 ManifoldType manifold;
150 MoveCommandResults<ManifoldType> command_results;
151 StrategyState strategy_state;
152 };
153
155 template <typename ManifoldType, typename StrategyState>
156 struct MoveRunResult
157 {
158 ManifoldType manifold;
159 MoveCommandResults<ManifoldType> command_results;
160 StrategyState strategy_state;
161 Int_precision checkpoint_events{};
162 };
163
165 struct MoveRunIdentity
166 {
167 std::string_view algorithm;
168 cdt::RandomSeed seed;
169 cdt::RandomStream stream;
170 };
171
177 template <typename ManifoldType, typename StrategyState,
178 typename ExecutePass, typename Report, typename Checkpoint>
179 [[nodiscard]] auto execute_move_run(
180 ManifoldType initial,
181 MoveCommandResults<ManifoldType> initial_command_results,
182 StrategyState initial_strategy_state,
183 Int_precision const completed_passes, MoveRunCadence const cadence,
184 MoveRunIdentity const identity, bool const writes_files,
185 ExecutePass execute_pass, Report report, Checkpoint checkpoint)
186 -> MoveRunResult<ManifoldType, StrategyState>
187 {
188 if (completed_passes < 0 ||
189 completed_passes >
190 std::numeric_limits<Int_precision>::max() - cadence.passes())
191 {
192 throw std::invalid_argument(
193 "Completed and configured passes exceed the supported range.");
194 }
195 auto current = std::move(initial);
196 auto command_totals = std::move(initial_command_results);
197 auto strategy_state = std::move(initial_strategy_state);
198 auto checkpoint_events = Int_precision{};
199
200 fmt::print("Starting {} algorithm in {}+1 dimensions ...\n",
201 identity.algorithm, ManifoldType::dimension - 1);
202 fmt::print("Effective random seed: {} (stream {}).\n", identity.seed,
203 identity.stream);
204 fmt::print("Making random moves ...\n");
205
206 for (auto pass_index = Int_precision{}; pass_index < cadence.passes();
207 ++pass_index)
208 {
209 auto const pass_number = completed_passes + pass_index + 1;
210 fmt::print("=== Pass {} ===\n", pass_number);
211 auto const attempts = current.N3();
212 auto pass = std::invoke(execute_pass, std::move(current),
213 std::move(strategy_state), attempts);
214 current = std::move(pass.manifold);
215 command_totals = accumulate_command_results(std::move(command_totals),
216 pass.command_results);
217 strategy_state = std::move(pass.strategy_state);
218
219 if (pass_number % cadence.checkpoint() == 0)
220 {
221 ++checkpoint_events;
222 std::invoke(report, std::as_const(current),
223 std::as_const(command_totals),
224 std::as_const(strategy_state));
225 if (writes_files)
226 {
227 fmt::print("Writing checkpoint for pass {}.\n", pass_number);
228 std::invoke(checkpoint, std::as_const(current),
229 std::as_const(command_totals),
230 std::as_const(strategy_state), pass_number);
231 }
232 }
233 }
234
235 fmt::print("=== Run results ===\n");
236 std::invoke(report, std::as_const(current), std::as_const(command_totals),
237 std::as_const(strategy_state));
238 return {.manifold = std::move(current),
239 .command_results = std::move(command_totals),
240 .strategy_state = std::move(strategy_state),
241 .checkpoint_events = checkpoint_events};
242 }
243 } // namespace detail
244} // namespace cdt
245
246#endif // CDT_PLUSPLUS_MOVE_RUN_HPP
auto consume_command_results(Command &command) -> MoveCommandResults< ManifoldType >
Consume cumulative MoveCommand counters exactly once.
Definition Move_run.hpp:135
auto accumulate_command_results(MoveCommandResults< ManifoldType > totals, MoveCommandResults< ManifoldType > const &delta) -> MoveCommandResults< ManifoldType >
Add one pass delta to accumulated command results.
Definition Move_run.hpp:122
auto parse_move_run_cadence(Int_precision const passes, Int_precision const checkpoint, std::string_view const strategy_name) -> MoveRunCadence
Convert a raw constructor boundary or throw its established error.
Definition Move_run.hpp:89
auto execute_move_run(ManifoldType initial, MoveCommandResults< ManifoldType > initial_command_results, StrategyState initial_strategy_state, Int_precision const completed_passes, MoveRunCadence const cadence, MoveRunIdentity const identity, bool const writes_files, ExecutePass execute_pass, Report report, Checkpoint checkpoint) -> MoveRunResult< ManifoldType, StrategyState >
Execute shared pass, accounting, checkpoint, and report cadence.
Definition Move_run.hpp:179
Track ergodic moves.
Run-owned random-number generation and reproducible stream splitting.
Positive pass count and checkpoint interval for a move run.
Definition Move_run.hpp:38
constexpr auto passes() const noexcept
Definition Move_run.hpp:78
MoveRunCadence()=default
Construct the valid single-pass default cadence.
static auto parse(Int_precision const passes, Int_precision const checkpoint) noexcept -> std::expected< MoveRunCadence, MoveRunCadenceError >
Parse raw counts into a cadence that proves positivity.
Definition Move_run.hpp:62
constexpr auto checkpoint() const noexcept
Definition Move_run.hpp:81
The data and methods to track ergodic moves.
clang-15 does not support std::format
std::int32_t Int_precision
Definition Settings.hpp:30
MoveRunCadenceError
Reasons raw move-run cadence cannot become a domain value.
Definition Move_run.hpp:29
@ NONPOSITIVE_CHECKPOINT
The checkpoint interval is not positive.
Definition Move_run.hpp:31
@ NONPOSITIVE_PASSES
The requested pass count is not positive.
Definition Move_run.hpp:30