//
// 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/>.
//
// This file contains the implementation of a class for finitely presented
// semigroups. The basic idea is that this object holds a number of member
// functions (in its Race _race member) and runs them competitively in multiple
// threads (maybe) to determine the structure of the fp semigroup. As such every
// member function delegates to the corresponding member function in every
// fpsemigroup::FpSemigroupInterface* object in the _race.
#include "libsemigroups/fpsemi.hpp"
#include <string>
// for string
#include "libsemigroups/froidure-pin-base.hpp" // for FroidurePinBase
#include "libsemigroups/kambites.hpp" // for Kambites
#include "libsemigroups/knuth-bendix.hpp" // for KnuthBendix
namespace libsemigroups {
using ToddCoxeter = fpsemigroup::ToddCoxeter;
using KnuthBendix = fpsemigroup::KnuthBendix;
using Kambites = fpsemigroup::Kambites<std::string>;
FpSemigroup::FpSemigroup(use_kambites val) : FpSemigroupInterface(), _race() {
if (val == use_kambites::yes) {
_race.add_runner(std::make_shared<Kambites>());
}
_race.add_runner(std::make_shared<ToddCoxeter>());
_race.add_runner(std::make_shared<KnuthBendix>());
}
//////////////////////////////////////////////////////////////////////////
// FpSemigroup - constructors - public
//////////////////////////////////////////////////////////////////////////
FpSemigroup::FpSemigroup() : FpSemigroup(use_kambites::yes) {}
FpSemigroup::FpSemigroup(std::shared_ptr<FroidurePinBase> S)
: FpSemigroup(use_kambites::no) {
S->run();
set_alphabet(S->number_of_generators());
for (
auto it = S->cbegin_rules(); it != S->cend_rules(); ++it) {
add_rule(*it);
}
}
//////////////////////////////////////////////////////////////////////////
// FpSemigroupInterface - pure virtual member functions - public
//////////////////////////////////////////////////////////////////////////
uint64_t FpSemigroup::size() {
if (is_obviously_infinite()) {
return POSITIVE_INFINITY;
}
else {
run();
// required so that the state is correct
return static_cast<FpSemigroupInterface*>(_race.winner().get())->size();
}
}
//////////////////////////////////////////////////////////////////////////////
// FpSemigroupInterface - pure virtual member functions - private
//////////////////////////////////////////////////////////////////////////////
void FpSemigroup::add_rule_impl(std::string
const& u, std::string
const& v) {
for (
auto runner : _race) {
static_cast<FpSemigroupInterface*>(runner.get())->add_rule(u, v);
}
}
std::shared_ptr<FroidurePinBase> FpSemigroup::froidure_pin_impl() {
// This loop is here in case one of the Runners in _race was created using
// a non-f.p. semigroup, so we can just return that and not run the _race.
for (
auto rnnr : _race) {
auto ptr =
static_cast<FpSemigroupInterface*>(rnnr.get());
if (ptr->has_froidure_pin()) {
return ptr->froidure_pin();
}
}
run();
// required to that the state is correct.
return static_cast<FpSemigroupInterface*>(_race.winner().get())
->froidure_pin();
}
bool FpSemigroup::is_obviously_infinite_impl() {
for (
auto it = _race.begin(); it < _race.end(); ++it) {
auto ptr =
static_cast<FpSemigroupInterface*>(it->get());
if (ptr->is_obviously_infinite()) {
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////
// FpSemigroupInterface - non-pure virtual member functions - private
//////////////////////////////////////////////////////////////////////////////
void FpSemigroup::set_alphabet_impl(std::string
const& lphbt) {
for (
auto runner : _race) {
static_cast<FpSemigroupInterface*>(runner.get())->set_alphabet(lphbt);
}
}
void FpSemigroup::set_alphabet_impl(size_t n) {
for (
auto runner : _race) {
static_cast<FpSemigroupInterface*>(runner.get())->set_alphabet(n);
}
}
bool FpSemigroup::is_obviously_finite_impl() {
for (
auto it = _race.begin(); it < _race.end(); ++it) {
auto ptr =
static_cast<FpSemigroupInterface*>(it->get());
if (ptr->is_obviously_finite()) {
return true;
}
}
return false;
}
}
// namespace libsemigroups