// // libsemigroups - C++ library for semigroups and monoids // Copyright (C) 2021 James D. Mitchell + Maria Tsalakou // // 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/>. //
#include <cstddef> // for size_t #include <iostream> // for to_string #include <string> // for to_string #include <unordered_set>
#include"bench-main.hpp"// for CATCH_CONFIG_ENABLE_BENCHMARKING #include"catch.hpp"// for TEST_CASE, BENCHMARK, REQUIRE
#include"libsemigroups/kambites.hpp"// for Kambites #include"libsemigroups/knuth-bendix.hpp"// for KnuthBendix #include"libsemigroups/knuth-bendix.hpp"// for random_string #include"libsemigroups/siso.hpp"// for cbegin_sislo
// TODO: // - include number of recursive calls to wp-prefix.
namespace libsemigroups { using detail::MultiStringView; using detail::power_string; using detail::random_string; using detail::random_strings; using fpsemigroup::Kambites;
namespace {
std::string zip(std::vector<std::string> const& x,
std::vector<std::string> const& y) {
LIBSEMIGROUPS_ASSERT(x.size() == y.size());
std::string result = ""; for (size_t i = 0; i < x.size(); ++i) {
result += x[i];
result += y[i];
} return result;
}
// Returns {u_1, u_2, ..., u_{exp}} where u_i are chosen with uniform // distribution in {s, t}
std::vector<std::string> random_sequence(std::string const& s,
std::string const& t,
size_t exp) { static std::random_device rd; static std::mt19937 generator(rd()); static std::uniform_int_distribution<> distribution(0, 1);
std::vector<std::string> result; while (exp > 0) { switch (distribution(generator)) { case 0: {
result.push_back(s); break;
} case 1: {
result.push_back(t); break;
}
}
exp--;
} return result;
}
} // namespace
//////////////////////////////////////////////////////////////////////// // Benchmark checking C(4) or higher - Example A.1 ////////////////////////////////////////////////////////////////////////
std::pair<std::string, std::string> example1(size_t N) {
std::string lhs, rhs; for (size_t b = 1; b <= N; ++b) {
lhs += "a" + std::string(b, 'b');
} for (size_t b = N + 1; b <= 2 * N; ++b) {
rhs += "a" + std::string(b, 'b');
} return std::make_pair(lhs, rhs);
}
template <typename T> void c4_ex_A1() { for (size_t N = 100; N <= 1000; N += 25) {
size_t M;
{
std::string lhs, rhs;
std::tie(lhs, rhs) = example1(N);
M = lhs.size() + rhs.size();
}
BENCHMARK_ADVANCED("Length of relation words = " + std::to_string(M))
(Catch::Benchmark::Chronometer meter) {
std::string lhs, rhs;
std::tie(lhs, rhs) = example1(N);
Kambites<T> k;
k.set_alphabet("ab");
k.add_rule(lhs, rhs);
meter.measure([&k]() { REQUIRE(k.small_overlap_class() >= 4); });
}; // NOLINT(readability/braces)
}
}
//////////////////////////////////////////////////////////////////////// // Benchmark checking small overlap condition - Example A.5 //////////////////////////////////////////////////////////////////////// // <a, b, c, d | a(bc) ^ m a = a (cb) ^ m a, a(bc) ^ m a = b d ^ m b >
template <typename T> void c4_ex_A5() { for (size_t m = 5000; m < 250000; m += 10000) {
BENCHMARK_ADVANCED("Length of relation words = "
+ std::to_string(7 * m + 8))
(Catch::Benchmark::Chronometer meter) {
std::string lhs1 = "a" + power_string("bc", m) + "a";
std::string rhs1 = "a" + power_string("cb", m) + "a";
std::string lhs2 = "b" + power_string("d", m) + "b";
std::string rhs2 = "a" + power_string("bc", m) + "a";
meter.measure([&lhs1, &rhs1, &lhs2, &rhs2]() {
Kambites<T> k;
k.set_alphabet("abcd");
k.add_rule(lhs1, rhs1);
k.add_rule(lhs2, rhs2);
REQUIRE(k.small_overlap_class() >= 4);
});
}; // NOLINT(readability/braces)
}
}
//////////////////////////////////////////////////////////////////////// // Benchmark wp-prefix - Example A.3 ////////////////////////////////////////////////////////////////////////
template <typename T> void equal_to_ex_A3(size_t m, size_t first, size_t last, size_t step) {
start: auto rules = random_strings(std::string("abcdefgh"), 8, 0, m);
Kambites<T> k;
k.set_alphabet("abcdefgh");
k.add_rule(rules[0], rules[1]);
k.add_rule(rules[2], rules[3]);
k.add_rule(rules[4], rules[5]);
k.add_rule(rules[6], rules[7]); if (k.small_overlap_class() < 4) { goto start;
}
for (size_t N = first; N <= last; N += step) { auto random = random_strings("abcdefgh", N, 0, 4 * N + 4); auto u = zip(random_sequence(rules[4], rules[5], N), random); auto v = zip(random_sequence(rules[4], rules[5], N), random);
BENCHMARK("length = " + std::to_string(u.size() + v.size())) {
REQUIRE(k.equal_to(u, v));
};
}
}
TEST_CASE("Example A3_300: equal_to (std::string)", "[quick][015]", ) {
equal_to_ex_A3<std::string>(300, 100, 180, 2); // This runs superslow with the same params as the next test
}
for (size_t N = 1000; N < 14000; N += 500) { auto random = random_strings("abcde", N, 0, 12); auto u = zip(random_sequence(w1, w2, N), random); auto v = zip(random_sequence(w3, w1, N), random);
BENCHMARK("length = " + std::to_string(u.size() + v.size())) {
REQUIRE(k.equal_to(u, v));
};
}
}
//////////////////////////////////////////////////////////////////////// // Benchmark normal_form - Example A.2 ////////////////////////////////////////////////////////////////////////
template <typename T> void normal_form_ex_A2(size_t m) { for (size_t N = 18; N <= 116; N += 2) {
std::string lhs = "a" + power_string("bc", m) + "a";
std::string rhs = "a" + power_string("cb", m) + "a";
Kambites<T> k;
k.set_alphabet("abc");
k.add_rule(lhs, rhs);
REQUIRE(k.small_overlap_class() >= 4); auto random = random_strings("abc", N, 0, 4 * N + 4); auto w = zip(random_sequence(lhs, rhs, N), random);
BENCHMARK("length = " + std::to_string(w.size())) {
REQUIRE_NOTHROW(k.normal_form(w));
};
}
}
for (size_t N = 20; N < 220; N += 5) { auto random = random_strings("abcdefgh", N, 0, 4 * N + 4); auto w = zip(random_sequence(rules[0], rules[7], N), random);
BENCHMARK("length = " + std::to_string(w.size())) {
REQUIRE_NOTHROW(k.normal_form(w));
};
}
}
for (size_t N = 50; N < 750; N += 18) { auto random = random_strings("abcde", N, 0, 12); auto w = zip(random_sequence(w3, w1, N), random);
BENCHMARK("length = " + std::to_string(w.size())) {
REQUIRE_NOTHROW(k.normal_form(w));
};
}
}
//////////////////////////////////////////////////////////////////////// // Benchmark normal_form - Example A.5 ////////////////////////////////////////////////////////////////////////
template <typename T> void normal_form_ex_A5(size_t m) {
std::string lhs1 = "a" + power_string("bc", m) + "a";
std::string rhs1 = "a" + power_string("cb", m) + "a";
std::string lhs2 = "b" + power_string("d", m) + "b";
std::string rhs2 = "a" + power_string("bc", m) + "a";
Kambites<T> k;
k.set_alphabet("abcd");
k.add_rule(lhs1, rhs1);
k.add_rule(lhs2, rhs2); for (size_t N = 18; N <= 310; N += 8) { auto random = random_strings("abcdefgh", N, 0, 4 * N + 4); auto w = zip(random_sequence(rhs1, rhs2, N), random);
BENCHMARK("length = " + std::to_string(w.size())) {
REQUIRE_NOTHROW(k.normal_form(w));
};
}
}
//////////////////////////////////////////////////////////////////////// // Benchmark number_of_normal_forms - Example A.2 ////////////////////////////////////////////////////////////////////////
template <typename T> void number_of_normal_forms_ex_A2(size_t m) {
std::array<size_t, 5> values = {0, 29381, 29516, 29523, 29523}; auto rg = ReportGuard(false);
std::string lhs = "a" + power_string("bc", m) + "a";
std::string rhs = "a" + power_string("cb", m) + "a";
BENCHMARK("Enumerate normal forms length 0 to 10, m = "
+ std::to_string(m)) {
Kambites<T> k;
k.set_alphabet("abc");
k.add_rule(lhs, rhs);
REQUIRE(k.number_of_normal_forms(0, 10) == values[m]);
};
} // NOLINT(readability/braces)
TEST_CASE("Example A2_1_2_3_4: number_of_normal_forms (std::string)", "[quick][033]", ) { for (size_t i = 1; i <= 4; ++i) {
number_of_normal_forms_ex_A2<std::string>(i);
}
}
TEST_CASE("Example A2_1_2_3_4: number_of_normal_forms (MultiStringView)", "[quick][034]", ) { for (size_t i = 1; i <= 4; ++i) {
number_of_normal_forms_ex_A2<MultiStringView>(i);
}
}
std::string swap_a_and_b(std::string const& w) {
std::string result; for (auto l : w) { if (l == 'a') {
result += "b";
} else {
result += "a";
}
} return result;
}
void normal_form_2_letter_1_relation_c4_monoids(size_t min,
size_t max,
size_t nr_words,
size_t length_words) { auto first
= cbegin_sislo("ab", std::string(min, 'a'), std::string(max, 'a')); auto last
= cbegin_sislo("ab", std::string(min, 'a'), std::string(max, 'a'));
size_t N = std::distance(
first, cend_sislo("ab", std::string(min, 'a'), std::string(max, 'a')));
std::advance(last, N - 1);
auto llast = last;
++llast;
std::unordered_set<std::string> set;
std::vector<Kambites<MultiStringView>> kk;
for (auto it1 = first; it1 != last; ++it1) { auto it2 = it1;
++it2; for (; it2 != llast; ++it2) {
Kambites<MultiStringView> k;
k.set_alphabet("ab");
k.add_rule(*it1, *it2); auto tmp = *it1 + "#" + *it2; if (set.insert(tmp).second) { if (k.small_overlap_class() >= 4) { auto u = swap_a_and_b(*it1); auto v = swap_a_and_b(*it2); if (shortlex_compare(u, v)) {
set.insert(u + "#" + v);
} else {
set.insert(v + "#" + u);
}
std::cout << *it1 << " = " << *it2 << std::endl;
kk.push_back(k);
}
}
}
} auto w = random_strings("ab", nr_words, length_words, length_words + 1);
size_t n = 0; for (auto& k : kk) {
n += 1;
BENCHMARK("n = " + std::to_string(n)) {
std::string u; for (size_t i = 0; i < nr_words; ++i) {
u += k.normal_form(w[i]);
} return u;
};
}
}
TEST_CASE("All 2-letter 1-relation C4 monoids 10 random words of length 10)", "[035]", ) {
normal_form_2_letter_1_relation_c4_monoids(7, 11, 10, 10);
}
TEST_CASE( "All 2-letter 1-relation C4 monoids 100 random words of length 100)", "[036]", ) {
normal_form_2_letter_1_relation_c4_monoids(7, 11, 100, 100);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.