30#ifndef LIBSEMIGROUPS_DETAIL_TODD_COXETER_IMPL_HPP_
31#define LIBSEMIGROUPS_DETAIL_TODD_COXETER_IMPL_HPP_
43#include "libsemigroups/constants.hpp"
44#include "libsemigroups/debug.hpp"
45#include "libsemigroups/forest.hpp"
46#include "libsemigroups/order.hpp"
47#include "libsemigroups/presentation.hpp"
48#include "libsemigroups/ranges.hpp"
49#include "libsemigroups/runner.hpp"
50#include "libsemigroups/types.hpp"
51#include "libsemigroups/word-graph.hpp"
53#include "cong-common-class.hpp"
54#include "felsch-graph.hpp"
55#include "node-managed-graph.hpp"
56#include "node-manager.hpp"
57#include "word-graph-with-sources.hpp"
140 class ToddCoxeterImpl :
public CongruenceCommon,
141 public FelschGraphSettings<ToddCoxeterImpl> {
142 using FelschGraphSettings_ = FelschGraphSettings<ToddCoxeterImpl>;
149 struct options :
public FelschGraphSettings_::options {
150 enum class strategy {
161 enum class lookahead_extent { full, partial };
164 enum class lookahead_style { hlt, felsch };
166 enum class def_policy : uint8_t {
167 no_stack_if_no_space,
170 discard_all_if_no_space,
175 enum class state : uint8_t { none, hlt, felsch, lookahead, lookbehind };
178 using index_type = node_type;
190 friend class SettingsGuard;
192 struct NonAtomicStats {
193 using time_point = std::chrono::high_resolution_clock::time_point;
196 time_point create_or_init_time;
197 std::chrono::nanoseconds all_runs_time;
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;
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;
210 time_point run_start_time;
212 uint64_t run_edges_active_at_start;
213 uint64_t run_nodes_active_at_start;
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;
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;
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;
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;
245 NonAtomicStats& init();
247 NonAtomicStats(NonAtomicStats
const&) =
default;
248 NonAtomicStats(NonAtomicStats&&) =
default;
249 NonAtomicStats& operator=(NonAtomicStats
const&) =
default;
250 NonAtomicStats& operator=(NonAtomicStats&&) =
default;
253 struct Stats :
public NonAtomicStats {
255 std::atomic_uint64_t lookahead_or_behind_nodes_killed;
256 std::atomic_uint64_t lookahead_or_behind_position;
261 Stats(Stats
const& that);
263 Stats& operator=(Stats
const& that);
264 Stats& operator=(Stats&& that);
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;
279 using Definition = std::pair<node_type, label_type>;
283 std::vector<Definition> _definitions;
284 ToddCoxeterImpl
const* _tc;
287 Definitions() : _any_skipped(false), _definitions(), _tc(nullptr) {}
290 Definitions(Definitions
const&) =
default;
291 Definitions(Definitions&&) =
default;
292 Definitions& operator=(Definitions
const& that) =
default;
293 Definitions& operator=(Definitions&&) =
default;
296 void init(ToddCoxeterImpl
const* tc) {
297 _any_skipped =
false;
298 _definitions.clear();
302 void emplace_back(node_type c, label_type x);
304 [[nodiscard]]
bool any_skipped() const noexcept {
308 [[nodiscard]]
bool empty() const noexcept {
309 return _definitions.empty();
312 void pop(Definition& d) {
314 _definitions.pop_back();
318 _definitions.clear();
322 bool is_active_node(node_type n)
const noexcept {
323 return _tc->current_word_graph().is_active_node(n);
332 :
public FelschGraph<NodeManagedGraph<node_type>, Definitions> {
333 friend class ToddCoxeterImpl;
339 = FelschGraph<NodeManagedGraph<node_type>, Definitions>;
344 mutable Forest _forest;
345 mutable bool _forest_valid;
346 Order _standardization_order;
355 Graph(Graph
const&) =
default;
356 Graph(Graph&&) =
default;
357 Graph& operator=(Graph
const&) =
default;
358 Graph& operator=(Graph&&) =
default;
363 WordGraph<node_type>
const& wg);
365 Graph& operator=(WordGraph<node_type>
const& wg);
371 using FelschGraph_::presentation;
372 using FelschGraph_::standardize;
373 using FelschGraph_::target_no_checks;
379#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
384 template <
typename Functor = Noop>
385 void process_coincidences(Functor&& func = Noop{});
391 void process_definitions();
399 [[nodiscard]]
bool is_spanning_tree_valid() const noexcept {
400 return _forest_valid;
404 Forest
const& current_spanning_tree()
const {
405 return const_cast<Graph&
>(*this).current_spanning_tree();
412 [[nodiscard]]
bool is_standardized(
Order val)
const {
413 return _standardization_order == val;
416 [[nodiscard]]
bool is_standardized()
const {
420 [[nodiscard]]
inline Order standardization_order() const noexcept {
421 return _standardization_order;
432 Forest& current_spanning_tree();
438 bool standardize(
Order val);
448 Graph& target_no_checks(node_type s,
450 node_type t)
noexcept;
452 Graph& register_target_no_checks(node_type s,
454 node_type t)
noexcept;
462 template <
typename Iterator>
463 void make_compatible(ToddCoxeterImpl* tc,
467 bool should_stop_early);
469 template <
bool RegDefs>
470 void push_definition_hlt(node_type
const& c,
478 void report_lookahead_stop_early(ToddCoxeterImpl* tc,
480 size_t killed_last_interval);
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;
494 std::vector<std::unique_ptr<Settings>> _settings_stack;
497 std::atomic<state> _state;
499 bool _ticker_running;
503 using word_graph_type = Graph;
510 ToddCoxeterImpl& init();
512 ToddCoxeterImpl(ToddCoxeterImpl
const& that);
513 ToddCoxeterImpl(ToddCoxeterImpl&&);
514 ToddCoxeterImpl& operator=(ToddCoxeterImpl
const&);
515 ToddCoxeterImpl& operator=(ToddCoxeterImpl&&);
527 template <
typename Node>
529 : ToddCoxeterImpl() {
530 LIBSEMIGROUPS_ASSERT(!_settings_stack.empty());
534 template <
typename Node>
549#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
553 template <
typename Node>
556 WordGraph<Node>
const& wg) {
561 template <
typename Node>
564 WordGraph<Node>
const& wg);
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);
577 template <
typename Iterator1,
581 ToddCoxeterImpl& add_generating_pair_no_checks(Iterator1 first1,
585 return CongruenceCommon::add_internal_generating_pair_no_checks<
586 ToddCoxeterImpl>(first1, last1, first2, last2);
589 template <
typename Iterator1,
593 ToddCoxeterImpl& add_generating_pair(Iterator1 first1,
597 return CongruenceCommon::add_generating_pair<ToddCoxeterImpl>(
598 first1, last1, first2, last2);
624 template <
typename Iterator1,
628 tril currently_contains_no_checks(Iterator1 first1,
631 Iterator4 last2)
const;
633 template <
typename Iterator1,
637 tril currently_contains(Iterator1 first1,
640 Iterator4 last2)
const {
641 return CongruenceCommon::currently_contains<ToddCoxeterImpl>(
642 first1, last1, first2, last2);
645 template <
typename Iterator1,
649 bool contains_no_checks(Iterator1 first1,
654 template <
typename Iterator1,
658 bool contains(Iterator1 first1,
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;
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);
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);
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);
707#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
709 template <
typename Time>
711#pragma GCC diagnostic push
712#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
714#pragma GCC diagnostic pop
718#pragma GCC diagnostic push
719#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
721#pragma GCC diagnostic pop
741 ToddCoxeterImpl&
def_max(
size_t val)
noexcept;
752 [[nodiscard]]
size_t def_max() const noexcept;
833 [[nodiscard]]
size_t f_defs() const noexcept;
1305 ToddCoxeterImpl&
save(
bool val) noexcept;
1317 [[nodiscard]]
bool save() const noexcept;
1381#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1413 using FelschGraphSettings_::def_version;
1414 using FelschGraphSettings_::settings;
1421#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1423 internal_presentation() const noexcept {
1424 return _word_graph.presentation();
1452 [[deprecated]] [[nodiscard]] uint64_t
1481 [[deprecated]] [[nodiscard]] uint64_t
1602 return _word_graph.current_spanning_tree();
1728 return _word_graph.stats().num_large_collapses;
1773 return _word_graph.standardize(val);
1944 template <
typename Func>
1992 template <
typename Func>
2062 template <
typename Func>
2093 template <
typename Func>
2149 template <
typename Iterator1,
typename Iterator2>
2151 Iterator2 last)
const;
2178 template <
typename Iterator1,
typename Iterator2>
2180 throw_if_letter_not_in_alphabet(first, last);
2209 template <
typename Iterator1,
typename Iterator2>
2237 template <
typename Iterator1,
typename Iterator2>
2239 throw_if_letter_not_in_alphabet(first, last);
2295 template <
typename OutputIterator>
2297 index_type i)
const;
2324 template <
typename OutputIterator>
2326 index_type i)
const;
2350 template <
typename Iterator>
2381 template <
typename Iterator>
2382 Iterator
word_of(Iterator d_first, index_type i) {
2395 [[nodiscard]]
bool finished_impl()
const override {
2399 void run_impl()
override;
2405 void copy_settings_into_graph();
2409 Settings& settings();
2410 Settings
const& settings()
const;
2412 void reset_settings_stack();
2414 [[nodiscard]]
bool any_change_last_run()
const;
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)
2429 [[nodiscard]]
float complete(int64_t num_edges)
const noexcept {
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);
2443 [[nodiscard]]
size_t lookahead_update_settings();
2445 ToddCoxeterImpl& perform_lookahead_impl(
bool should_stop_early);
2446 ToddCoxeterImpl& perform_lookbehind_impl();
2448 void hlt_lookahead(
bool should_stop_early);
2449 void felsch_lookahead(
bool should_stop_early);
2462 void R_over_C_style();
2470 using ReportCell_ = ReportCell<6>;
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;
2484 void add_timing_row(ReportCell_& rc)
const;
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;
2497#include "todd-coxeter-impl.tpp"
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
Namespace for everything in the libsemigroups library.
Definition action.hpp:44