libsemigroups  v3.5.1
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
todd-coxeter-impl.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2019-2025 James D. Mitchell
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17//
18
19// This file contains a declaration of a class for performing the Todd-Coxeter
20// algorithm for semigroups and monoids.
21//
22// TODO(1)
23// * re-implement reserve
24// * remove preferred_defs from FelschGraph etc (except where they are really
25// needed)? Or possibly reintroduce PrefDefs here
26// * implement number_of_nodes_killed_last_phase or similar, to allow easy
27// running of the previous perform_lookahead(stop_early).
28// * make all the non-core strategies helpers
29
30#ifndef LIBSEMIGROUPS_DETAIL_TODD_COXETER_IMPL_HPP_
31#define LIBSEMIGROUPS_DETAIL_TODD_COXETER_IMPL_HPP_
32
33#include <chrono> // for nanoseconds
34#include <cstddef> // for size_t
35#include <cstdint> // for uint32_t
36#include <iterator> // for bidirect...
37#include <memory> // for unique_ptr
38#include <numeric> // for iota
39#include <string> // for string
40#include <utility> // for move, pair
41#include <vector> // for vector
42
43#include "libsemigroups/constants.hpp" // for operator!=
44#include "libsemigroups/debug.hpp" // for LIBSEMIG...
45#include "libsemigroups/forest.hpp" // for Forest
46#include "libsemigroups/order.hpp" // for Order
47#include "libsemigroups/presentation.hpp" // for Presenta...
48#include "libsemigroups/ranges.hpp" // for operator|
49#include "libsemigroups/runner.hpp" // for Reporter
50#include "libsemigroups/types.hpp" // for word_type
51#include "libsemigroups/word-graph.hpp" // for WordGraph
52
53#include "cong-common-class.hpp" // for Congruen...
54#include "felsch-graph.hpp" // for FelschGraph
55#include "node-managed-graph.hpp" // for NodeMana...
56#include "node-manager.hpp" // for NodeMana...
57#include "word-graph-with-sources.hpp" // for WordGrap...
58
59namespace libsemigroups {
60
61 // NOTE: groups are defined here because the order they are declared is the
62 // order they appear in the output doc.
63
71
86
102
112
126
138
139 namespace detail {
140 class ToddCoxeterImpl : public CongruenceCommon,
141 public FelschGraphSettings<ToddCoxeterImpl> {
142 using FelschGraphSettings_ = FelschGraphSettings<ToddCoxeterImpl>;
143
144 public:
146 // Member types - public
148
149 struct options : public FelschGraphSettings_::options {
150 enum class strategy {
151 hlt,
152 felsch,
153 lookahead,
154 lookbehind,
155 CR,
156 R_over_C,
157 Cr,
158 Rc,
159 };
160
161 enum class lookahead_extent { full, partial };
162 // TODO(1) enum class lookbehind_extent { full, partial };
163
164 enum class lookahead_style { hlt, felsch };
165
166 enum class def_policy : uint8_t {
167 no_stack_if_no_space,
168 purge_from_top,
169 purge_all,
170 discard_all_if_no_space,
171 unlimited
172 };
173 }; // struct options
174
175 enum class state : uint8_t { none, hlt, felsch, lookahead, lookbehind };
176
177 using node_type = typename WordGraph<uint32_t>::node_type;
178 using index_type = node_type;
179 using label_type = typename WordGraph<uint32_t>::label_type;
180 using native_word_type = word_type;
181
182 private:
184 // Nested classes - private
186
187 struct Settings;
188
189 class SettingsGuard;
190 friend class SettingsGuard;
191
192 struct NonAtomicStats {
193 using time_point = std::chrono::high_resolution_clock::time_point;
194
195 // Data
196 time_point create_or_init_time;
197 std::chrono::nanoseconds all_runs_time;
198
199 std::chrono::nanoseconds all_hlt_phases_time;
200 std::chrono::nanoseconds all_felsch_phases_time;
201 std::chrono::nanoseconds all_lookahead_phases_time;
202 std::chrono::nanoseconds all_lookbehind_phases_time;
203
204 uint64_t all_num_hlt_phases;
205 uint64_t all_num_felsch_phases;
206 uint64_t all_num_lookahead_phases;
207 uint64_t all_num_lookbehind_phases;
208
209 uint64_t run_index;
210 time_point run_start_time;
211
212 uint64_t run_edges_active_at_start;
213 uint64_t run_nodes_active_at_start;
214
215 std::chrono::nanoseconds run_hlt_phases_time;
216 std::chrono::nanoseconds run_felsch_phases_time;
217 std::chrono::nanoseconds run_lookahead_phases_time;
218 std::chrono::nanoseconds run_lookbehind_phases_time;
219
220 uint64_t run_num_hlt_phases;
221 uint64_t run_num_felsch_phases;
222 uint64_t run_num_lookahead_phases;
223 uint64_t run_num_lookbehind_phases;
224
225 uint64_t phase_index;
226 uint64_t phase_edges_active_at_start;
227 float phase_complete_at_start;
228 uint64_t phase_nodes_defined_at_start;
229 uint64_t phase_nodes_killed_at_start;
230 uint64_t phase_nodes_active_at_start;
231 time_point phase_start_time;
232
233 mutable uint64_t report_index;
234 mutable uint64_t report_edges_active_prev;
235 mutable float report_complete_prev;
236 mutable uint64_t report_nodes_defined_prev;
237 mutable uint64_t report_nodes_killed_prev;
238 mutable uint64_t report_nodes_active_prev;
239
240 // Constructors + initializers
241 NonAtomicStats() {
242 init();
243 }
244
245 NonAtomicStats& init();
246
247 NonAtomicStats(NonAtomicStats const&) = default;
248 NonAtomicStats(NonAtomicStats&&) = default;
249 NonAtomicStats& operator=(NonAtomicStats const&) = default;
250 NonAtomicStats& operator=(NonAtomicStats&&) = default;
251 };
252
253 struct Stats : public NonAtomicStats {
254 // Data
255 std::atomic_uint64_t lookahead_or_behind_nodes_killed;
256 std::atomic_uint64_t lookahead_or_behind_position;
257
258 // Constructors + initialisers
259 Stats();
260 Stats& init();
261 Stats(Stats const& that);
262 Stats(Stats&& that);
263 Stats& operator=(Stats const& that);
264 Stats& operator=(Stats&& that);
265 };
266
267 void stats_run_start();
268 void stats_run_stop();
269 void stats_phase_start();
270 void stats_phase_stop();
271 void stats_report_stop() const;
272
273 public:
275 // Nested classes - public
277
278 class Definitions {
279 using Definition = std::pair<node_type, label_type>;
280
281 private:
282 bool _any_skipped;
283 std::vector<Definition> _definitions;
284 ToddCoxeterImpl const* _tc;
285
286 public:
287 Definitions() : _any_skipped(false), _definitions(), _tc(nullptr) {}
288 // TODO(1) init()
289
290 Definitions(Definitions const&) = default;
291 Definitions(Definitions&&) = default;
292 Definitions& operator=(Definitions const& that) = default;
293 Definitions& operator=(Definitions&&) = default;
294
295 // TODO(1) corresponding constructor
296 void init(ToddCoxeterImpl const* tc) {
297 _any_skipped = false;
298 _definitions.clear();
299 _tc = tc;
300 }
301
302 void emplace_back(node_type c, label_type x);
303
304 [[nodiscard]] bool any_skipped() const noexcept {
305 return _any_skipped;
306 }
307
308 [[nodiscard]] bool empty() const noexcept {
309 return _definitions.empty();
310 }
311
312 void pop(Definition& d) {
313 d = std::move(_definitions.back());
314 _definitions.pop_back();
315 }
316
317 void clear() {
318 _definitions.clear();
319 }
320
321 private:
322 bool is_active_node(node_type n) const noexcept {
323 return _tc->current_word_graph().is_active_node(n);
324 }
325 }; // class Definitions
326
327 // TODO(v4) document ToddCoxeterImpl::Graph, some of ToddCoxeterImpl's
328 // doc for deprecated mem fns already refers to mem fns of Graph, so when
329 // they are removed the doc will have no where to live if it isn't
330 // included here.
331 class Graph
332 : public FelschGraph<NodeManagedGraph<node_type>, Definitions> {
333 friend class ToddCoxeterImpl;
334
336 // Private aliases
338 using FelschGraph_
339 = FelschGraph<NodeManagedGraph<node_type>, Definitions>;
340
342 // Private data
344 mutable Forest _forest;
345 mutable bool _forest_valid;
346 Order _standardization_order;
347
348 public:
350 // Constructors and initializers
352 Graph();
353 Graph& init();
354
355 Graph(Graph const&) = default;
356 Graph(Graph&&) = default;
357 Graph& operator=(Graph const&) = default;
358 Graph& operator=(Graph&&) = default;
359
360 Graph& init(Presentation<word_type>&& p);
361
362 Graph& init(Presentation<word_type> const& p,
363 WordGraph<node_type> const& wg);
364
365 Graph& operator=(WordGraph<node_type> const& wg);
366
368 // FelschGraph_ mem fns
370
371 using FelschGraph_::presentation;
372 using FelschGraph_::standardize;
373 using FelschGraph_::target_no_checks;
374
376 // Modifiers
378
379#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
380 // NOTE: Should be private but can't be because used by is_non_trivial
381 // but is_non_trivial is declared in todd-coxeter-helpers.hpp and so
382 // it is not straightforward to make these functions friends,
383 // unfortunately.
384 template <typename Functor = Noop>
385 void process_coincidences(Functor&& func = Noop{});
386
387 // NOTE: Should be private but can't be because used by is_non_trivial
388 // but is_non_trivial is declared in todd-coxeter-helpers.hpp and so
389 // it is not straightforward to make these functions friends,
390 // unfortunately.
391 void process_definitions();
392#endif
393
395 // Spanning tree
397
398 // TODO(v4) doc
399 [[nodiscard]] bool is_spanning_tree_valid() const noexcept {
400 return _forest_valid;
401 }
402
403 // TODO(v4) doc
404 Forest const& current_spanning_tree() const {
405 return const_cast<Graph&>(*this).current_spanning_tree();
406 }
407
409 // Standardization
411
412 [[nodiscard]] bool is_standardized(Order val) const {
413 return _standardization_order == val;
414 }
415
416 [[nodiscard]] bool is_standardized() const {
417 return _standardization_order != Order::none;
418 }
419
420 [[nodiscard]] inline Order standardization_order() const noexcept {
421 return _standardization_order;
422 }
423
424 private:
425 // Almost all non-const mem fns are private, since they cannot be used
426 // anyway (we only permit const access to the word_graph)
427
429 // Spanning tree
431
432 Forest& current_spanning_tree();
433
435 // Standardization
437
438 bool standardize(Order val);
439
441 // FelschGraph_ mem fns overrides
443
444 // Functions that are present in the FelschGraph_, but must be
445 // overridden here so that the validation and standardization stuff is
446 // reset.
447
448 Graph& target_no_checks(node_type s,
449 label_type a,
450 node_type t) noexcept;
451
452 Graph& register_target_no_checks(node_type s,
453 label_type a,
454 node_type t) noexcept;
455
457 // Other modifiers
459
460 Graph& presentation_no_checks(Presentation<word_type> const& p);
461
462 template <typename Iterator>
463 void make_compatible(ToddCoxeterImpl* tc,
464 node_type& current,
465 Iterator first,
466 Iterator last,
467 bool should_stop_early);
468
469 template <bool RegDefs>
470 void push_definition_hlt(node_type const& c,
471 word_type const& u,
472 word_type const& v);
473
475 // Reporting
477
478 void report_lookahead_stop_early(ToddCoxeterImpl* tc,
479 size_t expected,
480 size_t killed_last_interval);
481 }; // class Graph
482
483 private:
485 // Data members - private
487
488 std::function<void(std::back_insert_iterator<word_type>,
489 typename word_type::const_iterator,
490 typename word_type::const_iterator)>
491 _lookbehind_collapser;
492 bool _finished;
493 bool _never_run;
494 std::vector<std::unique_ptr<Settings>> _settings_stack;
495 // _state must be atomic to avoid the situation where the ticker
496 // function is called concurrently with a new lookahead starting
497 std::atomic<state> _state;
498 Stats _stats;
499 bool _ticker_running;
500 Graph _word_graph;
501
502 public:
503 using word_graph_type = Graph;
504
506 // Constructors + initializers - public
508
509 ToddCoxeterImpl();
510 ToddCoxeterImpl& init();
511
512 ToddCoxeterImpl(ToddCoxeterImpl const& that);
513 ToddCoxeterImpl(ToddCoxeterImpl&&);
514 ToddCoxeterImpl& operator=(ToddCoxeterImpl const&);
515 ToddCoxeterImpl& operator=(ToddCoxeterImpl&&);
516
517 ~ToddCoxeterImpl();
518
519 ToddCoxeterImpl(congruence_kind knd, Presentation<word_type>&& p);
520 ToddCoxeterImpl& init(congruence_kind knd, Presentation<word_type>&& p);
521 ToddCoxeterImpl(congruence_kind knd, Presentation<word_type> const& p);
522 ToddCoxeterImpl& init(congruence_kind knd,
523 Presentation<word_type> const& p);
524
525 // TODO(1) a "make" function variant that throws if wg is not valid see
526 // below
527 template <typename Node>
528 ToddCoxeterImpl(congruence_kind knd, WordGraph<Node> const& wg)
529 : ToddCoxeterImpl() {
530 LIBSEMIGROUPS_ASSERT(!_settings_stack.empty());
531 init(knd, wg);
532 }
533
534 template <typename Node>
535 ToddCoxeterImpl& init(congruence_kind knd, WordGraph<Node> const& wg);
536
537 // TODO(1) rvalue ref WordGraph init + constructor
538
539 ToddCoxeterImpl(congruence_kind knd, ToddCoxeterImpl const& tc);
540
541 ToddCoxeterImpl& init(congruence_kind knd, ToddCoxeterImpl const& tc);
542
543 ToddCoxeterImpl& presentation_no_checks(Presentation<word_type> const& p);
544
545 // This is a constructor and not a helper so that everything that takes
546 // a presentation has the same constructors, regardless of what they use
547 // inside.
548
549#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
550 // Used in Sims
551 // TODO(1) could this and the next function be removed, and replaced
552 // with something else?
553 template <typename Node>
554 ToddCoxeterImpl(congruence_kind knd,
556 WordGraph<Node> const& wg) {
557 init(knd, p, wg);
558 }
559
560 // TODO(1) a to_todd_coxeter variant that throws if p is not valid
561 template <typename Node>
562 ToddCoxeterImpl& init(congruence_kind knd,
564 WordGraph<Node> const& wg);
565#endif
566
567 template <typename Iterator1, typename Iterator2>
568 void throw_if_letter_not_in_alphabet(Iterator1 first,
569 Iterator2 last) const {
570 internal_presentation().throw_if_letter_not_in_alphabet(first, last);
571 }
572
574 // Interface requirements - add_generating_pair
576
577 template <typename Iterator1,
578 typename Iterator2,
579 typename Iterator3,
580 typename Iterator4>
581 ToddCoxeterImpl& add_generating_pair_no_checks(Iterator1 first1,
582 Iterator2 last1,
583 Iterator3 first2,
584 Iterator4 last2) {
585 return CongruenceCommon::add_internal_generating_pair_no_checks<
586 ToddCoxeterImpl>(first1, last1, first2, last2);
587 }
588
589 template <typename Iterator1,
590 typename Iterator2,
591 typename Iterator3,
592 typename Iterator4>
593 ToddCoxeterImpl& add_generating_pair(Iterator1 first1,
594 Iterator2 last1,
595 Iterator3 first2,
596 Iterator4 last2) {
597 return CongruenceCommon::add_generating_pair<ToddCoxeterImpl>(
598 first1, last1, first2, last2);
599 }
600
602 // Interface requirements - number_of_classes
604
618 [[nodiscard]] uint64_t number_of_classes();
619
621 // Interface requirements - contains
623
624 template <typename Iterator1,
625 typename Iterator2,
626 typename Iterator3,
627 typename Iterator4>
628 tril currently_contains_no_checks(Iterator1 first1,
629 Iterator2 last1,
630 Iterator3 first2,
631 Iterator4 last2) const;
632
633 template <typename Iterator1,
634 typename Iterator2,
635 typename Iterator3,
636 typename Iterator4>
637 tril currently_contains(Iterator1 first1,
638 Iterator2 last1,
639 Iterator3 first2,
640 Iterator4 last2) const {
641 return CongruenceCommon::currently_contains<ToddCoxeterImpl>(
642 first1, last1, first2, last2);
643 }
644
645 template <typename Iterator1,
646 typename Iterator2,
647 typename Iterator3,
648 typename Iterator4>
649 bool contains_no_checks(Iterator1 first1,
650 Iterator2 last1,
651 Iterator3 first2,
652 Iterator4 last2);
653
654 template <typename Iterator1,
655 typename Iterator2,
656 typename Iterator3,
657 typename Iterator4>
658 bool contains(Iterator1 first1,
659 Iterator2 last1,
660 Iterator3 first2,
661 Iterator4 last2);
662
664 // Interface requirements - reduce
666
667 template <typename OutputIterator,
668 typename InputIterator1,
669 typename InputIterator2>
670 OutputIterator reduce_no_run_no_checks(OutputIterator d_first,
671 InputIterator1 first,
672 InputIterator2 last) const;
673
674 template <typename OutputIterator,
675 typename InputIterator1,
676 typename InputIterator2>
677 OutputIterator reduce_no_run(OutputIterator d_first,
678 InputIterator1 first,
679 InputIterator2 last) const {
680 return CongruenceCommon::reduce_no_run<ToddCoxeterImpl>(
681 d_first, first, last);
682 }
683
684 template <typename OutputIterator,
685 typename InputIterator1,
686 typename InputIterator2>
687 OutputIterator reduce_no_checks(OutputIterator d_first,
688 InputIterator1 first,
689 InputIterator2 last) {
690 return CongruenceCommon::reduce_no_checks<ToddCoxeterImpl>(
691 d_first, first, last);
692 }
693
694 template <typename OutputIterator,
695 typename InputIterator1,
696 typename InputIterator2>
697 OutputIterator reduce(OutputIterator d_first,
698 InputIterator1 first,
699 InputIterator2 last) {
700 return CongruenceCommon::reduce<ToddCoxeterImpl>(d_first, first, last);
701 }
702
704 // Settings - public
706
707#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
708 // This is documented in Reporter, so we don't duplicate the doc here.
709 template <typename Time>
710 [[deprecated]] void report_every(Time val) {
711#pragma GCC diagnostic push
712#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
714#pragma GCC diagnostic pop
715 }
716
717 [[deprecated]] [[nodiscard]] nanoseconds report_every() const noexcept {
718#pragma GCC diagnostic push
719#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
720 return Reporter::report_every();
721#pragma GCC diagnostic pop
722 }
723#endif
724
741 ToddCoxeterImpl& def_max(size_t val) noexcept;
742
752 [[nodiscard]] size_t def_max() const noexcept;
753
769 ToddCoxeterImpl& def_policy(options::def_policy val);
770
783 [[nodiscard]] options::def_policy def_policy() const noexcept;
784
808 ToddCoxeterImpl& f_defs(size_t val);
809
833 [[nodiscard]] size_t f_defs() const noexcept;
834
859 ToddCoxeterImpl& hlt_defs(size_t val);
860
884 [[nodiscard]] size_t hlt_defs() const noexcept;
885
919 ToddCoxeterImpl& large_collapse(size_t val) noexcept;
920
935 [[nodiscard]] size_t large_collapse() const noexcept;
936
954 ToddCoxeterImpl& lookahead_extent(options::lookahead_extent val) noexcept;
955
969 [[nodiscard]] options::lookahead_extent lookahead_extent() const noexcept;
970
990 ToddCoxeterImpl& lookahead_growth_factor(float val);
991
1003 [[nodiscard]] float lookahead_growth_factor() const noexcept;
1004
1024 ToddCoxeterImpl& lookahead_growth_threshold(size_t val) noexcept;
1025
1037 [[nodiscard]] size_t lookahead_growth_threshold() const noexcept;
1038
1059 ToddCoxeterImpl& lookahead_min(size_t val) noexcept;
1060
1074 [[nodiscard]] size_t lookahead_min() const noexcept;
1075
1091 ToddCoxeterImpl& lookahead_next(size_t val) noexcept;
1092
1105 [[nodiscard]] size_t lookahead_next() const noexcept;
1106
1128 ToddCoxeterImpl&
1130
1144
1166 ToddCoxeterImpl& lookahead_stop_early_ratio(float val);
1167
1179 float lookahead_stop_early_ratio() const noexcept;
1180
1198 ToddCoxeterImpl& lookahead_style(options::lookahead_style val) noexcept;
1199
1210 [[nodiscard]] options::lookahead_style lookahead_style() const noexcept;
1211
1235 [[nodiscard]] ToddCoxeterImpl& lookbehind_threshold(size_t val) noexcept;
1236
1251 [[nodiscard]] size_t lookbehind_threshold() const noexcept;
1252
1275 ToddCoxeterImpl& lower_bound(size_t val) noexcept;
1276
1288 [[nodiscard]] size_t lower_bound() const noexcept;
1289
1305 ToddCoxeterImpl& save(bool val) noexcept;
1306
1317 [[nodiscard]] bool save() const noexcept;
1318
1333 ToddCoxeterImpl& strategy(options::strategy val) noexcept;
1334
1345 [[nodiscard]] options::strategy strategy() const noexcept;
1346
1365 ToddCoxeterImpl& use_relations_in_extra(bool val) noexcept;
1366
1379 [[nodiscard]] bool use_relations_in_extra() const noexcept;
1380
1381#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1397 ToddCoxeterImpl& def_version(options::def_version val);
1398
1411 [[nodiscard]] options::def_version def_version() const noexcept;
1412#else
1413 using FelschGraphSettings_::def_version;
1414 using FelschGraphSettings_::settings;
1415#endif
1416
1418 // Accessors - public
1420
1421#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1422 [[nodiscard]] Presentation<word_type> const&
1423 internal_presentation() const noexcept {
1424 return _word_graph.presentation();
1425 }
1426#endif
1427
1450 // This isn't really necessary in C++, but in the python bindings we
1451 // don't bind ToddCoxeter::Graph and so we expose this here.
1452 [[deprecated]] [[nodiscard]] uint64_t
1453 number_of_nodes_active() const noexcept {
1454 return current_word_graph().number_of_nodes_active();
1455 }
1456
1479 // This isn't really necessary in C++, but in the python bindings we
1480 // don't bind ToddCoxeter::Graph and so we expose this here.
1481 [[deprecated]] [[nodiscard]] uint64_t
1482 number_of_edges_active() const noexcept {
1483 return current_word_graph().number_of_edges_active();
1484 }
1485
1501 // TODO(v4) move to the word graph itself
1502 [[nodiscard]] float complete() const noexcept {
1504 }
1505
1506 // [[nodiscard]] bool empty() const {
1507 // return (internal_presentation().rules.empty() &&
1508 // generating_pairs().empty()
1509 // && current_word_graph().number_of_nodes_active() == 1);
1510 // // FIXME(1) there's an issue where the word graph can have 0
1511 // nodes but
1512 // 1
1513 // // active node.
1514 // }
1515
1546 word_graph_type const& current_word_graph() const noexcept {
1547 return _word_graph;
1548 }
1549
1576 word_graph_type const& word_graph();
1577
1600 // TODO(v4) move the doc to Graph
1601 [[deprecated]] Forest const& current_spanning_tree() const {
1602 return _word_graph.current_spanning_tree();
1603 }
1604
1618 // TODO(v4) move the doc to Graph
1619 [[deprecated]] Forest const& spanning_tree();
1620
1667 [[deprecated]] inline Order standardization_order() const noexcept {
1668 return current_word_graph().standardization_order();
1669 }
1670
1689 [[deprecated]] bool is_standardized(Order val) const {
1690 return current_word_graph().is_standardized(val);
1691 }
1692
1709 [[deprecated]] bool is_standardized() const {
1710 return current_word_graph().is_standardized();
1711 }
1712
1725 // TODO(v4) deprecate and move to Graph, don't expose stats because it
1726 // contains a bunch of stuff that's probably not interesting
1727 [[nodiscard]] uint64_t number_of_large_collapses() const noexcept {
1728 return _word_graph.stats().num_large_collapses;
1729 }
1730
1732 // Modifiers - public
1734
1744
1769 // We don't deprecated this (at least for now) since we only provide
1770 // const access to _word_graph, and so require modifiers to also be
1771 // member functions of ToddCoxeterImpl
1772 bool standardize(Order val) {
1773 return _word_graph.standardize(val);
1774 }
1775
1786 ToddCoxeterImpl& perform_lookahead();
1787
1806 [[deprecated]] void perform_lookahead(bool stop_early);
1807
1819
1830 ToddCoxeterImpl& perform_lookahead_until(std::function<bool()>&& pred);
1831
1843 ToddCoxeterImpl&
1845 return perform_lookahead_until(std::function<bool()>(pred));
1846 }
1847
1869 // This test takes a couple of seconds to run.
1907 ToddCoxeterImpl& perform_lookbehind();
1908
1944 template <typename Func>
1945 ToddCoxeterImpl& perform_lookbehind_no_checks(Func&& collapser);
1946
1963
1992 template <typename Func>
1993 ToddCoxeterImpl&
1995 Func&& collapser);
1996
2013 ToddCoxeterImpl& perform_lookbehind_until(std::function<bool()>&& pred);
2014
2031 ToddCoxeterImpl&
2033 return perform_lookbehind_until(std::function<bool()>(pred));
2034 }
2035
2062 template <typename Func>
2063 ToddCoxeterImpl&
2065 Func&& collapser);
2066
2093 template <typename Func>
2094 ToddCoxeterImpl&
2096 Func&& collapser) {
2098 collapser);
2099 }
2100
2102 // Word -> index
2104
2120
2147 // NOTE: the graph contains one more node than there are element
2148 // if the underlying presentation does not contain the empty word
2149 template <typename Iterator1, typename Iterator2>
2150 index_type current_index_of_no_checks(Iterator1 first,
2151 Iterator2 last) const;
2152
2178 template <typename Iterator1, typename Iterator2>
2179 index_type current_index_of(Iterator1 first, Iterator2 last) const {
2180 throw_if_letter_not_in_alphabet(first, last);
2181 return current_index_of_no_checks(first, last);
2182 }
2183
2209 template <typename Iterator1, typename Iterator2>
2210 index_type index_of_no_checks(Iterator1 first, Iterator2 last);
2211
2237 template <typename Iterator1, typename Iterator2>
2238 index_type index_of(Iterator1 first, Iterator2 last) {
2239 throw_if_letter_not_in_alphabet(first, last);
2240 return index_of_no_checks(first, last);
2241 }
2242
2244
2246 // Index -> word
2248
2265
2293 // NOTE THAT: the graph contains one more node than there are element
2294 // if the underlying presentation does not contain the empty word
2295 template <typename OutputIterator>
2296 OutputIterator current_word_of_no_checks(OutputIterator d_first,
2297 index_type i) const;
2298
2324 template <typename OutputIterator>
2325 OutputIterator current_word_of(OutputIterator d_first,
2326 index_type i) const;
2327
2350 template <typename Iterator>
2351 Iterator word_of_no_checks(Iterator d_first, index_type i) {
2352 run();
2353 LIBSEMIGROUPS_ASSERT(finished());
2354 return current_word_of_no_checks(d_first, i);
2355 }
2356
2381 template <typename Iterator>
2382 Iterator word_of(Iterator d_first, index_type i) {
2383 run();
2384 LIBSEMIGROUPS_ASSERT(finished());
2385 return current_word_of(d_first, i);
2386 }
2387
2389
2390 private:
2392 // Runner - pure virtual member functions - private
2394
2395 [[nodiscard]] bool finished_impl() const override {
2396 return _finished;
2397 }
2398
2399 void run_impl() override;
2400
2402 // Misc member functions - private
2404
2405 void copy_settings_into_graph();
2406
2407 // WARNING: there's already a settings() mem fn in FelschGraphSettings,
2408 // beware of confusing the two.
2409 Settings& settings();
2410 Settings const& settings() const;
2411
2412 void reset_settings_stack();
2413
2414 [[nodiscard]] bool any_change_last_run() const;
2415
2416 // We take both values here, although we could compute them, so that in
2417 // report_progress_from_thread we do not report at one point in time
2418 // with some value, then within the same function call (if the graph is
2419 // changing a lot) report with another value
2420 // TODO(v4) move into Graph
2421 [[nodiscard]] float complete(uint64_t num_nodes,
2422 int64_t num_edges) const noexcept {
2423 return static_cast<float>(num_edges)
2424 / (static_cast<uint64_t>(num_nodes)
2425 * current_word_graph().out_degree());
2426 }
2427
2428 // TODO(v4) move into Graph
2429 [[nodiscard]] float complete(int64_t num_edges) const noexcept {
2431 num_edges);
2432 }
2433
2435 // Lookahead - private
2437
2438 [[nodiscard]] bool lookahead_stop_early(
2439 bool should_stop_early,
2440 std::chrono::high_resolution_clock::time_point& last_stop_early_check,
2441 uint64_t& killed_at_prev_interval);
2442
2443 [[nodiscard]] size_t lookahead_update_settings();
2444
2445 ToddCoxeterImpl& perform_lookahead_impl(bool should_stop_early);
2446 ToddCoxeterImpl& perform_lookbehind_impl();
2447
2448 void hlt_lookahead(bool should_stop_early);
2449 void felsch_lookahead(bool should_stop_early);
2450
2452 // Main strategies - private
2454
2455 void before_run();
2456 void after_run();
2457 void felsch();
2458 void hlt();
2459
2460 // TODO(v4) to helpers
2461 void CR_style();
2462 void R_over_C_style();
2463 void Cr_style();
2464 void Rc_style();
2465
2467 // ToddCoxeterImpl - reporting - private
2469
2470 using ReportCell_ = ReportCell<6>;
2471
2472 void report_after_phase() const;
2473 void report_after_run() const;
2474 void report_before_phase(std::string_view = "") const;
2475 void report_before_lookahead() const;
2476 void report_before_run() const;
2477 void report_lookahead_settings(size_t old_lookahead_next) const;
2478 void report_lookahead_stop_early(size_t expected,
2479 size_t killed_last_interval);
2480 void report_presentation() const;
2481 void report_progress_from_thread(bool divider) const;
2482 void report_times() const;
2483
2484 void add_timing_row(ReportCell_& rc) const;
2485
2486 // The 2nd (and 3rd) arguments for the next 2 functions are required
2487 // because we need the values at a fixed point in time (due to
2488 // multi-threaded reporting).
2489 void add_nodes_rows(ReportCell_& rc, uint64_t num_active_nodes) const;
2490 void add_edges_rows(ReportCell_& rc,
2491 uint64_t num_active_nodes,
2492 uint64_t num_active_edges) const;
2493 void add_lookahead_or_behind_row(ReportCell_& rc) const;
2494 }; // class ToddCoxeterImpl
2495 } // namespace detail
2496} // namespace libsemigroups
2497#include "todd-coxeter-impl.tpp"
2498#endif // LIBSEMIGROUPS_DETAIL_TODD_COXETER_IMPL_HPP_
Class representing a collection of spanning trees of a word graph.
Definition forest.hpp:46
For an implementation of presentations for semigroups or monoids.
Definition presentation.hpp:103
nanoseconds report_every() const noexcept
Get the minimum elapsed time between reports.
Definition runner.hpp:236
std::chrono::nanoseconds nanoseconds
Alias for std::chrono::nanoseconds.
Definition runner.hpp:102
void run()
Run until finished.
bool finished() const
Check if run has been run to completion or not.
Node node_type
The type of nodes in a word graph.
Definition word-graph.hpp:99
Node label_type
The type of edge labels in a word graph.
Definition word-graph.hpp:102
Presentation(Presentation< Word > const &) -> Presentation< Word >
Deduction guide.
float complete() const noexcept
Return the proportion of edges defined in the active part of the word graph.
Definition todd-coxeter-impl.hpp:1502
Forest const & spanning_tree()
Get the spanning tree of the underlying word graph.
uint64_t number_of_nodes_active() const noexcept
Return the number of nodes in the active part of the current word graph.
Definition todd-coxeter-impl.hpp:1453
word_graph_type const & current_word_graph() const noexcept
Get the current word graph.
Definition todd-coxeter-impl.hpp:1546
Forest const & current_spanning_tree() const
Get the current possible spanning tree of the underlying word graph.
Definition todd-coxeter-impl.hpp:1601
word_graph_type const & word_graph()
Get the word graph after performing a full congruence enumeration.
uint64_t number_of_edges_active() const noexcept
Return the number of edges in the active part of the current word graph.
Definition todd-coxeter-impl.hpp:1482
bool is_standardized(Order val) const
Check if the word graph is currently standardized with respect to a given order.
Definition todd-coxeter-impl.hpp:1689
Order standardization_order() const noexcept
Get the current standardization order of the underlying word graph.
Definition todd-coxeter-impl.hpp:1667
bool is_standardized() const
Check if the word graph is currently standardized with respect to any order.
Definition todd-coxeter-impl.hpp:1709
uint64_t number_of_large_collapses() const noexcept
Return the number of large collapses that have occurred.
Definition todd-coxeter-impl.hpp:1727
OutputIterator current_word_of(OutputIterator d_first, index_type i) const
Insert a current word representing a class with given index into an output iterator.
Iterator word_of_no_checks(Iterator d_first, index_type i)
Insert the word representing a class with given index into an output iterator.
Definition todd-coxeter-impl.hpp:2351
Iterator word_of(Iterator d_first, index_type i)
Insert the word representing a class with given index into an output iterator.
Definition todd-coxeter-impl.hpp:2382
OutputIterator current_word_of_no_checks(OutputIterator d_first, index_type i) const
Insert a current word representing a class with given index into an output iterator.
uint64_t number_of_classes()
Compute the number of classes in the congruence.
void perform_lookahead(bool stop_early)
Perform a lookahead.
ToddCoxeterImpl & perform_lookahead_for(std::chrono::nanoseconds t)
Perform a lookahead for a specified amount of time.
ToddCoxeterImpl & perform_lookbehind_no_checks(Func &&collapser)
Perform a lookbehind using a function to decide whether or not to collapse nodes.
ToddCoxeterImpl & perform_lookahead()
Perform a lookahead.
ToddCoxeterImpl & perform_lookbehind_until(std::function< bool()> const &pred)
Perform a lookbehind until a nullary predicate returns true or finished.
Definition todd-coxeter-impl.hpp:2032
void shrink_to_fit()
Shrink the underlying word graph to remove all dead nodes.
ToddCoxeterImpl & perform_lookbehind_until_no_checks(std::function< bool()> &&pred, Func &&collapser)
Perform a lookbehind until a nullary predicate returns true.
bool standardize(Order val)
Standardize the current_word_graph.
Definition todd-coxeter-impl.hpp:1772
ToddCoxeterImpl & perform_lookbehind_for_no_checks(std::chrono::nanoseconds t, Func &&collapser)
Perform a lookbehind for a specified amount of time with a collapser.
ToddCoxeterImpl & perform_lookahead_until(std::function< bool()> const &pred)
Perform a lookahead until a nullary predicate returns true or finished.
Definition todd-coxeter-impl.hpp:1844
ToddCoxeterImpl & perform_lookbehind()
Perform a lookbehind.
ToddCoxeterImpl & perform_lookbehind_until(std::function< bool()> &&pred)
Perform a lookbehind until a nullary predicate returns true or finished.
ToddCoxeterImpl & perform_lookbehind_until_no_checks(std::function< bool()> const &pred, Func &&collapser)
Perform a lookbehind until a nullary predicate returns true.
Definition todd-coxeter-impl.hpp:2095
ToddCoxeterImpl & perform_lookahead_until(std::function< bool()> &&pred)
Perform a lookahead until a nullary predicate returns true.
ToddCoxeterImpl & perform_lookbehind_for(std::chrono::nanoseconds t)
Perform a lookbehind for a specified amount of time.
options::def_version def_version() const noexcept
Get the current value of the definition version setting.
ToddCoxeterImpl & lookahead_extent(options::lookahead_extent val) noexcept
Set the lookahead extent.
ToddCoxeterImpl & lookahead_growth_factor(float val)
Set the lookahead growth factor.
ToddCoxeterImpl & lookahead_style(options::lookahead_style val) noexcept
Set the style of lookahead.
ToddCoxeterImpl & lookahead_stop_early_ratio(float val)
Set the lookahead stop early ratio.
ToddCoxeterImpl & lookahead_next(size_t val) noexcept
Set the threshold that will trigger a lookahead.
ToddCoxeterImpl & lookahead_min(size_t val) noexcept
Set the minimum value of lookahead_next.
ToddCoxeterImpl & lookbehind_threshold(size_t val) noexcept
Set the lookbehind threshold.
ToddCoxeterImpl & use_relations_in_extra(bool val) noexcept
Set whether or not to perform an HLT-style push of the defining relations at the identity.
size_t def_max() const noexcept
Get the current value of the setting for the maximum number of definitions.
ToddCoxeterImpl & def_version(options::def_version val)
Set the value of the definition version setting.
ToddCoxeterImpl & lookahead_growth_threshold(size_t val) noexcept
Set the lookahead growth threshold.
ToddCoxeterImpl & strategy(options::strategy val) noexcept
Specify the congruence enumeration strategy.
ToddCoxeterImpl & def_max(size_t val) noexcept
Set the maximum number of definitions in the stack.
ToddCoxeterImpl & def_policy(options::def_policy val)
Set the definition policy.
ToddCoxeterImpl & lookahead_stop_early_interval(std::chrono::nanoseconds val) noexcept
Set the lookahead stop early interval.
ToddCoxeterImpl & save(bool val) noexcept
Set whether or not to process definitions during HLT.
ToddCoxeterImpl & f_defs(size_t val)
Set the number of Felsch style definitions in ACE strategies.
ToddCoxeterImpl & lower_bound(size_t val) noexcept
Specify the minimum number of classes that may permit any enumeration early stop.
ToddCoxeterImpl & large_collapse(size_t val) noexcept
Set the size of a large collapse.
ToddCoxeterImpl & hlt_defs(size_t val)
Set the number of HLT style definitions in ACE strategies.
index_type current_index_of(Iterator1 first, Iterator2 last) const
Returns the current index of the class containing a word.
Definition todd-coxeter-impl.hpp:2179
index_type current_index_of_no_checks(Iterator1 first, Iterator2 last) const
Returns the current index of the class containing a word.
index_type index_of_no_checks(Iterator1 first, Iterator2 last)
Returns the index of the class containing a word.
index_type index_of(Iterator1 first, Iterator2 last)
Returns the index of the class containing a word.
Definition todd-coxeter-impl.hpp:2238
std::vector< letter_type > word_type
Type for a word over the generators of a semigroup.
Definition types.hpp:99
Order
The possible orderings of words and strings.
Definition order.hpp:54
tril
Enum to indicate true, false or not currently knowable.
Definition types.hpp:54
congruence_kind
Enum to indicate the sided-ness of a congruence.
Definition types.hpp:67
@ none
No ordering.
Definition order.hpp:56
T move(T... args)
Namespace for everything in the libsemigroups library.
Definition action.hpp:44