libsemigroups  v3.3.0
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
konieczny.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2019-2025 Finn Smith
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// This file contains a generic implementation of Konieczny's algorithm,
19// originally for computing subsemigroups of the boolean matrix monoid.
20
21// TODO(later):
22// * exception safety!
23// * expose iterators to relevant things in D-classes, in particular elements
24
25#ifndef LIBSEMIGROUPS_KONIECZNY_HPP_
26#define LIBSEMIGROUPS_KONIECZNY_HPP_
27
28#include <algorithm> // for binary_search
29#include <cstddef> // for size_t
30#include <initializer_list>
31#include <set> // for set
32#include <type_traits> // for is_pointer
33#include <unordered_map> // for unordered_map
34#include <unordered_set> // for unordered_set
35#include <utility> // for pair, make_pair
36#include <vector> // for vector
37
38#include "action.hpp" // for LeftAction, RightAction
39#include "adapters.hpp" // for Lambda, etc
40#include "constants.hpp" // for UNDEFINED
41#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
42#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
43#include "runner.hpp" // for Runner
44
45#include "detail/pool.hpp" // for detail::Pool
46#include "detail/report.hpp" // for report_default
47#include "detail/timer.hpp" // for Timer
48
49#include "detail/bruidhinn-traits.hpp" // for BruidhinnTraits
50
51namespace libsemigroups {
52
77
85 template <typename Element>
88 using element_type = typename detail::BruidhinnTraits<Element>::value_type;
89
92 typename detail::BruidhinnTraits<Element>::const_value_type;
93
97 typename ::libsemigroups::LambdaValue<element_type>::type;
98
101 typename ::libsemigroups::RhoValue<element_type>::type;
102
104 using rank_state_type = typename ::libsemigroups::RankState<element_type>;
105
112
115 using rho_orb_type
149 };
150
177 template <typename Element, typename Traits = KoniecznyTraits<Element>>
178 class Konieczny : public Runner, private detail::BruidhinnTraits<Element> {
179 // pointers are not currently supported
180 static_assert(!std::is_pointer_v<Element>,
181 "Pointer types are not currently supported by Konieczny");
182
184 // Konieczny - aliases - private
186
187 using internal_element_type =
188 typename detail::BruidhinnTraits<Element>::internal_value_type;
189 using internal_const_element_type =
190 typename detail::BruidhinnTraits<Element>::internal_const_value_type;
191 using internal_const_reference =
192 typename detail::BruidhinnTraits<Element>::internal_const_reference;
193 using internal_reference =
194 typename detail::BruidhinnTraits<Element>::internal_reference;
195
196 using PairHash = Hash<std::pair<size_t, size_t>>;
197
198 public:
200 // Konieczny - aliases - public
202
204 using element_type = typename Traits::element_type;
205
207 using const_element_type = typename Traits::const_element_type;
208
211 typename detail::BruidhinnTraits<Element>::const_reference;
212
216 using D_class_index_type = size_t;
217
219 using lambda_value_type = typename Traits::lambda_value_type;
220
222 using lambda_orb_type = typename Traits::lambda_orb_type;
223
225 using rho_value_type = typename Traits::rho_value_type;
226
228 using rho_orb_type = typename Traits::rho_orb_type;
229
231 using Degree = typename Traits::Degree;
232
234 using EqualTo = typename Traits::EqualTo;
235
237 using Lambda = typename Traits::Lambda;
238
240 using Less = typename Traits::Less;
241
243 using One = typename Traits::One;
244
246 using Product = typename Traits::Product;
247
249 using Rank = typename Traits::Rank;
250
252 using Rho = typename Traits::Rho;
253
255 using Swap = typename Traits::Swap;
256
257 private:
259 // Konieczny - aliases - private
261
262 using lambda_orb_index_type = typename lambda_orb_type::index_type;
263 using rho_orb_index_type = typename rho_orb_type::index_type;
264 using rank_type = size_t;
265 using rank_state_type = typename Traits::rank_state_type;
266 using left_indices_index_type = size_t;
267 using right_indices_index_type = size_t;
268
270 // Konieczny - internal structs - private
272
273 struct InternalHash : private detail::BruidhinnTraits<Element> {
274 size_t operator()(internal_const_element_type x) const {
275 return Hash<Element>()(this->to_external_const(x));
276 }
277 };
278
279 struct InternalEqualTo : private detail::BruidhinnTraits<Element> {
280 bool operator()(internal_const_reference x,
281 internal_const_reference y) const {
282 return EqualTo()(this->to_external_const(x),
283 this->to_external_const(y));
284 }
285 };
286
287 struct InternalLess : private detail::BruidhinnTraits<Element> {
288 bool operator()(internal_const_reference x,
289 internal_const_reference y) const {
290 return Less()(this->to_external_const(x), this->to_external_const(y));
291 }
292 };
293
294 struct InternalVecEqualTo : private detail::BruidhinnTraits<Element> {
295 size_t operator()(std::vector<internal_element_type> const& x,
296 std::vector<internal_element_type> const& y) const {
297 LIBSEMIGROUPS_ASSERT(x.size() == y.size());
298 return std::equal(x.cbegin(), x.cend(), y.cbegin(), InternalEqualTo());
299 }
300 };
301
302 struct InternalVecFree : private detail::BruidhinnTraits<Element> {
303 void operator()(std::vector<internal_element_type> const& x) {
304 for (auto it = x.cbegin(); it != x.cend(); ++it) {
305 this->internal_free(*it);
306 }
307 }
308 };
309
310 struct InternalVecCopy : private detail::BruidhinnTraits<Element> {
311 void operator()(std::vector<internal_element_type> const& source,
312 std::vector<internal_element_type>& target) {
313 InternalVecFree()(target);
314 for (auto it = source.cbegin(); it != source.cend(); ++it) {
315 target.push_back(this->internal_copy(*it));
316 }
317 }
318 };
319
320 struct OneParamLambda {
321 lambda_value_type operator()(const_reference x) const {
323 Lambda()(lval, x);
324 return lval;
325 }
326 };
327
328 struct OneParamRho {
329 rho_value_type operator()(const_reference x) const {
330 rho_value_type rval;
331 Rho()(rval, x);
332 return rval;
333 }
334 };
335
336 struct InternalRank {
337 template <typename SFINAE = size_t>
338 auto operator()(void*, const_reference x)
339 -> std::enable_if_t<std::is_void_v<typename rank_state_type::type>,
340 SFINAE> {
341 return Rank()(x);
342 }
343
344 template <typename SFINAE = size_t>
345 auto operator()(rank_state_type* state, const_reference x)
346 -> std::enable_if_t<!std::is_void_v<typename rank_state_type::type>,
347 SFINAE> {
348 return Rank()(*state, x);
349 }
350 };
351
352 struct RepInfo {
353 RepInfo(D_class_index_type D_idx,
354 internal_element_type elt,
355 lambda_orb_index_type lambda_idx,
356 rho_orb_index_type rho_idx)
357 : _D_idx(D_idx),
358 _elt(elt),
359 _lambda_idx(lambda_idx),
360 _rho_idx(rho_idx) {}
361
362 D_class_index_type _D_idx;
363 internal_element_type _elt;
364 lambda_orb_index_type _lambda_idx;
365 rho_orb_index_type _rho_idx;
366 };
367
368 public:
370 // Konieczny - constructor and destructor - public
372
383
394
405 Konieczny(Konieczny const& that);
406
420
423
426
427 ~Konieczny();
428
430 // Konieczny - forward class declarations - public/private
432
448 class DClass : protected detail::BruidhinnTraits<Element> {
449 // This friend is only here so that the virtual contains(x, lpos, rpos)
450 // method and the cbegin_left_indices etc. methods can be private.
451 friend class Konieczny<Element, Traits>;
452
454 // DClass - aliases - protected
456#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
457 using konieczny_type = Konieczny<Element, Traits>;
458 using internal_set_type = std::
459 unordered_set<internal_element_type, InternalHash, InternalEqualTo>;
460
462 // DClass - default constructor - private
464
465 private:
466 DClass();
467
468 void clear();
469
471 // DClass - constructors - protected
473 protected:
474 DClass(Konieczny* parent, internal_reference rep);
475
476 DClass(DClass const& that);
477
478 DClass& operator=(DClass const& that);
479
480 DClass(DClass&&) = delete;
481 DClass& operator=(DClass&&) = delete;
482
483#endif // ndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
484
485 public:
487 // DClass - destructor - public
489 virtual ~DClass();
491 // DClass - member functions - public
493
507 return this->to_external_const(_rep);
508 }
509
520 size_t size() const {
521 LIBSEMIGROUPS_ASSERT(this->class_computed());
523 }
524
535 size_t number_of_L_classes() const {
536 LIBSEMIGROUPS_ASSERT(_left_mults.size() > 0);
537 LIBSEMIGROUPS_ASSERT(this->class_computed());
538 return _left_mults.size();
539 }
540
551 size_t number_of_R_classes() const {
552 // compute_right_mults();
553 LIBSEMIGROUPS_ASSERT(_right_mults.size() > 0);
554 LIBSEMIGROUPS_ASSERT(this->class_computed());
555 return _right_mults.size();
556 }
557
569 size_t size_H_class() const {
570 // compute_H_class();
571 LIBSEMIGROUPS_ASSERT(_H_class.size() > 0);
572 LIBSEMIGROUPS_ASSERT(this->class_computed());
573 return _H_class.size();
574 }
575
583 bool is_regular_D_class() const noexcept {
584 return _is_regular_D_class;
585 }
586
604
609 virtual size_t number_of_idempotents() const {
610 return 0;
611 }
612
613 protected:
614#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
616 // DClass - iterators - protected
618 using const_iterator =
620
621 const_iterator cbegin_left_reps() {
622 compute_left_reps();
623 return _left_reps.cbegin();
624 }
625
626 const_iterator cend_left_reps() {
627 compute_left_reps();
628 return _left_reps.cend();
629 }
630
631 const_iterator cbegin_right_reps() {
632 compute_right_reps();
633 return _right_reps.cbegin();
634 }
635
636 const_iterator cend_right_reps() {
637 compute_right_reps();
638 return _right_reps.cend();
639 }
640
641 const_iterator cbegin_left_mults() {
642 compute_left_mults();
643 return _left_mults.cbegin();
644 }
645
646 const_iterator cend_left_mults() {
647 compute_left_mults();
648 return _left_mults.cend();
649 }
650
651 const_iterator cbegin_right_mults() {
652 compute_right_mults();
653 return _right_mults.cbegin();
654 }
655
656 const_iterator cend_right_mults() {
657 compute_right_mults();
658 return _right_mults.cend();
659 }
660
661 const_iterator cbegin_H_class() {
662 compute_H_class();
663 return _H_class.cbegin();
664 }
665
666 const_iterator cend_H_class() {
667 compute_H_class();
668 return _H_class.cend();
669 }
670
671 internal_element_type left_mults_inv(size_t i) {
672 compute_left_mults_inv();
673 return _left_mults_inv[i];
674 }
675
676 internal_element_type right_mults_inv(size_t i) {
677 compute_right_mults_inv();
678 return _right_mults_inv[i];
679 }
680
681 internal_element_type H_class_no_checks(size_t i) const {
682 return _H_class[i];
683 }
684
686 // DClass - initialisation member functions - protected
688 virtual void compute_frame() = 0;
689 virtual void compute_left_indices() = 0;
690 virtual void compute_left_mults() = 0;
691 virtual void compute_left_mults_inv() = 0;
692 virtual void compute_left_reps() = 0;
693 virtual void compute_right_indices() = 0;
694 virtual void compute_right_mults() = 0;
695 virtual void compute_right_mults_inv() = 0;
696 virtual void compute_right_reps() = 0;
697 virtual void compute_H_class() = 0;
698
700 // DClass - containment - protected
702
703 // Returns whether the element \p x belongs to this
704 // \f$\mathscr{D}\f$-class.
705 //
706 // Given an element \p x of the semigroup represented by \c parent, this
707 // function returns whether \p x is an element of the
708 // \f$\mathscr{D}\f$-class represented by \c this. If \p x is not an
709 // element of the semigroup, then the behaviour is undefined.
710 // This member function involved computing most of the frame for
711 // \c this, if it is not already known.
712 bool contains_no_checks(internal_const_reference x);
713
714 // Returns whether the element \p x belongs to this
715 // \f$\mathscr{D}\f$-class.
716 //
717 // This overload of DClass::contains_no_checks is provided in order to
718 // avoid recalculating the rank of \p x when it is already known.
719 bool contains_no_checks(internal_const_reference x, size_t rank);
720
721 // Returns whether the element \p x belongs to this
722 // \f$\mathscr{D}\f$-class.
723 //
724 // This overload of DClass::contains_no_checks is provided in order to
725 // avoid recalculating the rank, lambda value, and rho value of \p x
726 // when they are already known.
727 bool contains_no_checks(internal_const_reference x,
728 size_t rank,
729 lambda_orb_index_type lpos,
730 rho_orb_index_type rpos);
731
732 // Returns whether the element \p x belongs to this
733 // \f$\mathscr{D}\f$-class.
734 //
735 // This overload of DClass::contains_no_checks is provided in order to
736 // avoid recalculating the lambda value and rho value of \p x when they
737 // are already known.
738 virtual bool contains_no_checks(internal_const_reference x,
739 lambda_orb_index_type lpos,
740 rho_orb_index_type rpos)
741 = 0;
742
743 virtual bool contains(const_reference x,
744 lambda_orb_index_type lpos,
745 rho_orb_index_type rpos)
746 = 0;
747
749 // DClass - accessor member functions - protected
751
752 size_t number_of_left_reps_no_checks() const noexcept {
753 return _left_reps.size();
754 }
755
756 size_t number_of_right_reps_no_checks() const noexcept {
757 return _right_reps.size();
758 }
759
760 size_t size_H_class_no_checks() const noexcept {
761 return _H_class.size();
762 }
763
764 void push_left_mult(internal_const_reference x);
765
766 void push_left_mult_inv(internal_const_reference x);
767
768 void push_right_mult(internal_const_reference x);
769
770 void push_right_mult_inv(internal_const_reference x);
771
772 void push_left_rep(internal_const_reference x);
773
774 void push_right_rep(internal_const_reference x);
775
776 bool class_computed() const noexcept {
777 return _class_computed;
778 }
779
780 bool mults_computed() const noexcept {
781 return _mults_computed;
782 }
783
784 bool reps_computed() const noexcept {
785 return _reps_computed;
786 }
787
788 bool H_class_computed() const noexcept {
789 return _H_class_computed;
790 }
791
792 void set_class_computed(bool x) noexcept {
793 _class_computed = x;
794 }
795
796 void set_mults_computed(bool x) noexcept {
797 _mults_computed = x;
798 }
799
800 void set_reps_computed(bool x) noexcept {
801 _reps_computed = x;
802 }
803
804 void set_H_class_computed(bool x) noexcept {
805 _H_class_computed = x;
806 }
807
808 Konieczny* parent() const noexcept {
809 return _parent;
810 }
811
812 void set_parent(Konieczny* x) noexcept {
813 _parent = x;
814 }
815
816 // Watch out! Doesn't copy its argument
817 void push_back_H_class(internal_element_type x) {
818 _H_class.push_back(x);
819 }
820
821 std::vector<internal_element_type>& H_class() {
822 return _H_class;
823 }
824
825 lambda_value_type& tmp_lambda_value() const noexcept {
826 return _tmp_lambda_value;
827 }
828
829 rho_value_type& tmp_rho_value() const noexcept {
830 return _tmp_rho_value;
831 }
832
833 rank_type rank() const noexcept {
834 return _rank;
835 }
836
837 internal_set_type& internal_set() const noexcept {
838 return _tmp_internal_set;
839 }
840
841 // Elements must be freed before next used
842 std::vector<internal_element_type>& internal_vec() const noexcept {
843 return _tmp_internal_vec;
844 }
845
846 internal_reference unsafe_rep() noexcept {
847 return _rep;
848 }
849
850 std::vector<lambda_orb_index_type>& left_indices() {
851 return _left_indices;
852 }
853
854 std::vector<rho_orb_index_type>& right_indices() {
855 return _right_indices;
856 }
857
858 protected:
860 // DClass - index iterators - protected
862
863 typename std::vector<left_indices_index_type>::const_iterator
864 cbegin_left_indices() {
865 compute_left_indices();
866 return _left_indices.cbegin();
867 }
868
869 typename std::vector<left_indices_index_type>::const_iterator
870 cend_left_indices() {
871 compute_left_indices();
872 return _left_indices.cend();
873 }
874
875 typename std::vector<right_indices_index_type>::const_iterator
876 cbegin_right_indices() {
877 compute_right_indices();
878 return _right_indices.cbegin();
879 }
880
881 typename std::vector<right_indices_index_type>::const_iterator
882 cend_right_indices() {
883 compute_right_indices();
884 return _right_indices.cend();
885 }
886#endif
887
888 private:
890 // DClass - member functions - private
892
893 // Returns a set of representatives of L- or R-classes covered by \c
894 // this.
895 //
896 // The \f$\mathscr{D}\f$-classes of the parent semigroup are enumerated
897 // either by finding representatives of all L-classes or all R-classes.
898 // This member function returns the representatives obtainable by
899 // multipliying the representatives by generators on either the left or
900 // right.
901 std::vector<RepInfo>& covering_reps();
902
904 // DClass - data - private
906 bool _class_computed;
907 std::vector<internal_element_type> _H_class;
908 bool _H_class_computed;
909 bool _is_regular_D_class;
910 std::vector<lambda_orb_index_type> _left_indices;
911 std::vector<internal_element_type> _left_mults;
912 std::vector<internal_element_type> _left_mults_inv;
913 std::vector<internal_element_type> _left_reps;
914 bool _mults_computed;
915 Konieczny* _parent;
916 rank_type _rank;
917 internal_element_type _rep;
918 bool _reps_computed;
919 std::vector<rho_orb_index_type> _right_indices;
920 std::vector<internal_element_type> _right_mults;
921 std::vector<internal_element_type> _right_mults_inv;
922 std::vector<internal_element_type> _right_reps;
923 mutable internal_set_type _tmp_internal_set; // Does not own its elements
924 mutable std::vector<RepInfo>
925 _tmp_rep_info_vec; // RepInfos do not own their rep
926 mutable std::vector<internal_element_type> _tmp_internal_vec; // Does not
927 mutable lambda_value_type _tmp_lambda_value;
928 mutable rho_value_type _tmp_rho_value;
929 };
930
931 private:
932 class RegularDClass;
933 class NonRegularDClass;
934
935 public:
937 // Konieczny - member functions - public
939
952 size_t number_of_generators() const noexcept {
953 return _gens.empty() ? 0 : _gens.size() - 1;
954 }
955
976 const_reference generator(size_t pos) const {
977 if (pos >= number_of_generators()) {
979 "index out of bounds, expected value in [{}, {}) found {}",
980 0,
982 pos);
983 }
984 return this->to_external_const(_gens[pos]);
985 }
986
1002
1016
1031
1045
1057 run();
1059 }
1060
1071 size_t val = 0;
1075 [&val](DClass const& D) { val += D.number_of_L_classes(); });
1076 return val;
1077 }
1078
1093
1104 size_t val = 0;
1108 [&val](DClass const& D) { val += D.number_of_L_classes(); });
1109 return val;
1110 }
1111
1123 run();
1125 }
1126
1137 size_t val = 0;
1141 [&val](DClass const& D) { val += D.number_of_R_classes(); });
1142 return val;
1143 }
1144
1159
1170 size_t val = 0;
1174 [&val](DClass const& D) { val += D.number_of_R_classes(); });
1175 return val;
1176 }
1177
1189 run();
1191 }
1192
1203 size_t val = 0;
1206 [&val](DClass const& D) {
1207 val += (D.number_of_R_classes()
1208 * D.number_of_L_classes());
1209 });
1210 return val;
1211 }
1212
1224 run();
1226 }
1227
1238 size_t val = 0;
1242 [&val](RegularDClass const& D) { val += D.number_of_idempotents(); });
1243 return val;
1244 }
1245
1260
1271 size_t val = 0;
1274 [&val](DClass const& D) { val += D.size(); });
1275 return val;
1276 }
1277
1290 size_t size() {
1291 run();
1292 return current_size();
1293 }
1294
1306 size_t current_size() const {
1307 size_t val = 0;
1310 [&val](DClass const& D) { val += D.size(); });
1311 return val;
1312 }
1313
1326 size_t degree() const noexcept {
1327 return _degree;
1328 }
1329
1344 return Degree()(x) == degree()
1345 && get_containing_D_class(this->to_internal_const(x), true)
1346 != UNDEFINED;
1347 }
1348
1361 = get_containing_D_class(this->to_internal_const(x), true);
1362 if (i == UNDEFINED) {
1364 "the argument does not belong to this semigroup!");
1365 }
1366 return *_D_classes[i];
1367 }
1368
1385 return contains(x)
1386 && is_regular_element_no_checks(this->to_internal_const(x));
1387 }
1388
1404 template <typename T>
1405 Konieczny& add_generators(T const& first, T const& last);
1406
1420 return add_generators(&gen, &gen + 1);
1421 }
1422
1424 // Konieczny - iterators - public
1426
1429 = detail::BruidhinnConstIterator<element_type,
1431
1444 //! \sa cend_generators
1445 const_iterator cbegin_generators() const noexcept {
1446 return const_iterator(_gens.cbegin());
1447 }
1448
1462 //! \sa cbegin_generators
1463 const_iterator cend_generators() const noexcept {
1464 return const_iterator(_gens.cend() - 1);
1465 }
1466
1467 // forward decl, defined in konieczny.tpp
1468 template <typename T>
1469 struct DClassIteratorTraits;
1470
1479 = detail::ConstIteratorStateless<DClassIteratorTraits<DClass>>;
1480
1492 //! \no_libsemigroups_except
1493 // not noexcept because operator++ isn't necessarily
1495 auto it = _D_classes.cbegin();
1496 if (_run_initialised) {
1497 return const_d_class_iterator(it)
1498 + (_adjoined_identity_contained ? 0 : 1);
1499 } else {
1500 return const_d_class_iterator(it);
1501 }
1502 }
1503
1514 //! \exceptions
1515 //! \no_libsemigroups_except
1517 return const_d_class_iterator(_D_classes.cend());
1518 }
1519
1525 //! \returns
1526 //! A value of type \c const_d_class_iterator.
1528 run();
1529 return cbegin_current_D_classes();
1530 }
1531
1537 //! \returns
1538 //! A value of type \c const_d_class_iterator.
1540 run();
1541 return cend_current_D_classes();
1542 }
1543
1552 = detail::ConstIteratorStateless<DClassIteratorTraits<RegularDClass>>;
1553
1565 //! \no_libsemigroups_except
1566 //!
1567 // not noexcept because operator++ isn't necessarily
1569 auto it = _regular_D_classes.cbegin();
1570 if (_run_initialised) {
1572 + (_adjoined_identity_contained ? 0 : 1);
1573 } else {
1575 }
1576 }
1577
1588 //! \exceptions
1589 //! \no_libsemigroups_except
1591 cend_current_regular_D_classes() const noexcept {
1592 return const_regular_d_class_iterator(_regular_D_classes.cend());
1593 }
1594
1603 //! \exceptions
1604 //! \no_libsemigroups_except
1605 //!
1607 run();
1609 }
1610
1618 //!
1619 //! \exceptions
1620 //! \no_libsemigroups_except
1622 run();
1624 }
1625
1626 private:
1627 using PoolGuard = detail::PoolGuard<internal_element_type>;
1628
1630 // Konieczny - utility methods - private
1632
1633 // assumes its argument has valid lambda/rho values
1634 bool is_regular_element_no_checks(internal_const_reference x,
1635 lambda_orb_index_type lpos = UNDEFINED,
1636 rho_orb_index_type rpos = UNDEFINED) {
1637 LIBSEMIGROUPS_ASSERT(_lambda_orb.finished() && _rho_orb.finished());
1638 lpos = lpos != UNDEFINED ? lpos : get_lpos(x);
1639 rpos = rpos != UNDEFINED ? rpos : get_rpos(x);
1640 return get_lambda_group_index(x, lpos, rpos) != UNDEFINED;
1641 }
1642
1643 lambda_orb_index_type get_lpos(internal_const_reference x) const {
1644 Lambda()(_tmp_lambda_value1, this->to_external_const(x));
1645 return _lambda_orb.position(_tmp_lambda_value1);
1646 }
1647
1648 rho_orb_index_type get_rpos(internal_const_reference x) const {
1649 Rho()(_tmp_rho_value1, this->to_external_const(x));
1650 return _rho_orb.position(_tmp_rho_value1);
1651 }
1652
1653 // Returns a lambda orb index corresponding to a group H-class in the R-
1654 // class of \p x.
1655 // asserts its argument has lambda/rho values in the orbits.
1656 // modifies _tmp_lambda_value1
1657 // modifies _tmp_rho_value1
1658 lambda_orb_index_type get_lambda_group_index(internal_const_reference x,
1659 lambda_orb_index_type lpos
1660 = UNDEFINED,
1661 rho_orb_index_type rpos
1662 = UNDEFINED);
1663
1664 // Finds a group index of a H-class in the L-class of \p x.
1665 // modifies _tmp_lambda_value1
1666 // modifies _tmp_rho_value1
1667 rho_orb_index_type get_rho_group_index(internal_const_reference x,
1668 lambda_orb_index_type lpos
1669 = UNDEFINED,
1670 rho_orb_index_type rpos = UNDEFINED);
1671
1674 // TODO(later): it must be possible to do better than this
1675 void idem_in_H_class(internal_reference res,
1676 internal_const_reference x) const;
1677
1680 // modifies _tmp_lambda_value1
1681 void make_idem(internal_reference x);
1682
1686 void group_inverse(internal_element_type& res,
1687 internal_const_reference id,
1688 internal_const_reference x) const;
1689
1691 // modifies _tmp_lambda_value and _tmp_rho_value
1692 bool is_group_index(internal_const_reference x,
1693 internal_const_reference y,
1694 lambda_orb_index_type lpos = UNDEFINED,
1695 rho_orb_index_type rpos = UNDEFINED) const;
1696
1697 // pass full_check = true to use the contains method of the D-classes
1698 // instead of the contains_no_checks
1699 D_class_index_type get_containing_D_class(internal_const_reference x,
1700 bool const full_check = false);
1701
1702 void add_to_D_maps(D_class_index_type d);
1703
1705 // Konieczny - accessor member functions - private
1707
1708 void add_D_class(RegularDClass* D);
1709 void add_D_class(NonRegularDClass* D);
1710
1711 auto cbegin_internal_generators() const noexcept {
1712 return _gens.cbegin();
1713 }
1714
1715 auto cend_internal_generators() const noexcept {
1716 return _gens.cend();
1717 }
1718
1719 detail::Pool<internal_element_type>& element_pool() const {
1720 return _element_pool;
1721 }
1722
1723 size_t max_rank() const noexcept {
1724 if (_ranks.empty()) {
1725 return UNDEFINED;
1726 }
1727 return *_ranks.rbegin();
1728 }
1729
1731 // Konieczny - initialisation member functions - private
1733
1734 void free_internals();
1735
1736 void init_run();
1737
1738 void init_data();
1739
1740 void init_rank_state_and_rep_vecs();
1741
1742 void compute_orbs();
1743
1745 // Konieczny - validation member functions - private
1747
1748 void throw_if_bad_degree(const_reference x) const {
1749 size_t const n = Degree()(x);
1750 if (degree() != UNDEFINED && n != degree()) {
1752 "element has degree {} but should have degree {}", n, degree());
1753 }
1754 }
1755
1756 template <typename Iterator>
1757 void throw_if_bad_degree(Iterator first, Iterator last) const;
1758
1760 // Konieczny - Runner methods - private
1762
1763 bool finished_impl() const override;
1764 void run_impl() override;
1765 void report_before_run();
1766 void report_progress();
1767 void report_after_run();
1768
1770 // Konieczny - data - private
1772
1773 bool _adjoined_identity_contained;
1774 bool _can_accept_generators;
1775 std::vector<DClass*> _D_classes;
1776 std::vector<std::vector<D_class_index_type>> _D_rels;
1777 bool _data_initialised;
1778 size_t _degree;
1779 mutable detail::Pool<internal_element_type> _element_pool;
1780 std::vector<internal_element_type> _gens;
1781 std::unordered_map<std::pair<rho_orb_index_type, lambda_orb_index_type>,
1782 lambda_orb_index_type,
1783 PairHash>
1784 _group_indices;
1785 std::unordered_map<std::pair<rho_orb_index_type, lambda_orb_index_type>,
1786 rho_orb_index_type,
1787 PairHash>
1788 _group_indices_rev;
1789 lambda_orb_type _lambda_orb;
1790 std::unordered_map<lambda_orb_index_type, std::vector<D_class_index_type>>
1791 _lambda_to_D_map;
1792 std::vector<std::vector<RepInfo>> _nonregular_reps;
1793 internal_element_type _one;
1794 rank_state_type* _rank_state;
1795 std::set<rank_type> _ranks;
1796 std::vector<RegularDClass*> _regular_D_classes;
1797 std::vector<std::vector<RepInfo>> _regular_reps;
1798 size_t _reps_processed;
1799 rho_orb_type _rho_orb;
1800 std::unordered_map<rho_orb_index_type, std::vector<D_class_index_type>>
1801 _rho_to_D_map;
1802 bool _run_initialised;
1803 mutable lambda_value_type _tmp_lambda_value1;
1804 mutable lambda_value_type _tmp_lambda_value2;
1805 mutable rho_value_type _tmp_rho_value1;
1806 mutable rho_value_type _tmp_rho_value2;
1807 }; // class Konieczny
1808
1809 template <typename Element, typename Traits>
1810 bool Konieczny<Element, Traits>::finished_impl() const {
1811 return _ranks.empty() && _run_initialised;
1812 }
1813
1824 template <typename Element, typename Traits>
1825 [[nodiscard]] std::string
1827
1839 template <typename Element, typename Traits>
1840 [[nodiscard]] std::string
1842
1847 namespace konieczny {
1848
1862 template <typename Element, typename Traits, typename T>
1864 static_assert(!std::is_pointer_v<T>,
1865 "the template parameter T must not be a pointer");
1866 K.add_generators(coll.begin(), coll.end());
1867 }
1868
1879 template <typename Element, typename Traits>
1884 K.add_generators(coll.begin(), coll.end());
1885 }
1886
1887 } // namespace konieczny
1888
1899
1926 // TODO(1) to tpp
1927 template <template <typename...> typename Thing,
1928 typename Container,
1929 typename Traits = KoniecznyTraits<typename Container::value_type>>
1930 [[nodiscard]] std::enable_if_t<
1931 std::is_same_v<Konieczny<typename Container::value_type, Traits>,
1932 Thing<typename Container::value_type, Traits>>,
1933 Konieczny<typename Container::value_type, Traits>>
1934 make(Container const& gens) {
1935 if (gens.size() == 0) {
1937 "expected a positive number of generators, but got 0");
1938 }
1940 result.add_generators(std::begin(gens), std::end(gens));
1941 return result;
1942 }
1943
1970 template <template <typename...> typename Thing,
1971 typename Element,
1972 typename Traits = KoniecznyTraits<Element>>
1973 [[nodiscard]] std::enable_if_t<
1974 std::is_same_v<Konieczny<Element, Traits>, Thing<Element, Traits>>,
1975 Konieczny<Element, Traits>>
1979
1980} // namespace libsemigroups
1981#include "konieczny.tpp"
1982#endif // LIBSEMIGROUPS_KONIECZNY_HPP_
T cbegin(T... args)
A class representing a -class in a Konieczny object.
Definition konieczny.hpp:448
bool contains(const_reference x)
Test membership of an element within a -class.
size_t size() const
Get the size of a -class.
Definition konieczny.hpp:520
const_reference rep() const
Get the representative of the -class.
Definition konieczny.hpp:506
virtual size_t number_of_idempotents() const
Get the number of idempotents of a -class.
Definition konieczny.hpp:609
size_t number_of_R_classes() const
Get the number of -classes within a DClass.
Definition konieczny.hpp:551
bool is_regular_D_class() const noexcept
Test regularity of a -class.
Definition konieczny.hpp:583
size_t size_H_class() const
Get the size of the -classes within a DClass.
Definition konieczny.hpp:569
size_t number_of_L_classes() const
Get the number of -classes within a DClass.
Definition konieczny.hpp:535
Class implementing Konieczny's algorithm.
Definition konieczny.hpp:178
typename Traits::const_element_type const_element_type
The type of const elements.
Definition konieczny.hpp:207
bool is_regular_element(const_reference x)
Test regularity of an element.
Definition konieczny.hpp:1384
typename Traits::element_type element_type
The type of elements.
Definition konieczny.hpp:204
size_t current_number_of_idempotents() const
Returns the current number of idempotents.
Definition konieczny.hpp:1237
const_d_class_iterator cend_D_classes()
Returns a const iterator referring to past the pointer to the last -class.
Definition konieczny.hpp:1537
Konieczny()
Default constructor.
size_t size()
Returns the size.
Definition konieczny.hpp:1290
size_t current_size() const
Returns the current size.
Definition konieczny.hpp:1306
typename Traits::rho_value_type rho_value_type
The type of rho values.
Definition konieczny.hpp:225
const_regular_d_class_iterator cbegin_current_regular_D_classes() const
Returns a const iterator referring to a pointer to the current first regular -class.
Definition konieczny.hpp:1565
typename Traits::lambda_orb_type lambda_orb_type
The type of the orbit of the lambda values.
Definition konieczny.hpp:222
typename Traits::rho_orb_type rho_orb_type
The type of the orbit of the rho values.
Definition konieczny.hpp:228
typename Traits::Rank Rank
Adapter for calculating ranks.
Definition konieczny.hpp:249
const_iterator cbegin_generators() const noexcept
Returns a const iterator pointing to the first generator.
Definition konieczny.hpp:1444
typename Traits::EqualTo EqualTo
Adapter for testing equality.
Definition konieczny.hpp:234
bool contains(const_reference x)
Test membership of an element.
Definition konieczny.hpp:1343
size_t number_of_regular_R_classes()
Returns the number of regular -classes.
Definition konieczny.hpp:1155
size_t number_of_R_classes()
Returns the number of -classes.
Definition konieczny.hpp:1122
typename Traits::One One
Adapter for the identity element of the given type.
Definition konieczny.hpp:243
typename detail::BruidhinnTraits< Element >::const_reference const_reference
Type of element const references.
Definition konieczny.hpp:210
size_t number_of_D_classes()
Returns the number of -classes.
Definition konieczny.hpp:997
size_t number_of_regular_D_classes()
Returns the number of regular -classes.
Definition konieczny.hpp:1027
typename Traits::Degree Degree
Adapter for the degree of an element.
Definition konieczny.hpp:231
typename Traits::Less Less
Adapter for comparisons.
Definition konieczny.hpp:240
size_t degree() const noexcept
Returns the degree of elements.
Definition konieczny.hpp:1326
Konieczny(Konieczny const &that)
Copy constructor.
typename Traits::Lambda Lambda
Adapter for the action on LambdaValue's.
Definition konieczny.hpp:237
size_t number_of_regular_L_classes()
Returns the number of regular -classes.
Definition konieczny.hpp:1089
Konieczny & operator=(Konieczny &&)
Move assignment operator.
size_t number_of_regular_elements()
Returns the number of regular elements.
Definition konieczny.hpp:1256
size_t number_of_generators() const noexcept
Returns the number of generators.
Definition konieczny.hpp:952
DClass & D_class_of_element(const_reference x)
Returns the -class containing an element.
Definition konieczny.hpp:1359
size_t current_number_of_regular_elements() const
Returns the current number of regular elements.
Definition konieczny.hpp:1270
size_t number_of_idempotents()
Returns the number of idempotents.
Definition konieczny.hpp:1223
size_t current_number_of_regular_R_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1169
Konieczny & add_generator(const_reference gen)
Add a copy of an element to the generators of a Konieczny.
Definition konieczny.hpp:1419
size_t number_of_H_classes()
Returns the number of -classes.
Definition konieczny.hpp:1188
Konieczny & init()
Reinitialize an existing Konieczny object.
size_t current_number_of_H_classes() const
Returns the current number of -classes.
Definition konieczny.hpp:1202
typename Traits::Rho Rho
Adapter for the action on RhoValue's.
Definition konieczny.hpp:252
typename Traits::Swap Swap
Adapter for swapping.
Definition konieczny.hpp:255
size_t number_of_L_classes()
Returns the number of -classes.
Definition konieczny.hpp:1056
size_t current_number_of_regular_L_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1103
const_regular_d_class_iterator cend_current_regular_D_classes() const noexcept
Returns a const iterator referring to past the pointer to the current last regular -class.
Definition konieczny.hpp:1588
const_regular_d_class_iterator cend_regular_D_classes()
Returns a const iterator referring to past the pointer to the last regular -class.
Definition konieczny.hpp:1618
const_iterator cend_generators() const noexcept
Returns a const iterator pointing to one past the last generator.
Definition konieczny.hpp:1462
const_d_class_iterator cbegin_D_classes()
Returns a const iterator referring to a pointer to the first -class.
Definition konieczny.hpp:1525
size_t current_number_of_regular_D_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1041
typename Traits::Product Product
Adapter for the product of two elements.
Definition konieczny.hpp:246
typename Traits::lambda_value_type lambda_value_type
The type of lambda values.
Definition konieczny.hpp:219
const_d_class_iterator cbegin_current_D_classes() const
Returns a const iterator referring to a pointer to the current first -class.
Definition konieczny.hpp:1492
size_t D_class_index_type
Definition konieczny.hpp:216
const_regular_d_class_iterator cbegin_regular_D_classes()
Returns a const iterator referring to a pointer to the first regular -class.
Definition konieczny.hpp:1603
size_t current_number_of_D_classes() const
Returns the current number of -classes.
Definition konieczny.hpp:1012
Konieczny & operator=(Konieczny const &)
Copy assignment operator.
detail::BruidhinnConstIterator< element_type, std::vector< internal_element_type > > const_iterator
A type for const iterators through elements.
Definition konieczny.hpp:1428
detail::ConstIteratorStateless< DClassIteratorTraits< DClass > > const_d_class_iterator
Return type of cbegin_current_D_classes and cend_current_D_classes.
Definition konieczny.hpp:1477
const_d_class_iterator cend_current_D_classes() const noexcept
Returns a const iterator referring to past the pointer to the current last -class.
Definition konieczny.hpp:1514
const_reference generator(size_t pos) const
Returns a const reference to the generator given by an index.
Definition konieczny.hpp:976
size_t current_number_of_L_classes() const
Returns the current number of -classes.
Definition konieczny.hpp:1070
Konieczny(Konieczny &&that)
Move constructor.
detail::ConstIteratorStateless< DClassIteratorTraits< RegularDClass > > const_regular_d_class_iterator
Return type of cbegin_current_regular_D_classes and cend_current_regular_D_classes.
Definition konieczny.hpp:1549
Konieczny & add_generators(T const &first, T const &last)
Add collection of generators from iterators.
size_t current_number_of_R_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1136
void run()
Run until finished.
Runner()
Default constructor.
state
Enum class for the state of the Runner.
Definition runner.hpp:407
T distance(T... args)
T cend(T... args)
T equal(T... args)
T for_each(T... args)
Action< Element, Point, Func, Traits, side::right > RightAction
Definition action.hpp:933
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:943
bool contains_no_checks(Thing &thing, typename Thing::native_word_type const &u, typename Thing::native_word_type const &v)
Check containment of a pair of words.
Definition cong-common-helpers.hpp:513
Undefined const UNDEFINED
Value for something undefined.
#define LIBSEMIGROUPS_EXCEPTION(...)
Throw a LibsemigroupsException.
Definition exception.hpp:99
enable_if_is_same< Return, Blocks > make(Container const &cont)
Check the arguments, construct a Blocks object, and check it.
Definition bipart.hpp:856
This namespace contains helper functions for the Konieczny class template.
Definition konieczny.hpp:1847
void add_generators(Konieczny< Element, Traits > K, T const &coll)
Add collection of generators from container.
Definition konieczny.hpp:1863
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
T push_back(T... args)
T size(T... args)
Adapter for the degree of an element.
Definition adapters.hpp:166
Adapter for testing equality.
Definition adapters.hpp:420
Adapter for hashing.
Definition adapters.hpp:453
Adapter for the value of a left action.
Definition adapters.hpp:357
Adapter for the value of a right action.
Definition adapters.hpp:399
This is a traits class for use with Konieczny.
Definition konieczny.hpp:86
::libsemigroups::Degree< element_type > Degree
Adapter for the degree of an element.
Definition konieczny.hpp:146
typename ::libsemigroups::RhoValue< element_type >::type rho_value_type
Alias for RhoValue with template parameter element_type.
Definition konieczny.hpp:100
::libsemigroups::Product< element_type > Product
Adapter for the product of two elements.
Definition konieczny.hpp:125
::libsemigroups::Lambda< element_type, lambda_value_type > Lambda
Adapter for the action on LambdaValue's.
Definition konieczny.hpp:119
::libsemigroups::Rho< element_type, rho_value_type > Rho
Adapter for the action on RhoValue's.
Definition konieczny.hpp:122
typename detail::BruidhinnTraits< Element >::value_type element_type
The type of the elements of a Konieczny instance with const removed.
Definition konieczny.hpp:88
::libsemigroups::Hash< element_type > ElementHash
Adapter for hashing.
Definition konieczny.hpp:134
::libsemigroups::Less< element_type > Less
Adapter for comparisons.
Definition konieczny.hpp:143
::libsemigroups::Swap< element_type > Swap
Adapter for swapping.
Definition konieczny.hpp:140
LeftAction< element_type, rho_value_type, ImageLeftAction< element_type, rho_value_type > > rho_orb_type
Definition konieczny.hpp:114
typename ::libsemigroups::RankState< element_type > rank_state_type
Alias for RhoValue with template parameter element_type.
Definition konieczny.hpp:104
::libsemigroups::EqualTo< element_type > EqualTo
Adapter for testing equality.
Definition konieczny.hpp:137
typename detail::BruidhinnTraits< Element >::const_value_type const_element_type
The type of const elements of a Konieczny instance.
Definition konieczny.hpp:91
::libsemigroups::One< element_type > One
Adapter for the identity element of the given type.
Definition konieczny.hpp:131
::libsemigroups::Rank< element_type, rank_state_type > Rank
Adapter for calculating ranks.
Definition konieczny.hpp:128
RightAction< element_type, lambda_value_type, ImageRightAction< element_type, lambda_value_type > > lambda_orb_type
Definition konieczny.hpp:108
typename ::libsemigroups::LambdaValue< element_type >::type lambda_value_type
Definition konieczny.hpp:96
Adapter for the action on LambdaValue's.
Definition adapters.hpp:840
Adapter for comparisons.
Definition adapters.hpp:641
Adapter for the identity element of the given type.
Definition adapters.hpp:253
Adapter for the product of two elements.
Definition adapters.hpp:291
Adapter for calculating ranks.
Definition adapters.hpp:937
Adapter for the action on RhoValue's.
Definition adapters.hpp:861
Adapter for swapping.
Definition adapters.hpp:673