diff --git a/src/todd-coxeter.cpp b/src/todd-coxeter.cpp index b7ce76e8..d851c3e8 100644 --- a/src/todd-coxeter.cpp +++ b/src/todd-coxeter.cpp @@ -261,6 +261,8 @@ semigroup. :rtype: ToddCoxeter )pbdoc"); + //////////////////////////////////////////////////////////////////////// + thing.def( "current_index_of", [](ToddCoxeter_ const& self, Word const& w) { @@ -377,39 +379,14 @@ node corresponding to index *i* back to the root of that tree. )pbdoc"); //////////////////////////////////////////////////////////////////////// - // Helpers from cong-common.hpp . . . + // Lookahead/behind //////////////////////////////////////////////////////////////////////// - auto raises = R"pbdoc( -:raises LibsemigroupsError: - if the number of classes in *tc* is infinite. In this case, the - enumeration of *tc* will not terminate successfully.)pbdoc"sv; - - def_partition>( - m, - "ToddCoxeter", - "todd_coxeter", - doc{.only_document_once = true, .raises = raises, .var = "tc"}); - - def_non_trivial_classes>( - m, - "ToddCoxeter", - "todd_coxeter", - doc{.only_document_once = true, .raises = raises, .var = "tc"}); - - def_normal_forms>(m, - "ToddCoxeter", - "todd_coxeter", - doc{.detail = R"pbdoc( -The order of the classes, and the normal forms, that are returned are -controlled by :any:`ToddCoxeter.standardize`. This function triggers a full -enumeration of ``tc``.)pbdoc", - .only_document_once = true, - .raises = raises, - .var = "tc"}); thing.def( "perform_lookahead", - [](ToddCoxeter_& self) { return self.perform_lookahead(); }, + [](ToddCoxeter_& self) -> detail::ToddCoxeterImpl& { + return self.perform_lookahead(); + }, R"pbdoc( :sig=(self: ToddCoxeter) -> ToddCoxeter: @@ -429,7 +406,8 @@ style and extent of this lookahead are controlled by the settings thing.def( "perform_lookahead_for", - [](ToddCoxeter_& self, std::chrono::nanoseconds t) { + [](ToddCoxeter_& self, + std::chrono::nanoseconds t) -> detail::ToddCoxeterImpl& { return self.perform_lookahead_for(t); }, py::arg("t"), @@ -451,7 +429,8 @@ happens first. thing.def( "perform_lookahead_until", - [](ToddCoxeter_& self, std::function const& pred) { + [](ToddCoxeter_& self, + std::function const& pred) -> detail::ToddCoxeterImpl& { return self.perform_lookahead_until(pred); }, py::arg("pred"), @@ -472,7 +451,9 @@ This function runs a lookahead until the nullary predicate *pred* returns thing.def( "perform_lookbehind", - [](ToddCoxeter_& self) { return self.perform_lookbehind(); }, + [](ToddCoxeter_& self) -> detail::ToddCoxeterImpl& { + return self.perform_lookbehind(); + }, R"pbdoc( :sig=(self: ToddCoxeter) -> ToddCoxeter: @@ -535,7 +516,8 @@ Pro). thing.def( "perform_lookbehind_no_checks", [](ToddCoxeter_& self, - std::function const& collapser) { + std::function const& collapser) + -> detail::ToddCoxeterImpl& { auto wrap = [&collapser](auto d_it, auto first, auto last) { Word copy(first, last); // Shame to do so much copying here but couldn't figure out how to @@ -603,7 +585,8 @@ function :any:`ToddCoxeter.reduce_no_run`. thing.def( "perform_lookbehind_for", - [](ToddCoxeter_& self, std::chrono::nanoseconds t) { + [](ToddCoxeter_& self, + std::chrono::nanoseconds t) -> detail::ToddCoxeterImpl& { return self.perform_lookbehind_for(t); }, py::arg("t"), @@ -631,7 +614,8 @@ happens first. "perform_lookbehind_for_no_checks", [](ToddCoxeter_& self, std::chrono::nanoseconds t, - std::function const& collapser) { + std::function const& collapser) + -> detail::ToddCoxeterImpl& { auto wrap = [&collapser](auto d_it, auto first, auto last) { Word copy(first, last); // Shame to do so much copying here but couldn't figure out how to @@ -674,7 +658,8 @@ happens first. See :any:`perform_lookbehind_no_checks` for more details. thing.def( "perform_lookbehind_until", - [](ToddCoxeter_& self, std::function const& pred) { + [](ToddCoxeter_& self, + std::function const& pred) -> detail::ToddCoxeterImpl& { return self.perform_lookbehind_until(pred); }, py::arg("pred"), @@ -701,7 +686,8 @@ This function runs a lookbehind until the nullary predicate *pred* returns "perform_lookbehind_until_no_checks", [](ToddCoxeter_& self, std::function const& pred, - std::function const& collapser) { + std::function const& collapser) + -> detail::ToddCoxeterImpl& { auto wrap = [&collapser](auto d_it, auto first, auto last) { Word copy(first, last); // Shame to do so much copying here but couldn't figure out how to @@ -739,6 +725,38 @@ whichever happens first. does nothing but still might take some time to run). )pbdoc"); + //////////////////////////////////////////////////////////////////////// + // Helpers from cong-common.hpp . . . + //////////////////////////////////////////////////////////////////////// + + auto raises = R"pbdoc( +:raises LibsemigroupsError: + if the number of classes in *tc* is infinite. In this case, the + enumeration of *tc* will not terminate successfully.)pbdoc"sv; + + def_partition>( + m, + "ToddCoxeter", + "todd_coxeter", + doc{.only_document_once = true, .raises = raises, .var = "tc"}); + + def_non_trivial_classes>( + m, + "ToddCoxeter", + "todd_coxeter", + doc{.only_document_once = true, .raises = raises, .var = "tc"}); + + def_normal_forms>(m, + "ToddCoxeter", + "todd_coxeter", + doc{.detail = R"pbdoc( +The order of the classes, and the normal forms, that are returned are +controlled by :any:`ToddCoxeter.standardize`. This function triggers a full +enumeration of ``tc``.)pbdoc", + .only_document_once = true, + .raises = raises, + .var = "tc"}); + //////////////////////////////////////////////////////////////////////// // Helper functions - specific to ToddCoxeter //////////////////////////////////////////////////////////////////////// diff --git a/tests/test_todd_coxeter.py b/tests/test_todd_coxeter.py index f504c7dc..1a9a5296 100644 --- a/tests/test_todd_coxeter.py +++ b/tests/test_todd_coxeter.py @@ -420,22 +420,24 @@ def test_todd_coxeter_return_policy(): def test_todd_coxeter_perform_lookahead(): p = examples.full_transformation_monoid_Aiz58(10) tc = ToddCoxeter(congruence_kind.twosided, p) - tc.perform_lookahead() + assert tc.perform_lookahead() is tc tc.run_for(timedelta(seconds=0.01)) num_nodes = tc.number_of_nodes_active() - tc.perform_lookahead() + # Check the return type is correct + assert tc.perform_lookahead() is tc assert tc.number_of_nodes_active() < num_nodes def test_todd_coxeter_perform_lookahead_for(): p = examples.full_transformation_monoid_Aiz58(10) tc = ToddCoxeter(congruence_kind.twosided, p) - tc.perform_lookahead() + assert tc.perform_lookahead() is tc tc.run_for(timedelta(seconds=0.01)) num_nodes = tc.number_of_nodes_active() start_time = time.time() - tc.perform_lookahead_for(timedelta(seconds=0.1)) - assert time.time() - start_time <= 0.2 + # Check the return type is correct + assert tc.perform_lookahead_for(timedelta(seconds=0.1)) is tc + assert time.time() - start_time <= 1.0 assert tc.number_of_nodes_active() < num_nodes @@ -445,7 +447,8 @@ def test_todd_coxeter_perform_lookahead_until(): tc.perform_lookahead() tc.run_for(timedelta(seconds=0.01)) num_nodes = tc.number_of_nodes_active() - tc.perform_lookahead_until(lambda: tc.number_of_nodes_active() < num_nodes) + # Check the return type is correct + assert tc.perform_lookahead_until(lambda: tc.number_of_nodes_active() < num_nodes) is tc assert tc.number_of_nodes_active() < num_nodes @@ -456,8 +459,9 @@ def test_todd_coxeter_perform_lookbehind_for(): tc.run_for(timedelta(seconds=0.01)) num_nodes = tc.number_of_nodes_active() start_time = time.time() - tc.perform_lookbehind_for(timedelta(seconds=0.1)) - assert time.time() - start_time <= 0.2 + # Run and check the return type is correct + assert tc.perform_lookbehind_for(timedelta(seconds=0.1)) is tc + assert time.time() - start_time <= 1.0 assert tc.number_of_nodes_active() < num_nodes @@ -467,7 +471,8 @@ def test_todd_coxeter_perform_lookbehind_until(): tc.perform_lookbehind() tc.run_for(timedelta(seconds=0.01)) num_nodes = tc.number_of_nodes_active() - tc.perform_lookbehind_until(lambda: tc.number_of_nodes_active() < num_nodes) + # Run and check the return type is correct + assert tc.perform_lookbehind_until(lambda: tc.number_of_nodes_active() < num_nodes) is tc assert tc.number_of_nodes_active() < num_nodes @@ -478,8 +483,9 @@ def test_todd_coxeter_perform_lookbehind_for_no_checks(): tc.run_for(timedelta(seconds=0.01)) num_nodes = tc.number_of_nodes_active() start_time = time.time() - tc.perform_lookbehind_for_no_checks(timedelta(seconds=0.1), lambda w: []) - assert time.time() - start_time <= 0.2 + # Run and check the return type is correct + assert tc.perform_lookbehind_for_no_checks(timedelta(seconds=0.1), lambda w: []) is tc + assert time.time() - start_time <= 1.0 assert tc.number_of_nodes_active() < num_nodes @@ -489,7 +495,11 @@ def test_todd_coxeter_perform_lookbehind_until_no_checks(): tc.perform_lookbehind() tc.run_for(timedelta(seconds=0.01)) num_nodes = tc.number_of_nodes_active() - tc.perform_lookbehind_until_no_checks( - lambda: tc.number_of_nodes_active() < num_nodes, lambda w: [] + # Run and check the return type is correct + assert ( + tc.perform_lookbehind_until_no_checks( + lambda: tc.number_of_nodes_active() < num_nodes, lambda w: [] + ) + is tc ) assert tc.number_of_nodes_active() < num_nodes