libsemigroups  v3.0.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
78
86 template <typename Element>
89 using element_type = typename detail::BruidhinnTraits<Element>::value_type;
90
93 typename detail::BruidhinnTraits<Element>::const_value_type;
94
98 typename ::libsemigroups::LambdaValue<element_type>::type;
99
102 typename ::libsemigroups::RhoValue<element_type>::type;
103
105 using rank_state_type = typename ::libsemigroups::RankState<element_type>;
106
113
116 using rho_orb_type
150 };
151
178 template <typename Element, typename Traits = KoniecznyTraits<Element>>
179 class Konieczny : public Runner, private detail::BruidhinnTraits<Element> {
180 // pointers are not currently supported
181 static_assert(!std::is_pointer_v<Element>,
182 "Pointer types are not currently supported by Konieczny");
183
185 // Konieczny - aliases - private
187
188 using internal_element_type =
189 typename detail::BruidhinnTraits<Element>::internal_value_type;
190 using internal_const_element_type =
191 typename detail::BruidhinnTraits<Element>::internal_const_value_type;
192 using internal_const_reference =
193 typename detail::BruidhinnTraits<Element>::internal_const_reference;
194 using internal_reference =
195 typename detail::BruidhinnTraits<Element>::internal_reference;
196
197 using PairHash = Hash<std::pair<size_t, size_t>>;
198
199 public:
201 // Konieczny - aliases - public
203
205 using element_type = typename Traits::element_type;
206
208 using const_element_type = typename Traits::const_element_type;
209
212 typename detail::BruidhinnTraits<Element>::const_reference;
213
217 using D_class_index_type = size_t;
218
220 using lambda_value_type = typename Traits::lambda_value_type;
221
223 using lambda_orb_type = typename Traits::lambda_orb_type;
224
226 using rho_value_type = typename Traits::rho_value_type;
227
229 using rho_orb_type = typename Traits::rho_orb_type;
230
232 using Degree = typename Traits::Degree;
233
235 using EqualTo = typename Traits::EqualTo;
236
238 using Lambda = typename Traits::Lambda;
239
241 using Less = typename Traits::Less;
242
244 using One = typename Traits::One;
245
247 using Product = typename Traits::Product;
248
250 using Rank = typename Traits::Rank;
251
253 using Rho = typename Traits::Rho;
254
256 using Swap = typename Traits::Swap;
257
258 private:
260 // Konieczny - aliases - private
262
263 using lambda_orb_index_type = typename lambda_orb_type::index_type;
264 using rho_orb_index_type = typename rho_orb_type::index_type;
265 using rank_type = size_t;
266 using rank_state_type = typename Traits::rank_state_type;
267 using left_indices_index_type = size_t;
268 using right_indices_index_type = size_t;
269
271 // Konieczny - internal structs - private
273
274 struct InternalHash : private detail::BruidhinnTraits<Element> {
275 size_t operator()(internal_const_element_type x) const {
276 return Hash<Element>()(this->to_external_const(x));
277 }
278 };
279
280 struct InternalEqualTo : private detail::BruidhinnTraits<Element> {
281 bool operator()(internal_const_reference x,
282 internal_const_reference y) const {
283 return EqualTo()(this->to_external_const(x),
284 this->to_external_const(y));
285 }
286 };
287
288 struct InternalLess : private detail::BruidhinnTraits<Element> {
289 bool operator()(internal_const_reference x,
290 internal_const_reference y) const {
291 return Less()(this->to_external_const(x), this->to_external_const(y));
292 }
293 };
294
295 struct InternalVecEqualTo : private detail::BruidhinnTraits<Element> {
296 size_t operator()(std::vector<internal_element_type> const& x,
297 std::vector<internal_element_type> const& y) const {
298 LIBSEMIGROUPS_ASSERT(x.size() == y.size());
299 return std::equal(x.cbegin(), x.cend(), y.cbegin(), InternalEqualTo());
300 }
301 };
302
303 struct InternalVecFree : private detail::BruidhinnTraits<Element> {
304 void operator()(std::vector<internal_element_type> const& x) {
305 for (auto it = x.cbegin(); it != x.cend(); ++it) {
306 this->internal_free(*it);
307 }
308 }
309 };
310
311 struct InternalVecCopy : private detail::BruidhinnTraits<Element> {
312 void operator()(std::vector<internal_element_type> const& source,
313 std::vector<internal_element_type>& target) {
314 InternalVecFree()(target);
315 for (auto it = source.cbegin(); it != source.cend(); ++it) {
316 target.push_back(this->internal_copy(*it));
317 }
318 }
319 };
320
321 struct OneParamLambda {
322 lambda_value_type operator()(const_reference x) const {
324 Lambda()(lval, x);
325 return lval;
326 }
327 };
328
329 struct OneParamRho {
330 rho_value_type operator()(const_reference x) const {
331 rho_value_type rval;
332 Rho()(rval, x);
333 return rval;
334 }
335 };
336
337 struct InternalRank {
338 template <typename SFINAE = size_t>
339 auto operator()(void*, const_reference x)
340 -> std::enable_if_t<std::is_void_v<typename rank_state_type::type>,
341 SFINAE> {
342 return Rank()(x);
343 }
344
345 template <typename SFINAE = size_t>
346 auto operator()(rank_state_type* state, const_reference x)
347 -> std::enable_if_t<!std::is_void_v<typename rank_state_type::type>,
348 SFINAE> {
349 return Rank()(*state, x);
350 }
351 };
352
353 struct RepInfo {
354 RepInfo(D_class_index_type D_idx,
355 internal_element_type elt,
356 lambda_orb_index_type lambda_idx,
357 rho_orb_index_type rho_idx)
358 : _D_idx(D_idx),
359 _elt(elt),
360 _lambda_idx(lambda_idx),
361 _rho_idx(rho_idx) {}
362
363 D_class_index_type _D_idx;
364 internal_element_type _elt;
365 lambda_orb_index_type _lambda_idx;
366 rho_orb_index_type _rho_idx;
367 };
368
369 public:
371 // Konieczny - constructor and destructor - public
373
384
395
406 Konieczny(Konieczny const& that);
407
421
424
427
428 ~Konieczny();
429
431 // Konieczny - forward class declarations - public/private
433
449 class DClass : protected detail::BruidhinnTraits<Element> {
450 // This friend is only here so that the virtual contains(x, lpos, rpos)
451 // method and the cbegin_left_indices etc. methods can be private.
452 friend class Konieczny<Element, Traits>;
453
455 // DClass - aliases - protected
457#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
458 using konieczny_type = Konieczny<Element, Traits>;
459 using internal_set_type = std::
460 unordered_set<internal_element_type, InternalHash, InternalEqualTo>;
461
463 // DClass - default constructor - private
465
466 private:
467 DClass();
468
469 void clear();
470
472 // DClass - constructors - protected
474 protected:
475 DClass(Konieczny* parent, internal_reference rep);
476
477 DClass(DClass const& that);
478
479 DClass& operator=(DClass const& that);
480
481 DClass(DClass&&) = delete;
482 DClass& operator=(DClass&&) = delete;
483
484#endif // ndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
485
486 public:
488 // DClass - destructor - public
490 virtual ~DClass();
492 // DClass - member functions - public
494
508 return this->to_external_const(_rep);
509 }
510
521 size_t size() const {
522 LIBSEMIGROUPS_ASSERT(this->class_computed());
524 }
525
536 size_t number_of_L_classes() const {
537 LIBSEMIGROUPS_ASSERT(_left_mults.size() > 0);
538 LIBSEMIGROUPS_ASSERT(this->class_computed());
539 return _left_mults.size();
540 }
541
552 size_t number_of_R_classes() const {
553 // compute_right_mults();
554 LIBSEMIGROUPS_ASSERT(_right_mults.size() > 0);
555 LIBSEMIGROUPS_ASSERT(this->class_computed());
556 return _right_mults.size();
557 }
558
570 size_t size_H_class() const {
571 // compute_H_class();
572 LIBSEMIGROUPS_ASSERT(_H_class.size() > 0);
573 LIBSEMIGROUPS_ASSERT(this->class_computed());
574 return _H_class.size();
575 }
576
584 bool is_regular_D_class() const noexcept {
585 return _is_regular_D_class;
586 }
587
605
610 virtual size_t number_of_idempotents() const {
611 return 0;
612 }
613
614 protected:
615#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
617 // DClass - iterators - protected
619 using const_iterator =
621
622 const_iterator cbegin_left_reps() {
623 compute_left_reps();
624 return _left_reps.cbegin();
625 }
626
627 const_iterator cend_left_reps() {
628 compute_left_reps();
629 return _left_reps.cend();
630 }
631
632 const_iterator cbegin_right_reps() {
633 compute_right_reps();
634 return _right_reps.cbegin();
635 }
636
637 const_iterator cend_right_reps() {
638 compute_right_reps();
639 return _right_reps.cend();
640 }
641
642 const_iterator cbegin_left_mults() {
643 compute_left_mults();
644 return _left_mults.cbegin();
645 }
646
647 const_iterator cend_left_mults() {
648 compute_left_mults();
649 return _left_mults.cend();
650 }
651
652 const_iterator cbegin_right_mults() {
653 compute_right_mults();
654 return _right_mults.cbegin();
655 }
656
657 const_iterator cend_right_mults() {
658 compute_right_mults();
659 return _right_mults.cend();
660 }
661
662 const_iterator cbegin_H_class() {
663 compute_H_class();
664 return _H_class.cbegin();
665 }
666
667 const_iterator cend_H_class() {
668 compute_H_class();
669 return _H_class.cend();
670 }
671
672 internal_element_type left_mults_inv(size_t i) {
673 compute_left_mults_inv();
674 return _left_mults_inv[i];
675 }
676
677 internal_element_type right_mults_inv(size_t i) {
678 compute_right_mults_inv();
679 return _right_mults_inv[i];
680 }
681
682 internal_element_type H_class_no_checks(size_t i) const {
683 return _H_class[i];
684 }
685
687 // DClass - initialisation member functions - protected
689 virtual void compute_frame() = 0;
690 virtual void compute_left_indices() = 0;
691 virtual void compute_left_mults() = 0;
692 virtual void compute_left_mults_inv() = 0;
693 virtual void compute_left_reps() = 0;
694 virtual void compute_right_indices() = 0;
695 virtual void compute_right_mults() = 0;
696 virtual void compute_right_mults_inv() = 0;
697 virtual void compute_right_reps() = 0;
698 virtual void compute_H_class() = 0;
699
701 // DClass - containment - protected
703
704 // Returns whether the element \p x belongs to this
705 // \f$\mathscr{D}\f$-class.
706 //
707 // Given an element \p x of the semigroup represented by \c parent, this
708 // function returns whether \p x is an element of the
709 // \f$\mathscr{D}\f$-class represented by \c this. If \p x is not an
710 // element of the semigroup, then the behaviour is undefined.
711 // This member function involved computing most of the frame for
712 // \c this, if it is not already known.
713 bool contains_no_checks(internal_const_reference x);
714
715 // Returns whether the element \p x belongs to this
716 // \f$\mathscr{D}\f$-class.
717 //
718 // This overload of DClass::contains_no_checks is provided in order to
719 // avoid recalculating the rank of \p x when it is already known.
720 bool contains_no_checks(internal_const_reference x, size_t rank);
721
722 // Returns whether the element \p x belongs to this
723 // \f$\mathscr{D}\f$-class.
724 //
725 // This overload of DClass::contains_no_checks is provided in order to
726 // avoid recalculating the rank, lambda value, and rho value of \p x
727 // when they are already known.
728 bool contains_no_checks(internal_const_reference x,
729 size_t rank,
730 lambda_orb_index_type lpos,
731 rho_orb_index_type rpos);
732
733 // Returns whether the element \p x belongs to this
734 // \f$\mathscr{D}\f$-class.
735 //
736 // This overload of DClass::contains_no_checks is provided in order to
737 // avoid recalculating the lambda value and rho value of \p x when they
738 // are already known.
739 virtual bool contains_no_checks(internal_const_reference x,
740 lambda_orb_index_type lpos,
741 rho_orb_index_type rpos)
742 = 0;
743
744 virtual bool contains(const_reference x,
745 lambda_orb_index_type lpos,
746 rho_orb_index_type rpos)
747 = 0;
748
750 // DClass - accessor member functions - protected
752
753 size_t number_of_left_reps_no_checks() const noexcept {
754 return _left_reps.size();
755 }
756
757 size_t number_of_right_reps_no_checks() const noexcept {
758 return _right_reps.size();
759 }
760
761 size_t size_H_class_no_checks() const noexcept {
762 return _H_class.size();
763 }
764
765 void push_left_mult(internal_const_reference x);
766
767 void push_left_mult_inv(internal_const_reference x);
768
769 void push_right_mult(internal_const_reference x);
770
771 void push_right_mult_inv(internal_const_reference x);
772
773 void push_left_rep(internal_const_reference x);
774
775 void push_right_rep(internal_const_reference x);
776
777 bool class_computed() const noexcept {
778 return _class_computed;
779 }
780
781 bool mults_computed() const noexcept {
782 return _mults_computed;
783 }
784
785 bool reps_computed() const noexcept {
786 return _reps_computed;
787 }
788
789 bool H_class_computed() const noexcept {
790 return _H_class_computed;
791 }
792
793 void set_class_computed(bool x) noexcept {
794 _class_computed = x;
795 }
796
797 void set_mults_computed(bool x) noexcept {
798 _mults_computed = x;
799 }
800
801 void set_reps_computed(bool x) noexcept {
802 _reps_computed = x;
803 }
804
805 void set_H_class_computed(bool x) noexcept {
806 _H_class_computed = x;
807 }
808
809 Konieczny* parent() const noexcept {
810 return _parent;
811 }
812
813 void set_parent(Konieczny* x) noexcept {
814 _parent = x;
815 }
816
817 // Watch out! Doesn't copy its argument
818 void push_back_H_class(internal_element_type x) {
819 _H_class.push_back(x);
820 }
821
822 std::vector<internal_element_type>& H_class() {
823 return _H_class;
824 }
825
826 lambda_value_type& tmp_lambda_value() const noexcept {
827 return _tmp_lambda_value;
828 }
829
830 rho_value_type& tmp_rho_value() const noexcept {
831 return _tmp_rho_value;
832 }
833
834 rank_type rank() const noexcept {
835 return _rank;
836 }
837
838 internal_set_type& internal_set() const noexcept {
839 return _tmp_internal_set;
840 }
841
842 // Elements must be freed before next used
843 std::vector<internal_element_type>& internal_vec() const noexcept {
844 return _tmp_internal_vec;
845 }
846
847 internal_reference unsafe_rep() noexcept {
848 return _rep;
849 }
850
851 std::vector<lambda_orb_index_type>& left_indices() {
852 return _left_indices;
853 }
854
855 std::vector<rho_orb_index_type>& right_indices() {
856 return _right_indices;
857 }
858
859 protected:
861 // DClass - index iterators - protected
863
864 typename std::vector<left_indices_index_type>::const_iterator
865 cbegin_left_indices() {
866 compute_left_indices();
867 return _left_indices.cbegin();
868 }
869
870 typename std::vector<left_indices_index_type>::const_iterator
871 cend_left_indices() {
872 compute_left_indices();
873 return _left_indices.cend();
874 }
875
876 typename std::vector<right_indices_index_type>::const_iterator
877 cbegin_right_indices() {
878 compute_right_indices();
879 return _right_indices.cbegin();
880 }
881
882 typename std::vector<right_indices_index_type>::const_iterator
883 cend_right_indices() {
884 compute_right_indices();
885 return _right_indices.cend();
886 }
887#endif
888
889 private:
891 // DClass - member functions - private
893
894 // Returns a set of representatives of L- or R-classes covered by \c
895 // this.
896 //
897 // The \f$\mathscr{D}\f$-classes of the parent semigroup are enumerated
898 // either by finding representatives of all L-classes or all R-classes.
899 // This member function returns the representatives obtainable by
900 // multipliying the representatives by generators on either the left or
901 // right.
902 std::vector<RepInfo>& covering_reps();
903
905 // DClass - data - private
907 bool _class_computed;
908 std::vector<internal_element_type> _H_class;
909 bool _H_class_computed;
910 bool _is_regular_D_class;
911 std::vector<lambda_orb_index_type> _left_indices;
912 std::vector<internal_element_type> _left_mults;
913 std::vector<internal_element_type> _left_mults_inv;
914 std::vector<internal_element_type> _left_reps;
915 bool _mults_computed;
916 Konieczny* _parent;
917 rank_type _rank;
918 internal_element_type _rep;
919 bool _reps_computed;
920 std::vector<rho_orb_index_type> _right_indices;
921 std::vector<internal_element_type> _right_mults;
922 std::vector<internal_element_type> _right_mults_inv;
923 std::vector<internal_element_type> _right_reps;
924 mutable internal_set_type _tmp_internal_set; // Does not own its elements
925 mutable std::vector<RepInfo>
926 _tmp_rep_info_vec; // RepInfos do not own their rep
927 mutable std::vector<internal_element_type> _tmp_internal_vec; // Does not
928 mutable lambda_value_type _tmp_lambda_value;
929 mutable rho_value_type _tmp_rho_value;
930 };
931
932 private:
933 class RegularDClass;
934 class NonRegularDClass;
935
936 public:
938 // Konieczny - member functions - public
940
953 size_t number_of_generators() const noexcept {
954 return _gens.empty() ? 0 : _gens.size() - 1;
955 }
956
977 const_reference generator(size_t pos) const {
978 if (pos >= number_of_generators()) {
980 "index out of bounds, expected value in [{}, {}) found {}",
981 0,
983 pos);
984 }
985 return this->to_external_const(_gens[pos]);
986 }
987
1003
1017
1032
1046
1058 run();
1060 }
1061
1072 size_t val = 0;
1076 [&val](DClass const& D) { val += D.number_of_L_classes(); });
1077 return val;
1078 }
1079
1094
1105 size_t val = 0;
1109 [&val](DClass const& D) { val += D.number_of_L_classes(); });
1110 return val;
1111 }
1112
1124 run();
1126 }
1127
1138 size_t val = 0;
1142 [&val](DClass const& D) { val += D.number_of_R_classes(); });
1143 return val;
1144 }
1145
1160
1171 size_t val = 0;
1175 [&val](DClass const& D) { val += D.number_of_R_classes(); });
1176 return val;
1177 }
1178
1190 run();
1192 }
1193
1204 size_t val = 0;
1207 [&val](DClass const& D) {
1208 val += (D.number_of_R_classes()
1209 * D.number_of_L_classes());
1210 });
1211 return val;
1212 }
1213
1225 run();
1227 }
1228
1239 size_t val = 0;
1243 [&val](RegularDClass const& D) { val += D.number_of_idempotents(); });
1244 return val;
1245 }
1246
1261
1272 size_t val = 0;
1275 [&val](DClass const& D) { val += D.size(); });
1276 return val;
1277 }
1278
1291 size_t size() {
1292 run();
1293 return current_size();
1294 }
1295
1307 size_t current_size() const {
1308 size_t val = 0;
1311 [&val](DClass const& D) { val += D.size(); });
1312 return val;
1313 }
1314
1327 size_t degree() const noexcept {
1328 return _degree;
1329 }
1330
1345 return Degree()(x) == degree()
1346 && get_containing_D_class(this->to_internal_const(x), true)
1347 != UNDEFINED;
1348 }
1349
1362 = get_containing_D_class(this->to_internal_const(x), true);
1363 if (i == UNDEFINED) {
1365 "the argument does not belong to this semigroup!");
1366 }
1367 return *_D_classes[i];
1368 }
1369
1386 return contains(x)
1387 && is_regular_element_no_checks(this->to_internal_const(x));
1388 }
1389
1403 template <typename T>
1404 void add_generators(T const& first, T const& last);
1405
1417 add_generators(&gen, &gen + 1);
1418 }
1419
1421 // Konieczny - iterators - public
1423
1426 = detail::BruidhinnConstIterator<element_type,
1428
1441 //! \sa cend_generators
1442 const_iterator cbegin_generators() const noexcept {
1443 return const_iterator(_gens.cbegin());
1444 }
1445
1459 //! \sa cbegin_generators
1460 const_iterator cend_generators() const noexcept {
1461 return const_iterator(_gens.cend() - 1);
1462 }
1463
1464 // forward decl, defined in konieczny.tpp
1465 template <typename T>
1466 struct DClassIteratorTraits;
1467
1476 = detail::ConstIteratorStateless<DClassIteratorTraits<DClass>>;
1477
1489 //! \no_libsemigroups_except
1490 // not noexcept because operator++ isn't necessarily
1492 auto it = _D_classes.cbegin();
1493 if (_run_initialised) {
1494 return const_d_class_iterator(it)
1495 + (_adjoined_identity_contained ? 0 : 1);
1496 } else {
1497 return const_d_class_iterator(it);
1498 }
1499 }
1500
1511 //! \exceptions
1512 //! \no_libsemigroups_except
1514 return const_d_class_iterator(_D_classes.cend());
1515 }
1516
1522 //! \returns
1523 //! A value of type \c const_d_class_iterator.
1525 run();
1526 return cbegin_current_D_classes();
1527 }
1528
1534 //! \returns
1535 //! A value of type \c const_d_class_iterator.
1537 run();
1538 return cend_current_D_classes();
1539 }
1540
1549 = detail::ConstIteratorStateless<DClassIteratorTraits<RegularDClass>>;
1550
1562 //! \no_libsemigroups_except
1563 //!
1564 // not noexcept because operator++ isn't necessarily
1566 auto it = _regular_D_classes.cbegin();
1567 if (_run_initialised) {
1569 + (_adjoined_identity_contained ? 0 : 1);
1570 } else {
1572 }
1573 }
1574
1585 //! \exceptions
1586 //! \no_libsemigroups_except
1588 cend_current_regular_D_classes() const noexcept {
1589 return const_regular_d_class_iterator(_regular_D_classes.cend());
1590 }
1591
1600 //! \exceptions
1601 //! \no_libsemigroups_except
1602 //!
1604 run();
1606 }
1607
1615 //!
1616 //! \exceptions
1617 //! \no_libsemigroups_except
1619 run();
1621 }
1622
1623 private:
1624 using PoolGuard = detail::PoolGuard<internal_element_type>;
1625
1627 // Konieczny - utility methods - private
1629
1630 // assumes its argument has valid lambda/rho values
1631 bool is_regular_element_no_checks(internal_const_reference x,
1632 lambda_orb_index_type lpos = UNDEFINED,
1633 rho_orb_index_type rpos = UNDEFINED) {
1634 LIBSEMIGROUPS_ASSERT(_lambda_orb.finished() && _rho_orb.finished());
1635 lpos = lpos != UNDEFINED ? lpos : get_lpos(x);
1636 rpos = rpos != UNDEFINED ? rpos : get_rpos(x);
1637 return get_lambda_group_index(x, lpos, rpos) != UNDEFINED;
1638 }
1639
1640 lambda_orb_index_type get_lpos(internal_const_reference x) const {
1641 Lambda()(_tmp_lambda_value1, this->to_external_const(x));
1642 return _lambda_orb.position(_tmp_lambda_value1);
1643 }
1644
1645 rho_orb_index_type get_rpos(internal_const_reference x) const {
1646 Rho()(_tmp_rho_value1, this->to_external_const(x));
1647 return _rho_orb.position(_tmp_rho_value1);
1648 }
1649
1650 // Returns a lambda orb index corresponding to a group H-class in the R-
1651 // class of \p x.
1652 // asserts its argument has lambda/rho values in the orbits.
1653 // modifies _tmp_lambda_value1
1654 // modifies _tmp_rho_value1
1655 lambda_orb_index_type get_lambda_group_index(internal_const_reference x,
1656 lambda_orb_index_type lpos
1657 = UNDEFINED,
1658 rho_orb_index_type rpos
1659 = UNDEFINED);
1660
1661 // Finds a group index of a H-class in the L-class of \p x.
1662 // modifies _tmp_lambda_value1
1663 // modifies _tmp_rho_value1
1664 rho_orb_index_type get_rho_group_index(internal_const_reference x,
1665 lambda_orb_index_type lpos
1666 = UNDEFINED,
1667 rho_orb_index_type rpos = UNDEFINED);
1668
1671 // TODO(later): it must be possible to do better than this
1672 void idem_in_H_class(internal_reference res,
1673 internal_const_reference x) const;
1674
1677 // modifies _tmp_lambda_value1
1678 void make_idem(internal_reference x);
1679
1683 void group_inverse(internal_element_type& res,
1684 internal_const_reference id,
1685 internal_const_reference x) const;
1686
1688 // modifies _tmp_lambda_value and _tmp_rho_value
1689 bool is_group_index(internal_const_reference x,
1690 internal_const_reference y,
1691 lambda_orb_index_type lpos = UNDEFINED,
1692 rho_orb_index_type rpos = UNDEFINED) const;
1693
1694 // pass full_check = true to use the contains method of the D-classes
1695 // instead of the contains_no_checks
1696 D_class_index_type get_containing_D_class(internal_const_reference x,
1697 bool const full_check = false);
1698
1699 void add_to_D_maps(D_class_index_type d);
1700
1702 // Konieczny - accessor member functions - private
1704
1705 void add_D_class(RegularDClass* D);
1706 void add_D_class(NonRegularDClass* D);
1707
1708 auto cbegin_internal_generators() const noexcept {
1709 return _gens.cbegin();
1710 }
1711
1712 auto cend_internal_generators() const noexcept {
1713 return _gens.cend();
1714 }
1715
1716 detail::Pool<internal_element_type>& element_pool() const {
1717 return _element_pool;
1718 }
1719
1720 size_t max_rank() const noexcept {
1721 if (_ranks.empty()) {
1722 return UNDEFINED;
1723 }
1724 return *_ranks.rbegin();
1725 }
1726
1728 // Konieczny - initialisation member functions - private
1730
1731 void free_internals();
1732
1733 void init_run();
1734
1735 void init_data();
1736
1737 void init_rank_state_and_rep_vecs();
1738
1739 void compute_orbs();
1740
1742 // Konieczny - validation member functions - private
1744
1745 void throw_if_bad_degree(const_reference x) const {
1746 size_t const n = Degree()(x);
1747 if (degree() != UNDEFINED && n != degree()) {
1749 "element has degree {} but should have degree {}", n, degree());
1750 }
1751 }
1752
1753 template <typename Iterator>
1754 void throw_if_bad_degree(Iterator first, Iterator last) const;
1755
1757 // Konieczny - Runner methods - private
1759
1760 bool finished_impl() const override;
1761 void run_impl() override;
1762 void report_before_run();
1763 void report_progress();
1764 void report_after_run();
1765
1767 // Konieczny - data - private
1769
1770 bool _adjoined_identity_contained;
1771 bool _can_accept_generators;
1772 std::vector<DClass*> _D_classes;
1773 std::vector<std::vector<D_class_index_type>> _D_rels;
1774 bool _data_initialised;
1775 size_t _degree;
1776 mutable detail::Pool<internal_element_type> _element_pool;
1777 std::vector<internal_element_type> _gens;
1778 std::unordered_map<std::pair<rho_orb_index_type, lambda_orb_index_type>,
1779 lambda_orb_index_type,
1780 PairHash>
1781 _group_indices;
1782 std::unordered_map<std::pair<rho_orb_index_type, lambda_orb_index_type>,
1783 rho_orb_index_type,
1784 PairHash>
1785 _group_indices_rev;
1786 lambda_orb_type _lambda_orb;
1787 std::unordered_map<lambda_orb_index_type, std::vector<D_class_index_type>>
1788 _lambda_to_D_map;
1789 std::vector<std::vector<RepInfo>> _nonregular_reps;
1790 internal_element_type _one;
1791 rank_state_type* _rank_state;
1792 std::set<rank_type> _ranks;
1793 std::vector<RegularDClass*> _regular_D_classes;
1794 std::vector<std::vector<RepInfo>> _regular_reps;
1795 size_t _reps_processed;
1796 rho_orb_type _rho_orb;
1797 std::unordered_map<rho_orb_index_type, std::vector<D_class_index_type>>
1798 _rho_to_D_map;
1799 bool _run_initialised;
1800 mutable lambda_value_type _tmp_lambda_value1;
1801 mutable lambda_value_type _tmp_lambda_value2;
1802 mutable rho_value_type _tmp_rho_value1;
1803 mutable rho_value_type _tmp_rho_value2;
1804 }; // class Konieczny
1805
1806 template <typename Element, typename Traits>
1807 bool Konieczny<Element, Traits>::finished_impl() const {
1808 return _ranks.empty() && _run_initialised;
1809 }
1810
1821 template <typename Element, typename Traits>
1822 [[nodiscard]] std::string
1824
1836 template <typename Element, typename Traits>
1837 [[nodiscard]] std::string
1839
1844 namespace konieczny {
1845
1859 template <typename Element, typename Traits, typename T>
1861 static_assert(!std::is_pointer_v<T>,
1862 "the template parameter T must not be a pointer");
1863 K.add_generators(coll.begin(), coll.end());
1864 }
1865
1876 template <typename Element, typename Traits>
1881 K.add_generators(coll.begin(), coll.end());
1882 }
1883
1884 } // namespace konieczny
1885
1896
1923 // TODO(1) to tpp
1924 template <template <typename...> typename Thing,
1925 typename Container,
1926 typename Traits = KoniecznyTraits<typename Container::value_type>>
1927 [[nodiscard]] std::enable_if_t<
1928 std::is_same_v<Konieczny<typename Container::value_type, Traits>,
1929 Thing<typename Container::value_type, Traits>>,
1930 Konieczny<typename Container::value_type, Traits>>
1931 make(Container const& gens) {
1932 if (gens.size() == 0) {
1934 "expected a positive number of generators, but got 0");
1935 }
1937 result.add_generators(std::begin(gens), std::end(gens));
1938 return result;
1939 }
1940
1967 template <template <typename...> typename Thing,
1968 typename Element,
1969 typename Traits = KoniecznyTraits<Element>>
1970 [[nodiscard]] std::enable_if_t<
1971 std::is_same_v<Konieczny<Element, Traits>, Thing<Element, Traits>>,
1972 Konieczny<Element, Traits>>
1976
1977} // namespace libsemigroups
1978#include "konieczny.tpp"
1979#endif // LIBSEMIGROUPS_KONIECZNY_HPP_
T cbegin(T... args)
A class representing a -class in a Konieczny object.
Definition konieczny.hpp:449
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:521
const_reference rep() const
Get the representative of the -class.
Definition konieczny.hpp:507
virtual size_t number_of_idempotents() const
Get the number of idempotents of a -class.
Definition konieczny.hpp:610
size_t number_of_R_classes() const
Get the number of -classes within a DClass.
Definition konieczny.hpp:552
bool is_regular_D_class() const noexcept
Test regularity of a -class.
Definition konieczny.hpp:584
size_t size_H_class() const
Get the size of the -classes within a DClass.
Definition konieczny.hpp:570
size_t number_of_L_classes() const
Get the number of -classes within a DClass.
Definition konieczny.hpp:536
Class implementing Konieczny's algorithm.
Definition konieczny.hpp:179
typename Traits::const_element_type const_element_type
The type of const elements.
Definition konieczny.hpp:208
bool is_regular_element(const_reference x)
Test regularity of an element.
Definition konieczny.hpp:1385
typename Traits::element_type element_type
The type of elements.
Definition konieczny.hpp:205
size_t current_number_of_idempotents() const
Returns the current number of idempotents.
Definition konieczny.hpp:1238
const_d_class_iterator cend_D_classes()
Returns a const iterator referring to past the pointer to the last -class.
Definition konieczny.hpp:1534
Konieczny()
Default constructor.
size_t size()
Returns the size.
Definition konieczny.hpp:1291
size_t current_size() const
Returns the current size.
Definition konieczny.hpp:1307
typename Traits::rho_value_type rho_value_type
The type of rho values.
Definition konieczny.hpp:226
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:1562
typename Traits::lambda_orb_type lambda_orb_type
The type of the orbit of the lambda values.
Definition konieczny.hpp:223
typename Traits::rho_orb_type rho_orb_type
The type of the orbit of the rho values.
Definition konieczny.hpp:229
typename Traits::Rank Rank
Adapter for calculating ranks.
Definition konieczny.hpp:250
const_iterator cbegin_generators() const noexcept
Returns a const iterator pointing to the first generator.
Definition konieczny.hpp:1441
typename Traits::EqualTo EqualTo
Adapter for testing equality.
Definition konieczny.hpp:235
bool contains(const_reference x)
Test membership of an element.
Definition konieczny.hpp:1344
size_t number_of_regular_R_classes()
Returns the number of regular -classes.
Definition konieczny.hpp:1156
void add_generator(const_reference gen)
Add a copy of an element to the generators of a Konieczny.
Definition konieczny.hpp:1416
size_t number_of_R_classes()
Returns the number of -classes.
Definition konieczny.hpp:1123
typename Traits::One One
Adapter for the identity element of the given type.
Definition konieczny.hpp:244
typename detail::BruidhinnTraits< Element >::const_reference const_reference
Type of element const references.
Definition konieczny.hpp:211
size_t number_of_D_classes()
Returns the number of -classes.
Definition konieczny.hpp:998
size_t number_of_regular_D_classes()
Returns the number of regular -classes.
Definition konieczny.hpp:1028
typename Traits::Degree Degree
Adapter for the degree of an element.
Definition konieczny.hpp:232
typename Traits::Less Less
Adapter for comparisons.
Definition konieczny.hpp:241
size_t degree() const noexcept
Returns the degree of elements.
Definition konieczny.hpp:1327
Konieczny(Konieczny const &that)
Copy constructor.
typename Traits::Lambda Lambda
Adapter for the action on LambdaValue's.
Definition konieczny.hpp:238
size_t number_of_regular_L_classes()
Returns the number of regular -classes.
Definition konieczny.hpp:1090
Konieczny & operator=(Konieczny &&)
Move assignment operator.
size_t number_of_regular_elements()
Returns the number of regular elements.
Definition konieczny.hpp:1257
size_t number_of_generators() const noexcept
Returns the number of generators.
Definition konieczny.hpp:953
DClass & D_class_of_element(const_reference x)
Returns the -class containing an element.
Definition konieczny.hpp:1360
size_t current_number_of_regular_elements() const
Returns the current number of regular elements.
Definition konieczny.hpp:1271
size_t number_of_idempotents()
Returns the number of idempotents.
Definition konieczny.hpp:1224
size_t current_number_of_regular_R_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1170
void add_generators(T const &first, T const &last)
Add collection of generators from iterators.
size_t number_of_H_classes()
Returns the number of -classes.
Definition konieczny.hpp:1189
Konieczny & init()
Reinitialize an existing Konieczny object.
size_t current_number_of_H_classes() const
Returns the current number of -classes.
Definition konieczny.hpp:1203
typename Traits::Rho Rho
Adapter for the action on RhoValue's.
Definition konieczny.hpp:253
typename Traits::Swap Swap
Adapter for swapping.
Definition konieczny.hpp:256
size_t number_of_L_classes()
Returns the number of -classes.
Definition konieczny.hpp:1057
size_t current_number_of_regular_L_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1104
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:1585
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:1615
const_iterator cend_generators() const noexcept
Returns a const iterator pointing to one past the last generator.
Definition konieczny.hpp:1459
const_d_class_iterator cbegin_D_classes()
Returns a const iterator referring to a pointer to the first -class.
Definition konieczny.hpp:1522
size_t current_number_of_regular_D_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1042
typename Traits::Product Product
Adapter for the product of two elements.
Definition konieczny.hpp:247
typename Traits::lambda_value_type lambda_value_type
The type of lambda values.
Definition konieczny.hpp:220
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:1489
size_t D_class_index_type
Definition konieczny.hpp:217
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:1600
size_t current_number_of_D_classes() const
Returns the current number of -classes.
Definition konieczny.hpp:1013
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:1425
detail::ConstIteratorStateless< DClassIteratorTraits< DClass > > const_d_class_iterator
Return type of cbegin_current_D_classes and cend_current_D_classes.
Definition konieczny.hpp:1474
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:1511
const_reference generator(size_t pos) const
Returns a const reference to the generator given by an index.
Definition konieczny.hpp:977
size_t current_number_of_L_classes() const
Returns the current number of -classes.
Definition konieczny.hpp:1071
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:1546
size_t current_number_of_R_classes() const
Returns the current number of regular -classes.
Definition konieczny.hpp:1137
void run()
Run until finished.
Runner()
Default constructor.
state
Enum class for the state of the Runner.
Definition runner.hpp:362
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:870
Action< Element, Point, Func, Traits, side::left > LeftAction
Definition action.hpp:880
std::string to_human_readable_repr(AhoCorasick const &ac)
Return a string representation.
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:95
enable_if_is_same< Return, Blocks > make(Container const &cont)
Check the arguments, construct a Blocks object, and check it.
Definition bipart.hpp:798
This namespace contains helper functions for the Konieczny class template.
Definition konieczny.hpp:1844
void add_generators(Konieczny< Element, Traits > K, T const &coll)
Add collection of generators from container.
Definition konieczny.hpp:1860
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: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
This is a traits class for use with Konieczny.
Definition konieczny.hpp:87
::libsemigroups::Degree< element_type > Degree
Adapter for the degree of an element.
Definition konieczny.hpp:147
typename ::libsemigroups::RhoValue< element_type >::type rho_value_type
Alias for RhoValue with template parameter element_type.
Definition konieczny.hpp:101
::libsemigroups::Product< element_type > Product
Adapter for the product of two elements.
Definition konieczny.hpp:126
::libsemigroups::Lambda< element_type, lambda_value_type > Lambda
Adapter for the action on LambdaValue's.
Definition konieczny.hpp:120
::libsemigroups::Rho< element_type, rho_value_type > Rho
Adapter for the action on RhoValue's.
Definition konieczny.hpp:123
typename detail::BruidhinnTraits< Element >::value_type element_type
The type of the elements of a Konieczny instance with const removed.
Definition konieczny.hpp:89
::libsemigroups::Hash< element_type > ElementHash
Adapter for hashing.
Definition konieczny.hpp:135
::libsemigroups::Less< element_type > Less
Adapter for comparisons.
Definition konieczny.hpp:144
::libsemigroups::Swap< element_type > Swap
Adapter for swapping.
Definition konieczny.hpp:141
LeftAction< element_type, rho_value_type, ImageLeftAction< element_type, rho_value_type > > rho_orb_type
Definition konieczny.hpp:115
typename ::libsemigroups::RankState< element_type > rank_state_type
Alias for RhoValue with template parameter element_type.
Definition konieczny.hpp:105
::libsemigroups::EqualTo< element_type > EqualTo
Adapter for testing equality.
Definition konieczny.hpp:138
typename detail::BruidhinnTraits< Element >::const_value_type const_element_type
The type of const elements of a Konieczny instance.
Definition konieczny.hpp:92
::libsemigroups::One< element_type > One
Adapter for the identity element of the given type.
Definition konieczny.hpp:132
::libsemigroups::Rank< element_type, rank_state_type > Rank
Adapter for calculating ranks.
Definition konieczny.hpp:129
RightAction< element_type, lambda_value_type, ImageRightAction< element_type, lambda_value_type > > lambda_orb_type
Definition konieczny.hpp:109
typename ::libsemigroups::LambdaValue< element_type >::type lambda_value_type
Definition konieczny.hpp:97
Adapter for the action on LambdaValue's.
Definition adapters.hpp:833
Adapter for comparisons.
Definition adapters.hpp:634
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 calculating ranks.
Definition adapters.hpp:930
Adapter for the action on RhoValue's.
Definition adapters.hpp:854
Adapter for swapping.
Definition adapters.hpp:666