13#include <doctest/doctest.h>
14#include <fmt/ranges.h>
17using namespace manifolds;
19SCENARIO(
"MoveCommand special members" * doctest::test_suite(
"move_command"))
21 spdlog::debug(
"MoveCommand special members.\n");
22 GIVEN(
"A MoveCommand.")
24 WHEN(
"It's properties are examined.")
26 THEN(
"It is no-throw destructible.")
29 spdlog::debug(
"It is no-throw destructible.\n");
31 THEN(
"It is not default constructible.")
35 THEN(
"It is copy constructible.")
38 spdlog::debug(
"It is copy constructible.\n");
40 THEN(
"It is copy assignable.")
43 spdlog::debug(
"It is copy assignable.\n");
45 THEN(
"It is no-throw move constructible.")
48 spdlog::debug(
"Small function optimization supported.");
49 spdlog::debug(
"It is no-throw move constructible.\n");
51 THEN(
"It is no-throw move assignable.")
54 spdlog::debug(
"It is no-throw move assignable.\n");
56 THEN(
"It is no-throw swappable")
59 spdlog::debug(
"It is no-throw swappable.\n");
61 THEN(
"It is constructible from a Manifold.")
64 spdlog::debug(
"It is constructible from a Manifold.\n");
70SCENARIO(
"Invoking a move with a function pointer" *
71 doctest::test_suite(
"move_command"))
73 spdlog::debug(
"Invoking a move with a function pointer.\n");
74 GIVEN(
"A valid manifold.")
76 auto constexpr desired_simplices = 640;
77 auto constexpr desired_timeslices = 4;
78 Manifold_3 manifold(desired_simplices, desired_timeslices);
79 REQUIRE(manifold.is_correct());
80 WHEN(
"A function pointer is constructed for a move.")
83 THEN(
"Running the function makes the move.")
85 auto result = move23(manifold);
87 CHECK(ergodic_moves::check_move(manifold, result.value(),
88 move_tracker::move_type::TWO_THREE));
90 fmt::print(
"Manifold properties:\n");
91 manifold.print_details();
92 fmt::print(
"Moved manifold properties:\n");
93 result->print_details();
99SCENARIO(
"Invoking a move with a lambda" * doctest::test_suite(
"move_command"))
101 spdlog::debug(
"Invoking a move with a lambda.\n");
102 GIVEN(
"A valid manifold.")
104 auto constexpr desired_simplices = 640;
105 auto constexpr desired_timeslices = 4;
106 Manifold_3 manifold(desired_simplices, desired_timeslices);
107 REQUIRE(manifold.is_correct());
108 WHEN(
"A lambda is constructed for a move.")
110 auto const move23 = [](
Manifold_3& manifold_3) {
113 THEN(
"Running the lambda makes the move.")
115 auto result = move23(manifold);
117 CHECK(ergodic_moves::check_move(manifold, result,
118 move_tracker::move_type::TWO_THREE));
120 fmt::print(
"Manifold properties:\n");
121 manifold.print_details();
122 fmt::print(
"Moved manifold properties:\n");
123 result.print_details();
129SCENARIO(
"Invoking a move with apply_move and a function pointer" *
130 doctest::test_suite(
"move_command"))
132 spdlog::debug(
"Invoking a move with apply_move and a function pointer.\n");
133 GIVEN(
"A valid manifold.")
135 auto constexpr desired_simplices = 640;
136 auto constexpr desired_timeslices = 4;
137 Manifold_3 manifold(desired_simplices, desired_timeslices);
138 REQUIRE(manifold.is_correct());
139 WHEN(
"Apply_move is used for a move.")
142 THEN(
"Invoking apply_move() makes the move.")
146 CHECK(ergodic_moves::check_move(manifold, result.value(),
147 move_tracker::move_type::TWO_THREE));
149 fmt::print(
"Manifold properties:\n");
150 manifold.print_details();
151 fmt::print(
"Moved manifold properties:\n");
152 result->print_details();
158SCENARIO(
"MoveCommand initialization" * doctest::test_suite(
"move_command"))
160 spdlog::debug(
"MoveCommand initialization.\n");
161 GIVEN(
"A valid manifold.")
163 auto constexpr desired_simplices = 640;
164 auto constexpr desired_timeslices = 4;
165 Manifold_3 manifold(desired_simplices, desired_timeslices);
166 REQUIRE(manifold.is_correct());
167 WHEN(
"A Command is constructed with a manifold.")
170 THEN(
"The original is still valid.")
172 REQUIRE(manifold.is_correct());
174 manifold.print_details();
176 THEN(
"It contains the manifold.")
178 CHECK_EQ(manifold.N3(), command.get_const_results().N3());
179 CHECK_EQ(manifold.N3_31(), command.get_const_results().N3_31());
180 CHECK_EQ(manifold.N3_22(), command.get_const_results().N3_22());
181 CHECK_EQ(manifold.N3_13(), command.get_const_results().N3_13());
182 CHECK_EQ(manifold.N3_31_13(), command.get_const_results().N3_31_13());
183 CHECK_EQ(manifold.N2(), command.get_const_results().N2());
184 CHECK_EQ(manifold.N1(), command.get_const_results().N1());
185 CHECK_EQ(manifold.N1_TL(), command.get_const_results().N1_TL());
186 CHECK_EQ(manifold.N1_SL(), command.get_const_results().N1_SL());
187 CHECK_EQ(manifold.N0(), command.get_const_results().N0());
188 CHECK_EQ(manifold.max_time(), command.get_const_results().max_time());
189 CHECK_EQ(manifold.min_time(), command.get_const_results().min_time());
191 fmt::print(
"Manifold properties:\n");
192 manifold.print_details();
193 manifold.print_volume_per_timeslice();
194 fmt::print(
"Command.get_const_results() properties:\n");
195 command.get_const_results().print_details();
196 command.get_const_results().print_volume_per_timeslice();
198 THEN(
"The two manifolds are distinct.")
200 auto* manifold_ptr = &manifold;
201 auto const* manifold2_ptr = &command.get_const_results();
202 CHECK_NE(manifold_ptr, manifold2_ptr);
204 THEN(
"Attempted, succeeded, and failed moves are initialized to 0.")
206 CHECK_EQ(command.get_attempted().total(), 0);
207 CHECK_EQ(command.get_succeeded().total(), 0);
208 CHECK_EQ(command.get_failed().total(), 0);
211 fmt::print(
"Attempted moves are {}\n",
212 command.get_attempted().moves_view());
213 fmt::print(
"Successful moves are {}\n",
214 command.get_succeeded().moves_view());
215 fmt::print(
"Failed moves are {}\n", command.get_failed().moves_view());
221SCENARIO(
"Queueing and executing moves" * doctest::test_suite(
"move_command"))
223 spdlog::debug(
"Queueing and executing moves.\n");
224 GIVEN(
"A valid manifold.")
226 auto constexpr desired_simplices = 9600;
227 auto constexpr desired_timeslices = 7;
228 Manifold_3 manifold(desired_simplices, desired_timeslices);
229 REQUIRE(manifold.is_correct());
230 WHEN(
"Move_command copies the manifold and applies the move.")
232 THEN(
"The original is not mutated.")
238 command.enqueue(move_tracker::move_type::THREE_TWO);
244 CHECK_EQ(command.get_attempted().three_two_moves(), 1);
247 CHECK_EQ(command.get_succeeded().three_two_moves(), 1);
250 CHECK_EQ(command.get_failed().three_two_moves(), 0);
253 auto result = command.get_results();
256 auto* manifold_ptr = &manifold;
257 auto* result_ptr = &result;
258 REQUIRE_FALSE(manifold_ptr == result_ptr);
260 "The manifold and the result in the MoveCommand are distinct "
264 CHECK_NE(manifold.N3_22(), result.N3_22());
265 CHECK_NE(manifold.N1_TL(), result.N1_TL());
266 fmt::print(
"The original manifold is unchanged by Move_command.\n");
269 WHEN(
"A (4,4) move is queued.")
272 command.enqueue(move_tracker::move_type::FOUR_FOUR);
273 THEN(
"It is executed correctly.")
279 CHECK_EQ(command.get_attempted().four_four_moves(), 1);
282 CHECK_EQ(command.get_succeeded().four_four_moves(), 1);
285 CHECK_EQ(command.get_failed().four_four_moves(), 0);
288 auto const& result = command.get_results();
291 CHECK_EQ(result.get_triangulation().number_of_finite_cells(),
292 manifold.get_triangulation().number_of_finite_cells());
293 REQUIRE(ergodic_moves::check_move(manifold, result,
294 move_tracker::move_type::FOUR_FOUR));
295 fmt::print(
"Move left triangulation unchanged.\n");
298 WHEN(
"A (2,3) move is queued.")
301 command.enqueue(move_tracker::move_type::TWO_THREE);
302 THEN(
"It is executed correctly.")
308 CHECK_EQ(command.get_attempted().two_three_moves(), 1);
311 CHECK_EQ(command.get_succeeded().two_three_moves(), 1);
314 CHECK_EQ(command.get_failed().two_three_moves(), 0);
317 auto const& result = command.get_const_results();
320 CHECK_EQ(result.get_triangulation().number_of_finite_cells(),
321 manifold.get_triangulation().number_of_finite_cells() + 1);
322 REQUIRE(ergodic_moves::check_move(manifold, result,
323 move_tracker::move_type::TWO_THREE));
324 fmt::print(
"Triangulation added a finite cell.\n");
327 WHEN(
"A (3,2) move is queued.")
330 command.enqueue(move_tracker::move_type::THREE_TWO);
331 THEN(
"It is executed correctly.")
337 CHECK_EQ(command.get_attempted().three_two_moves(), 1);
340 CHECK_EQ(command.get_succeeded().three_two_moves(), 1);
343 CHECK_EQ(command.get_failed().three_two_moves(), 0);
346 auto const& result = command.get_const_results();
349 CHECK_EQ(result.get_triangulation().number_of_finite_cells(),
350 manifold.get_triangulation().number_of_finite_cells() - 1);
351 REQUIRE(ergodic_moves::check_move(manifold, result,
352 move_tracker::move_type::THREE_TWO));
353 fmt::print(
"Triangulation removed a finite cell.\n");
356 WHEN(
"A (2,6) move is queued.")
359 command.enqueue(move_tracker::move_type::TWO_SIX);
360 THEN(
"It is executed correctly.")
366 CHECK_EQ(command.get_attempted().two_six_moves(), 1);
369 CHECK_EQ(command.get_succeeded().two_six_moves(), 1);
372 CHECK_EQ(command.get_failed().two_six_moves(), 0);
375 auto const& result = command.get_const_results();
378 CHECK_EQ(result.get_triangulation().number_of_finite_cells(),
379 manifold.get_triangulation().number_of_finite_cells() + 4);
380 REQUIRE(ergodic_moves::check_move(manifold, result,
381 move_tracker::move_type::TWO_SIX));
382 fmt::print(
"Triangulation added 4 finite cells.\n");
385 WHEN(
"A (6,2) move is queued.")
388 command.enqueue(move_tracker::move_type::SIX_TWO);
389 THEN(
"It is executed correctly.")
395 CHECK_EQ(command.get_attempted().six_two_moves(), 1);
398 CHECK_EQ(command.get_succeeded().six_two_moves(), 1);
401 CHECK_EQ(command.get_failed().six_two_moves(), 0);
404 auto const& result = command.get_const_results();
407 CHECK_EQ(result.get_triangulation().number_of_finite_cells(),
408 manifold.get_triangulation().number_of_finite_cells() - 4);
409 CHECK(ergodic_moves::check_move(manifold, result,
410 move_tracker::move_type::SIX_TWO));
411 fmt::print(
"Triangulation removed 4 finite cells.\n");
416SCENARIO(
"Executing multiple moves on the queue" *
417 doctest::test_suite(
"move_command"))
419 spdlog::debug(
"Executing multiple moves on the queue.\n");
420 GIVEN(
"A valid manifold")
422 auto constexpr desired_simplices = 9600;
423 auto constexpr desired_timeslices = 7;
424 Manifold_3 const manifold(desired_simplices, desired_timeslices);
425 REQUIRE(manifold.is_correct());
426 WHEN(
"(2,3) and (3,2) moves are queued.")
429 command.enqueue(move_tracker::move_type::TWO_THREE);
430 command.enqueue(move_tracker::move_type::THREE_TWO);
431 THEN(
"There are two moves in the queue.") { CHECK_EQ(command.size(), 2); }
432 THEN(
"The moves are executed correctly.")
438 CHECK_EQ(command.get_attempted().total(), 2);
439 command.print_attempts();
442 auto successful_23_moves = command.get_succeeded().two_three_moves();
443 CHECK_EQ(successful_23_moves, 1);
444 fmt::print(
"There was {} successful (2,3) move.\n",
445 successful_23_moves);
448 auto successful_32_moves = command.get_succeeded().three_two_moves();
449 CHECK_EQ(successful_32_moves, 1);
450 fmt::print(
"There was {} successful (3,2) move.\n",
451 successful_32_moves);
454 CHECK_EQ(command.get_failed().total(), 0);
455 command.print_errors();
458 auto const& result = command.get_const_results();
461 CHECK_EQ(result.get_triangulation().number_of_finite_cells(),
462 manifold.get_triangulation().number_of_finite_cells());
463 REQUIRE(ergodic_moves::check_move(manifold, result,
464 move_tracker::move_type::FOUR_FOUR));
465 fmt::print(
"Triangulation moves cancelled out.");
468 WHEN(
"One of each move is queued.")
471 command.enqueue(move_tracker::move_type::TWO_THREE);
472 command.enqueue(move_tracker::move_type::TWO_SIX);
473 command.enqueue(move_tracker::move_type::FOUR_FOUR);
474 command.enqueue(move_tracker::move_type::SIX_TWO);
475 command.enqueue(move_tracker::move_type::THREE_TWO);
476 THEN(
"There are five moves in the queue.")
478 CHECK_EQ(command.size(), 5);
480 THEN(
"The moves are executed correctly.")
486 CHECK_EQ(command.get_attempted().total(), 5);
487 command.print_attempts();
490 auto successful_23_moves = command.get_succeeded().two_three_moves();
491 CHECK_EQ(successful_23_moves, 1);
492 fmt::print(
"There was {} successful (2,3) move.\n",
493 successful_23_moves);
496 auto successful_26_moves = command.get_succeeded().two_six_moves();
497 CHECK_EQ(successful_26_moves, 1);
498 fmt::print(
"There was {} successful (2,6) move.\n",
499 successful_26_moves);
502 auto successful_44_moves = command.get_succeeded().four_four_moves();
503 CHECK_EQ(successful_44_moves, 1);
504 fmt::print(
"There was {} successful (4,4) move.\n",
505 successful_44_moves);
508 auto successful_62_moves = command.get_succeeded().six_two_moves();
509 CHECK_EQ(successful_62_moves, 1);
510 fmt::print(
"There was {} successful (6,2) move.\n",
511 successful_62_moves);
514 auto successful_32_moves = command.get_succeeded().three_two_moves();
515 CHECK_EQ(successful_32_moves, 1);
516 fmt::print(
"There was {} successful (3,2) move.\n",
517 successful_32_moves);
520 CHECK_EQ(command.get_failed().total(), 0);
521 command.print_errors();
524 auto const& result = command.get_const_results();
527 CHECK_EQ(result.get_triangulation().number_of_finite_cells(),
528 manifold.get_triangulation().number_of_finite_cells());
529 REQUIRE(ergodic_moves::check_move(manifold, result,
530 move_tracker::move_type::FOUR_FOUR));
531 fmt::print(
"Triangulation moves cancelled out.");
auto constexpr apply_move(ManifoldType &&t_manifold, FunctionType t_move) noexcept -> decltype(auto)
An applicative function similar to std::apply on a manifold.
auto do_23_move(Manifold &t_manifold) -> Expected
Perform a (2,3) move.
Do ergodic moves using the Command pattern.
SCENARIO("Perform bistellar flip on Delaunay triangulation" *doctest::test_suite("bistellar"))