// 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 third 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
#include "libsemigroups/siso.hpp" // for cbegin_sislo
#include "libsemigroups/types.hpp" // for word_type
namespace libsemigroups {
struct LibsemigroupsException;
constexpr
bool REPORT =
false ;
using rule_type = fpsemigroup::KnuthBendix::rule_type;
namespace fpsemigroup {
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"050" ,
"(fpsemi) Chapter 11, Lemma 1.8 (q = 6, r = 5) in NR "
"(infinite)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ABCabc" );
kb.add_rule(
"aA" ,
"" );
kb.add_rule(
"Aa" ,
"" );
kb.add_rule(
"bB" ,
"" );
kb.add_rule(
"Bb" ,
"" );
kb.add_rule(
"cC" ,
"" );
kb.add_rule(
"Cc" ,
"" );
kb.add_rule(
"aa" ,
"" );
kb.add_rule(
"bbb" ,
"" );
kb.add_rule(
"abaBaBabaBab" ,
"" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 16);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 1206);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(2, 3),
kb.cend_normal_forms())
== std::vector<std::string>({
"AB" ,
"AC" ,
"Ab" ,
"Ac" ,
"BA" ,
"BC" ,
"Bc" ,
"CA" ,
"CB" ,
"CC" ,
"Cb" ,
"bA" ,
"bC" ,
"bc" ,
"cA" ,
"cB" ,
"cb" ,
"cc" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"051" ,
"(fpsemi) Chapter 11, Section 2 (q = 6, r = 2, "
"alpha = "
"abaabba) in NR (size 4)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aaa" ,
"a" );
kb.add_rule(
"bbbbbbb" ,
"b" );
kb.add_rule(
"abaabba" ,
"bb" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 4);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 4);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 4);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 10),
kb.cend_normal_forms())
== std::vector<std::string>({
"a" ,
"b" ,
"aa" ,
"ab" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"052" ,
"(fpsemi) Chapter 8, Theorem 4.2 in NR (infinite)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aaa" ,
"a" );
kb.add_rule(
"bbbb" ,
"b" );
kb.add_rule(
"bababababab" ,
"b" );
kb.add_rule(
"baab" ,
"babbbab" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 8);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY)
== POSITIVE_INFINITY);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>({
"a" ,
"b" ,
"aa" ,
"ab" ,
"ba" ,
"bb" ,
"aab" ,
"aba" ,
"abb" ,
"baa" ,
"bab" ,
"bba" ,
"bbb" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"053" ,
"(fpsemi) equal_to fp semigroup" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abc" );
kb.add_rule(
"ab" ,
"ba" );
kb.add_rule(
"ac" ,
"ca" );
kb.add_rule(
"aa" ,
"a" );
kb.add_rule(
"ac" ,
"a" );
kb.add_rule(
"ca" ,
"a" );
kb.add_rule(
"bb" ,
"bb" );
kb.add_rule(
"bc" ,
"cb" );
kb.add_rule(
"bbb" ,
"b" );
kb.add_rule(
"bc" ,
"b" );
kb.add_rule(
"cb" ,
"b" );
kb.add_rule(
"a" ,
"b" );
REQUIRE(kb.equal_to(
"aa" ,
"a" ));
REQUIRE(kb.equal_to(
"bb" ,
"bb" ));
REQUIRE(kb.equal_to(
"bc" ,
"cb" ));
REQUIRE(kb.equal_to(
"ba" ,
"ccabc" ));
REQUIRE(kb.equal_to(
"cb" ,
"bbbc" ));
REQUIRE(!kb.equal_to(
"ba" ,
"c" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"054" ,
"(fpsemi) equal_to free semigroup" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(2);
REQUIRE(!kb.equal_to(word_type({0}), word_type({1})));
REQUIRE(kb.equal_to(word_type({0}), word_type({0})));
REQUIRE(kb.equal_to(word_type({0, 0, 0, 0, 0, 0, 0}),
word_type({0, 0, 0, 0, 0, 0, 0})));
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 62);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 62);
REQUIRE(std::equal(kb.cbegin_normal_forms(0, 6),
kb.cend_normal_forms(),
cbegin_sislo(kb.alphabet(),
kb.alphabet(0),
std::string(6, kb.alphabet(1)[0]))));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"055" ,
"(fpsemi) from GAP smalloverlap gap/test.gi (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][smalloverlap]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abcdefg" );
kb.add_rule(
"abcd" ,
"ce" );
kb.add_rule(
"df" ,
"dg" );
REQUIRE(kb.is_obviously_infinite());
REQUIRE(!kb.confluent());
REQUIRE(kb.equal_to(
"dfabcdf" ,
"dfabcdg" ));
REQUIRE(kb.equal_to(
"abcdf" ,
"ceg" ));
REQUIRE(kb.equal_to(
"abcdf" ,
"cef" ));
kb.run();
REQUIRE(kb.number_of_active_rules() == 3);
REQUIRE(kb.confluent());
REQUIRE(kb.equal_to(
"dfabcdf" ,
"dfabcdg" ));
REQUIRE(kb.equal_to(
"abcdf" ,
"ceg" ));
REQUIRE(kb.equal_to(
"abcdf" ,
"cef" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 17921);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 17921);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 2),
kb.cend_normal_forms())
== std::vector<std::string>({
"a" ,
"b" ,
"c" ,
"d" ,
"e" ,
"f" ,
"g" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"056" ,
"(fpsemi) from GAP smalloverlap gap/test.gi:49 (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][smalloverlap]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abcdefgh" );
kb.add_rule(
"abcd" ,
"ce" );
kb.add_rule(
"df" ,
"hd" );
REQUIRE(kb.is_obviously_infinite());
REQUIRE(kb.confluent());
REQUIRE(kb.equal_to(
"abchd" ,
"abcdf" ));
REQUIRE(!kb.equal_to(
"abchf" ,
"abcdf" ));
REQUIRE(kb.equal_to(
"abchd" ,
"abchd" ));
REQUIRE(kb.equal_to(
"abchdf" ,
"abchhd" ));
// Test cases (4) and (5)
REQUIRE(kb.equal_to(
"abchd" ,
"cef" ));
REQUIRE(kb.equal_to(
"cef" ,
"abchd" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 35199);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 35199);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 2),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"a" ,
"b" ,
"c" ,
"d" ,
"e" ,
"f" ,
"g" ,
"h" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"057" ,
"(fpsemi) from GAP smalloverlap gap/test.gi:63 (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][smalloverlap]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abcdefgh" );
kb.add_rule(
"afh" ,
"bgh" );
kb.add_rule(
"hc" ,
"d" );
REQUIRE(kb.is_obviously_infinite());
REQUIRE(!kb.confluent());
// Test case (6)
REQUIRE(kb.equal_to(
"afd" ,
"bgd" ));
kb.run();
REQUIRE(kb.number_of_active_rules() == 3);
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 34819);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 34819);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 2),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"a" ,
"b" ,
"c" ,
"d" ,
"e" ,
"f" ,
"g" ,
"h" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"058" ,
"(fpsemi) from GAP smalloverlap gap/test.gi:70 (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][smalloverlap]" ) {
auto rg = ReportGuard(REPORT);
// The following permits a more complex test of case (6), which also
// involves using the case (2) code to change the prefix being looked for:
KnuthBendix kb;
kb.set_alphabet(
"abcdefghij" );
kb.add_rule(
"afh" ,
"bgh" );
kb.add_rule(
"hc" ,
"de" );
kb.add_rule(
"ei" ,
"j" );
REQUIRE(kb.is_obviously_infinite());
REQUIRE(!kb.confluent());
REQUIRE(kb.equal_to(
"afdj" ,
"bgdj" ));
REQUIRE_THROWS_AS(!kb.equal_to(
"xxxxxxxxxxxxxxxxxxxxxxx" ,
"b" ),
LibsemigroupsException);
kb.run();
REQUIRE(kb.number_of_active_rules() == 5);
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 102255);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 102255);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 2),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"a" ,
"b" ,
"c" ,
"d" ,
"e" ,
"f" ,
"g" ,
"h" ,
"i" ,
"j" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"059" ,
"(fpsemi) from GAP smalloverlap gap/test.gi:77 (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][smalloverlap][no-"
"valgrind]" ) {
auto rg = ReportGuard(REPORT);
// A slightly more complicated presentation for testing case (6), in which
// the max piece suffixes of the first two relation words no longer agree
// (since fh and gh are now pieces).
KnuthBendix kb;
kb.set_alphabet(
"abcdefghijkl" );
kb.add_rule(
"afh" ,
"bgh" );
kb.add_rule(
"hc" ,
"de" );
kb.add_rule(
"ei" ,
"j" );
kb.add_rule(
"fhk" ,
"ghl" );
REQUIRE(kb.is_obviously_infinite());
REQUIRE(!kb.confluent());
REQUIRE(kb.equal_to(
"afdj" ,
"bgdj" ));
kb.run();
REQUIRE(kb.number_of_active_rules() == 7);
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 255932);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY)
== POSITIVE_INFINITY);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 255932);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, 2),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"a" ,
"b" ,
"c" ,
"d" ,
"e" ,
"f" ,
"g" ,
"h" ,
"i" ,
"j" ,
"k" ,
"l" }));
// The following is for comparison with the Kambites class.
// size_t N = std::distance(cbegin_sislo("abcdefghijkl", "a", "bgdk"),
// cend_sislo("abcdefghijkl", "a", "bgdk"));
// REQUIRE(N == 4522);
// for (auto it1 = cbegin_sislo("abcdefghijkl", "a", "bgdk");
// it1 != cend_sislo("abcdefghijkl", "a", "bgdk");
// ++it1) {
// for (auto it2 = cbegin_sislo("abcdefghijkl", "a", "bgdk"); it2 !=
// it1;
// ++it2) {
// if (kb.equal_to(*it1, *it2)) {
// N--;
// break;
// }
// }
// }
// REQUIRE(N == 4392);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"060" ,
"(fpsemi) from GAP smalloverlap gap/test.gi:85 (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][smalloverlap]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"cab" );
// runs forever with a different order
kb.add_rule(
"aabc" ,
"acba" );
REQUIRE(kb.is_obviously_infinite());
REQUIRE(kb.confluent());
// Confirmed with GAP
REQUIRE(!kb.equal_to(
"a" ,
"b" ));
REQUIRE(kb.equal_to(
"aabcabc" ,
"aabccba" ));
kb.run();
REQUIRE(kb.number_of_active_rules() == 1);
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.active_rules() == std::vector<rule_type>({{
"aabc" ,
"acba" }}));
REQUIRE(kb.number_of_normal_forms(0, 6) == 356);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"061" ,
"(fpsemi) Von Dyck (2,3,7) group (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ABabc" );
kb.set_identity(
"" );
kb.set_inverses(
"abABc" );
kb.add_rule(
"aaaa" ,
"AAA" );
kb.add_rule(
"bb" ,
"B" );
kb.add_rule(
"BA" ,
"c" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 30);
REQUIRE(kb.confluent());
REQUIRE(!kb.equal_to(
"a" ,
"b" ));
REQUIRE(!kb.equal_to(
"aabcabc" ,
"aabccba" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 88);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY)
== POSITIVE_INFINITY);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 88);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 2),
kb.cend_normal_forms())
== std::vector<std::string>({
"" ,
"A" ,
"B" ,
"a" ,
"b" ,
"c" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"062" ,
"(fpsemi) Von Dyck (2,3,7) group - different "
"presentation (infinite)" ,
"[no-valgrind][quick][knuth-bendix][fpsemigroup]["
"fpsemi][kbmag]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abcAB" );
kb.add_rule(
"aaaa" ,
"AAA" );
kb.add_rule(
"bb" ,
"B" );
kb.add_rule(
"abababa" ,
"BABABAB" );
kb.add_rule(
"BA" ,
"c" );
REQUIRE(!kb.confluent());
kb.overlap_policy(KnuthBendix::options::overlap::MAX_AB_BC);
kb.max_rules(100);
kb.run();
REQUIRE(kb.number_of_active_rules() == 101);
kb.run();
REQUIRE(kb.number_of_active_rules() == 101);
kb.max_rules(250);
kb.run();
REQUIRE(kb.number_of_active_rules() == 259);
// kb.max_rules(POSITIVE_INFINITY);
// kb.run();
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"063" ,
"(fpsemi) rewriting system from KnuthBendixCongruenceByPairs 08" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abc" );
kb.add_rule(
"bbbbbbb" ,
"b" );
kb.add_rule(
"ccccc" ,
"c" );
kb.add_rule(
"bccba" ,
"bccb" );
kb.add_rule(
"bccbc" ,
"bccb" );
kb.add_rule(
"bbcbca" ,
"bbcbc" );
kb.add_rule(
"bbcbcb" ,
"bbcbc" );
REQUIRE(!kb.confluent());
REQUIRE(kb.number_of_active_rules() == 6);
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 8);
REQUIRE(kb.equal_to(
"bbbbbbb" ,
"b" ));
REQUIRE(kb.equal_to(
"ccccc" ,
"c" ));
REQUIRE(kb.equal_to(
"bccba" ,
"bccb" ));
REQUIRE(kb.equal_to(
"bccbc" ,
"bccb" ));
REQUIRE(kb.equal_to(
"bcbca" ,
"bcbc" ));
REQUIRE(kb.equal_to(
"bcbcb" ,
"bcbc" ));
REQUIRE(kb.equal_to(
"bcbcc" ,
"bcbc" ));
REQUIRE(kb.equal_to(
"bccbb" ,
"bccb" ));
REQUIRE(kb.equal_to(
"bccb" ,
"bccbb" ));
REQUIRE(!kb.equal_to(
"aaaa" ,
"bccbb" ));
std::vector<rule_type> rules = kb.active_rules();
REQUIRE(rules[0] == rule_type(
"bcbca" ,
"bcbc" ));
REQUIRE(rules[1] == rule_type(
"bcbcb" ,
"bcbc" ));
REQUIRE(rules[2] == rule_type(
"bcbcc" ,
"bcbc" ));
REQUIRE(rules[3] == rule_type(
"bccba" ,
"bccb" ));
REQUIRE(rules[4] == rule_type(
"bccbb" ,
"bccb" ));
REQUIRE(rules[5] == rule_type(
"bccbc" ,
"bccb" ));
REQUIRE(rules[6] == rule_type(
"ccccc" ,
"c" ));
REQUIRE(rules[7] == rule_type(
"bbbbbbb" ,
"b" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 356);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY)
== POSITIVE_INFINITY);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 356);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 2),
kb.cend_normal_forms())
== std::vector<std::string>({
"a" ,
"b" ,
"c" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"064" ,
"(fpsemi) rewriting system from Congruence 20" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aaa" ,
"a" );
kb.add_rule(
"ab" ,
"ba" );
kb.add_rule(
"aa" ,
"a" );
kb.run();
REQUIRE(kb.equal_to(
"abbbbbbbbbbbbbb" ,
"aabbbbbbbbbbbbbb" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
}
// 2-generator free abelian group (with this ordering KB terminates - but
// no all)
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"065" ,
"(fpsemi) (from kbmag/standalone/kb_data/ab2)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"aAbB" );
kb.set_identity(
"" );
kb.set_inverses(
"AaBb" );
kb.add_rule(
"Bab" ,
"a" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 8);
REQUIRE(kb.equal_to(
"Bab" ,
"a" ));
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 6) == 61);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY)
== POSITIVE_INFINITY);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 61);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>({
"" ,
"a" ,
"A" ,
"b" ,
"B" ,
"aa" ,
"ab" ,
"aB" ,
"AA" ,
"Ab" ,
"AB" ,
"bb" ,
"BB" ,
"aaa" ,
"aab" ,
"aaB" ,
"abb" ,
"aBB" ,
"AAA" ,
"AAb" ,
"AAB" ,
"Abb" ,
"ABB" ,
"bbb" ,
"BBB" }));
}
// This group is actually D_22 (although it wasn't meant to be). All
// generators are unexpectedly involutory.
// knuth_bendix does not terminate with the commented out ordering,
// terminates almost immediately with the uncommented order.
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"066" ,
"(fpsemi) (from kbmag/standalone/kb_data/d22) (1 / 3)"
"(infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
// KnuthBendix kb;
// kb.set_alphabet("aAbBcCdDyYfF");
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_active_rules() == 41);
REQUIRE(kb.equal_to(
"bfBY" ,
"" ));
REQUIRE(kb.equal_to(
"cyCD" ,
"" ));
REQUIRE(kb.equal_to(
"ybYA" ,
"" ));
REQUIRE(kb.equal_to(
"fCFB" ,
"" ));
REQUIRE(kb.equal_to(
"CAd" ,
"dFD" ));
REQUIRE(kb.equal_to(
"FDa" ,
"aCA" ));
REQUIRE(kb.equal_to(
"adFD" ,
"" ));
REQUIRE(kb.equal_to(
"daCA" ,
"" ));
REQUIRE(
kb.active_rules()
== std::vector<rule_type>(
{{
"a" ,
"A" }, {
"b" ,
"B" }, {
"c" ,
"C" }, {
"d" ,
"D" },
{
"f" ,
"F" }, {
"y" ,
"Y" }, {
"AA" ,
"" }, {
"BB" ,
"" },
{
"BC" ,
"AB" }, {
"BF" ,
"Ay" }, {
"CA" ,
"AD" }, {
"CB" ,
"BA" },
{
"CC" ,
"" }, {
"CD" ,
"AF" }, {
"CF" ,
"BY" }, {
"DA" ,
"AC" },
{
"DC" ,
"CY" }, {
"DD" ,
"" }, {
"DF" ,
"AD" }, {
"DY" ,
"BD" },
{
"FA" ,
"CY" }, {
"FB" ,
"BY" }, {
"FC" ,
"Ay" }, {
"FD" ,
"DA" },
{
"FF" ,
"AA" }, {
"FY" ,
"BA" }, {
"YA" ,
"BY" }, {
"YB" ,
"BF" },
{
"YC" ,
"CD" }, {
"YD" ,
"DB" }, {
"YF" ,
"AB" }, {
"YY" ,
"" },
{
"BAB" ,
"C" }, {
"BAC" ,
"AYd" }, {
"BAD" ,
"ABA" }, {
"BAF" ,
"ADY" },
{
"BAY" ,
"F" }, {
"BDB" ,
"ACY" }, {
"DBA" ,
"ADY" }, {
"DBD" ,
"Y" },
{
"DBY" ,
"ADB" }}));
REQUIRE(kb.size() == 22);
REQUIRE(kb.number_of_normal_forms(0, 3) == 17);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 22);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 22);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
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" }));
}
// No generators - no anything!
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"067" ,
"(fpsemi) (from kbmag/standalone/kb_data/degen1)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
REQUIRE(kb.confluent());
REQUIRE_THROWS_AS(kb.run(), LibsemigroupsException);
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 0);
REQUIRE(kb.size() == 0);
REQUIRE_THROWS_AS(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
LibsemigroupsException);
}
// Symmetric group S_4
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"068" ,
"(fpsemi) (from kbmag/standalone/kb_data/s4)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi][kbmag][shortlex]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abB" );
kb.set_identity(
"" );
kb.set_inverses(
"aBb" );
kb.add_rule(
"bb" ,
"B" );
kb.add_rule(
"BaBa" ,
"abab" );
REQUIRE(!kb.confluent());
kb.knuth_bendix_by_overlap_length();
REQUIRE(kb.confluent());
REQUIRE(kb.number_of_active_rules() == 11);
REQUIRE(kb.size() == 24);
REQUIRE(kb.number_of_normal_forms(0, 6) == 23);
REQUIRE(kb.number_of_normal_forms(6, 7) == 1);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 24);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 6), kb.cend_normal_forms())
== 23);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 7),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"" ,
"a" ,
"b" ,
"B" ,
"ab" ,
"aB" ,
"ba" ,
"Ba" ,
"aba" ,
"aBa" ,
"bab" ,
"baB" ,
"Bab" ,
"BaB" ,
"abab" ,
"abaB" ,
"aBab" ,
"aBaB" ,
"baBa" ,
"Baba" ,
"abaBa" ,
"aBaba" ,
"baBab" ,
"abaBab" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"069" ,
"(fpsemi) fp semigroup (infinite)" ,
"[quick][knuth-bendix][fpsemigroup][fpsemi]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(3);
kb.add_rule({0, 1}, {1, 0});
kb.add_rule({0, 2}, {2, 0});
kb.add_rule({0, 0}, {0});
kb.add_rule({0, 2}, {0});
kb.add_rule({2, 0}, {0});
kb.add_rule({1, 1}, {1, 1});
kb.add_rule({1, 2}, {2, 1});
kb.add_rule({1, 1, 1}, {1});
kb.add_rule({1, 2}, {1});
kb.add_rule({2, 1}, {1});
kb.add_rule({0}, {1});
REQUIRE(kb.confluent());
REQUIRE(kb.equal_to(word_type({0, 0}), word_type({0})));
REQUIRE(kb.equal_to(word_type({1, 1}), word_type({1, 1})));
REQUIRE(kb.equal_to(word_type({1, 2}), word_type({2, 1})));
REQUIRE(kb.equal_to(word_type({1, 0}), word_type({2, 2, 0, 1, 2})));
REQUIRE(kb.equal_to(word_type({2, 1}), word_type({1, 1, 1, 2})));
REQUIRE(!kb.equal_to(word_type({1, 0}), word_type({2})));
REQUIRE(kb.size() == POSITIVE_INFINITY);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"070" ,
"(fpsemi) Chapter 11, Section 1 (q = 4, r = 3) "
"in NR (size 86)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aaa" ,
"a" );
kb.add_rule(
"bbbbb" ,
"b" );
kb.add_rule(
"abbbabb" ,
"bba" );
REQUIRE(!kb.confluent());
kb.knuth_bendix_by_overlap_length();
REQUIRE(kb.number_of_active_rules() == 20);
REQUIRE(kb.confluent());
// Check that rewrite to a non-pointer argument does not rewrite its
// argument
std::string w =
"aaa" ;
REQUIRE(kb.rewrite(w) ==
"a" );
REQUIRE(w ==
"aaa" );
// defining relations
REQUIRE(kb.rewrite(
"aaa" ) == kb.rewrite(
"a" ));
REQUIRE(kb.rewrite(
"bbbbb" ) == kb.rewrite(
"b" ));
REQUIRE(kb.rewrite(
"abbbabb" ) == kb.rewrite(
"bba" ));
// consequential relations (Chapter 11, Lemma 1.1 in NR)
REQUIRE(kb.rewrite(
"babbbb" ) == kb.rewrite(
"ba" ));
REQUIRE(kb.rewrite(
"baabbbb" ) == kb.rewrite(
"baa" ));
REQUIRE(kb.rewrite(
"aabbbbbbbbbba" ) == kb.rewrite(
"bbbbbbbbbba" ));
REQUIRE(kb.rewrite(
"babbbbbbbbaa" ) == kb.rewrite(
"babbbbbbbb" ));
REQUIRE(kb.rewrite(
"baabbbbbbaa" ) == kb.rewrite(
"baabbbbbb" ));
REQUIRE(kb.rewrite(
"bbbbaabbbbaa" ) == kb.rewrite(
"bbbbaa" ));
REQUIRE(kb.rewrite(
"bbbaa" ) == kb.rewrite(
"baabb" ));
REQUIRE(kb.rewrite(
"abbbaabbba" ) == kb.rewrite(
"bbbbaa" ));
REQUIRE(kb.size() == 86);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 86);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 86);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"071" ,
"(fpsemi) Chapter 11, Section 1 (q = 8, r = 5) in NR "
"(size 746)" ,
"[no-valgrind][knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aaa" ,
"a" );
kb.add_rule(
"bbbbbbbbb" ,
"b" );
kb.add_rule(
"abbbbbabb" ,
"bba" );
// kb.clear_stack_interval(0);
REQUIRE(!kb.confluent());
kb.knuth_bendix_by_overlap_length();
REQUIRE(kb.number_of_active_rules() == 105);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 746);
// defining relations
REQUIRE(kb.rewrite(
"aaa" ) == kb.rewrite(
"a" ));
REQUIRE(kb.rewrite(
"bbbbbbbbb" ) == kb.rewrite(
"b" ));
REQUIRE(kb.rewrite(
"abbbbbabb" ) == kb.rewrite(
"bba" ));
// consequential relations (Chapter 11, Lemma 1.1 in NR)
REQUIRE(kb.rewrite(
"babbbbbbbb" ) == kb.rewrite(
"ba" ));
REQUIRE(kb.rewrite(
"baabbbbbbbb" ) == kb.rewrite(
"baa" ));
REQUIRE(kb.rewrite(
"aabbbbbbbbbbbba" ) == kb.rewrite(
"bbbbbbbbbbbba" ));
REQUIRE(kb.rewrite(
"babbbbbbbbbbaa" ) == kb.rewrite(
"babbbbbbbbbb" ));
REQUIRE(kb.rewrite(
"baabbbbbbbbaa" ) == kb.rewrite(
"baabbbbbbbb" ));
REQUIRE(kb.rewrite(
"bbbbbbbbaabbbbbbbbaa" ) == kb.rewrite(
"bbbbbbbbaa" ));
REQUIRE(kb.rewrite(
"bbbaa" ) == kb.rewrite(
"baabb" ));
REQUIRE(kb.rewrite(
"abbbbbaabbbbba" ) == kb.rewrite(
"bbbbbbbbaa" ));
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 746);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 746);
}
// See KBFP 07 also.
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"072" ,
"(fpsemi) Chapter 7, Theorem 3.9 in NR (size 240)" ,
"[no-valgrind][knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aaa" ,
"a" );
kb.add_rule(
"bbbb" ,
"b" );
kb.add_rule(
"abbba" ,
"aa" );
kb.add_rule(
"baab" ,
"bb" );
kb.add_rule(
"aabababababa" ,
"aa" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 24);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 240);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 240);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 240);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"073" ,
"(fpsemi) F(2, 5) - Chapter 9, Section 1 in NR "
"(size 11)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
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.number_of_active_rules() == 24);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 11);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 11);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 11);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"a" ,
"b" ,
"c" ,
"d" ,
"e" ,
"aa" ,
"ac" ,
"ad" ,
"bb" ,
"be" ,
"aad" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"074" ,
"(fpsemi) F(2, 6) - Chapter 9, Section 1 in NR" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abcdef" );
kb.add_rule(
"ab" ,
"" );
kb.add_rule(
"bc" ,
"d" );
kb.add_rule(
"cd" ,
"e" );
kb.add_rule(
"de" ,
"f" );
kb.add_rule(
"ef" ,
"a" );
kb.add_rule(
"fa" ,
"b" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 35);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 12);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 12);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 12);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== std::vector<std::string>({
"" ,
"a" ,
"b" ,
"c" ,
"d" ,
"e" ,
"f" ,
"aa" ,
"ac" ,
"ae" ,
"bd" ,
"df" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"075" ,
"(fpsemi) Chapter 10, Section 4 in NR (infinite)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abc" );
kb.add_rule(
"aaaa" ,
"a" );
kb.add_rule(
"bbbb" ,
"b" );
kb.add_rule(
"cccc" ,
"c" );
kb.add_rule(
"abab" ,
"aaa" );
kb.add_rule(
"bcbc" ,
"bbb" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 31);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY)
== POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 10) == 8823);
}
// Note: the fourth relator in NR's thesis incorrectly has exponent 3, it
// should be 2. With exponent 3, the presentation defines the trivial
// group, with exponent of 2, it defines the symmetric group as desired.
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"076" ,
"(fpsemi) Sym(5) from Chapter 3, Proposition "
"1.1 in NR "
"(size 120)" ,
"[no-valgrind][knuth-bendix][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ABab" );
kb.add_rule(
"aa" ,
"" );
kb.add_rule(
"bbbbb" ,
"" );
kb.add_rule(
"babababa" ,
"" );
kb.add_rule(
"bB" ,
"" );
kb.add_rule(
"Bb" ,
"" );
kb.add_rule(
"BabBab" ,
"" );
kb.add_rule(
"aBBabbaBBabb" ,
"" );
kb.add_rule(
"aBBBabbbaBBBabbb" ,
"" );
kb.add_rule(
"aA" ,
"" );
kb.add_rule(
"Aa" ,
"" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 36);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 120);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 120);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 120);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>({
"" ,
"A" ,
"B" ,
"b" ,
"AB" ,
"Ab" ,
"BA" ,
"BB" ,
"bA" ,
"bb" ,
"ABA" ,
"ABB" ,
"AbA" ,
"Abb" ,
"BAB" ,
"BAb" ,
"BBA" ,
"bAB" ,
"bAb" ,
"bbA" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"077" ,
"(fpsemi) SL(2, 7) from Chapter 3, Proposition "
"1.5 in NR "
"(size 336)" ,
"[no-valgrind][quick][knuth-bendix][fpsemigroup][fpsemi]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abAB" );
kb.add_rule(
"aaaaaaa" ,
"" );
kb.add_rule(
"bb" ,
"ababab" );
kb.add_rule(
"bb" ,
"aaaabaaaabaaaabaaaab" );
kb.add_rule(
"aA" ,
"" );
kb.add_rule(
"Aa" ,
"" );
kb.add_rule(
"bB" ,
"" );
kb.add_rule(
"Bb" ,
"" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 152);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 336);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 336);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 336);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"" ,
"a" ,
"b" ,
"A" ,
"B" ,
"aa" ,
"ab" ,
"aB" ,
"ba" ,
"bb" ,
"bA" ,
"Ab" ,
"AA" ,
"AB" ,
"Ba" ,
"BA" ,
"aaa" ,
"aab" ,
"aaB" ,
"aba" ,
"abb" ,
"abA" ,
"aBa" ,
"aBA" ,
"baa" ,
"bab" ,
"baB" ,
"bbA" ,
"bAA" ,
"Aba" ,
"AAb" ,
"AAA" ,
"AAB" ,
"ABa" ,
"Baa" ,
"BAA" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"078" ,
"(fpsemi) bicyclic monoid (infinite)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"ab" ,
"" );
REQUIRE(kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 1);
REQUIRE(kb.confluent());
REQUIRE(kb.is_obviously_infinite());
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 10) == 55);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 10), kb.cend_normal_forms())
== 55);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"" ,
"a" ,
"b" ,
"aa" ,
"ba" ,
"bb" ,
"aaa" ,
"baa" ,
"bba" ,
"bbb" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"079" ,
"(fpsemi) plactic monoid of degree 2 (infinite)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"abc" );
kb.add_rule(
"aba" ,
"baa" );
kb.add_rule(
"bba" ,
"bab" );
kb.add_rule(
"ac" ,
"" );
kb.add_rule(
"ca" ,
"" );
kb.add_rule(
"bc" ,
"" );
kb.add_rule(
"cb" ,
"" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 3);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 10) == 19);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 10), kb.cend_normal_forms())
== 19);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>(
{
"" ,
"a" ,
"c" ,
"aa" ,
"cc" ,
"aaa" ,
"ccc" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"080" ,
"(fpsemi) example before Chapter 7, Proposition "
"1.1 in NR (infinite)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aa" ,
"a" );
kb.add_rule(
"bb" ,
"b" );
REQUIRE(kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 2);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_normal_forms(0, 10) == 18);
REQUIRE(
std::distance(kb.cbegin_normal_forms(0, 10), kb.cend_normal_forms())
== 18);
REQUIRE(
std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>({
"a" ,
"b" ,
"ab" ,
"ba" ,
"aba" ,
"bab" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"081" ,
"(fpsemi) Chapter 7, Theorem 3.6 in NR (size 243)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
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" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 12);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 243);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 243);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 243);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>({
"a" ,
"b" ,
"aa" ,
"ab" ,
"ba" ,
"bb" ,
"aab" ,
"aba" ,
"abb" ,
"baa" ,
"bab" ,
"bba" ,
"bbb" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"082" ,
"(fpsemi) finite semigroup (size 99)" ,
"[knuth-bendix][fpsemigroup][fpsemi][quick]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_alphabet(
"ab" );
kb.add_rule(
"aaa" ,
"a" );
kb.add_rule(
"bbbb" ,
"b" );
kb.add_rule(
"abababab" ,
"aa" );
REQUIRE(!kb.confluent());
kb.run();
REQUIRE(kb.number_of_active_rules() == 9);
REQUIRE(kb.confluent());
REQUIRE(kb.size() == 99);
REQUIRE(kb.number_of_normal_forms(0, POSITIVE_INFINITY) == 99);
REQUIRE(std::distance(kb.cbegin_normal_forms(0, POSITIVE_INFINITY),
kb.cend_normal_forms())
== 99);
REQUIRE(std::vector<std::string>(kb.cbegin_normal_forms(0, 4),
kb.cend_normal_forms())
== std::vector<std::string>({
"a" ,
"b" ,
"aa" ,
"ab" ,
"ba" ,
"bb" ,
"aab" ,
"aba" ,
"abb" ,
"baa" ,
"bab" ,
"bba" ,
"bbb" }));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"998" ,
"Giles Gardam in \" A counterexample to the unit conjecture
for group
"
"rings\" (https:
//arxiv.org/abs/2102.11818)",
"[fpsemigroup][fail]" ) {
KnuthBendix k;
k.set_alphabet(
"bABea" );
k.set_identity(
"e" );
k.set_inverses(
"BabeA" );
k.add_rule(
"Abba" ,
"BB" );
k.add_rule(
"Baab" ,
"AA" );
k.knuth_bendix_by_overlap_length();
REQUIRE(k.size() == POSITIVE_INFINITY);
}
}
// namespace fpsemigroup
}
// namespace libsemigroups
Messung V0.5 C=89 H=97 G=93
¤ Dauer der Verarbeitung: 0.6 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland