// // libsemigroups - C++ library for semigroups and monoids // Copyright (C) 2019 James D. Mitchell // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //
#include"libsemigroups/cong-intf.hpp"
#include <algorithm> // for remove_if
#include"libsemigroups/constants.hpp"// for UNDEFINED #include"libsemigroups/debug.hpp"// for LIBSEMIGROUPS_ASSERT #include"libsemigroups/exception.hpp"// for LIBSEMIGROUPS_EXCEPTION #include"libsemigroups/fpsemi-intf.hpp"// for FpSemigroupInterface #include"libsemigroups/froidure-pin-base.hpp"// for FroidurePinBase #include"libsemigroups/report.hpp"// for REPORT_VERBOSE_DEFAULT #include"libsemigroups/string.hpp"// for detail::to_string
namespace libsemigroups {
class CongruenceInterface::LazyFroidurePin { public:
LazyFroidurePin() = default;
std::shared_ptr<FroidurePinBase> froidure_pin() const { if (!has_froidure_pin()) { if (_fp_semigroup != nullptr
&& !_fp_semigroup->is_obviously_infinite()) {
_froidure_pin = _fp_semigroup->froidure_pin();
} else { // This can be the case if a CongruenceInterface is default // constructed, i.e. constructed neither from a FroidurePinBase // nor an FpSemigroupInterface, or the _fp_semigroup is obviously // infinite
LIBSEMIGROUPS_EXCEPTION("no parent FroidurePin can be determined!");
}
} return _froidure_pin;
}
void CongruenceInterface::set_number_of_generators(size_t n) { if (number_of_generators() != UNDEFINED) { if (number_of_generators() != n) {
LIBSEMIGROUPS_EXCEPTION("cannot change the number of generators");
} else { return; // do nothing
}
} elseif (n == 0) {
LIBSEMIGROUPS_EXCEPTION("the number of generators must be non-zero!");
} elseif (started()) {
LIBSEMIGROUPS_EXCEPTION( "cannot set the number of generator at this stage");
}
_nr_gens = n;
set_number_of_generators_impl(n);
reset();
}
///////////////////////////////////////////////////////////////////////// // CongruenceInterface - non-virtual methods - public /////////////////////////////////////////////////////////////////////////
void CongruenceInterface::add_pair(word_type const& u, word_type const& v) { if (started()) {
LIBSEMIGROUPS_EXCEPTION( "cannot add further generating pairs at this stage");
}
validate_word(u);
validate_word(v); if (u == v) { return;
} elseif (has_parent_froidure_pin()
&& parent_froidure_pin()->equal_to(u, v)) { return;
} // Note that _gen_pairs might contain pairs of distinct words that // represent the same element of the parent semigroup (if any).
_gen_pairs.emplace_back(u, v);
add_pair_impl(u, v);
reset();
}
word_type CongruenceInterface::class_index_to_word(class_index_type i) { if (number_of_generators() == UNDEFINED) {
LIBSEMIGROUPS_EXCEPTION("no generators have been defined");
} elseif (i >= number_of_classes()) {
LIBSEMIGROUPS_EXCEPTION("invalid class index, expected a value in the " "range [0, %d), found %d",
number_of_classes(),
i);
} return class_index_to_word_impl(i);
}
// Basic exception guarantee (since is_quotient_obviously_infinite() may // change the object).
std::shared_ptr<FroidurePinBase>
CongruenceInterface::quotient_froidure_pin() { if (_quotient != nullptr) {
LIBSEMIGROUPS_ASSERT(kind() == congruence_kind::twosided); return _quotient;
} elseif (kind() != congruence_kind::twosided) {
LIBSEMIGROUPS_EXCEPTION("the congruence must be two-sided");
}
_quotient = quotient_impl();
_quotient->immutable(true); return _quotient;
}
bool CongruenceInterface::is_quotient_obviously_infinite() { // If has_parent_froidure_pin(), then that is either finite (and so this // is not obviously infinite), or infinite, which is undecidable in // general, so we leave the answer to this question to // is_quotient_obviously_infinite_impl in the derived class. if (number_of_generators() == UNDEFINED) { // If number_of_generators() is undefined, then there is no quotient yet, // and so it is not obviously infinite, or anything!
REPORT_VERBOSE("not obviously infinite (no generators yet defined)"); returnfalse;
} elseif (has_quotient_froidure_pin()
&& quotient_froidure_pin()->finished()) { // If the quotient FroidurePin is fully enumerated, it must be // finite, and hence this is not (obviously) infinite.
REPORT_VERBOSE("not obviously infinite (finite)"); returnfalse;
} elseif (has_parent_froidure_pin() && parent_froidure_pin()->finished()) {
REPORT_VERBOSE("not obviously infinite (parent finite)"); returnfalse;
} elseif (is_quotient_obviously_infinite_impl()) { // The derived class of CongruenceInterface knows the quotient is // infinite returntrue;
}
REPORT_VERBOSE("the quotient is not obviously infinite . . ."); returnfalse;
}
void CongruenceInterface::set_number_of_generators_impl(size_t) { // do nothing
}
void CongruenceInterface::add_generators_impl(size_t) { // do nothing
}
std::shared_ptr<CongruenceInterface::non_trivial_classes_type const>
CongruenceInterface::non_trivial_classes_impl() { if (!_parent->can_compute_froidure_pin()) {
LIBSEMIGROUPS_EXCEPTION("Cannot determine the parent FroidurePin and so " "cannot compute non-trivial classes!");
} // The next line may trigger an infinite computation auto fp = _parent->froidure_pin(); auto ntc = non_trivial_classes_type(number_of_classes(),
std::vector<word_type>());
bool CongruenceInterface::validate_letter(letter_type c) const { if (number_of_generators() == UNDEFINED) {
LIBSEMIGROUPS_EXCEPTION("no generators have been defined");
} return c < _nr_gens;
}
void CongruenceInterface::validate_word(word_type const& w) const { for (auto l : w) { // validate_letter throws if no generators are defined if (!validate_letter(l)) {
LIBSEMIGROUPS_EXCEPTION( "letter index out of bounds in word %s, expected " "value in [0, %d), got %d",
detail::to_string(w).c_str(),
_nr_gens,
l);
}
}
}
std::string const&
CongruenceInterface::congruence_kind_to_string(congruence_kind typ) { switch (typ) { case congruence_kind::twosided: return STRING_TWOSIDED; case congruence_kind::left: return STRING_LEFT; case congruence_kind::right: return STRING_RIGHT; default:
LIBSEMIGROUPS_EXCEPTION("incorrect type");
}
}
///////////////////////////////////////////////////////////////////////// // CongruenceInterface - static data members - private /////////////////////////////////////////////////////////////////////////
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.