// libsemigroups - C++ library for semigroups and monoids
// Copyright (C) 2020 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 is the second of six that contains tests for the KnuthBendix
// classes. In a mostly vain attempt to speed up compilation the tests are
// split across 6 files as follows:
//
// 1: contains quick tests for fpsemigroup::KnuthBendix created from rules and
// all commented out tests.
//
// 2: contains more quick tests for fpsemigroup::KnuthBendix created from rules
//
// 3: contains yet more quick tests for fpsemigroup::KnuthBendix created from
// rules
//
// 4: contains standard and extreme test for fpsemigroup::KnuthBendix created
// from rules
//
// 5: contains tests for fpsemigroup::KnuthBendix created from FroidurePin
// instances
//
// 6: contains tests for congruence::KnuthBendix.
// #define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
#include <iostream> // for ostringstream
#include <string> // for string
#include <vector> // for vector
#include "catch.hpp" // for REQUIRE, REQUIRE_NOTHROW, REQUIRE_THROWS_AS
#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE
#include "libsemigroups/constants.hpp" // for POSITIVE_INFINITY
#include "libsemigroups/knuth-bendix.hpp" // for KnuthBendix, operator<<
#include "libsemigroups/report.hpp" // for ReportGuard
namespace libsemigroups {
struct LibsemigroupsException;
constexpr bool REPORT = false ;
using rule_type = fpsemigroup::KnuthBendix::rule_type;
namespace fpsemigroup {
// Fibonacci group F(2,5) - monoid presentation - has order 12 (group
// elements + empty word)
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"021" ,
"(from kbmag/standalone/kb_data/f25monoid)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("abcde" );
kb.add_rule("ab" , "c" );
kb.add_rule("bc" , "d" );
kb.add_rule("cd" , "e" );
kb.add_rule("de" , "a" );
kb.add_rule("ea" , "b" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 24);
REQUIRE(kb.equal_to("ab" , "c" ));
REQUIRE(kb.equal_to("bc" , "d" ));
REQUIRE(kb.equal_to("cd" , "e" ));
REQUIRE(kb.equal_to("de" , "a" ));
REQUIRE(kb.equal_to("ea" , "b" ));
REQUIRE(kb.equal_to("cc" , "ad" ));
REQUIRE(kb.equal_to("dd" , "be" ));
REQUIRE(kb.equal_to("ee" , "ca" ));
REQUIRE(kb.equal_to("ec" , "bb" ));
REQUIRE(kb.equal_to("db" , "aa" ));
REQUIRE(kb.equal_to("aac" , "be" ));
REQUIRE(kb.equal_to("bd" , "aa" ));
REQUIRE(kb.equal_to("bbe" , "aad" ));
REQUIRE(kb.equal_to("aaa" , "e" ));
REQUIRE(kb.equal_to("eb" , "be" ));
REQUIRE(kb.equal_to("ba" , "c" ));
REQUIRE(kb.equal_to("da" , "ad" ));
REQUIRE(kb.equal_to("ca" , "ac" ));
REQUIRE(kb.equal_to("ce" , "bb" ));
REQUIRE(kb.equal_to("cb" , "d" ));
REQUIRE(kb.equal_to("ed" , "a" ));
REQUIRE(kb.equal_to("dc" , "e" ));
REQUIRE(kb.equal_to("ae" , "b" ));
REQUIRE(kb.equal_to("bbb" , "a" ));
REQUIRE(
kb.active_rules()
== std::vector<rule_type>(
{{"ab" , "c" }, {"ae" , "b" }, {"ba" , "c" }, {"bc" , "d" },
{"bd" , "aa" }, {"ca" , "ac" }, {"cb" , "d" }, {"cc" , "ad" },
{"cd" , "e" }, {"ce" , "bb" }, {"da" , "ad" }, {"db" , "aa" },
{"dc" , "e" }, {"dd" , "be" }, {"de" , "a" }, {"ea" , "b" },
{"eb" , "be" }, {"ec" , "bb" }, {"ed" , "a" }, {"ee" , "ca" },
{"aaa" , "e" }, {"aac" , "be" }, {"bbb" , "ed" }, {"bbe" , "aad" }}));
REQUIRE(
std::vector<std::string>(
{"a" , "b" , "c" , "d" , "e" , "aa" , "ac" , "ad" , "bb" , "be" , "aad" })
== std::vector<std::string>(kb.cbegin_normal_forms(0, 5),
kb.cend_normal_forms()));
REQUIRE(kb.size() == 11);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 11);
}
// trivial group - BHN presentation
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"022" ,
"(from kbmag/standalone/kb_data/degen4a)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbBcC" );
kb.set_identity("" );
kb.set_inverses("AaBbCc" );
kb.add_rule("Aba" , "bb" );
kb.add_rule("Bcb" , "cc" );
kb.add_rule("Cac" , "aa" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 6);
REQUIRE(kb.equal_to("Aba" , "bb" ));
REQUIRE(kb.equal_to("Bcb" , "cc" ));
REQUIRE(kb.equal_to("Cac" , "aa" ));
REQUIRE(kb.active_rules()
== std::vector<rule_type>({{"A" , "" },
{"B" , "" },
{"C" , "" },
{"a" , "" },
{"b" , "" },
{"c" , "" }}));
REQUIRE(kb.size() == 1);
REQUIRE(std::vector<std::string>({"" })
== std::vector<std::string>(
kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms()));
}
// Torus group
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"023" ,
"(from kbmag/standalone/kb_data/torus)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAcCbBdD" );
kb.set_identity("" );
kb.set_inverses("AaCcBbDd" );
kb.add_rule("ABab" , "DCdc" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 16);
REQUIRE(kb.equal_to("DCdc" , "ABab" ));
REQUIRE(kb.active_rules()
== std::vector<rule_type>({{"Aa" , "" },
{"Bb" , "" },
{"Cc" , "" },
{"Dd" , "" },
{"aA" , "" },
{"bB" , "" },
{"cC" , "" },
{"dD" , "" },
{"BAba" , "CDcd" },
{"BabC" , "aDCd" },
{"DCdc" , "ABab" },
{"DcdA" , "cBAb" },
{"bCDc" , "AbaD" },
{"baDC" , "abCD" },
{"dABa" , "CdcB" },
{"dcBA" , "cdAB" }}));
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 7), kb.cend_normal_forms())
== 155577);
REQUIRE(
std::vector<std::string>(
{"" , "a" , "A" , "c" , "C" , "b" , "B" , "d" , "D" , "aa" , "ac" ,
"aC" , "ab" , "aB" , "ad" , "aD" , "AA" , "Ac" , "AC" , "Ab" , "AB" , "Ad" ,
"AD" , "ca" , "cA" , "cc" , "cb" , "cB" , "cd" , "cD" , "Ca" , "CA" , "CC" ,
"Cb" , "CB" , "Cd" , "CD" , "ba" , "bA" , "bc" , "bC" , "bb" , "bd" , "bD" ,
"Ba" , "BA" , "Bc" , "BC" , "BB" , "Bd" , "BD" , "da" , "dA" , "dc" , "dC" ,
"db" , "dB" , "dd" , "Da" , "DA" , "Dc" , "DC" , "Db" , "DB" , "DD" })
== std::vector<std::string>(kb.cbegin_normal_forms(0, 3),
kb.cend_normal_forms()));
}
// 3-fold cover of A_6
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"024" ,
"(from kbmag/standalone/kb_data/3a6)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("abAB" );
kb.set_identity("" );
kb.set_inverses("ABab" );
kb.add_rule("aaa" , "" );
kb.add_rule("bbb" , "" );
kb.add_rule("abababab" , "" );
kb.add_rule("aBaBaBaBaB" , "" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 183);
REQUIRE(kb.equal_to("aaa" , "" ));
REQUIRE(kb.equal_to("bbb" , "" ));
REQUIRE(kb.equal_to("BaBaBaBaB" , "aa" ));
REQUIRE(kb.equal_to("bababa" , "aabb" ));
REQUIRE(kb.equal_to("ababab" , "bbaa" ));
REQUIRE(kb.equal_to("aabbaa" , "babab" ));
REQUIRE(kb.equal_to("bbaabb" , "ababa" ));
REQUIRE(kb.equal_to("bababbabab" , "aabbabbaa" ));
REQUIRE(kb.equal_to("ababaababa" , "bbaabaabb" ));
REQUIRE(kb.equal_to("bababbabaababa" , "aabbabbaabaabb" ));
REQUIRE(kb.equal_to("bbaabaabbabbaa" , "ababaababbabab" ));
REQUIRE(kb.size() == 1080);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 1080);
REQUIRE(std::vector<std::string>({"" ,
"a" ,
"b" ,
"A" ,
"B" ,
"ab" ,
"aB" ,
"ba" ,
"bA" ,
"Ab" ,
"AB" ,
"Ba" ,
"BA" })
== std::vector<std::string>(kb.cbegin_normal_forms(0, 3),
kb.cend_normal_forms()));
}
// Free group on 2 generators
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"025" ,
"(from kbmag/standalone/kb_data/f2)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbB" );
kb.set_identity("" );
kb.set_inverses("AaBb" );
REQUIRE(kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 4);
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(std::vector<std::string>({"" ,
"a" ,
"A" ,
"b" ,
"B" ,
"aa" ,
"ab" ,
"aB" ,
"AA" ,
"Ab" ,
"AB" ,
"ba" ,
"bA" ,
"bb" ,
"Ba" ,
"BA" ,
"BB" })
== std::vector<std::string>(kb.cbegin_normal_forms(0, 3),
kb.cend_normal_forms()));
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 5), kb.cend_normal_forms())
== 161);
}
// Symmetric group S_16
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"026" ,
"(from kbmag/standalone/kb_data/s16)" ,
"[quick][knuth-bendix][kbmag][shortlex][no-valgrind]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("abcdefghijklmno" );
kb.set_identity("" );
kb.set_inverses("abcdefghijklmno" );
kb.add_rule("bab" , "aba" );
kb.add_rule("ca" , "ac" );
kb.add_rule("da" , "ad" );
kb.add_rule("ea" , "ae" );
kb.add_rule("fa" , "af" );
kb.add_rule("ga" , "ag" );
kb.add_rule("ha" , "ah" );
kb.add_rule("ia" , "ai" );
kb.add_rule("ja" , "aj" );
kb.add_rule("ka" , "ak" );
kb.add_rule("la" , "al" );
kb.add_rule("ma" , "am" );
kb.add_rule("na" , "an" );
kb.add_rule("oa" , "ao" );
kb.add_rule("cbc" , "bcb" );
kb.add_rule("db" , "bd" );
kb.add_rule("eb" , "be" );
kb.add_rule("fb" , "bf" );
kb.add_rule("gb" , "bg" );
kb.add_rule("hb" , "bh" );
kb.add_rule("ib" , "bi" );
kb.add_rule("jb" , "bj" );
kb.add_rule("kb" , "bk" );
kb.add_rule("lb" , "bl" );
kb.add_rule("mb" , "bm" );
kb.add_rule("nb" , "bn" );
kb.add_rule("ob" , "bo" );
kb.add_rule("dcd" , "cdc" );
kb.add_rule("ec" , "ce" );
kb.add_rule("fc" , "cf" );
kb.add_rule("gc" , "cg" );
kb.add_rule("hc" , "ch" );
kb.add_rule("ic" , "ci" );
kb.add_rule("jc" , "cj" );
kb.add_rule("kc" , "ck" );
kb.add_rule("lc" , "cl" );
kb.add_rule("mc" , "cm" );
kb.add_rule("nc" , "cn" );
kb.add_rule("oc" , "co" );
kb.add_rule("ede" , "ded" );
kb.add_rule("fd" , "df" );
kb.add_rule("gd" , "dg" );
kb.add_rule("hd" , "dh" );
kb.add_rule("id" , "di" );
kb.add_rule("jd" , "dj" );
kb.add_rule("kd" , "dk" );
kb.add_rule("ld" , "dl" );
kb.add_rule("md" , "dm" );
kb.add_rule("nd" , "dn" );
kb.add_rule("od" , "do" );
kb.add_rule("fef" , "efe" );
kb.add_rule("ge" , "eg" );
kb.add_rule("he" , "eh" );
kb.add_rule("ie" , "ei" );
kb.add_rule("je" , "ej" );
kb.add_rule("ke" , "ek" );
kb.add_rule("le" , "el" );
kb.add_rule("me" , "em" );
kb.add_rule("ne" , "en" );
kb.add_rule("oe" , "eo" );
kb.add_rule("gfg" , "fgf" );
kb.add_rule("hf" , "fh" );
kb.add_rule("if" , "fi" );
kb.add_rule("jf" , "fj" );
kb.add_rule("kf" , "fk" );
kb.add_rule("lf" , "fl" );
kb.add_rule("mf" , "fm" );
kb.add_rule("nf" , "fn" );
kb.add_rule("of" , "fo" );
kb.add_rule("hgh" , "ghg" );
kb.add_rule("ig" , "gi" );
kb.add_rule("jg" , "gj" );
kb.add_rule("kg" , "gk" );
kb.add_rule("lg" , "gl" );
kb.add_rule("mg" , "gm" );
kb.add_rule("ng" , "gn" );
kb.add_rule("og" , "go" );
kb.add_rule("ihi" , "hih" );
kb.add_rule("jh" , "hj" );
kb.add_rule("kh" , "hk" );
kb.add_rule("lh" , "hl" );
kb.add_rule("mh" , "hm" );
kb.add_rule("nh" , "hn" );
kb.add_rule("oh" , "ho" );
kb.add_rule("jij" , "iji" );
kb.add_rule("ki" , "ik" );
kb.add_rule("li" , "il" );
kb.add_rule("mi" , "im" );
kb.add_rule("ni" , "in" );
kb.add_rule("oi" , "io" );
kb.add_rule("kjk" , "jkj" );
kb.add_rule("lj" , "jl" );
kb.add_rule("mj" , "jm" );
kb.add_rule("nj" , "jn" );
kb.add_rule("oj" , "jo" );
kb.add_rule("lkl" , "klk" );
kb.add_rule("mk" , "km" );
kb.add_rule("nk" , "kn" );
kb.add_rule("ok" , "ko" );
kb.add_rule("mlm" , "lml" );
kb.add_rule("nl" , "ln" );
kb.add_rule("ol" , "lo" );
kb.add_rule("nmn" , "mnm" );
kb.add_rule("om" , "mo" );
kb.add_rule("ono" , "non" );
REQUIRE(!kb.confluent());
// kb.knuth_bendix_by_overlap_length();
kb.run(); // faster
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 211); // verified with KBMAG
REQUIRE(kb.gilman_digraph().number_of_nodes() == 121);
REQUIRE(kb.gilman_digraph().number_of_edges() == 680);
// verified with KBMAG
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 7), kb.cend_normal_forms())
== 49436);
REQUIRE(kb.number_of_normal_forms(0, 7) == 49436);
// verified with KBMAG
REQUIRE(kb.number_of_normal_forms(0, 11) == 2554607);
REQUIRE(kb.size() == 20922789888000);
}
// Presentation of group A_4 regarded as monoid presentation - gives
// infinite monoid.
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"027" ,
"(from kbmag/standalone/kb_data/a4monoid)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("abB" );
kb.add_rule("bb" , "B" );
kb.add_rule("BaB" , "aba" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 6);
REQUIRE(kb.equal_to("bb" , "B" ));
REQUIRE(kb.equal_to("BaB" , "aba" ));
REQUIRE(kb.equal_to("Bb" , "bB" ));
REQUIRE(kb.equal_to("Baaba" , "abaaB" ));
REQUIRE(kb.equal_to("BabB" , "abab" ));
REQUIRE(kb.equal_to("Bababa" , "ababaB" ));
REQUIRE(kb.active_rules()
== std::vector<rule_type>({{{"Bb" , "bB" },
{"bb" , "B" },
{"BaB" , "aba" },
{"BabB" , "abab" },
{"Baaba" , "abaaB" },
{"Bababa" , "ababaB" }}}));
}
// fairly clearly the trivial group
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"028" ,
"(from kbmag/standalone/kb_data/degen3)" ,
"[quick][knuth-bendix][kbmag][shortlex][no-valgrind]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbB" );
kb.add_rule("ab" , "" );
kb.add_rule("abb" , "" );
REQUIRE(kb.active_rules()
== std::vector<rule_type>({{"a" , "" }, {"b" , "" }}));
REQUIRE(kb.number_of_active_rules() == 2);
REQUIRE(kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 2);
REQUIRE(kb.equal_to("b" , "" ));
REQUIRE(kb.equal_to("a" , "" ));
REQUIRE(kb.active_rules()
== std::vector<rule_type>({{"a" , "" }, {"b" , "" }}));
}
// infinite cyclic group
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"029" ,
"(from kbmag/standalone/kb_data/ab1)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aA" );
kb.set_identity("" );
kb.set_inverses("Aa" );
REQUIRE(kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 2);
REQUIRE(kb.size() == POSITIVE_INFINITY);
}
// A generator, but trivial.
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"030" ,
"(from kbmag/standalone/kb_data/degen2)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aA" );
kb.add_rule("a" , "" );
REQUIRE(kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 1);
REQUIRE(kb.equal_to("a" , "" ));
REQUIRE(kb.active_rules() == std::vector<rule_type>({{"a" , "" }}));
}
// Fibonacci group F(2,5)
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"031" ,
"(from kbmag/standalone/kb_data/f25)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbBcCdDyY" );
kb.add_rule("ab" , "c" );
kb.add_rule("bc" , "d" );
kb.add_rule("cd" , "y" );
kb.add_rule("dy" , "a" );
kb.add_rule("ya" , "b" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 24);
REQUIRE(kb.equal_to("ab" , "c" ));
REQUIRE(kb.equal_to("bc" , "d" ));
REQUIRE(kb.equal_to("cd" , "y" ));
REQUIRE(kb.equal_to("dy" , "a" ));
REQUIRE(kb.equal_to("ya" , "b" ));
REQUIRE(kb.equal_to("cc" , "ad" ));
REQUIRE(kb.equal_to("dd" , "by" ));
REQUIRE(kb.equal_to("yy" , "ac" ));
REQUIRE(kb.equal_to("yc" , "bb" ));
REQUIRE(kb.equal_to("db" , "aa" ));
REQUIRE(kb.equal_to("aac" , "by" ));
REQUIRE(kb.equal_to("bd" , "aa" ));
REQUIRE(kb.equal_to("bby" , "aad" ));
REQUIRE(kb.equal_to("aaa" , "y" ));
REQUIRE(kb.equal_to("yb" , "by" ));
REQUIRE(kb.equal_to("ba" , "c" ));
REQUIRE(kb.equal_to("da" , "ad" ));
REQUIRE(kb.equal_to("ca" , "ac" ));
REQUIRE(kb.equal_to("cy" , "bb" ));
REQUIRE(kb.equal_to("cb" , "d" ));
REQUIRE(kb.equal_to("yd" , "a" ));
REQUIRE(kb.equal_to("dc" , "y" ));
REQUIRE(kb.equal_to("ay" , "b" ));
REQUIRE(kb.equal_to("bbb" , "a" ));
REQUIRE(
kb.active_rules()
== std::vector<rule_type>(
{{"ab" , "c" }, {"ay" , "b" }, {"ba" , "c" }, {"bc" , "d" },
{"bd" , "aa" }, {"ca" , "ac" }, {"cb" , "d" }, {"cc" , "ad" },
{"cd" , "y" }, {"cy" , "bb" }, {"da" , "ad" }, {"db" , "aa" },
{"dc" , "y" }, {"dd" , "by" }, {"dy" , "a" }, {"ya" , "b" },
{"yb" , "by" }, {"yc" , "bb" }, {"yd" , "a" }, {"yy" , "ca" },
{"aaa" , "y" }, {"aac" , "by" }, {"bbb" , "yd" }, {"bby" , "aad" }}));
}
// Von Dyck (2,3,7) group - infinite hyperbolic - small tidyint works better
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"032" ,
"(from kbmag/standalone/kb_data/237)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbBc" );
kb.set_identity("" );
kb.set_inverses("AaBbc" );
kb.add_rule("aaaa" , "AAA" );
kb.add_rule("bb" , "B" );
kb.add_rule("BA" , "c" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 32);
REQUIRE(kb.active_rules()
== std::vector<rule_type>({{"Aa" , "" },
{"Ac" , "b" },
{"BA" , "c" },
{"BB" , "b" },
{"Bb" , "" },
{"Bc" , "bA" },
{"aA" , "" },
{"ab" , "c" },
{"bB" , "" },
{"ba" , "AB" },
{"bb" , "B" },
{"bc" , "A" },
{"cB" , "a" },
{"ca" , "B" },
{"cb" , "aB" },
{"cc" , "" },
{"BaB" , "bAb" },
{"bAB" , "Ba" },
{"cAB" , "aBa" },
{"AAAA" , "aaa" },
{"AAAb" , "aaac" },
{"aaaa" , "AAA" },
{"bAbA" , "Bac" },
{"cAAA" , "Baaa" },
{"cAbA" , "aBac" },
{"ABaaa" , "bAAA" },
{"Baaac" , "cAAb" },
{"bAABaac" , "BacAAb" },
{"cAABaac" , "aBacAAb" },
{"BaaaBaaa" , "cAAbAAA" },
{"bAABaaBaaa" , "BacAAbAAA" },
{"cAABaaBaaa" , "aBacAAbAAA" }}));
REQUIRE(kb.size() == POSITIVE_INFINITY);
}
// Cyclic group of order 2.
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"033" ,
"(from kbmag/standalone/kb_data/c2)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("a" );
kb.add_rule("aa" , "" );
REQUIRE(kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 1);
REQUIRE(kb.active_rules() == std::vector<rule_type>({{"aa" , "" }}));
}
// The group is S_4, and the subgroup H of order 4. There are 30 reduced
// words - 24 for the group elements, and 6 for the 6 cosets Hg.
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"034" ,
"(from kbmag/standalone/kb_data/cosets)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("HaAbB" );
kb.add_rule("aaa" , "" );
kb.add_rule("bbbb" , "" );
kb.add_rule("abab" , "" );
kb.add_rule("Hb" , "H" );
kb.add_rule("HH" , "H" );
kb.add_rule("aH" , "H" );
kb.add_rule("bH" , "H" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 14);
REQUIRE(kb.equal_to("aaa" , "" ));
REQUIRE(kb.equal_to("Hb" , "H" ));
REQUIRE(kb.equal_to("HH" , "H" ));
REQUIRE(kb.equal_to("aH" , "H" ));
REQUIRE(kb.equal_to("bH" , "H" ));
REQUIRE(kb.equal_to("bab" , "aa" ));
REQUIRE(kb.equal_to("bbb" , "aba" ));
REQUIRE(kb.equal_to("Hab" , "Haa" ));
REQUIRE(kb.equal_to("abaab" , "bbaa" ));
REQUIRE(kb.equal_to("baaba" , "aabb" ));
REQUIRE(kb.equal_to("Haabb" , "Haaba" ));
REQUIRE(kb.equal_to("bbaabb" , "abba" ));
REQUIRE(kb.equal_to("aabbaa" , "baab" ));
REQUIRE(kb.equal_to("baabba" , "abbaab" ));
REQUIRE(kb.active_rules()
== std::vector<rule_type>({{{"HH" , "H" },
{"Hb" , "H" },
{"aH" , "H" },
{"bH" , "H" },
{"Hab" , "Haa" },
{"aaa" , "" },
{"bab" , "aa" },
{"bbb" , "aba" },
{"Haabb" , "Haaba" },
{"abaab" , "bbaa" },
{"baaba" , "aabb" },
{"aabbaa" , "baab" },
{"baabba" , "abbaab" },
{"bbaabb" , "abba" }}}));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"035" ,
"Example 5.1 in Sims (KnuthBendix 09 again)" ,
"[quick][knuth-bendix][fpsemigroup]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbB" );
kb.add_rule("aA" , "" );
kb.add_rule("Aa" , "" );
kb.add_rule("bB" , "" );
kb.add_rule("Bb" , "" );
kb.add_rule("ba" , "ab" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 8);
REQUIRE(kb.confluent());
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"036" ,
"(from kbmag/standalone/kb_data/nilp2)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("cCbBaA" );
kb.set_identity("" );
kb.set_inverses("CcBbAa" );
kb.add_rule("ba" , "abc" );
kb.add_rule("ca" , "ac" );
kb.add_rule("cb" , "bc" );
REQUIRE(!kb.confluent());
// The following never terminates (requires recursive order?)
// kb.knuth_bendix_by_overlap_length();
// REQUIRE(kb.confluent());
// REQUIRE(kb.number_of_active_rules() == 32758);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"037" ,
"Example 6.4 in Sims" ,
"[quick][knuth-bendix][fpsemigroup][no-valgrind]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("abc" );
kb.add_rule("aa" , "" );
kb.add_rule("bc" , "" );
kb.add_rule("bbb" , "" );
kb.add_rule("ababababababab" , "" );
kb.add_rule("abacabacabacabac" , "" );
REQUIRE(kb.number_of_active_rules() == 5);
REQUIRE(!kb.confluent());
kb.max_rules(10);
kb.run();
REQUIRE(kb.number_of_active_rules() == 10);
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 10);
REQUIRE(!kb.confluent());
kb.max_rules(20);
kb.run();
REQUIRE(kb.number_of_active_rules() == 21);
REQUIRE(!kb.confluent());
kb.max_rules(LIMIT_MAX);
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 40);
}
// Von Dyck (2,3,7) group - infinite hyperbolic
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"038" ,
"KnuthBendix 071 again" ,
"[no-valgrind][quick][knuth-bendix][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbBc" );
kb.set_identity("" );
kb.set_inverses("AaBbc" );
kb.add_rule("BA" , "c" );
kb.add_rule("Bb" , "bB" );
kb.add_rule("bb" , "B" );
kb.add_rule("AAAa" , "aAAA" );
kb.add_rule("aaaa" , "AAA" );
kb.add_rule("BaAAA" , "cAAa" );
kb.add_rule("BaaAAA" , "cAAaa" );
kb.add_rule("BaAaAAA" , "cAAaAa" );
kb.add_rule("BaaaAAA" , "cAAaaa" );
kb.add_rule("BaAAaAAA" , "cAAaAAa" );
kb.add_rule("BaAaaAAA" , "cAAaAaa" );
kb.add_rule("BaaAaAAA" , "cAAaaAa" );
kb.add_rule("BaAAaaAAA" , "cAAaAAaa" );
kb.add_rule("BaAaAaAAA" , "cAAaAaAa" );
kb.add_rule("BaAaaaAAA" , "cAAaAaaa" );
kb.add_rule("BaaAAaAAA" , "cAAaaAAa" );
kb.add_rule("BaaAaaAAA" , "cAAaaAaa" );
kb.add_rule("BaAAaAaAAA" , "cAAaAAaAa" );
kb.add_rule("BaAAaaaAAA" , "cAAaAAaaa" );
kb.add_rule("BaAaAAaAAA" , "cAAaAaAAa" );
kb.add_rule("BaAaAaaAAA" , "cAAaAaAaa" );
kb.add_rule("BaAaaAaAAA" , "cAAaAaaAa" );
kb.add_rule("BaaAAaaAAA" , "cAAaaAAaa" );
kb.add_rule("BaaAaAaAAA" , "cAAaaAaAa" );
kb.add_rule("BaAAaAAaAAA" , "cAAaAAaAAa" );
kb.add_rule("BaAAaAaaAAA" , "cAAaAAaAaa" );
kb.add_rule("BaAAaaAaAAA" , "cAAaAAaaAa" );
kb.add_rule("BaAaAAaaAAA" , "cAAaAaAAaa" );
kb.add_rule("BaAaAaAaAAA" , "cAAaAaAaAa" );
kb.add_rule("BaAaaAAaAAA" , "cAAaAaaAAa" );
kb.add_rule("BaaAAaAaAAA" , "cAAaaAAaAa" );
kb.add_rule("BaaAaAAaAAA" , "cAAaaAaAAa" );
kb.add_rule("BaAAaAAaaAAA" , "cAAaAAaAAaa" );
kb.add_rule("BaAAaAaAaAAA" , "cAAaAAaAaAa" );
kb.add_rule("BaAAaaAAaAAA" , "cAAaAAaaAAa" );
kb.add_rule("BaAaAAaAaAAA" , "cAAaAaAAaAa" );
kb.add_rule("BaAaAaAAaAAA" , "cAAaAaAaAAa" );
kb.add_rule("BaaAAaAAaAAA" , "cAAaaAAaAAa" );
kb.add_rule("BaAAaAAaAaAAA" , "cAAaAAaAAaAa" );
kb.add_rule("BaAAaAaAAaAAA" , "cAAaAAaAaAAa" );
kb.add_rule("BaAaAAaAAaAAA" , "cAAaAaAAaAAa" );
kb.add_rule("BaAAaAAaAAaAAA" , "cAAaAAaAAaAAa" );
REQUIRE(kb.number_of_active_rules() == 9);
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 32);
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(4, 5) == 24);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(4, 5),
kb.cend_normal_forms())
== std::vector<std::string>(
{"aaaB" , "aaac" , "aaBa" , "aacA" , "aBaa" , "aBac" ,
"acAA" , "acAb" , "AAAB" , "AAbA" , "AABa" , "AbAA" ,
"AbAb" , "ABaa" , "ABac" , "bAAA" , "bAAb" , "bAAB" ,
"Baaa" , "BaaB" , "Baac" , "BacA" , "cAAb" , "cAAB" }));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"039" ,
"Example 5.4 in Sims (KnuthBendix 11 again) "
"(different overlap policy)" ,
"[quick][knuth-bendix][fpsemigroup]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("Bab" );
kb.add_rule("aa" , "" );
kb.add_rule("bB" , "" );
kb.add_rule("bbb" , "" );
kb.add_rule("ababab" , "" );
kb.overlap_policy(KnuthBendix::options::overlap::AB_BC);
REQUIRE(!kb.confluent());
kb.knuth_bendix_by_overlap_length();
REQUIRE(kb.number_of_active_rules() == 11);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 12);
REQUIRE(kb.number_of_normal_forms(4, 5) == 0);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== std::vector<std::string>({"" ,
"B" ,
"a" ,
"b" ,
"Ba" ,
"aB" ,
"ab" ,
"ba" ,
"BaB" ,
"Bab" ,
"aBa" ,
"baB" }));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"040" ,
"Example 5.4 in Sims (KnuthBendix 11 again) "
"(different overlap policy)" ,
"[quick][knuth-bendix][fpsemigroup]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("Bab" );
kb.add_rule("aa" , "" );
kb.add_rule("bB" , "" );
kb.add_rule("bbb" , "" );
kb.add_rule("ababab" , "" );
kb.overlap_policy(KnuthBendix::options::overlap::MAX_AB_BC);
// The next line tests that we don't delete the old OverlapMeasure.
kb.overlap_policy(KnuthBendix::options::overlap::MAX_AB_BC);
REQUIRE(!kb.confluent());
kb.knuth_bendix_by_overlap_length();
REQUIRE(kb.number_of_active_rules() == 11);
REQUIRE(kb.confluent());
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"041" ,
"operator<<" ,
"[quick][knuth-bendix]" ) {
std::ostringstream os;
KnuthBendix kb1;
kb1.set_alphabet("Bab" );
kb1.add_rule("aa" , "" );
kb1.add_rule("bB" , "" );
kb1.add_rule("bbb" , "" );
kb1.add_rule("ababab" , "" );
os << kb1; // Does not do anything visible
KnuthBendix kb2;
kb2.set_alphabet("cbaB" );
kb2.add_rule("aa" , "" );
kb2.add_rule("bB" , "" );
kb2.add_rule("bbb" , "" );
kb2.add_rule("ababab" , "" );
os << kb2; // Does not do anything visible
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"042" ,
"confluence_interval" ,
"[quick][knuth-bendix]" ) {
KnuthBendix kb;
kb.set_alphabet("Bab" );
kb.add_rule("aa" , "" );
kb.add_rule("bB" , "" );
kb.add_rule("bbb" , "" );
kb.add_rule("ababab" , "" );
kb.check_confluence_interval(LIMIT_MAX);
kb.check_confluence_interval(10);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"043" ,
"max_overlap" ,
"[quick][knuth-bendix]" ) {
KnuthBendix kb;
kb.set_alphabet("Bab" );
kb.add_rule("aa" , "" );
kb.add_rule("bB" , "" );
kb.add_rule("bbb" , "" );
kb.add_rule("ababab" , "" );
kb.max_overlap(10);
kb.max_overlap(-11);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"044" ,
"(fpsemi) (from kbmag/standalone/kb_data/d22) (2 / 3) (finite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("ABCDYFabcdyf" );
kb.set_identity("" );
kb.set_inverses("abcdyfABCDYF" );
kb.add_rule("aCAd" , "" );
kb.add_rule("bfBY" , "" );
kb.add_rule("cyCD" , "" );
kb.add_rule("dFDa" , "" );
kb.add_rule("ybYA" , "" );
kb.add_rule("fCFB" , "" );
REQUIRE(!kb.confluent());
kb.knuth_bendix_by_overlap_length();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_rules() == 18);
REQUIRE(kb.size() == 22);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== std::vector<std::string>({"" , "A" , "B" , "C" , "D" , "Y" ,
"F" , "AB" , "AC" , "AD" , "AY" , "AF" ,
"BA" , "BD" , "BY" , "CY" , "DB" , "ABA" ,
"ABD" , "ABY" , "ACY" , "ADB" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"045" ,
"(fpsemi) (from kbmag/standalone/kb_data/d22) (3 / 3) (finite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("aAbBcCdDyYfF" );
kb.set_identity("" );
kb.set_inverses("AaBbCcDdYyFf" );
kb.add_rule("aCAd" , "" );
kb.add_rule("bfBY" , "" );
kb.add_rule("cyCD" , "" );
kb.add_rule("dFDa" , "" );
kb.add_rule("ybYA" , "" );
kb.add_rule("fCFB" , "" );
REQUIRE(!kb.confluent());
kb.knuth_bendix_by_overlap_length();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_rules() == 18);
REQUIRE(kb.size() == 22);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"046" ,
"(fpsemi) small example" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("ab" );
kb.add_rule("aaa" , "a" );
kb.add_rule("bbbb" , "b" );
kb.add_rule("ababababab" , "aa" );
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 243);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 3),
kb.cend_normal_forms())
== std::vector<std::string>({"a" , "b" , "aa" , "ab" , "ba" , "bb" }));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" , "047" , "code coverage" , "[quick]" ) {
KnuthBendix kb1;
KnuthBendix kb2(kb1);
REQUIRE(kb1.size() == 0);
kb1.set_alphabet("ab" );
kb1.add_rule("aaa" , "a" );
KnuthBendix kb3(kb1);
REQUIRE(kb3.number_of_rules() == 1);
REQUIRE_THROWS_AS(kb3.set_identity("ab" ), LibsemigroupsException);
REQUIRE_NOTHROW(kb3.set_identity("a" ));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"048" ,
"small overlap 1" ,
"[quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("BCA" );
kb.add_rule("AABC" , "ACBA" );
REQUIRE(kb.confluent());
REQUIRE(kb.normal_form("CBACBAABCAABCACBACBA" ) == "CBACBACBAACBAACBACBA" );
REQUIRE(kb.equal_to("CBAABCABCAABCAABCABC" , "CBACBAABCAABCACBACBA" ));
REQUIRE(kb.equal_to("CBAABCABCAABCAABCABC" , "CBACBAABCAABCACBACBA" ));
REQUIRE(kb.equal_to("AABCAABCCACAACBBCBCCACBBAABCBA" ,
"ACBAACBACACAACBBCBCCACBBACBABA" ));
REQUIRE(kb.equal_to("CACCBABACCBABACCAAAABCAABCBCAA" ,
"CACCBABACCBABACCAAACBAACBABCAA" ));
REQUIRE(kb.equal_to("CAAACAABCCBABCCBCCBCACABACBBAC" ,
"CAAACACBACBABCCBCCBCACABACBBAC" ));
REQUIRE(kb.equal_to("BABCACBACBCCCCCAACCAAABAABCBCC" ,
"BABCACBACBCCCCCAACCAAABACBABCC" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
// REQUIRE(std::vector<std::string>(cbegin_silo("BCA", 5, 6),
// cend_silo("BCA", 5, 6))
// == std::vector<std::string>());
// REQUIRE(number_of_words(3, 20, 21) == size_t(18446744071562067968ULL));
// auto lex_normal_form = [&kb](std::string const& w) {
// auto ww = kb.normal_form(w);
// auto it = std::find_if(cbegin_silo("BCA", ww, 4 * w.size()),
// cend_silo("BCA", ww.size(), 4 * w.size()),
// [&kb, &ww](std::string const& u) {
// return kb.normal_form(u) == ww;
// });
// return *it;
// };
// kb.run();
// REQUIRE(kb.finished());
// REQUIRE(lex_normal_form("BBBBB") == "BBBBB");
// REQUIRE(kb.normal_form("AABCB") == "ACBAB");
// REQUIRE(lex_normal_form("AABCB") == "");
// std::vector<std::string> result(number_of_words(3, 5, 20));
// std::transform(cbegin_
// TODO(later) The following code spends the majority of its time in
// FpSemigroupInterface::validate_letter
// auto it =
// REQUIRE(it != cend_silo("BCA", 0, 80));
// REQUIRE(*it == "CBACBAABCAABCACBACBA");
}
// Symmetric group S_9
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"049" ,
"(from kbmag/standalone/kb_data/s9)" ,
"[quick][knuth-bendix][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet("abcdefgh" );
kb.set_identity("" );
kb.set_inverses("abcdefgh" );
kb.add_rule("bab" , "aba" );
kb.add_rule("ca" , "ac" );
kb.add_rule("da" , "ad" );
kb.add_rule("ea" , "ae" );
kb.add_rule("fa" , "af" );
kb.add_rule("ga" , "ag" );
kb.add_rule("ha" , "ah" );
kb.add_rule("cbc" , "bcb" );
kb.add_rule("db" , "bd" );
kb.add_rule("eb" , "be" );
kb.add_rule("fb" , "bf" );
kb.add_rule("gb" , "bg" );
kb.add_rule("hb" , "bh" );
kb.add_rule("dcd" , "cdc" );
kb.add_rule("ec" , "ce" );
kb.add_rule("fc" , "cf" );
kb.add_rule("gc" , "cg" );
kb.add_rule("hc" , "ch" );
kb.add_rule("ede" , "ded" );
kb.add_rule("fd" , "df" );
kb.add_rule("gd" , "dg" );
kb.add_rule("hd" , "dh" );
kb.add_rule("fef" , "efe" );
kb.add_rule("ge" , "eg" );
kb.add_rule("he" , "eh" );
kb.add_rule("gfg" , "fgf" );
kb.add_rule("hf" , "fh" );
kb.add_rule("hgh" , "ghg" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 57);
REQUIRE(kb.size() == 362880);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"019" ,
"(fpsemi) C(4) monoid" ,
"[quick][knuthbendix][fpsemigroup][fpsemi]" ) {
KnuthBendix k;
k.set_alphabet("abcde" );
k.add_rule("bceac" , "aeebbc" );
k.add_rule("aeebbc" , "dabcd" );
k.run();
REQUIRE(k.confluent());
}
} // namespace fpsemigroup
} // namespace libsemigroups
quality 92%
¤ Dauer der Verarbeitung: 0.31 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland