libsemigroups  v3.1.3
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
action.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 generic implementation of a class Action which
20// represents the action of a semigroup on a set.
21
22#ifndef LIBSEMIGROUPS_ACTION_HPP_
23#define LIBSEMIGROUPS_ACTION_HPP_
24
25#include <cstddef> // for size_t
26#include <stack> // for stack
27#include <type_traits> // for is_trivially_default_construc...
28#include <unordered_map> // for unordered_map
29#include <utility> // for pair
30#include <vector> // for vector
31
32#include "adapters.hpp" // for One
33#include "constants.hpp" // for UNDEFINED
34#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
35#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
36#include "forest.hpp" // for Forest
37#include "gabow.hpp" // for Gabow
38#include "runner.hpp" // for Runner
39#include "word-graph.hpp" // for WordGraph
40
41#include "detail/bruidhinn-traits.hpp" // for detail::BruidhinnTraits
42#include "detail/report.hpp" // for report_default
43
44namespace libsemigroups {
82
91 enum class side {
98 };
99
171 template <typename Element,
172 typename Point,
173 typename Func,
174 typename Traits,
175 side LeftOrRight>
176 class Action : public Runner, private detail::BruidhinnTraits<Point> {
178 // Action - typedefs - private
180
181 using internal_point_type =
182 typename detail::BruidhinnTraits<Point>::internal_value_type;
183 using internal_const_point_type =
184 typename detail::BruidhinnTraits<Point>::internal_const_value_type;
185 using internal_const_reference =
186 typename detail::BruidhinnTraits<Point>::internal_const_reference;
187
188 struct InternalEqualTo : private detail::BruidhinnTraits<Point> {
189 using EqualTo = typename Traits::EqualTo;
190 bool operator()(internal_const_point_type x,
191 internal_const_point_type y) const {
192 return EqualTo()(this->to_external_const(x),
193 this->to_external_const(y));
194 }
195 };
196
197 struct InternalHash : private detail::BruidhinnTraits<Point> {
198 using Hash = typename Traits::Hash;
199 size_t operator()(internal_const_point_type x) const {
200 return Hash()(this->to_external_const(x));
201 }
202 };
203
204 using Degree = typename Traits::Degree;
205
206 // Forward decls
207 class MultiplierCache;
208 struct Options;
209
210 static_assert(
213 internal_const_point_type>::type>::value,
214 "internal_const_element_type must be const or pointer to const");
215
216 public:
218 // Action - typedefs - public
220
225 using element_type = Element;
226
231 using point_type = Point;
232
238 using index_type = size_t;
239
250 using action_type = Func;
251
256 template <typename Elment,
257 typename Pint,
258 typename Fnc,
259 typename Trits,
260 side LftOrRight>
261 // TODO make this a free function, and non-friend
265
270 // TODO make this a free function, and non-friend
271 friend std::ostream& operator<<(std::ostream& os, Action const& action) {
272 os << detail::to_string(action);
273 return os;
274 }
275
277 // Action - iterators - public
279
285 = detail::BruidhinnConstIterator<point_type,
287
293 typename detail::BruidhinnTraits<Point>::const_reference;
294
300 typename detail::BruidhinnTraits<Point>::const_pointer;
301
302 private:
304 // Action - internal types with call operators - private
306
307 using ActionOp = Func;
308 using One = typename Traits::One;
309 using Product = typename Traits::Product;
310 using Swap = typename Traits::Swap;
311
313 "the 3rd template parameter Func is not trivially "
314 "default constructible");
315 // TODO(2) more static assertions
316
318 // Action - product functions for left/right multiplication - private
320
321 auto internal_product(element_type& xy,
322 element_type const& x,
323 element_type const& y) {
324 if constexpr (LeftOrRight == side::right) {
325 Product()(xy, x, y);
326 } else {
327 Product()(xy, y, x);
328 }
329 }
330
332 // Action - data members - private
334
335 // TODO(1) change size_t -> uint32_t
337 WordGraph<uint32_t> _graph;
338 std::unordered_map<internal_const_point_type,
339 size_t,
340 InternalHash,
341 InternalEqualTo>
342 _map;
343 Options _options;
345 MultiplierCache _multipliers_from_scc_root;
346 MultiplierCache _multipliers_to_scc_root;
347 size_t _pos;
348 Gabow<uint32_t> _scc;
349 internal_point_type _tmp_point;
350 bool _tmp_point_init;
351
352 public:
354 // Action - constructor + destructor - public
356
367 Action();
368
378 Action& init();
379
380 //! Default copy constructor.
381 Action(Action const& that) : Action() {
382 *this = that;
383 }
384
385 //! Default move constructor.
386 Action(Action&& that) : Action() {
387 *this = std::move(that);
388 }
389
391 Action& operator=(Action const&);
392
395
396 ~Action();
397
399 // Action - modifiers - public
401
415 Action& reserve(size_t val);
416
433
447 //! Constant.
448 Action& add_generator(element_type const& gen) {
449 throw_if_bad_degree(gen);
450 return add_generator_no_checks(gen);
451 }
452
466 //! Constant.
468 _gens.push_back(gen);
469 return *this;
470 }
471
473 // Action - member functions: position, empty, size, etc - public
475
484 //! Constant.
485 [[nodiscard]] size_t number_of_generators() const noexcept {
486 return _gens.size();
487 }
488
497 //! Constant.
498 [[nodiscard]] std::vector<Element> const& generators() const noexcept {
499 return _gens;
500 }
501
517 [[nodiscard]] index_type position(const_reference_point_type pt) const;
518
528 //! Constant.
529 [[nodiscard]] bool empty() const noexcept {
530 return _orb.empty();
531 }
532
546 [[nodiscard]] inline const_reference_point_type
547 operator[](index_type pos) const noexcept {
548 LIBSEMIGROUPS_ASSERT(pos < _orb.size());
549 return this->to_external_const(_orb[pos]);
550 }
551
564 //! Constant.
565 [[nodiscard]] inline const_reference_point_type at(index_type pos) const {
566 return this->to_external_const(_orb.at(pos));
567 }
568
580 //! points in the orbit and \f$n\f$ is the number of generators.
581 [[nodiscard]] size_t size() {
582 run();
583 return _orb.size();
584 }
585
597 //! Constant.
598 [[nodiscard]] size_t current_size() const noexcept {
599 return _orb.size();
600 }
601
615 //! Constant.
616 [[nodiscard]] const_iterator cbegin() const noexcept {
617 return const_iterator(_orb.cbegin());
618 }
619
620 //! \copydoc cbegin
621 [[nodiscard]] const_iterator begin() const noexcept {
622 return cbegin();
623 }
624
638 // TODO(1) add a reference to the ranges page when it exists
639 [[nodiscard]] auto range() const noexcept {
640 return rx::iterator_range(_orb.cbegin(), _orb.cend())
641 | rx::transform([this](auto const& pt) {
642 return this->to_external_const(pt);
643 });
644 }
645
660 //! Constant.
661 [[nodiscard]] const_iterator cend() const noexcept {
662 return const_iterator(_orb.cend());
663 }
664
665 //! \copydoc cend
666 [[nodiscard]] const_iterator end() const noexcept {
667 return cend();
668 }
669
671 // Action - member functions: strongly connected components - public
673
687 //! Constant.
688 [[nodiscard]] bool cache_scc_multipliers() const noexcept {
689 return _options._cache_scc_multipliers;
690 }
691
707 //! Constant.
708 Action& cache_scc_multipliers(bool val) noexcept {
709 _options._cache_scc_multipliers = val;
710 return *this;
711 }
712
730 //! enumerated orbit.
732 return multiplier_private<true>(
733 _multipliers_from_scc_root, _scc.spanning_forest(), pos);
734 }
735
753 //! enumerated orbit.
755 return multiplier_private<false>(
756 _multipliers_to_scc_root, _scc.reverse_spanning_forest(), pos);
757 }
758
778 // TODO(2) this could be a helper
779 return root_of_scc(position(x));
780 }
781
798 //! enumerated orbit.
800 return this->to_external_const(_orb[_scc.root_of(pos)]);
801 }
802
813 //! enumerated orbit.
814 [[nodiscard]] WordGraph<uint32_t> const& word_graph() {
815 run();
816 return _graph;
817 }
818
833 //! enumerated orbit.
834 [[nodiscard]] Gabow<uint32_t> const& scc() {
835 run();
836 return _scc;
837 }
838
851 // These functions allow the action operation (defined by Func) to be called
852 // on an instance of Action. This isn't very helpful in C++ code, but is in
853 // the python bindings, where figuring out the type of Func is a bit fiddly.
854 static void apply(point_type& result,
855 point_type const& pt,
856 element_type const& x) {
857 ActionOp()(result, pt, x);
858 }
859
870 //! \no_libsemigroups_except
871 [[nodiscard]] static point_type apply(point_type const& pt,
872 element_type const& x) {
873 point_type result;
874 apply(result, pt, x);
875 return result;
876 }
877
878 private:
880 // Runner - pure virtual member functions - private
882
883 [[nodiscard]] bool finished_impl() const override {
884 return (_pos == _orb.size()) && (_graph.out_degree() == _gens.size());
885 }
886
887 void run_impl() override;
888
890 // Action - member functions - private
892
893 template <bool Forward>
894 element_type multiplier_private(MultiplierCache& mults,
895 Forest const& f,
896 index_type pos);
897
898 void throw_if_index_out_of_range(index_type i) const;
899 void throw_if_no_generators() const;
900 void throw_if_bad_degree(element_type const&) const;
901 }; // class Action
902
911 template <typename Element, typename Point>
926
931 template <typename Element,
932 typename Point,
933 typename Func = ImageRightAction<Element, Point>,
934 typename Traits = ActionTraits<Element, Point>>
936
941 template <typename Element,
942 typename Point,
943 typename Func = ImageLeftAction<Element, Point>,
944 typename Traits = ActionTraits<Element, Point>>
946
962 template <typename Element,
963 typename Point,
964 typename Func,
965 typename Traits,
966 side LeftOrRight>
969} // namespace libsemigroups
970
971#include "action.tpp"
972#endif // LIBSEMIGROUPS_ACTION_HPP_
Class for generating the action of a semigroup.
Definition action.hpp:176
index_type position(const_reference_point_type pt) const
Returns the position of a point in the so far discovered points.
size_t size()
Returns the size of the fully enumerated action.
Definition action.hpp:580
auto range() const noexcept
Returns a range object containing the current points in the action.
Definition action.hpp:638
Action & init()
Initialize an existing Action object.
Action & operator=(Action const &)
Default copy assignment operator.
typename detail::BruidhinnTraits< Point >::const_reference const_reference_point_type
The type of a const reference to a point_type.
Definition action.hpp:291
const_iterator begin() const noexcept
Returns a const_iterator (random access iterator) pointing at the first point.
Definition action.hpp:620
friend std::ostringstream & operator<<(std::ostringstream &os, Action< Elment, Pint, Fnc, Trits, LftOrRight > const &action)
Insertion operator.
Action & add_generator_no_checks(element_type const &gen)
Add a generator to the action.
Definition action.hpp:466
bool empty() const noexcept
Checks if the Action contains any points.
Definition action.hpp:528
Func action_type
Type of the action of element_type on point_type.
Definition action.hpp:250
Element element_type
The template parameter Element.
Definition action.hpp:225
typename detail::BruidhinnTraits< Point >::const_pointer const_pointer_point_type
The type of a const pointer to a point_type.
Definition action.hpp:298
element_type multiplier_from_scc_root(index_type pos)
Returns a multiplier from a scc root to a given index.
Definition action.hpp:730
const_iterator end() const noexcept
Returns a const_iterator (random access iterator) pointing one past the last point.
Definition action.hpp:665
Action & add_generator(element_type const &gen)
Add a generator to the action.
Definition action.hpp:447
element_type multiplier_to_scc_root(index_type pos)
Returns a multiplier from a given index to a scc root.
Definition action.hpp:753
size_t number_of_generators() const noexcept
Returns the number of generators.
Definition action.hpp:484
Action & reserve(size_t val)
Increase the capacity to a value that is greater or equal to val.
size_t index_type
The type of the index of a point.
Definition action.hpp:238
Point point_type
The template parameter Point.
Definition action.hpp:231
static void apply(point_type &result, point_type const &pt, element_type const &x)
Apply the template parameter Func in-place.
Definition action.hpp:853
detail::BruidhinnConstIterator< point_type, std::vector< internal_point_type > > const_iterator
The type of a const iterator pointing to a point_type.
Definition action.hpp:284
const_iterator cend() const noexcept
Returns a const_iterator (random access iterator) pointing one past the last point.
Definition action.hpp:660
Action()
Default constructor.
Gabow< uint32_t > const & scc()
Returns a reference to a Gabow object for strongly connected components.
Definition action.hpp:833
size_t current_size() const noexcept
Returns the number of points found so far.
Definition action.hpp:597
std::vector< Element > const & generators() const noexcept
Returns a const reference to the vector of generators.
Definition action.hpp:497
const_reference_point_type root_of_scc(const_reference_point_type x)
Returns a const reference to the root point of a strongly connected component.
Definition action.hpp:776
const_iterator cbegin() const noexcept
Returns a const_iterator (random access iterator) pointing at the first point.
Definition action.hpp:615
Action & add_seed(const_reference_point_type seed)
Add a seed to the action.
WordGraph< uint32_t > const & word_graph()
Definition action.hpp:813
friend std::ostream & operator<<(std::ostream &os, Action const &action)
Definition action.hpp:271
bool cache_scc_multipliers() const noexcept
Returns whether or not we are caching scc multipliers.
Definition action.hpp:687
const_reference_point_type at(index_type pos) const
Returns a const reference to the point in a given position.
Definition action.hpp:564
const_reference_point_type operator[](index_type pos) const noexcept
Returns a const reference to the point in a given position.
Definition action.hpp:546
Class implementing Gabow's algorithm for computing strongly connected components of a WordGraph.
Definition gabow.hpp:61
void run()
Run until finished.
Runner()
Default constructor.
Class for representing word graphs.
Definition word-graph.hpp:83
size_type out_degree() const noexcept
Returns the out-degree.
Definition word-graph.hpp:824
Action< Element, Point, Func, Traits, side::right > RightAction
Definition action.hpp:935
std::string to_human_readable_repr(Action< Element, Point, Func, Traits, LeftOrRight > const &action)
Return a human readable representation of an Action object.
Action< Element, Point, Func, Traits, side::left > LeftAction
Definition action.hpp:945
side
Enum class indicating the handedness or side of an action.
Definition action.hpp:91
@ right
Definition action.hpp:97
@ left
Definition action.hpp:94
T move(T... args)
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
T size(T... args)
Definition action.hpp:912
::libsemigroups::Hash< Point > Hash
Adapter for hashing.
Definition action.hpp:916
::libsemigroups::Swap< Element > Swap
Adapter for swapping.
Definition action.hpp:920
::libsemigroups::Degree< Element > Degree
Adapter for the degree of an element.
Definition action.hpp:914
::libsemigroups::EqualTo< Point > EqualTo
Adapter for testing equality.
Definition action.hpp:918
::libsemigroups::Product< Element > Product
Adapter for the product of two elements.
Definition action.hpp:924
::libsemigroups::One< Element > One
Adapter for the identity element of the given type.
Definition action.hpp:922
Adapter for the degree of an element.
Definition adapters.hpp:159
Adapter for testing equality.
Definition adapters.hpp:413
Adapter for hashing.
Definition adapters.hpp:446
Adapter for the value of a left action.
Definition adapters.hpp:350
Adapter for the value of a right action.
Definition adapters.hpp:392
Adapter for the identity element of the given type.
Definition adapters.hpp:246
Adapter for the product of two elements.
Definition adapters.hpp:284
Adapter for swapping.
Definition adapters.hpp:666