1 // 2 // libsemigroups - C++ library for semigroups and monoids 3 // Copyright (C) 2019 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 stuff for creating congruence over FroidurePin objects or 20 // over FpSemigroup objects. 21 22 #ifndef LIBSEMIGROUPS_INCLUDE_CONG_HPP_ 23 #define LIBSEMIGROUPS_INCLUDE_CONG_HPP_ 24 25 #include <cstddef> // for size_t 26 #include <memory> // for shared_ptr 27 28 #include "cong-intf.hpp" // for congruence::type 29 #include "knuth-bendix.hpp" // for KnuthBendix 30 #include "race.hpp" // for Race 31 #include "runner.hpp" // for Runner 32 #include "todd-coxeter.hpp" // for ToddCoxeter 33 #include "types.hpp" // for word_type 34 35 namespace libsemigroups { 36 class FpSemigroup; // Forward declaration 37 class FroidurePinBase; // Forward declaration, constructor parameters 38 39 //! Defined in ``cong.hpp``. 40 //! 41 //! On this page we describe the functionality relating to the 42 //! Congruence class. This class can be used for computing a congruence 43 //! over a semigroup by running every applicable algorithm from 44 //! ``libsemigroups`` (and some variants of the same algorithm) in parallel. 45 //! This class is provided for convenience, at present it is not very 46 //! customisable, and lacks some of the fine grained control offered by the 47 //! classes implementing individual algorithms, such as 48 //! congruence::ToddCoxeter and congruence::KnuthBendix. 49 //! 50 //! \sa congruence_type and tril. 51 //! \par Example 52 //! \code 53 //! FpSemigroup S; 54 //! S.set_alphabet(3); 55 //! S.set_identity(0); 56 //! S.add_rule({1, 2}, {0}); 57 //! S.is_obviously_infinite(); // false 58 //! 59 //! Congruence cong(twosided, S); 60 //! cong.add_pair({1, 1, 1}, {0}); 61 //! cong.nr_classes(); // 3 62 //! \endcode 63 class Congruence final : public CongruenceInterface { 64 public: 65 //! This struct holds various enums which effect the coset enumeration 66 //! process used by ToddCoxeter::run. 67 //! 68 //! \sa policy::runners. 69 struct policy { 70 //! This enum allows setting the policy used when adding runners to an 71 //! instance of this type during construction. 72 enum class runners { 73 //! Adds a predetermined selection of runners. 74 standard, 75 //! Adds no runners. 76 none 77 }; 78 }; 79 80 ////////////////////////////////////////////////////////////////////////// 81 // Congruence - constructors - public 82 ////////////////////////////////////////////////////////////////////////// 83 84 //! Constructs an empty instance of an interface to a congruence of type 85 //! specified by the argument. 86 //! 87 //! \param type the type of the congruence. 88 //! 89 //! \par Complexity 90 //! Constant. 91 //! 92 //! \sa set_nr_generators and add_pair. 93 explicit Congruence(congruence_type type, 94 policy::runners = policy::runners::standard); 95 96 //! Constructs a Congruence over the FroidurePin instance \p S 97 //! representing a left/right/2-sided congruence according to \p type. 98 //! 99 //! \tparam T a class derived from FroidurePinBase. 100 //! 101 //! \param type whether the congruence is left, right, or 2-sided 102 //! \param S a const reference to the semigroup over which the congruence 103 //! is defined. 104 //! 105 //! \par Exceptions 106 //! Does not throw itself but functions called by this function may 107 //! throw. 108 //! 109 //! \par Complexity 110 //! Linear in `S.size()`. 111 //! 112 //! \warning the parameter `T const& S` is copied, this might be expensive, 113 //! use a std::shared_ptr to avoid the copy! 114 template <typename T> Congruence(congruence_type type,T const & S)115 Congruence(congruence_type type, T const& S) 116 : Congruence(type, 117 static_cast<std::shared_ptr<FroidurePinBase>>( 118 std::make_shared<T>(S))) { 119 static_assert( 120 std::is_base_of<FroidurePinBase, T>::value, 121 "the template parameter must be a derived class of FroidurePinBase"); 122 } 123 124 //! Constructs a Congruence over the FroidurePin instance \p S 125 //! representing a left/right/2-sided congruence according to \p type. 126 //! \param type whether the congruence is left, right, or 2-sided 127 //! \param S a shared_ptr to the semigroup over which the congruence is 128 //! defined. 129 //! 130 //! \par Exceptions 131 //! Does not throw itself but functions called by this function may 132 //! throw. 133 //! 134 //! \par Complexity 135 //! Constant. 136 //! 137 //! \note 138 //! The FroidurePinBase pointed to by \p S is not copied. 139 Congruence(congruence_type type, std::shared_ptr<FroidurePinBase> S); 140 141 //! Constructs a Congruence over the FpSemigroup instance \p S 142 //! representing a left/right/2-sided congruence according to \p type. 143 //! \param type whether the congruence is left, right, or 2-sided 144 //! \param S a const reference to the finitely presented semigroup over 145 //! which the congruence is defined. 146 //! 147 //! \par Exceptions 148 //! Does not throw itself but functions called by this function may 149 //! throw. 150 //! 151 //! \par Complexity 152 //! Constant. 153 Congruence(congruence_type type, FpSemigroup& S); 154 155 ~Congruence() = default; 156 157 //! A Congruence instance is not default-constructible. 158 //! This constructor is deleted. 159 Congruence() = delete; 160 161 //! A Congruence instance is not copyable. 162 //! This constructor is deleted. 163 Congruence(Congruence const&) = delete; 164 165 //! A Congruence instance is not copy assignable. 166 //! This constructor is deleted. 167 Congruence& operator=(Congruence const&) = delete; 168 169 //! A Congruence instance is not move copyable. 170 //! This constructor is deleted. 171 Congruence(Congruence&&) = delete; 172 173 //! A Congruence instance is not move assignable. 174 //! This constructor is deleted. 175 Congruence& operator=(Congruence&&) = delete; 176 177 ////////////////////////////////////////////////////////////////////////// 178 // CongruenceInterface - non-pure virtual member functions - public 179 ////////////////////////////////////////////////////////////////////////// 180 181 bool contains(word_type const&, word_type const&) override; 182 tril const_contains(word_type const&, word_type const&) const override; 183 184 ////////////////////////////////////////////////////////////////////////// 185 // Congruence - member functions - public 186 ////////////////////////////////////////////////////////////////////////// 187 188 //! Returns the congruence::KnuthBendix instance used to compute the 189 //! congruence (if any). 190 //! 191 //! \par Parameters 192 //! (None) 193 //! 194 //! \returns A shared_ptr to a congruence::KnuthBendix or nullptr. 195 //! 196 //! \par Exceptions 197 //! Does not throw itself but functions called by this function may 198 //! throw. 199 //! 200 //! \par Complexity 201 //! Constant. 202 //! 203 //! \sa has_knuth_bendix(). knuth_bendix() const204 std::shared_ptr<congruence::KnuthBendix> knuth_bendix() const { 205 using KnuthBendix = congruence::KnuthBendix; 206 return _race.find_runner<KnuthBendix>(); 207 } 208 209 //! Checks if a congruence::KnuthBendix instance is being used to compute 210 //! the congruence. 211 //! 212 //! \par Parameters 213 //! (None) 214 //! 215 //! \returns A `bool`. 216 //! 217 //! \par Exceptions 218 //! Does not throw itself but functions called by this function may 219 //! throw. 220 //! 221 //! \par Complexity 222 //! Constant. 223 //! 224 //! \sa knuth_bendix(). has_knuth_bendix() const225 bool has_knuth_bendix() const { 226 return knuth_bendix() != nullptr; 227 } 228 229 //! Returns the congruence::ToddCoxeter instance used to compute the 230 //! congruence (if any). 231 //! 232 //! \par Parameters 233 //! (None) 234 //! 235 //! \returns A shared_ptr to a congruence::ToddCoxeter or nullptr. 236 //! 237 //! \par Exceptions 238 //! Does not throw itself but functions called by this function may 239 //! throw. 240 //! 241 //! \par Complexity 242 //! Constant. 243 //! 244 //! \sa has_todd_coxeter. todd_coxeter() const245 std::shared_ptr<congruence::ToddCoxeter> todd_coxeter() const { 246 using congruence::ToddCoxeter; 247 return _race.find_runner<ToddCoxeter>(); 248 } 249 250 //! Checks if a congruence::ToddCoxeter instance is being used to compute 251 //! the congruence. 252 //! 253 //! \par Parameters 254 //! (None) 255 //! 256 //! \returns A `bool`. 257 //! 258 //! \par Exceptions 259 //! Does not throw itself but functions called by this function may 260 //! throw. 261 //! 262 //! \par Complexity 263 //! Constant. 264 //! 265 //! \sa todd_coxeter. has_todd_coxeter() const266 bool has_todd_coxeter() const { 267 return todd_coxeter() != nullptr; 268 } 269 270 // The next function is required by the GAP package Semigroups. 271 //! No doc 272 template <typename T> add_runner(T const & r)273 void add_runner(T const& r) { 274 static_assert(std::is_base_of<CongruenceInterface, T>::value, 275 "the template parameter T must be a derived class of " 276 "CongruenceInterface"); 277 _race.add_runner(std::make_shared<T>(r)); 278 } 279 280 private: 281 ////////////////////////////////////////////////////////////////////////// 282 // CongruenceInterface - pure virtual member functions - private 283 ////////////////////////////////////////////////////////////////////////// 284 285 word_type class_index_to_word_impl(class_index_type) override; 286 size_t nr_classes_impl() override; 287 std::shared_ptr<FroidurePinBase> quotient_impl() override; 288 class_index_type word_to_class_index_impl(word_type const&) override; 289 run_impl()290 void run_impl() override { 291 _race.run(); 292 } 293 finished_impl() const294 bool finished_impl() const override { 295 return _race.finished(); 296 } 297 298 ////////////////////////////////////////////////////////////////////////// 299 // CongruenceInterface - non-pure virtual member functions - private 300 ////////////////////////////////////////////////////////////////////////// 301 302 void add_pair_impl(word_type const&, word_type const&) override; 303 std::shared_ptr<CongruenceInterface::non_trivial_classes_type const> 304 non_trivial_classes_impl() override; 305 bool is_quotient_obviously_finite_impl() override; 306 bool is_quotient_obviously_infinite_impl() override; 307 void set_nr_generators_impl(size_t) override; 308 309 ///////////////////////////////////////////////////////////////////////// 310 // Congruence - data - private 311 ///////////////////////////////////////////////////////////////////////// 312 detail::Race _race; 313 }; 314 } // namespace libsemigroups 315 316 #endif // LIBSEMIGROUPS_INCLUDE_CONG_HPP_ 317