Skip to content

Commit

Permalink
Add to_(inverse_)presentation tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Joseph-Edwards committed Jul 8, 2024
1 parent f6e84ac commit 93e5cb2
Show file tree
Hide file tree
Showing 2 changed files with 220 additions and 12 deletions.
5 changes: 5 additions & 0 deletions tests/test-presentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,7 @@ namespace libsemigroups {

ip.inverses_no_checks({2, 1, 0});
REQUIRE(ip != ip2);
ip.validate();
}

template <typename W>
Expand All @@ -1033,6 +1034,7 @@ namespace libsemigroups {
REQUIRE(ip.inverse(0) == 2);
REQUIRE(ip.inverse(1) == 1);
REQUIRE(ip.inverse(2) == 0);
ip.validate();
}

} // namespace
Expand Down Expand Up @@ -2838,6 +2840,7 @@ namespace libsemigroups {
REQUIRE(ip.rules.size() == 2);
presentation::add_rule(ip, {0, 0, 0}, {0});
REQUIRE_THROWS_AS(ip.validate(), LibsemigroupsException);
REQUIRE_EXCEPTION_MSG(ip.inverse(0), "no inverses have been defined");
ip.inverses_no_checks({2, 1, 0});
ip.validate();
check_inverse_constructors(ip);
Expand All @@ -2854,6 +2857,7 @@ namespace libsemigroups {
REQUIRE(ip.rules.size() == 2);
presentation::add_rule(ip, {0, 0, 0}, {0});
REQUIRE_THROWS_AS(ip.validate(), LibsemigroupsException);
REQUIRE_EXCEPTION_MSG(ip.inverse(0), "no inverses have been defined");
ip.inverses_no_checks({2, 1, 0});
ip.validate();
check_inverse_constructors(ip);
Expand All @@ -2870,6 +2874,7 @@ namespace libsemigroups {
REQUIRE(ip.rules.size() == 2);
presentation::add_rule(ip, {0, 0, 0}, {0});
REQUIRE_THROWS_AS(ip.validate(), LibsemigroupsException);
REQUIRE_EXCEPTION_MSG(ip.inverse(0), "no inverses have been defined");
ip.inverses_no_checks({2, 1, 0});
ip.validate();
check_inverse_constructors(ip);
Expand Down
227 changes: 215 additions & 12 deletions tests/test-to-presentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,165 @@ namespace libsemigroups {
template <typename W1, typename W2>
void check_to_presentation_from_presentation() {
Presentation<W1> p;
p.alphabet(2);
p.contains_empty_word(false);
presentation::add_rule_no_checks(p, {0, 1, 2}, {0, 1});
presentation::add_rule_no_checks(p, {0, 1, 2}, {});
// intentionally bad
REQUIRE_THROWS_AS(p.validate(), LibsemigroupsException);
REQUIRE_THROWS_AS(to_presentation<W2>(p), LibsemigroupsException);

p.alphabet_from_rules();
REQUIRE(p.alphabet() == W1({0, 1, 2}));
p.alphabet(3);
p.contains_empty_word(true);
if constexpr (std::is_same_v<W1, std::string>) {
presentation::add_rule_no_checks(p, "abc", "ab");
presentation::add_rule_no_checks(p, "abc", "");
} else {
presentation::add_rule_no_checks(p, {0, 1, 2}, {0, 1});
presentation::add_rule_no_checks(p, {0, 1, 2}, {});
}
p.validate();

Presentation<W2> q = to_presentation<W2>(p);
REQUIRE(q.contains_empty_word());

if constexpr (std::is_same_v<W2, std::string>) {
REQUIRE(q.alphabet() == "abc");
REQUIRE(q.rules == std::vector<W2>({"abc", "ab", "abc", ""}));
} else {
REQUIRE(q.alphabet() == W2({0, 1, 2}));
REQUIRE(q.rules == std::vector<W2>({{0, 1, 2}, {0, 1}, {0, 1, 2}, {}}));
}
q.validate();

// Check p hasn't been destroyed
REQUIRE(p.contains_empty_word());
auto q = to_presentation<W2>(p);
if constexpr (std::is_same_v<W1, std::string>) {
REQUIRE(p.alphabet() == "abc");
REQUIRE(p.rules == std::vector<W1>({"abc", "ab", "abc", ""}));
} else {
REQUIRE(p.alphabet() == W1({0, 1, 2}));
REQUIRE(p.rules == std::vector<W1>({{0, 1, 2}, {0, 1}, {0, 1, 2}, {}}));
}
p.validate();

// Check two conversions gets you back to where you started
REQUIRE(p == to_presentation<W1>(q));
}

template <typename W1, typename W2>
void check_to_presentation_from_presentation_with_function() {
Presentation<W1> p;
p.alphabet(3);
p.contains_empty_word(true);
if constexpr (std::is_same_v<W1, std::string>) {
presentation::add_rule_no_checks(p, "abc", "ab");
presentation::add_rule_no_checks(p, "abc", "");
} else {
presentation::add_rule_no_checks(p, {0, 1, 2}, {0, 1});
presentation::add_rule_no_checks(p, {0, 1, 2}, {});
}

auto f1 = [&p](auto val) {
return presentation::human_readable_letter<W2>(p.index(val) + 7);
};
Presentation<W2> q = to_presentation<W2>(p, f1);
REQUIRE(q.contains_empty_word());
if constexpr (std::is_same_v<W2, std::string>) {
REQUIRE(q.alphabet() == "hij");
REQUIRE(q.rules == std::vector<W2>({"hij", "hi", "hij", ""}));
} else {
REQUIRE(q.alphabet() == W2({7, 8, 9}));
REQUIRE(q.rules == std::vector<W2>({{7, 8, 9}, {7, 8}, {7, 8, 9}, {}}));
}
q.validate();

auto f2 = [&p](auto val) { return p.index(val); };
Presentation<W2> r = to_presentation<W2>(p, f2);
REQUIRE(r.contains_empty_word());
REQUIRE(r.alphabet() == W2({0, 1, 2}));
REQUIRE(r.rules == std::vector<W2>({{0, 1, 2}, {0, 1}, {0, 1, 2}, {}}));

r.validate();
}

template <typename W1, typename W2>
void check_to_inverse_presentation() {
InversePresentation<W1> ip;
ip.alphabet(3);
ip.contains_empty_word(true);
if constexpr (std::is_same_v<W1, std::string>) {
presentation::add_rule_no_checks(ip, "abc", "ab");
presentation::add_rule_no_checks(ip, "abc", "");
ip.inverses_no_checks("cba");
} else {
presentation::add_rule_no_checks(ip, {0, 1, 2}, {0, 1});
presentation::add_rule_no_checks(ip, {0, 1, 2}, {});
ip.inverses_no_checks({2, 1, 0});
}
ip.validate();

auto iq = to_inverse_presentation<W2>(ip);
REQUIRE(iq.contains_empty_word());

if constexpr (std::is_same_v<W2, std::string>) {
REQUIRE(iq.alphabet() == "abc");
REQUIRE(iq.rules == std::vector<W2>({"abc", "ab", "abc", ""}));
REQUIRE(iq.inverses() == "cba");
} else {
REQUIRE(iq.alphabet() == W2({0, 1, 2}));
REQUIRE(iq.rules
== std::vector<W2>({{0, 1, 2}, {0, 1}, {0, 1, 2}, {}}));
REQUIRE(iq.inverses() == W2({2, 1, 0}));
}
iq.validate();

// Check p hasn't been destroyed
REQUIRE(ip.contains_empty_word());
if constexpr (std::is_same_v<W1, std::string>) {
REQUIRE(ip.alphabet() == "abc");
REQUIRE(ip.rules == std::vector<W1>({"abc", "ab", "abc", ""}));
REQUIRE(ip.inverses() == "cba");
} else {
REQUIRE(ip.alphabet() == W1({0, 1, 2}));
REQUIRE(ip.rules
== std::vector<W1>({{0, 1, 2}, {0, 1}, {0, 1, 2}, {}}));
REQUIRE(ip.inverses() == W1({2, 1, 0}));
}
ip.validate();

// Check two conversions gets you back to where you started
REQUIRE(ip == to_inverse_presentation<W1>(iq));

auto f = [&ip](auto val) { return ip.index(val) + 3; };
InversePresentation<W2> ir = to_inverse_presentation<W2>(ip, f);
REQUIRE(ir.contains_empty_word());
REQUIRE(ir.alphabet() == W2({3, 4, 5}));
REQUIRE(ir.rules == std::vector<W2>({{3, 4, 5}, {3, 4}, {3, 4, 5}, {}}));
REQUIRE(ir.inverses() == W2({5, 4, 3}));

ir.validate();
}

template <typename Word>
void check_to_inverse_presentation_from_presentation() {
Presentation<Word> p;
p.alphabet(3);
if constexpr (std::is_same_v<Word, std::string>) {
presentation::add_rule_no_checks(p, "abc", "ab");
presentation::add_rule_no_checks(p, "acb", "c");
} else {
presentation::add_rule_no_checks(p, {0, 1, 2}, {0, 1});
presentation::add_rule_no_checks(p, {0, 2, 1}, {2});
}
p.validate();

InversePresentation<Word> ip = to_inverse_presentation(p);
REQUIRE(!ip.contains_empty_word());
if constexpr (std::is_same_v<Word, std::string>) {
REQUIRE(ip.alphabet() == "abcdef");
REQUIRE(ip.rules == std::vector<Word>({"abc", "ab", "acb", "c"}));
REQUIRE(ip.inverses() == "defabc");
} else {
REQUIRE(ip.alphabet() == Word({0, 1, 2, 3, 4, 5}));
REQUIRE(ip.rules
== std::vector<Word>({{0, 1, 2}, {0, 1}, {0, 2, 1}, {2}}));
REQUIRE(ip.inverses() == Word({3, 4, 5, 0, 1, 2}));
}

REQUIRE(ip == to_inverse_presentation(ip));
}
} // namespace

Expand Down Expand Up @@ -140,10 +283,37 @@ namespace libsemigroups {
word_type>();
check_to_presentation_from_presentation<StaticVector1<uint8_t, 3>,
std::string>();
// The function calls below correctly cause compile errors
// check_to_presentation_from_presentation<std::string, std::string>();
// check_to_presentation_from_presentation<word_type, word_type>();
// check_to_presentation_from_presentation<StaticVector1<uint8_t, 3>,
// StaticVector1<uint8_t, 3>>();
}

LIBSEMIGROUPS_TEST_CASE("to_presentation",
"003",
"presentation from presentation with function",
"[quick][to_presentation]") {
check_to_presentation_from_presentation_with_function<std::string,
word_type>();
check_to_presentation_from_presentation_with_function<
std::string,
StaticVector1<uint8_t, 3>>();
check_to_presentation_from_presentation_with_function<word_type,
std::string>();
check_to_presentation_from_presentation_with_function<
word_type,
StaticVector1<uint8_t, 3>>();
check_to_presentation_from_presentation_with_function<
StaticVector1<uint8_t, 3>,
word_type>();
check_to_presentation_from_presentation_with_function<
StaticVector1<uint8_t, 3>,
std::string>();
}

LIBSEMIGROUPS_TEST_CASE("to_presentation",
"004",
"presentation from presentation and alphabet",
"[quick][to_presentation]") {
Presentation<word_type> p;
Expand All @@ -168,7 +338,7 @@ namespace libsemigroups {
}

LIBSEMIGROUPS_TEST_CASE("to_presentation",
"004",
"005",
"use human readable alphabet for to_presentation",
"[quick][presentation]") {
Presentation<word_type> p;
Expand All @@ -185,4 +355,37 @@ namespace libsemigroups {
REQUIRE(q.rules == std::vector<std::string>({"xy", ""}));
}

LIBSEMIGROUPS_TEST_CASE("to_inverse_presentation",
"006",
"inverse presentation from inverse presentation",
"[quick][to_presentation]") {
check_to_inverse_presentation<std::string, word_type>();
check_to_inverse_presentation<std::string, StaticVector1<uint8_t, 3>>();
check_to_inverse_presentation<word_type, std::string>();
check_to_inverse_presentation<word_type, StaticVector1<uint8_t, 3>>();
check_to_inverse_presentation<StaticVector1<uint8_t, 3>, word_type>();
check_to_inverse_presentation<StaticVector1<uint8_t, 3>, std::string>();
// The function calls below correctly cause compile errors
// check_to_inverse_presentation<std::string, std::string>();
// check_to_inverse_presentation<word_type, word_type>();
// check_to_inverse_presentation<StaticVector1<uint8_t, 3>,
// StaticVector1<uint8_t, 3>>();
}

LIBSEMIGROUPS_TEST_CASE("to_inverse_presentation",
"007",
"inverse presentation from presentation",
"[quick][to_presentation]") {
check_to_inverse_presentation_from_presentation<std::string>();
check_to_inverse_presentation_from_presentation<word_type>();
check_to_inverse_presentation_from_presentation<
StaticVector1<uint8_t, 6>>();

Presentation<std::vector<uint16_t>> p;
p.alphabet(32767);
REQUIRE_NOTHROW(to_inverse_presentation(p));
p.alphabet(32768);
REQUIRE_THROWS(to_inverse_presentation(p));
}

} // namespace libsemigroups

0 comments on commit 93e5cb2

Please sign in to comment.