// 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 sixth 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 "catch.hpp" // for REQUIRE, REQUIRE_NOTHROW, REQUIRE_THROWS_AS
#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE
#include "libsemigroups/fpsemi-examples.hpp" // for chinese_monoid
#include "libsemigroups/knuth-bendix.hpp" // for KnuthBendix, operator<<
#include "libsemigroups/report.hpp" // for ReportGuard
#include "libsemigroups/types.hpp" // for word_type
namespace libsemigroups {
struct LibsemigroupsException;
constexpr bool REPORT = false ;
using fpsemigroup::author;
using fpsemigroup::make;
using fpsemigroup::chinese_monoid;
using fpsemigroup::partial_transformation_monoid;
namespace congruence {
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"103" ,
"(cong) free semigroup congruence (5 classes)" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({0}, {1, 1});
REQUIRE(!kb.finished());
REQUIRE(kb.number_of_classes() == 5);
REQUIRE(kb.finished());
REQUIRE(kb.word_to_class_index({0, 0, 1}) == 4);
REQUIRE(kb.word_to_class_index({0, 0, 0, 0, 1}) == 4);
REQUIRE(kb.word_to_class_index({0, 1, 1, 0, 0, 1}) == 4);
REQUIRE(kb.word_to_class_index({0, 0, 0}) == 0);
REQUIRE(kb.word_to_class_index({1}) == 1);
REQUIRE(kb.word_to_class_index({0, 0, 0, 0}) == 2);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"104" ,
"free semigroup congruence (6 classes)" ,
"[quick][cong][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(5);
kb.add_pair({0, 0}, {0});
kb.add_pair({0, 1}, {1});
kb.add_pair({1, 0}, {1});
kb.add_pair({0, 2}, {2});
kb.add_pair({2, 0}, {2});
kb.add_pair({0, 3}, {3});
kb.add_pair({3, 0}, {3});
kb.add_pair({0, 4}, {4});
kb.add_pair({4, 0}, {4});
kb.add_pair({1, 2}, {0});
kb.add_pair({2, 1}, {0});
kb.add_pair({3, 4}, {0});
kb.add_pair({4, 3}, {0});
kb.add_pair({2, 2}, {0});
kb.add_pair({1, 4, 2, 3, 3}, {0});
kb.add_pair({4, 4, 4}, {0});
REQUIRE(kb.number_of_classes() == 6);
// Throws because there's no parent semigroup
REQUIRE_THROWS_AS(kb.number_of_non_trivial_classes(),
LibsemigroupsException);
REQUIRE(kb.word_to_class_index({1}) == kb.word_to_class_index({2}));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"105" ,
"(cong) free semigroup congruence (16 classes)" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(4);
kb.add_pair({3}, {2});
kb.add_pair({0, 3}, {0, 2});
kb.add_pair({1, 1}, {1});
kb.add_pair({1, 3}, {1, 2});
kb.add_pair({2, 1}, {2});
kb.add_pair({2, 2}, {2});
kb.add_pair({2, 3}, {2});
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({0, 0, 1}, {1});
kb.add_pair({0, 0, 2}, {2});
kb.add_pair({0, 1, 2}, {1, 2});
kb.add_pair({1, 0, 0}, {1});
kb.add_pair({1, 0, 2}, {0, 2});
kb.add_pair({2, 0, 0}, {2});
kb.add_pair({0, 1, 0, 1}, {1, 0, 1});
kb.add_pair({0, 2, 0, 2}, {2, 0, 2});
kb.add_pair({1, 0, 1, 0}, {1, 0, 1});
kb.add_pair({1, 2, 0, 1}, {1, 0, 1});
kb.add_pair({1, 2, 0, 2}, {2, 0, 2});
kb.add_pair({2, 0, 1, 0}, {2, 0, 1});
kb.add_pair({2, 0, 2, 0}, {2, 0, 2});
REQUIRE(kb.number_of_classes() == 16);
// REQUIRE(kb.knuth_bendix().number_of_active_rules() == 16);
REQUIRE(kb.word_to_class_index({2}) == kb.word_to_class_index({3}));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"106" ,
"(cong) free semigroup congruence (6 classes)" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(11);
kb.add_pair({2}, {1});
kb.add_pair({4}, {3});
kb.add_pair({5}, {0});
kb.add_pair({6}, {3});
kb.add_pair({7}, {1});
kb.add_pair({8}, {3});
kb.add_pair({9}, {3});
kb.add_pair({10}, {0});
kb.add_pair({0, 2}, {0, 1});
kb.add_pair({0, 4}, {0, 3});
kb.add_pair({0, 5}, {0, 0});
kb.add_pair({0, 6}, {0, 3});
kb.add_pair({0, 7}, {0, 1});
kb.add_pair({0, 8}, {0, 3});
kb.add_pair({0, 9}, {0, 3});
kb.add_pair({0, 10}, {0, 0});
kb.add_pair({1, 1}, {1});
kb.add_pair({1, 2}, {1});
kb.add_pair({1, 4}, {1, 3});
kb.add_pair({1, 5}, {1, 0});
kb.add_pair({1, 6}, {1, 3});
kb.add_pair({1, 7}, {1});
kb.add_pair({1, 8}, {1, 3});
kb.add_pair({1, 9}, {1, 3});
kb.add_pair({1, 10}, {1, 0});
kb.add_pair({3, 1}, {3});
kb.add_pair({3, 2}, {3});
kb.add_pair({3, 3}, {3});
kb.add_pair({3, 4}, {3});
kb.add_pair({3, 5}, {3, 0});
kb.add_pair({3, 6}, {3});
kb.add_pair({3, 7}, {3});
kb.add_pair({3, 8}, {3});
kb.add_pair({3, 9}, {3});
kb.add_pair({3, 10}, {3, 0});
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({0, 0, 1}, {1});
kb.add_pair({0, 0, 3}, {3});
kb.add_pair({0, 1, 3}, {1, 3});
kb.add_pair({1, 0, 0}, {1});
kb.add_pair({1, 0, 3}, {0, 3});
kb.add_pair({3, 0, 0}, {3});
kb.add_pair({0, 1, 0, 1}, {1, 0, 1});
kb.add_pair({0, 3, 0, 3}, {3, 0, 3});
kb.add_pair({1, 0, 1, 0}, {1, 0, 1});
kb.add_pair({1, 3, 0, 1}, {1, 0, 1});
kb.add_pair({1, 3, 0, 3}, {3, 0, 3});
kb.add_pair({3, 0, 1, 0}, {3, 0, 1});
kb.add_pair({3, 0, 3, 0}, {3, 0, 3});
REQUIRE(kb.number_of_classes() == 16);
REQUIRE(kb.word_to_class_index({0}) == kb.word_to_class_index({5}));
REQUIRE(kb.word_to_class_index({0}) == kb.word_to_class_index({10}));
REQUIRE(kb.word_to_class_index({1}) == kb.word_to_class_index({2}));
REQUIRE(kb.word_to_class_index({1}) == kb.word_to_class_index({7}));
REQUIRE(kb.word_to_class_index({3}) == kb.word_to_class_index({4}));
REQUIRE(kb.word_to_class_index({3}) == kb.word_to_class_index({6}));
REQUIRE(kb.word_to_class_index({3}) == kb.word_to_class_index({8}));
REQUIRE(kb.word_to_class_index({3}) == kb.word_to_class_index({9}));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"107" ,
"(cong) free semigroup congruence (240 classes)" ,
"[no-valgrind][quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 0}, {0, 0});
kb.add_pair({1, 0, 0, 1}, {1, 1});
kb.add_pair({0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0});
REQUIRE(kb.number_of_classes() == 240);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"108" ,
"(cong) free semigroup congruence (240 classes)" ,
"[no-valgrind][quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 0}, {0, 0});
kb.add_pair({1, 0, 0, 1}, {1, 1});
kb.add_pair({0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0});
REQUIRE_NOTHROW(kb.knuth_bendix().froidure_pin());
REQUIRE_THROWS_AS(kb.add_pair({0}, {1}), LibsemigroupsException);
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"109" ,
"(cong) less" ,
"[no-valgrind][quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
{
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
kb.run();
REQUIRE(!kb.less({0, 1, 1, 1, 0, 0, 1, 1, 1, 0}, {1, 1, 1, 1, 0, 0}));
REQUIRE(!kb.less({0, 1, 1, 0}, {0, 1, 1, 0}));
}
{
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
REQUIRE(!kb.less({0, 1, 1, 1, 0, 0, 1, 1, 1, 0}, {1, 1, 1, 1, 0, 0}));
REQUIRE(!kb.less({0, 1, 1, 0}, {0, 1, 1, 0}));
}
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"110" ,
"(cong) less" ,
"[quick][congruence][knuth-bendix][cong][no-valgrind]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1, 1, 1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
REQUIRE(kb.less({0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1}));
}
LIBSEMIGROUPS_TEST_CASE(
"KnuthBendix" ,
"111" ,
"(cong) constructors" ,
"[quick][congruence][knuth-bendix][cong][no-valgrind]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1, 1, 1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
REQUIRE(kb.number_of_classes() == 746);
auto copy(kb);
REQUIRE(copy.number_of_classes() == 746);
REQUIRE(copy.number_of_generators() == 2);
// the copy uses the "active rules" of kb, of which there are 105 since
// knuth-bendix has already been run.
REQUIRE(copy.number_of_generating_pairs() == 105);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"112" ,
"(cong) const_contains/contains" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
REQUIRE(kb.const_contains({0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1})
== tril::unknown);
REQUIRE(kb.const_contains({0, 0, 0}, {0, 0, 0}) == tril::TRUE );
REQUIRE_THROWS_AS(kb.const_contains({0, 0, 2}, {0, 0, 0}),
LibsemigroupsException);
REQUIRE(kb.const_contains({0, 0, 0}, {0}) == tril::TRUE );
REQUIRE(kb.number_of_classes() == 12);
REQUIRE(kb.const_contains({0, 0, 0}, {1, 1}) == tril::FALSE );
REQUIRE(!kb.contains({0, 0, 0}, {1, 1}));
REQUIRE(kb.contains({0, 0, 0}, {0, 0, 0}));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"113" ,
"(cong) is_quotient_obviously_finite" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
REQUIRE(!kb.is_quotient_obviously_finite());
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"114" ,
"(cong) class_index_to_word" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
REQUIRE(kb.class_index_to_word(0) == word_type({0}));
REQUIRE(kb.class_index_to_word(1) == word_type({1}));
REQUIRE(kb.class_index_to_word(2) == word_type({0, 0}));
REQUIRE(kb.class_index_to_word(3) == word_type({0, 1}));
REQUIRE(kb.class_index_to_word(4) == word_type({1, 0}));
REQUIRE(kb.class_index_to_word(5) == word_type({1, 1}));
REQUIRE(kb.class_index_to_word(6) == word_type({0, 0, 1}));
REQUIRE(kb.class_index_to_word(7) == word_type({0, 1, 1}));
REQUIRE(kb.class_index_to_word(8) == word_type({1, 1, 1}));
REQUIRE(kb.class_index_to_word(9) == word_type({0, 0, 1, 1}));
REQUIRE(kb.class_index_to_word(10) == word_type({0, 1, 1, 1}));
REQUIRE(kb.class_index_to_word(11) == word_type({0, 0, 1, 1, 1}));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"115" ,
"(cong) quotient_froidure_pin" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(2);
kb.add_pair({0, 0, 0}, {0});
kb.add_pair({1, 1, 1, 1}, {1});
kb.add_pair({0, 1, 1, 1, 1, 1, 0, 1, 1}, {1, 1, 0});
REQUIRE(kb.quotient_froidure_pin()->size() == 12);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"116" ,
"(cong) set_number_of_generators" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
REQUIRE_NOTHROW(kb.set_number_of_generators(2));
REQUIRE_THROWS_AS(kb.set_number_of_generators(3), LibsemigroupsException);
REQUIRE_NOTHROW(kb.set_number_of_generators(2));
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"117" ,
"(cong) number of classes when obv-inf" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(3);
kb.add_pair({0, 1}, {1, 0});
kb.add_pair({0, 2}, {2, 0});
kb.add_pair({0, 0}, {0});
kb.add_pair({0, 2}, {0});
kb.add_pair({2, 0}, {0});
kb.add_pair({1, 1}, {1, 1});
kb.add_pair({1, 2}, {2, 1});
kb.add_pair({1, 1, 1}, {1});
kb.add_pair({1, 2}, {1});
kb.add_pair({2, 1}, {1});
kb.add_pair({0}, {1});
REQUIRE(kb.is_quotient_obviously_infinite());
REQUIRE(kb.number_of_classes() == POSITIVE_INFINITY);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"020" ,
"(cong) Chinese monoid" ,
"[quick][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
KnuthBendix kb;
kb.set_number_of_generators(3);
for (auto const & rel : chinese_monoid(3)) {
kb.add_pair(rel.first, rel.second);
}
REQUIRE(kb.is_quotient_obviously_infinite());
REQUIRE(kb.number_of_classes() == POSITIVE_INFINITY);
REQUIRE(kb.number_of_generating_pairs() == 8);
REQUIRE(std::vector<relation_type>(kb.cbegin_generating_pairs(),
kb.cend_generating_pairs())
== std::vector<relation_type>({{{1, 0, 0}, {0, 1, 0}},
{{2, 0, 0}, {0, 2, 0}},
{{1, 1, 0}, {1, 0, 1}},
{{2, 1, 0}, {2, 0, 1}},
{{2, 1, 0}, {1, 2, 0}},
{{2, 2, 0}, {2, 0, 2}},
{{2, 1, 1}, {1, 2, 1}},
{{2, 2, 1}, {2, 1, 2}}}));
REQUIRE(kb.knuth_bendix().number_of_normal_forms(0, 10) == 1175);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"083" ,
"(cong) partial_transformation_monoid4" ,
"[standard][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
size_t n = 4;
auto s = partial_transformation_monoid(n, author::Sutov);
auto p = make<Presentation<word_type>>(s);
p.alphabet(n + 2);
presentation::replace_word(p, word_type({}), {n + 1});
presentation::add_identity_rules(p, n + 1);
KnuthBendix kb;
kb.set_number_of_generators(n + 2);
for (size_t i = 0; i < p.rules.size() - 1; i += 2) {
kb.add_pair(p.rules[i], p.rules[i + 1]);
}
REQUIRE(!kb.is_quotient_obviously_infinite());
REQUIRE(kb.number_of_classes() == 625);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"118" ,
"(cong) partial_transformation_monoid5" ,
"[extreme][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
size_t n = 5;
auto s = partial_transformation_monoid(n, author::Sutov);
auto p = make<Presentation<word_type>>(s);
p.alphabet(n + 2);
presentation::replace_word(p, word_type({}), {n + 1});
presentation::add_identity_rules(p, n + 1);
KnuthBendix kb;
kb.set_number_of_generators(n + 2);
for (size_t i = 0; i < p.rules.size() - 1; i += 2) {
kb.add_pair(p.rules[i], p.rules[i + 1]);
}
REQUIRE(!kb.is_quotient_obviously_infinite());
REQUIRE(kb.number_of_classes() == 7776);
}
LIBSEMIGROUPS_TEST_CASE("KnuthBendix" ,
"119" ,
"(cong) full_transformation_monoid Iwahori" ,
"[extreme][congruence][knuth-bendix][cong]" ) {
auto rg = ReportGuard(REPORT);
size_t n = 5;
auto s = full_transformation_monoid(n, author::Iwahori);
auto p = make<Presentation<word_type>>(s);
p.alphabet(n + 1);
presentation::replace_word(p, word_type({}), {n});
presentation::add_identity_rules(p, n);
KnuthBendix kb;
kb.set_number_of_generators(n + 1);
for (size_t i = 0; i < p.rules.size() - 1; i += 2) {
kb.add_pair(p.rules[i], p.rules[i + 1]);
}
REQUIRE(!kb.is_quotient_obviously_infinite());
REQUIRE(kb.number_of_classes() == 3125);
}
} // namespace congruence
} // namespace libsemigroups
quality 90%
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland