//
// libsemigroups - C++ library for semigroups and monoids
// Copyright (C) 2022 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/ >.
//
#define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
#include <cstddef> // for size_t
#include <iostream> // for cout
#include <algorithm> // for for_each
#include <chrono> // for duration, microsec...
#include <cstddef> // for size_t
#include <cstdint> // for size_t
#include <iostream> // for string, char_traits
#include <iterator> // for advance
#include <string> // for swap, basic_string
#include <type_traits> // for remove_reference<>...
#include <utility> // for move
#include <vector> // for vector, operator==
#include "catch.hpp" // for REQUIRE, REQUIRE_THROWS_AS, REQUI...
#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE
#include "libsemigroups/constants.hpp" // for UNDEFINED
#include "libsemigroups/digraph-helper.hpp" // for make, last_node_on...
#include "libsemigroups/digraph.hpp" // for ActionDigraph, ope...
#include "libsemigroups/exception.hpp" // for LibsemigroupsExcep...
#include "libsemigroups/fpsemi-examples.hpp" // for make, fibonacci_se...
#include "libsemigroups/int-range.hpp" // for IntegralRange<>::v...
#include "libsemigroups/iterator.hpp" // for ConstIteratorState...
#include "libsemigroups/order.hpp" // for LexicographicalCom...
#include "libsemigroups/present.hpp" // for add_rule_and_check
#include "libsemigroups/report.hpp" // for ReportGuard
#include "libsemigroups/stephen.hpp" // for Stephen, Stephen::...
#include "libsemigroups/todd-coxeter-digraph.hpp" // for ToddCoxeterDigraph
#include "libsemigroups/types.hpp" // for word_type
#include "libsemigroups/word.hpp" // for StringToWord, word...
namespace libsemigroups {
namespace {
void check_000(Stephen& s) {
s.set_word({0}).run();
REQUIRE(s.word_graph().number_of_nodes() == 2);
REQUIRE(s.word_graph()
== action_digraph_helper::make<size_t>(
2, {{1, UNDEFINED}, {UNDEFINED, 1}}));
REQUIRE(stephen::number_of_words_accepted(s) == POSITIVE_INFINITY);
{
auto first = stephen::cbegin_words_accepted(s);
auto last = stephen::cbegin_words_accepted(s);
std::advance(last, 10);
REQUIRE(std::vector<word_type>(first, last)
== std::vector<word_type>({{0},
{0, 1},
{0, 1, 1},
{0, 1, 1, 1},
{0, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1}}));
}
{
auto first = stephen::cbegin_left_factors(s);
auto last = stephen::cbegin_left_factors(s);
std::advance(last, 10);
REQUIRE(std::vector<word_type>(first, last)
== std::vector<word_type>({{},
{0},
{0, 1},
{0, 1, 1},
{0, 1, 1, 1},
{0, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1, 1}}));
}
}
void verify_c4_normal_form(Presentation<std::string> const & p,
std::string const & word,
std::string const & nf) {
detail::StringToWord string_to_word(p.alphabet());
Stephen S(p);
S.set_word(string_to_word(word)).run();
auto words = std::vector<word_type>(stephen::cbegin_words_accepted(S),
stephen::cend_words_accepted(S));
std::vector<std::string> strings(words.size(), "" );
std::transform(
words.cbegin(), words.cend(), strings.begin(), [&p](auto const & w) {
return detail::word_to_string(p.alphabet(), w.cbegin(), w.cend());
});
std::sort(strings.begin(),
strings.end(),
LexicographicalCompare<std::string>());
REQUIRE(strings.front() == nf);
REQUIRE(std::all_of(strings.cbegin(),
strings.cend(),
[&S, &string_to_word](auto const & w) {
return stephen::accepts(S, string_to_word(w));
}));
REQUIRE(stephen::number_of_words_accepted(S) == strings.size());
}
void verify_c4_equal_to(Presentation<std::string> const & p,
std::string const & word1,
std::string const & word2) {
detail::StringToWord string_to_word(p.alphabet());
Stephen S(p);
S.set_word(string_to_word(word1)).run();
REQUIRE(stephen::accepts(S, string_to_word(word2)));
S.set_word(string_to_word(word2)).run();
REQUIRE(stephen::accepts(S, string_to_word(word1)));
}
void verify_c4_not_equal_to(Presentation<std::string> const & p,
std::string const & word1,
std::string const & word2) {
detail::StringToWord string_to_word(p.alphabet());
Stephen S(p);
S.set_word(string_to_word(word1)).run();
REQUIRE(!stephen::accepts(S, string_to_word(word2)));
S.set_word(string_to_word(word2)).run();
REQUIRE(!stephen::accepts(S, string_to_word(word1)));
}
} // namespace
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"000" ,
"basic test 1" ,
"[quick][stephen]" ) {
auto rg = ReportGuard(true );
Presentation<word_type> p;
p.alphabet(2);
presentation::add_rule_and_check(p, {0}, {0, 1});
Stephen s;
s.init(p);
check_000(s);
s.init(p);
check_000(s);
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"001" ,
"basic test 2" ,
"[quick][stephen]" ) {
auto rg = ReportGuard(true );
Presentation<word_type> p;
p.alphabet(2);
presentation::add_rule_and_check(p, {0, 0, 0}, {0});
presentation::add_rule_and_check(p, {1, 1, 1}, {1});
presentation::add_rule_and_check(p, {0, 1, 0, 1}, {0, 0});
Stephen s(p);
s.set_word({1, 1, 0, 1}).run();
REQUIRE(s.word_graph().number_of_nodes() == 7);
REQUIRE(s.word_graph()
== action_digraph_helper::make<size_t>(7,
{{UNDEFINED, 1},
{UNDEFINED, 2},
{3, 1},
{4, 5},
{3, 6},
{6, 3},
{5, 4}}));
REQUIRE(stephen::number_of_words_accepted(s) == POSITIVE_INFINITY);
word_type w = {1, 1, 0, 1};
REQUIRE(action_digraph_helper::last_node_on_path_nc(
s.word_graph(), 0, w.begin(), w.end())
.first
== 5);
w = {1, 1, 0, 0, 1, 0};
REQUIRE(action_digraph_helper::last_node_on_path_nc(
s.word_graph(), 0, w.begin(), w.end())
.first
== 5);
REQUIRE(stephen::accepts(s, {1, 1, 0, 0, 1, 0}));
REQUIRE(stephen::accepts(s, {1, 1, 0, 0, 1, 0}));
REQUIRE(!stephen::accepts(s, {}));
REQUIRE(!stephen::accepts(s, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
REQUIRE(!stephen::accepts(s, {1, 1, 1}));
{
auto first = stephen::cbegin_words_accepted(s);
auto last = stephen::cbegin_words_accepted(s);
std::advance(last, 10);
REQUIRE(std::vector<word_type>(first, last)
== std::vector<word_type>({{1, 1, 0, 1},
{1, 1, 0, 0, 0, 1},
{1, 1, 0, 0, 1, 0},
{1, 1, 0, 1, 0, 0},
{1, 1, 0, 1, 1, 1},
{1, 1, 1, 1, 0, 1},
{1, 1, 0, 0, 0, 0, 0, 1},
{1, 1, 0, 0, 0, 0, 1, 0},
{1, 1, 0, 0, 0, 1, 0, 0},
{1, 1, 0, 0, 0, 1, 1, 1}}));
}
{
auto first = stephen::cbegin_left_factors(s);
auto last = stephen::cbegin_left_factors(s);
std::advance(last, 10);
REQUIRE(std::vector<word_type>(first, last)
== std::vector<word_type>({{},
{1},
{1, 1},
{1, 1, 0},
{1, 1, 1},
{1, 1, 0, 0},
{1, 1, 0, 1},
{1, 1, 1, 1},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 1}}));
REQUIRE(stephen::number_of_left_factors(s) == POSITIVE_INFINITY);
std::for_each(first, last, [&s](auto const & w) {
return stephen::is_left_factor(s, w);
});
}
s.set_word({0, 0}).run();
REQUIRE(s.word_graph().number_of_nodes() == 5);
REQUIRE(s.word_graph()
== action_digraph_helper::make<size_t>(
5, {{1, UNDEFINED}, {2, 3}, {1, 4}, {4, 1}, {3, 2}}));
p.rules.clear();
presentation::add_rule_and_check(p, {0, 0, 0}, {0});
presentation::add_rule_and_check(p, {1, 1, 1}, {1});
s.init(p).set_word({0, 0}).run();
REQUIRE(s.word_graph().number_of_nodes() == 3);
REQUIRE(s.word_graph()
== action_digraph_helper::make<size_t>(
3, {{1, UNDEFINED}, {2, UNDEFINED}, {1, UNDEFINED}}));
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"002" ,
"full transf monoid" ,
"[quick][stephen]" ) {
using namespace fpsemigroup;
auto rg = ReportGuard(true );
size_t n = 5;
auto p = make<Presentation<word_type>>(
full_transformation_monoid(n, author::Iwahori));
presentation::replace_word(p, {}, {n});
p.alphabet(n + 1);
presentation::add_identity_rules(p, n);
p.validate();
Stephen s;
s.init(std::move(p)).set_word({0, 1, 0, 1, 1, 1, 0, 2, 0, 1, 2, 0}).run();
REQUIRE(s.word_graph().number_of_nodes() == 121);
REQUIRE(s.word_graph()
== action_digraph_helper::make<size_t>(
121, {{1, 2, 3, 4, UNDEFINED, 5},
{5, 6, 7, 8, UNDEFINED, 1},
{9, 5, 10, 11, UNDEFINED, 2},
{12, 13, 5, 14, UNDEFINED, 3},
{15, 16, 17, 5, UNDEFINED, 4},
{1, 2, 3, 4, UNDEFINED, 5},
{18, 1, 19, 20, UNDEFINED, 6},
{21, 22, 1, 23, UNDEFINED, 7},
{24, 25, 26, 1, UNDEFINED, 8},
{2, 18, 27, 28, UNDEFINED, 9},
{29, 30, 2, 31, UNDEFINED, 10},
{32, 33, 34, 2, UNDEFINED, 11},
{3, 35, 21, 36, UNDEFINED, 12},
{37, 3, 30, 38, UNDEFINED, 13},
{39, 40, 41, 3, UNDEFINED, 14},
{4, 42, 43, 24, UNDEFINED, 15},
{44, 4, 45, 33, UNDEFINED, 16},
{46, 47, 4, 41, UNDEFINED, 17},
{6, 9, 48, 49, UNDEFINED, 18},
{50, 51, 6, 52, UNDEFINED, 19},
{53, 54, 55, 6, UNDEFINED, 20},
{7, 56, 12, 57, UNDEFINED, 21},
{58, 7, 51, 59, UNDEFINED, 22},
{60, 61, 62, 7, UNDEFINED, 23},
{8, 63, 64, 15, UNDEFINED, 24},
{65, 8, 66, 54, UNDEFINED, 25},
{67, 68, 8, 62, UNDEFINED, 26},
{56, 58, 9, 69, UNDEFINED, 27},
{63, 65, 70, 9, UNDEFINED, 28},
{10, 50, 56, 71, UNDEFINED, 29},
{51, 10, 13, 72, UNDEFINED, 30},
{73, 74, 75, 10, UNDEFINED, 31},
{11, 53, 76, 63, UNDEFINED, 32},
{54, 11, 77, 16, UNDEFINED, 33},
{78, 79, 11, 75, UNDEFINED, 34},
{48, 12, 50, 80, UNDEFINED, 35},
{64, 81, 67, 12, UNDEFINED, 36},
{13, 48, 58, 82, UNDEFINED, 37},
{83, 77, 79, 13, UNDEFINED, 38},
{14, 84, 60, 64, UNDEFINED, 39},
{85, 14, 74, 77, UNDEFINED, 40},
{62, 75, 14, 17, UNDEFINED, 41},
{49, 15, 86, 53, UNDEFINED, 42},
{57, 87, 15, 60, UNDEFINED, 43},
{16, 49, 88, 65, UNDEFINED, 44},
{89, 72, 16, 74, UNDEFINED, 45},
{17, 90, 57, 67, UNDEFINED, 46},
{91, 17, 72, 79, UNDEFINED, 47},
{35, 37, 18, 92, UNDEFINED, 48},
{42, 44, 93, 18, UNDEFINED, 49},
{19, 29, 35, 94, UNDEFINED, 50},
{30, 19, 22, 95, UNDEFINED, 51},
{96, 97, 98, 19, UNDEFINED, 52},
{20, 32, 99, 42, UNDEFINED, 53},
{33, 20, 100, 25, UNDEFINED, 54},
{101, 102, 20, 98, UNDEFINED, 55},
{27, 21, 29, 103, UNDEFINED, 56},
{43, 104, 46, 21, UNDEFINED, 57},
{22, 27, 37, 105, UNDEFINED, 58},
{106, 100, 102, 22, UNDEFINED, 59},
{23, 107, 39, 43, UNDEFINED, 60},
{108, 23, 97, 100, UNDEFINED, 61},
{41, 98, 23, 26, UNDEFINED, 62},
{28, 24, 109, 32, UNDEFINED, 63},
{36, 110, 24, 39, UNDEFINED, 64},
{25, 28, 111, 44, UNDEFINED, 65},
{112, 95, 25, 97, UNDEFINED, 66},
{26, 113, 36, 46, UNDEFINED, 67},
{114, 26, 95, 102, UNDEFINED, 68},
{107, 108, 115, 27, UNDEFINED, 69},
{113, 114, 28, 115, UNDEFINED, 70},
{109, 112, 113, 29, UNDEFINED, 71},
{116, 45, 47, 30, UNDEFINED, 72},
{31, 96, 107, 109, UNDEFINED, 73},
{97, 31, 40, 45, UNDEFINED, 74},
{115, 41, 31, 34, UNDEFINED, 75},
{103, 106, 32, 107, UNDEFINED, 76},
{117, 38, 33, 40, UNDEFINED, 77},
{34, 101, 103, 113, UNDEFINED, 78},
{102, 34, 38, 47, UNDEFINED, 79},
{99, 117, 101, 35, UNDEFINED, 80},
{111, 36, 112, 117, UNDEFINED, 81},
{110, 111, 114, 37, UNDEFINED, 82},
{38, 99, 106, 110, UNDEFINED, 83},
{92, 39, 96, 99, UNDEFINED, 84},
{40, 92, 108, 111, UNDEFINED, 85},
{94, 116, 42, 96, UNDEFINED, 86},
{105, 43, 116, 106, UNDEFINED, 87},
{104, 105, 44, 108, UNDEFINED, 88},
{45, 94, 104, 112, UNDEFINED, 89},
{93, 46, 94, 101, UNDEFINED, 90},
{47, 93, 105, 114, UNDEFINED, 91},
{84, 85, 118, 48, UNDEFINED, 92},
{90, 91, 49, 118, UNDEFINED, 93},
{86, 89, 90, 50, UNDEFINED, 94},
{119, 66, 68, 51, UNDEFINED, 95},
{52, 73, 84, 86, UNDEFINED, 96},
{74, 52, 61, 66, UNDEFINED, 97},
{118, 62, 52, 55, UNDEFINED, 98},
{80, 83, 53, 84, UNDEFINED, 99},
{120, 59, 54, 61, UNDEFINED, 100},
{55, 78, 80, 90, UNDEFINED, 101},
{79, 55, 59, 68, UNDEFINED, 102},
{76, 120, 78, 56, UNDEFINED, 103},
{88, 57, 89, 120, UNDEFINED, 104},
{87, 88, 91, 58, UNDEFINED, 105},
{59, 76, 83, 87, UNDEFINED, 106},
{69, 60, 73, 76, UNDEFINED, 107},
{61, 69, 85, 88, UNDEFINED, 108},
{71, 119, 63, 73, UNDEFINED, 109},
{82, 64, 119, 83, UNDEFINED, 110},
{81, 82, 65, 85, UNDEFINED, 111},
{66, 71, 81, 89, UNDEFINED, 112},
{70, 67, 71, 78, UNDEFINED, 113},
{68, 70, 82, 91, UNDEFINED, 114},
{75, 118, 69, 70, UNDEFINED, 115},
{72, 86, 87, 119, UNDEFINED, 116},
{77, 80, 120, 81, UNDEFINED, 117},
{98, 115, 92, 93, UNDEFINED, 118},
{95, 109, 110, 116, UNDEFINED, 119},
{100, 103, 117, 104, UNDEFINED, 120}}));
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"003" ,
"from step_hen 002" ,
"[quick][stephen]" ) {
Presentation<std::string> p;
p.alphabet("ab" );
presentation::add_rule_and_check(p, "aaa" , "a" );
presentation::add_rule_and_check(p, "bbb" , "b" );
presentation::add_rule_and_check(p, "abab" , "aa" );
Stephen S(p);
detail::StringToWord string_to_word("ab" );
S.set_word(string_to_word("bbab" ));
REQUIRE(stephen::accepts(S, string_to_word("bbaaba" )));
REQUIRE(!stephen::accepts(S, string_to_word("" )));
REQUIRE(!stephen::accepts(S, string_to_word("aaaaaaaaaa" )));
REQUIRE(!stephen::accepts(S, string_to_word("bbb" )));
S.set_word(string_to_word("bba" ));
REQUIRE(stephen::accepts(S, string_to_word("bbabb" )));
REQUIRE(stephen::accepts(S, string_to_word("bba" )));
REQUIRE(!stephen::accepts(S, string_to_word("bbb" )));
REQUIRE(!stephen::accepts(S, string_to_word("a" )));
REQUIRE(!stephen::accepts(S, string_to_word("ab" )));
S.set_word(string_to_word("bbaab" ));
REQUIRE(stephen::accepts(S, string_to_word("bbaba" )));
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"004" ,
"from step_hen 003" ,
"[quick][stephen]" ) {
Presentation<std::string> p;
p.alphabet("abcdefg" );
presentation::add_rule_and_check(p, "aaaeaa" , "abcd" );
presentation::add_rule_and_check(p, "ef" , "dg" );
Stephen S(p);
detail::StringToWord string_to_word("abcdefg" );
S.set_word(string_to_word("abcef" )).run();
REQUIRE(string_to_word("abcef" ) == word_type({0, 1, 2, 4, 5}));
REQUIRE(S.word_graph()
== action_digraph_helper::make<size_t>(
11,
{{1,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED},
{2, 3, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED},
{4,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED},
{UNDEFINED,
UNDEFINED,
5,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED},
{UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
6,
UNDEFINED,
UNDEFINED},
{UNDEFINED, UNDEFINED, UNDEFINED, 7, 8, UNDEFINED, UNDEFINED},
{9,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED},
{UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
10},
{UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
10,
UNDEFINED},
{7,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED},
{UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED,
UNDEFINED}}));
auto rule = string_to_word(p.rules[0]);
auto m = action_digraph_helper::last_node_on_path(
S.word_graph(), 0, rule.cbegin(), rule.cend())
.first;
rule = string_to_word(p.rules[1]);
auto n = action_digraph_helper::last_node_on_path(
S.word_graph(), 0, rule.cbegin(), rule.cend())
.first;
REQUIRE(m != UNDEFINED);
REQUIRE(n != UNDEFINED);
REQUIRE(m == n);
REQUIRE(S.word_graph().number_of_nodes() == 11);
REQUIRE(stephen::accepts(S, string_to_word("aaaeaag" )));
REQUIRE(stephen::number_of_words_accepted(S) == 3);
REQUIRE(std::vector<word_type>(stephen::cbegin_words_accepted(S),
stephen::cend_words_accepted(S))
== std::vector<word_type>(
{{0, 1, 2, 3, 6}, {0, 1, 2, 4, 5}, {0, 0, 0, 4, 0, 0, 6}}));
S.set_word(string_to_word("aaaeaaaeaa" )).run();
REQUIRE(S.word_graph().number_of_nodes() == 15);
REQUIRE(stephen::number_of_words_accepted(S) == 3);
REQUIRE(stephen::accepts(S, string_to_word("aaaeabcd" )));
REQUIRE(std::vector<word_type>(stephen::cbegin_words_accepted(S),
stephen::cend_words_accepted(S))
== std::vector<word_type>({{0, 0, 0, 4, 0, 1, 2, 3},
{0, 1, 2, 3, 0, 4, 0, 0},
{0, 0, 0, 4, 0, 0, 0, 4, 0, 0}}));
S.set_word(string_to_word("aaaeaag" )).run();
REQUIRE(S.word_graph().number_of_nodes() == 11);
REQUIRE(stephen::number_of_words_accepted(S) == 3);
REQUIRE(std::vector<word_type>(stephen::cbegin_words_accepted(S),
stephen::cend_words_accepted(S))
== std::vector<word_type>(
{{0, 1, 2, 3, 6}, {0, 1, 2, 4, 5}, {0, 0, 0, 4, 0, 0, 6}}));
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"005" ,
"from step_hen 004" ,
"[quick][stephen]" ) {
Presentation<std::string> p;
p.alphabet("abc" );
presentation::add_rule_and_check(p, "ab" , "ba" );
presentation::add_rule_and_check(p, "ac" , "cc" );
presentation::add_rule_and_check(p, "ac" , "a" );
presentation::add_rule_and_check(p, "cc" , "a" );
presentation::add_rule_and_check(p, "bc" , "cc" );
presentation::add_rule_and_check(p, "bcc" , "b" );
presentation::add_rule_and_check(p, "bc" , "b" );
presentation::add_rule_and_check(p, "cc" , "b" );
presentation::add_rule_and_check(p, "a" , "b" );
Stephen S(p);
detail::StringToWord string_to_word("abc" );
S.set_word(string_to_word("abcc" )).run();
REQUIRE(stephen::accepts(S, string_to_word("baac" )));
REQUIRE(S.word_graph().number_of_nodes() == 3);
REQUIRE(stephen::number_of_words_accepted(S) == POSITIVE_INFINITY);
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"006" ,
"from step_hen 005" ,
"[quick][stephen]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "bb" , "c" );
presentation::add_rule_and_check(p, "caca" , "abab" );
presentation::add_rule_and_check(p, "bc" , "d" );
presentation::add_rule_and_check(p, "cb" , "d" );
presentation::add_rule_and_check(p, "aa" , "d" );
presentation::add_rule_and_check(p, "ad" , "a" );
presentation::add_rule_and_check(p, "da" , "a" );
presentation::add_rule_and_check(p, "bd" , "b" );
presentation::add_rule_and_check(p, "db" , "b" );
presentation::add_rule_and_check(p, "cd" , "c" );
presentation::add_rule_and_check(p, "dc" , "c" );
Stephen S(p);
detail::StringToWord string_to_word("abcd" );
S.set_word(string_to_word("dabdaaadabab" )).run();
REQUIRE(stephen::accepts(S, string_to_word("abdadcaca" )));
REQUIRE(S.word_graph().number_of_nodes() == 25);
REQUIRE(stephen::number_of_words_accepted(S) == POSITIVE_INFINITY);
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"007" ,
"Fibonacci(4, 6)" ,
"[stephen][extreme]" ) {
using namespace fpsemigroup;
auto rg = ReportGuard(true );
auto p = make<Presentation<word_type>>(fibonacci_semigroup(4, 6));
Stephen S(p);
S.set_word({0, 1, 2, 3}).run_for(std::chrono::seconds(10));
REQUIRE(!S.finished());
}
LIBSEMIGROUPS_TEST_CASE(
"Stephen" ,
"008" ,
"C(4) monoid normal form (test_case_knuth_bendix_055)" ,
"[stephen][quick]" ) {
auto rg = ReportGuard(false );
Presentation<std::string> p;
p.alphabet("abcdefg" );
presentation::add_rule_and_check(p, "abcd" , "ce" );
presentation::add_rule_and_check(p, "df" , "dg" );
detail::StringToWord string_to_word("abcdefg" );
Stephen S(p);
S.set_word(string_to_word("dfabcdf" )).run();
REQUIRE(S.word_graph().number_of_nodes() == 9);
REQUIRE(stephen::number_of_words_accepted(S) == 8);
auto words = std::vector<word_type>(stephen::cbegin_words_accepted(S),
stephen::cend_words_accepted(S));
std::vector<std::string> strings(words.size(), "" );
std::transform(
words.cbegin(), words.cend(), strings.begin(), [&p](auto const & w) {
return detail::word_to_string(p.alphabet(), w.cbegin(), w.cend());
});
REQUIRE(strings
== std::vector<std::string>({"dfcef" ,
"dfceg" ,
"dgcef" ,
"dgceg" ,
"dfabcdf" ,
"dfabcdg" ,
"dgabcdf" ,
"dgabcdg" }));
std::sort(
strings.begin(), strings.end(), LexicographicalCompare<std::string>());
REQUIRE(strings.front() == "dfabcdf" );
REQUIRE(std::all_of(
strings.cbegin(), strings.cend(), [&S, &string_to_word](auto const & w) {
return stephen::accepts(S, string_to_word(w));
}));
REQUIRE(stephen::number_of_words_accepted(S) == strings.size());
S.set_word(string_to_word("abcdfceg" )).run();
REQUIRE(stephen::number_of_words_accepted(S) == 16);
words = std::vector<word_type>(stephen::cbegin_words_accepted(S),
stephen::cend_words_accepted(S));
strings.resize(stephen::number_of_words_accepted(S));
std::transform(
words.cbegin(), words.cend(), strings.begin(), [&p](auto const & w) {
return detail::word_to_string(p.alphabet(), w.cbegin(), w.cend());
});
std::sort(
strings.begin(), strings.end(), LexicographicalCompare<std::string>());
REQUIRE(strings
== std::vector<std::string>({"abcdfabcdf" ,
"abcdfabcdg" ,
"abcdfcef" ,
"abcdfceg" ,
"abcdgabcdf" ,
"abcdgabcdg" ,
"abcdgcef" ,
"abcdgceg" ,
"cefabcdf" ,
"cefabcdg" ,
"cefcef" ,
"cefceg" ,
"cegabcdf" ,
"cegabcdg" ,
"cegcef" ,
"cegceg" }));
REQUIRE(strings.front() == "abcdfabcdf" );
REQUIRE(stephen::accepts(S, string_to_word("abcdfabcdf" )));
}
LIBSEMIGROUPS_TEST_CASE(
"Stephen" ,
"009" ,
"C(4) monoid normal form (test_case_gap_smalloverlap_85)" ,
"[stephen][quick]" ) {
auto rg = ReportGuard(false );
Presentation<std::string> p;
p.alphabet("cab" );
presentation::add_rule_and_check(p, "aabc" , "acba" );
detail::StringToWord string_to_word("cab" );
Stephen S(p);
S.set_word(string_to_word("a" )).run();
REQUIRE(!stephen::accepts(S, string_to_word("b" )));
S.set_word(string_to_word("aabcabc" )).run();
REQUIRE(stephen::accepts(S, string_to_word("aabccba" )));
S.set_word(string_to_word("aabccba" )).run();
REQUIRE(stephen::accepts(S, string_to_word("aabcabc" )));
S.set_word(string_to_word("acba" )).run();
auto words = std::vector<word_type>(stephen::cbegin_words_accepted(S),
stephen::cend_words_accepted(S));
std::vector<std::string> strings(words.size(), "" );
std::transform(
words.cbegin(), words.cend(), strings.begin(), [&p](auto const & w) {
return detail::word_to_string(p.alphabet(), w.cbegin(), w.cend());
});
REQUIRE(strings == std::vector<std::string>({"acba" , "aabc" }));
verify_c4_normal_form(p, "acba" , "aabc" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"010" ,
"code coverage" ,
"[stephen][quick]" ) {
auto rg = ReportGuard(true );
Presentation<std::string> p;
REQUIRE_THROWS_AS(Stephen(p), LibsemigroupsException);
p.alphabet("abcdefg" );
detail::StringToWord string_to_word("abcdefg" );
Stephen S(p);
auto w = string_to_word("abbbddbcbcbc" );
S.set_word(w);
S.run();
REQUIRE(S.finished());
S.run();
S.set_word(string_to_word("abbbddbcbcbc" )); // resets
S.report_every(std::chrono::microseconds(10));
S.run();
Stephen T(S);
REQUIRE(stephen::accepts(T, w));
REQUIRE(!stephen::accepts(T, string_to_word("abbbd" )));
REQUIRE(stephen::number_of_words_accepted(T) == 1);
REQUIRE(stephen::number_of_left_factors(T) == w.size() + 1);
REQUIRE(stephen::accepts(S, w));
REQUIRE(!stephen::accepts(S, string_to_word("abbbd" )));
REQUIRE(stephen::number_of_words_accepted(S) == 1);
REQUIRE(stephen::number_of_left_factors(S) == w.size() + 1);
Stephen U(std::move(S));
REQUIRE(stephen::accepts(U, w));
REQUIRE(!stephen::accepts(U, string_to_word("abbbd" )));
REQUIRE(stephen::number_of_words_accepted(U) == 1);
REQUIRE(stephen::number_of_left_factors(U) == w.size() + 1);
S = T;
REQUIRE(stephen::accepts(T, w));
REQUIRE(!stephen::accepts(T, string_to_word("abbbd" )));
REQUIRE(stephen::number_of_words_accepted(T) == 1);
REQUIRE(stephen::number_of_left_factors(T) == w.size() + 1);
REQUIRE(stephen::accepts(S, w));
REQUIRE(!stephen::accepts(S, string_to_word("abbbd" )));
REQUIRE(stephen::number_of_words_accepted(S) == 1);
REQUIRE(stephen::number_of_left_factors(S) == w.size() + 1);
Stephen V;
V = std::move(S);
REQUIRE(stephen::accepts(V, w));
REQUIRE(!stephen::accepts(V, string_to_word("abbbd" )));
REQUIRE(stephen::number_of_words_accepted(V) == 1);
REQUIRE(stephen::number_of_left_factors(V) == w.size() + 1);
REQUIRE(V.word() == w);
REQUIRE(V.accept_state() == 12);
}
LIBSEMIGROUPS_TEST_CASE(
"Stephen" ,
"011" ,
"C(4) monoid normal form (test_case_gap_smalloverlap_49)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcdefgh" );
presentation::add_rule_and_check(p, "abcd" , "ce" );
presentation::add_rule_and_check(p, "df" , "hd" );
verify_c4_equal_to(p, "abchd" , "abcdf" );
verify_c4_equal_to(p, "abchd" , "abchd" );
verify_c4_equal_to(p, "abchdf" , "abchhd" );
verify_c4_equal_to(p, "abchd" , "cef" );
verify_c4_equal_to(p, "cef" , "abchd" );
verify_c4_not_equal_to(p, "abchf" , "abcdf" );
verify_c4_equal_to(p, "hdfabce" , "dffababcd" );
verify_c4_normal_form(p, "hdfabce" , "dffababcd" );
}
LIBSEMIGROUPS_TEST_CASE(
"Stephen" ,
"012" ,
"C(4) monoid normal form (test_case_gap_smalloverlap_63)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcdefgh" );
presentation::add_rule_and_check(p, "afh" , "bgh" );
presentation::add_rule_and_check(p, "hc" , "d" );
verify_c4_equal_to(p, "afd" , "bgd" );
verify_c4_equal_to(p, "bghcafhbgd" , "afdafhafd" );
verify_c4_normal_form(p, "bghcafhbgd" , "afdafhafd" );
}
LIBSEMIGROUPS_TEST_CASE(
"Stephen" ,
"013" ,
"C(4) monoid equal to (test_case_gap_smalloverlap_70)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcdefghij" );
presentation::add_rule_and_check(p, "afh" , "bgh" );
presentation::add_rule_and_check(p, "hc" , "de" );
presentation::add_rule_and_check(p, "ei" , "j" );
verify_c4_equal_to(p, "afdj" , "bgdj" );
verify_c4_not_equal_to(p, "xxxxxxxxxxxxxxxxxxxxxxx" , "b" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"014" ,
"C(4) monoid normal form (test_case_ex_3_13_14)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "abbba" , "cdc" );
verify_c4_normal_form(p, "cdcdcabbbabbbabbcd" , "abbbadcabbbabbbabbcd" );
verify_c4_equal_to(p, "cdcdcabbbabbbabbcd" , "abbbadcabbbabbbabbcd" );
verify_c4_equal_to(p, "abbbadcbbba" , "cdabbbcdc" );
verify_c4_equal_to(p, "cdabbbcdc" , "cdabbbcdc" );
verify_c4_normal_form(p, "cdabbbcdc" , "abbbadcbbba" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"015" ,
"C(4) monoid normal form (test_case_ex_3_15)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "aabc" , "acba" );
std::string original = "cbacbaabcaabcacbacba" ;
std::string expected = "cbaabcabcaabcaabcabc" ;
verify_c4_equal_to(p, "cbaabcabcaabcaabccba" , original);
verify_c4_equal_to(p, original, expected);
verify_c4_equal_to(p, expected, original);
verify_c4_equal_to(p, "cbaabcabcaabcaabccba" , expected);
verify_c4_equal_to(p, original, "cbaabcabcaabcaabccba" );
verify_c4_equal_to(p, expected, "cbaabcabcaabcaabccba" );
verify_c4_normal_form(p, original, expected);
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"016" ,
"C(4) monoid normal form (test_case_ex_3_16)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "abcd" , "acca" );
std::string original = "bbcabcdaccaccabcddd" ;
std::string expected = "bbcabcdabcdbcdbcddd" ;
verify_c4_equal_to(p, original, expected);
verify_c4_equal_to(p, expected, original);
verify_c4_normal_form(p, original, expected);
verify_c4_normal_form(p, expected, expected);
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"017" ,
"C(4) monoid normal form (test_case_mt_3)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "abcd" , "accca" );
verify_c4_normal_form(p, "bbcabcdaccaccabcddd" , "bbcabcdaccaccabcddd" );
verify_c4_equal_to(p, "bbcabcdaccaccabcddd" , "bbcabcdaccaccabcddd" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"018" ,
"C(4) monoid normal form (test_case_mt_5)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abc" );
presentation::add_rule_and_check(p, "ac" , "cbbbbc" );
verify_c4_normal_form(p, "acbbbbc" , "aac" );
verify_c4_equal_to(p, "acbbbbc" , "aac" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"019" ,
"C(4) monoid normal form (test_case_mt_6)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abc" );
presentation::add_rule_and_check(p, "ccab" , "cbac" );
verify_c4_normal_form(p, "bacbaccabccabcbacbac" , "bacbacbaccbaccbacbac" );
verify_c4_equal_to(p, "bacbaccabccabcbacbac" , "bacbacbaccbaccbacbac" );
verify_c4_normal_form(p, "ccabcbaccab" , "cbaccbacbac" );
verify_c4_equal_to(p, "ccabcbaccab" , "cbaccbacbac" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"020" ,
"C(4) monoid normal form (test_case_mt_10)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcdefghij" );
presentation::add_rule_and_check(p, "afh" , "bgh" );
presentation::add_rule_and_check(p, "hc" , "de" );
presentation::add_rule_and_check(p, "ei" , "j" );
verify_c4_normal_form(p, "bgdj" , "afdei" );
verify_c4_equal_to(p, "bgdj" , "afdei" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"021" ,
"C(4) monoid normal form (test_case_mt_13)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "abcd" , "dcba" );
verify_c4_normal_form(p, "dcbdcba" , "abcdbcd" );
verify_c4_equal_to(p, "dcbdcba" , "abcdbcd" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"022" ,
"C(4) monoid normal form (test_case_mt_14)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "abca" , "dcbd" );
verify_c4_normal_form(p, "dcbabca" , "abcacbd" );
verify_c4_equal_to(p, "dcbabca" , "abcacbd" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"023" ,
"C(4) monoid normal form (test_case_mt_15)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "abcd" , "dcba" );
presentation::add_rule_and_check(p, "adda" , "dbbd" );
verify_c4_normal_form(p, "dbbabcd" , "addacba" );
verify_c4_equal_to(p, "dbbabcd" , "addacba" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"024" ,
"C(4) monoid normal form (test_case_mt_16)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcdefg" );
presentation::add_rule_and_check(p, "abcd" , "acca" );
presentation::add_rule_and_check(p, "gf" , "ge" );
verify_c4_normal_form(p, "accabcdgf" , "abcdbcdge" );
verify_c4_equal_to(p, "accabcdgf" , "abcdbcdge" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"025" ,
"C(4) monoid normal form (test_case_mt_17)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(
p, "ababbabbbabbbb" , "abbbbbabbbbbbabbbbbbbabbbbbbbb" );
presentation::add_rule_and_check(
p, "cdcddcdddcdddd" , "cdddddcddddddcdddddddcdddddddd" );
verify_c4_normal_form(
p, "abbbacdddddcddddddcdddddddcdddddddd" , "abbbacdcddcdddcdddd" );
verify_c4_equal_to(
p, "abbbacdddddcddddddcdddddddcdddddddd" , "abbbacdcddcdddcdddd" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"026" ,
"C(4) monoid normal form (test_case_weak_1)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "acba" , "aabc" );
presentation::add_rule_and_check(p, "acba" , "dbbbd" );
verify_c4_equal_to(p, "aaabc" , "adbbbd" );
verify_c4_equal_to(p, "adbbbd" , "aaabc" );
verify_c4_equal_to(p, "aaabcadbbbd" , "adbbbdadbbbd" );
verify_c4_equal_to(p, "aaabcaaabc" , "adbbbdadbbbd" );
verify_c4_equal_to(p, "acba" , "dbbbd" );
verify_c4_equal_to(p, "acbabbbd" , "aabcbbbd" );
verify_c4_equal_to(p, "aabcbbbd" , "acbabbbd" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"027" ,
"C(4) monoid normal form (test_case_weak_2)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "acba" , "aabc" );
presentation::add_rule_and_check(p, "acba" , "adbd" );
verify_c4_equal_to(p, "acbacba" , "aabcabc" );
verify_c4_normal_form(p, "acbacba" , "aabcabc" );
verify_c4_equal_to(p, "aabcabc" , "acbacba" );
verify_c4_normal_form(p, "aabcabc" , "aabcabc" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"028" ,
"C(4) monoid normal form (test_case_weak_3)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcde" );
presentation::add_rule_and_check(p, "bceac" , "aeebbc" );
presentation::add_rule_and_check(p, "aeebbc" , "dabcd" );
verify_c4_normal_form(p, "bceacdabcd" , "aeebbcaeebbc" );
verify_c4_normal_form(p, "aeebbcaeebbc" , "aeebbcaeebbc" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"029" ,
"C(4) monoid normal form (test_case_weak_4)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "acba" , "aabc" );
presentation::add_rule_and_check(p, "acba" , "dbbd" );
verify_c4_normal_form(p, "bbacbcaaabcbbd" , "bbacbcaaabcbbd" );
verify_c4_normal_form(p, "acbacba" , "aabcabc" );
verify_c4_normal_form(p, "aabcabc" , "aabcabc" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"030" ,
"C(4) monoid normal form (test_case_weak_5)" ,
"[stephen][quick]" ) {
Presentation<std::string> p;
p.alphabet("abcd" );
presentation::add_rule_and_check(p, "acba" , "aabc" );
presentation::add_rule_and_check(p, "acba" , "adbd" );
verify_c4_normal_form(p, "acbacba" , "aabcabc" );
verify_c4_normal_form(p, "aabcabc" , "aabcabc" );
}
LIBSEMIGROUPS_TEST_CASE("Stephen" ,
"031" ,
"Test behaviour when uninitialised" ,
"[stephen][quick]" ) {
Stephen S;
REQUIRE_THROWS_AS(S.accept_state(), LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::cbegin_words_accepted(S),
LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::cend_words_accepted(S), LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::cbegin_left_factors(S), LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::cend_left_factors(S), LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::is_left_factor(S, {0, 0, 0}),
LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::accepts(S, {0, 0, 0}), LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::number_of_left_factors(S),
LibsemigroupsException);
REQUIRE_THROWS_AS(stephen::number_of_words_accepted(S),
LibsemigroupsException);
REQUIRE_THROWS_AS(S.run(), LibsemigroupsException);
}
} // namespace libsemigroups
quality 84%
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland