libsemigroups  v3.0.0
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
stephen.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2022-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#ifndef LIBSEMIGROUPS_STEPHEN_HPP_
20#define LIBSEMIGROUPS_STEPHEN_HPP_
21
22#include <array> // for array
23#include <cstddef> // for size_t
24#include <cstdint> // for uint32_t
25#include <memory> // for shared_ptr
26#include <string> // for string
27#include <tuple> // for tie
28#include <utility> // for make_pair
29#include <vector> // for vector
30
31#include "constants.hpp" // for Max, UNDEFINED
32#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
33#include "dot.hpp" // for Dot
34#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
35#include "paths.hpp" // for Paths
36#include "presentation.hpp" // for Presentation
37#include "runner.hpp" // for Runner
38#include "types.hpp" // for word_type
39#include "word-graph.hpp" // for WordGraph
40
41#include "detail/felsch-graph.hpp" // for DoNotReg...
42#include "detail/node-managed-graph.hpp" // for NodeMana...
43#include "detail/node-manager.hpp" // for NodeManager
44#include "detail/report.hpp" // for report_n...
45#include "detail/string.hpp" // for group_di...
46#include "detail/word-graph-with-sources.hpp" // for WordGrap...
47
48// TODO(2)
49// * update so that run_for, run_until work properly (at present basically
50// run_impl starts again from scratch every time)
51// * minimal rep (as per Reinis) (named normal_form?)
52// * invert() - just swap the initial and accept states and re-standardize
53// * idempotent() - just make the accept state = initial state.
54// * class_of for inverse Stephen (i.e. all walks in the graph through all
55// nodes) (not sure how to do this just yet). This is different than
56// words_accepted see Corollary 3.2 in Stephen's "Presentations of inverse
57// monoids" paper (not thesis).
58// * canonical_form (as per Howie's book)
59
64
65namespace libsemigroups {
66
89 template <typename PresentationType>
90 class Stephen : public Runner {
91 template <typename Q>
92 static constexpr bool is_valid_presentation() {
93 return std::is_same_v<Q, Presentation<word_type>>
94 || std::is_same_v<Q, InversePresentation<word_type>>;
95 // TODO(2): uncomment when we figure out how to handle std::string
96 // presentations
97 //|| std::is_same_v<Q, Presentation<std::string>>
98 //|| std::is_same_v<Q, InversePresentation<std::string>>;
99 }
100
101 // TODO (2): Change the error message once std::string presentations are
102 // supported
103 static_assert(is_valid_presentation<PresentationType>(),
104 "the template parameter PresentationType must be "
105 "Presentation<word_type> or InversePresentation<word_type>");
106
107 public:
109 using presentation_type = PresentationType;
110
115
116 private:
117 class StephenGraph; // forward decl
118
119 // Data members
120 node_type _accept_state;
121 bool _finished;
122 bool _is_word_set;
124 word_type _word;
125 StephenGraph _word_graph;
126
127 public:
136
147
148 // TODO(2): Implement make<Stephen> function which checks args
149 // Should presentation::throw_if_not_normalized (until we separate the
150 // implementation and external interface later on).
151 // Should also throw if `p.throw_if_bad_alphabet_or_rules()` throws.
152 // Should also throw if if `p.alphabet().size()` is `0`.
153
162 // Not noexcept because allocated memory
163 explicit Stephen(PresentationType const& p) : Stephen() {
164 init(p);
165 }
166
175 explicit Stephen(PresentationType&& p) : Stephen() {
176 init(std::move(p));
177 }
178
188 init(ptr);
189 }
190
192 Stephen(Stephen const& that) = default;
193
195 Stephen(Stephen&&) = default;
196
198 Stephen& operator=(Stephen const&) = default;
199
201 Stephen& operator=(Stephen&&) = default;
202
203 ~Stephen() = default;
204
216 Stephen& init(PresentationType const& p) {
218 }
219
231 Stephen& init(PresentationType&& p) {
233 }
234
247
256 presentation_type const& presentation() const noexcept {
257 return *_presentation;
258 }
259
275 template <typename Iterator1, typename Iterator2>
276 Stephen& set_word(Iterator1 first, Iterator2 last) {
277 presentation().throw_if_letter_not_in_alphabet(first, last);
278 return set_word_no_checks(first, last);
279 }
280
296 template <typename Iterator1, typename Iterator2>
297 Stephen& set_word_no_checks(Iterator1 first, Iterator2 last);
298
308 bool is_word_set() const noexcept {
309 return _is_word_set;
310 }
311
321 word_type const& word() const {
322 throw_if_not_ready();
323 return _word;
324 }
325
338 throw_if_not_ready();
339 return _word_graph;
340 }
341
355 // Throws if run throws, also this is not in the helper namespace because
356 // we cache the return value.
358
367 static constexpr node_type initial_state() noexcept {
368 return 0;
369 }
370
391
412
413 private:
414 void report_before_run();
415 void report_after_run();
416
417 Stephen& init_after_presentation_set();
418 void throw_if_presentation_empty(presentation_type const& p) const {
419 if (p.alphabet().empty()) {
420 LIBSEMIGROUPS_EXCEPTION("the presentation must not have 0 generators");
421 }
422 }
423 void throw_if_not_ready() const;
424 void init_word_graph_from_word_no_checks() {
425 _word_graph.init(presentation());
426 _word_graph.report_prefix("Stephen");
427 _word_graph.complete_path(
428 presentation(), 0, _word.cbegin(), _word.cend());
429 // Here so we have accurate data when using to_human_readable_repr
430 _word_graph.number_of_active_nodes(_word_graph.number_of_nodes_active());
431 }
432
433 void run_impl() override;
434 void really_run_impl();
435
436 bool finished_impl() const noexcept override {
437 return _finished;
438 }
439
440 void standardize() {
441 word_graph::standardize(_word_graph);
442 _word_graph.induced_subgraph_no_checks(
443 0, _word_graph.number_of_nodes_active());
444 }
445 };
446
447 // Deduction guides
448 // The following is not a mistake but intentional, if no presentation type is
449 // explicitly used, then we use Presentation<word_type>.
450 // Presentation<std::string> is not allowed.
451 // TODO(2): allow for Presentation<std::string> by templating on Word (after
452 // we separate implementation and interface)
453
463
473
483
493 ->Stephen<Presentation<word_type>>;
494
505
516
527
538 // TODO(2): other shared_ptr guides?
539
540} // namespace libsemigroups
541
542namespace libsemigroups {
552 namespace stephen {
553
587 template <typename PresentationType>
589
614 template <typename PresentationType>
616
643 template <typename PresentationType>
645 s.run();
647 return paths.source(s.initial_state()).target(s.accept_state());
648 }
649
673 template <typename PresentationType>
675 s.run();
677 return paths.source(s.initial_state());
678 }
679
718 // Not noexcept because number_of_paths isn't
719 template <typename PresentationType>
721 size_t min = 0,
722 size_t max = POSITIVE_INFINITY) {
723 s.run();
724 using node_type = typename Stephen<PresentationType>::node_type;
725 return number_of_paths(
726 s.word_graph(), node_type(0), s.accept_state(), min, max);
727 }
728
755 // Not noexcept because number_of_paths isn't
756 template <typename PresentationType>
758 size_t min = 0,
759 size_t max = POSITIVE_INFINITY) {
760 s.run();
761 return number_of_paths(s.word_graph(), 0, min, max);
762 }
763
775 template <typename PresentationType>
777
790 // things?
791 template <typename PresentationType>
796
811 template <typename PresentationType>
816
817 } // namespace stephen
818
838 template <typename PresentationType>
840 Stephen<PresentationType> const& y) {
841 if (x.presentation() != y.presentation()) {
843 "x.presentation() must equal y.presentation() when comparing "
844 "Stephen instances")
845 }
846 return equal_to_no_checks(x, y);
847 }
848
870 template <typename PresentationType>
872 Stephen<PresentationType> const& y) {
873 return stephen::accepts(const_cast<Stephen<PresentationType>&>(x), y.word())
875 x.word());
876 }
877
886 template <typename PresentationType>
887 [[nodiscard]] std::string
889} // namespace libsemigroups
890
891#include "stephen.tpp"
892
893#endif // LIBSEMIGROUPS_STEPHEN_HPP_
T cbegin(T... args)
A representation of a graph in the DOT language of Graphviz.
Definition dot.hpp:115
For an implementation of inverse presentations for semigroups or monoids.
Definition presentation.hpp:2188
Range for iterating through paths in a WordGraph.
Definition paths.hpp:601
uint64_t number_of_paths(WordGraph< Node1 > const &wg, Node2 source)
For an implementation of presentations for semigroups or monoids.
Definition presentation.hpp:102
void run()
Run until finished.
Runner()
Default constructor.
For constructing the word graph of left factors of a word in an f.p. semigroup.
Definition stephen.hpp:90
Stephen & operator=(Stephen const &)=default
Default copy assignment operator.
Stephen(PresentationType const &p)
Construct from a presentation (copy).
Definition stephen.hpp:163
WordGraph< uint32_t > word_graph_type
The return type of the function word_graph.
Definition stephen.hpp:112
presentation_type const & presentation() const noexcept
Get the input presentation.
Definition stephen.hpp:256
Stephen & operator=(Stephen &&)=default
Default move assignment operator.
Stephen & init(std::shared_ptr< PresentationType > const &ptr)
Initialize from a shared pointer to presentation (copy).
node_type accept_state()
Get the accept state of the word graph.
Stephen & set_word(Iterator1 first, Iterator2 last)
Set the initial word.
Definition stephen.hpp:276
bool is_word_set() const noexcept
Check if the initial word is set.
Definition stephen.hpp:308
Stephen & init(PresentationType &&p)
Initialize from a presentation (move).
Definition stephen.hpp:231
PresentationType presentation_type
The underlying presentation type.
Definition stephen.hpp:109
Stephen(PresentationType &&p)
Construct from a presentation (move).
Definition stephen.hpp:175
Stephen(Stephen const &that)=default
Default copy constructor.
Stephen & init(PresentationType const &p)
Initialize from a presentation (copy).
Definition stephen.hpp:216
Stephen(std::shared_ptr< PresentationType > const &ptr)
Construct from a shared pointer to presentation (copy).
Definition stephen.hpp:187
word_type const & word() const
Get the initial word.
Definition stephen.hpp:321
void append_no_checks(Stephen< PresentationType > &that)
Append a Stephen instance (no checks).
Stephen & init()
Reinitialize an existing Stephen instance.
Stephen(Stephen &&)=default
Default move constructor.
static constexpr node_type initial_state() noexcept
Get the initial state of the word graph.
Definition stephen.hpp:367
Stephen()
Default constructor.
word_graph_type const & word_graph() const
Get the word graph.
Definition stephen.hpp:337
word_graph_type::node_type node_type
The node type of word_graph_type.
Definition stephen.hpp:114
Stephen & set_word_no_checks(Iterator1 first, Iterator2 last)
Set the initial word (no checks).
void operator*=(Stephen< PresentationType > &that)
Append a Stephen instance.
Class for representing word graphs.
Definition word-graph.hpp:82
uint32_t node_type
Definition word-graph.hpp:98
T cend(T... args)
std::string to_human_readable_repr(AhoCorasick const &ac)
Return a string representation.
PositiveInfinity const POSITIVE_INFINITY
Value for positive infinity.
#define LIBSEMIGROUPS_EXCEPTION(...)
Throw a LibsemigroupsException.
Definition exception.hpp:95
bool operator==(Presentation< Word > const &lhop, Presentation< Word > const &rhop)
Compare for equality.
Definition presentation.hpp:2346
Stephen(Presentation< word_type > const &) -> Stephen< Presentation< word_type > >
Deduction guide.
std::vector< letter_type > word_type
Type for a word over the generators of a semigroup.
Definition types.hpp:101
T make_shared(T... args)
T move(T... args)
Namespace containing helper functions for the Paths class.
Definition paths.hpp:56
Helper functions for the Stephen class.
Definition stephen.hpp:552
Dot dot(Stephen< PresentationType > &s)
Returns a Dot object representing the Stephen word graph.
auto words_accepted(Stephen< PresentationType > &s)
Returns a range object containing all words accepted by a Stephen instance in short-lex order.
Definition stephen.hpp:644
Stephen< PresentationType > & set_word(Stephen< PresentationType > &s, word_type const &w)
Set the initial word.
Definition stephen.hpp:792
bool is_left_factor(Stephen< PresentationType > &s, word_type const &w)
Check if a word is a left factor of Stephen::word.
auto left_factors(Stephen< PresentationType > &s)
Returns a range object containing all the words (in short-lex order) that are left factors of Stephen...
Definition stephen.hpp:674
uint64_t number_of_words_accepted(Stephen< PresentationType > &s, size_t min=0, size_t max=POSITIVE_INFINITY)
Returns the number of words accepted with length in a given range.
Definition stephen.hpp:720
bool accepts(Stephen< PresentationType > &s, word_type const &w)
Check if a word is accepted by a Stephen instance.
Stephen< PresentationType > & set_word_no_checks(Stephen< PresentationType > &s, word_type const &w)
Set the initial word (no checks).
Definition stephen.hpp:812
uint64_t number_of_left_factors(Stephen< PresentationType > &s, size_t min=0, size_t max=POSITIVE_INFINITY)
Returns the number of left factors with length in a given range.
Definition stephen.hpp:757
bool standardize(Graph &wg, Forest &f, Order val)
Standardizes a word graph in-place.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
bool equal_to_no_checks(Stephen< PresentationType > const &x, Stephen< PresentationType > const &y)
Check equality of two Stephen instances (no checks).
Definition stephen.hpp:871