From a87285d5295e30074b2bdaa24e5dda1313922fb6 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Oct 2025 15:14:07 +0100 Subject: [PATCH 01/11] Python script to extract code examples from libsemigroups documentation Ability to collect code examples and write them to test-docs-code-examples.cpp. Update made to Makefile.am to build tests. FIX: includes. --- Makefile.am | 6 + etc/extract-doc-examples.py | 237 ++++++++++++++++++++++++++++++ tests/test-docs-code-examples.cpp | 0 3 files changed, 243 insertions(+) create mode 100644 etc/extract-doc-examples.py create mode 100644 tests/test-docs-code-examples.cpp diff --git a/Makefile.am b/Makefile.am index fd0b499e0..3e67e2bfc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -812,6 +812,7 @@ EXTRA_PROGRAMS += test_cong_all EXTRA_PROGRAMS += test_cong_common EXTRA_PROGRAMS += test_constants EXTRA_PROGRAMS += test_containers +EXTRA_PROGRAMS += test_docs_code_examples EXTRA_PROGRAMS += test_dot EXTRA_PROGRAMS += test_felsch_tree EXTRA_PROGRAMS += test_forest @@ -899,6 +900,7 @@ test_all_SOURCES += tests/test-cong-common.cpp test_all_SOURCES += tests/test-cong.cpp test_all_SOURCES += tests/test-constants.cpp test_all_SOURCES += tests/test-containers.cpp +test_all_SOURCES += tests/test-docs-code-examples.cpp test_all_SOURCES += tests/test-dot.cpp test_all_SOURCES += tests/test-felsch-tree.cpp test_all_SOURCES += tests/test-forest.cpp @@ -1012,6 +1014,10 @@ test_containers_SOURCES = tests/test-containers.cpp test_containers_SOURCES += tests/test-main.cpp test_containers_SOURCES += third_party/Catch2-3.8.0/catch_amalgamated_patch.cpp +test_docs_code_examples_SOURCES = tests/test-docs-code-examples.cpp +test_docs_code_examples_SOURCES += tests/test-main.cpp +test_docs_code_examples_SOURCES += third_party/Catch2-3.8.0/catch_amalgamated_patch.cpp + test_dot_SOURCES = tests/test-dot.cpp test_dot_SOURCES += tests/test-main.cpp test_dot_SOURCES += third_party/Catch2-3.8.0/catch_amalgamated_patch.cpp diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py new file mode 100644 index 000000000..ea98b30e8 --- /dev/null +++ b/etc/extract-doc-examples.py @@ -0,0 +1,237 @@ +import os +import sys +import argparse +from pathlib import Path + +######################################################################## +# CONSTANTS +######################################################################## + +HEADER_TEXT = """// libsemigroups - C++ library for semigroups and monoids +// Copyright (C) 2021-2025 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 . +// + +#include "Catch2-3.8.0/catch_amalgamated.hpp" // for REQUIRE, REQUIRE_NOTHROW, REQUIRE_THROWS_AS +#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE +""" + +######################################################################## +# INTERNAL +######################################################################## + + +def __error(msg: str) -> None: + sys.stderr.write(f"\033[0;31m{msg}\n\033[0m") + + +def __bold(msg: str) -> None: + sys.stderr.write(f"\033[1m{msg}\n\033[0m") + + +def __parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Extract code example blocks from documentation.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" + Examples: + python3 extract_code.py <-- Process specific folder + Flags: + -r | Process folder recursively + """, + ) + + parser.add_argument( + "folder_path", + nargs="?", + default=".", + help="Path to the folder to process (default: current directory)", + ) + + parser.add_argument( + "-r", + "--recursive", + action="store_true", + help="Process subdirectories recursively", + ) + + parser.add_argument( + "--version", action="version", version="Code Block Extractor 1.0" + ) + + args = parser.parse_args() + + return args + + +######################################################################## +# CODE BLOCK EXTRACTION +######################################################################## + + +def extract_code_blocks(file_path): + """ + Extract code examples from a file. + + Args: + file_path (Path): Path to the file to process + + Returns: + list: List of code blocks found in the file + [["content", "start_line"], ...] + """ + code_blocks = [] + + try: + with open(file_path, "r", encoding="utf-8", errors="ignore") as file: + in_code_block = False + current_block = [] + + for line_num, line in enumerate(file, 1): + line = line.lstrip() + line = line.removeprefix("//!") + line = line.rstrip("\n\r") + + if "\\code" in line: + if in_code_block: + __error( + f"Warning: Found \\code while already in code block at { + file_path + }:{line_num}" + ) + in_code_block = True + current_block = [] + continue + + if "\\endcode" in line: + if not in_code_block: + __error( + f"Warning: Found \\endcode without matching \\code at { + file_path + }:{line_num}" + ) + else: + code_blocks.append( + { + "content": "\n".join(current_block), + "start_line": line_num - len(current_block), + } + ) + in_code_block = False + current_block = [] + continue + + if in_code_block: + if "using namespace libsemigroups" in line: + continue + current_block.append(line) + + # discard unclosed code blocks + if in_code_block and current_block: + __error( + f"Warning: Unclosed code block at end of file {file_path}") + + except Exception as e: + print(f"Error reading file {file_path}: {e}") + + return code_blocks + + +def process_folder(folder_path, recursive=False): + """ + Process all files in a folder to find code examples. + + Args: + folder_path (string): Path to the folder to process + recursive (bool): Whether to process subdirectories recursively + """ + folder = Path(folder_path) + + if not folder.exists(): + print(f"Error: Directory '{folder_path}' does not exist.") + sys.exit(1) + + if not folder.is_dir(): + print(f"Error: '{folder_path}' is not a directory.") + sys.exit(1) + + print(f"Searching for code blocks in folder: {folder.absolute()}") + if recursive: + print("Processing subdirectories recursively...") + print("=" * 60) + + # Get files + if recursive: + files = folder.rglob("*") + else: + files = folder.glob("*") + + # Filter + files = [f for f in files if f.is_file()] + + if len(files) == 0: + print("No files found in the specified directory.") + return + + total_blocks = 0 + + try: + with open("./tests/test-docs-code-examples.cpp", "w") as testfile: + testfile.write(f"{HEADER_TEXT}\n") + testfile.write("namespace libsemigroups {\n") # Open namespace + + for file_path in sorted(files): + # Extract example code + code_blocks = extract_code_blocks(file_path) + + # Write to cpp test file + if code_blocks: + for i, block in enumerate(code_blocks, 1): + testfile.write( + f'// {file_path.relative_to(folder)}: Line { + block["start_line"] + }\nLIBSEMIGROUPS_TEST_CASE("docs", "{total_blocks}", "{ + file_path.relative_to(folder) + }", "[docs][quick]") {{\n' + ) + if block["content"].strip(): + testfile.write(" " + block["content"]) + else: + testfile.write("// ~ empty code block ~") + testfile.write("\n}\n\n") + total_blocks += 1 + + testfile.write("\n}") # Close namespace + except IOError as e: + print(f"Could not write to test file: {e}") + + if total_blocks == 0: + print("No code blocks found in any files.") + else: + print(f"Total code blocks found: {total_blocks}") + + +######################################################################## +# MAIN +######################################################################### + + +def main(): + args = __parse_args() + process_folder(args.folder_path, args.recursive) + + +if __name__ == "__main__": + main() diff --git a/tests/test-docs-code-examples.cpp b/tests/test-docs-code-examples.cpp new file mode 100644 index 000000000..e69de29bb From 43a45382ff89883171f1699893e5f3b0e912f803 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 15 Oct 2025 14:45:12 +0100 Subject: [PATCH 02/11] Generating test-docs-code-examples.cpp Compiler Errors indicate capturing non-executable code blocks (label differently?) or errors in the example code. --- etc/extract-doc-examples.py | 3 +- tests/test-docs-code-examples.cpp | 987 ++++++++++++++++++++++++++++++ 2 files changed, 989 insertions(+), 1 deletion(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index ea98b30e8..8aa9fae97 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -25,7 +25,8 @@ // #include "Catch2-3.8.0/catch_amalgamated.hpp" // for REQUIRE, REQUIRE_NOTHROW, REQUIRE_THROWS_AS -#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE +#include "libsemigroups/libsemigroups.hpp" // for * +#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE """ ######################################################################## diff --git a/tests/test-docs-code-examples.cpp b/tests/test-docs-code-examples.cpp index e69de29bb..0d395fc26 100644 --- a/tests/test-docs-code-examples.cpp +++ b/tests/test-docs-code-examples.cpp @@ -0,0 +1,987 @@ +// libsemigroups - C++ library for semigroups and monoids +// Copyright (C) 2021-2025 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 . +// + +#include "Catch2-3.8.0/catch_amalgamated.hpp" // for REQUIRE, REQUIRE_NOTHROW, REQUIRE_THROWS_AS +#include "libsemigroups/libsemigroups.hpp" // for * +#include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE + +namespace libsemigroups { +// action.hpp: Line 60 +LIBSEMIGROUPS_TEST_CASE("docs", "0", "action.hpp", "[docs][quick]") { + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> + o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + o.size(); // returns 65536 +} + +// action.hpp: Line 143 +LIBSEMIGROUPS_TEST_CASE("docs", "1", "action.hpp", "[docs][quick]") { + auto rg = ReportGuard(true); + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> + o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + o.size(); // 65536 + o.scc().number_of_components(); // 17 +} + +// adapters.hpp: Line 120 +LIBSEMIGROUPS_TEST_CASE("docs", "2", "adapters.hpp", "[docs][quick]") { + template <> + struct Complexity { + constexpr size_t operator()(KBE const&) const noexcept { + return LIMIT_MAX; + } + }; +} + +// adapters.hpp: Line 158 +LIBSEMIGROUPS_TEST_CASE("docs", "3", "adapters.hpp", "[docs][quick]") { + template <> + struct Degree { + constexpr inline size_t operator()(BMat8 const&) const noexcept { + return 8; + } + }; +} + +// adapters.hpp: Line 196 +LIBSEMIGROUPS_TEST_CASE("docs", "4", "adapters.hpp", "[docs][quick]") { + template + struct IncreaseDegree< + Integral, + typename std::enable_if::value>::type> + { + void operator()(Integral&, size_t) const noexcept { + } + }; +} + +// adapters.hpp: Line 223 +LIBSEMIGROUPS_TEST_CASE("docs", "5", "adapters.hpp", "[docs][quick]") { + Element operator()(Element const& x) const noexcept { + return this->operator()(Degree()(x)); + } +} + +// adapters.hpp: Line 239 +LIBSEMIGROUPS_TEST_CASE("docs", "6", "adapters.hpp", "[docs][quick]") { + template + struct One< + T, + typename std::enable_if::value>::type> { + T operator()(size_t = 0) const noexcept { + return T::one(); + } + + T operator()(T const&) const noexcept { + return T::one(); + } + }; +} + +// adapters.hpp: Line 282 +LIBSEMIGROUPS_TEST_CASE("docs", "7", "adapters.hpp", "[docs][quick]") { + template <> + struct Product { + void operator()(size_t& xy, size_t x, size_t y, size_t = 0) const + noexcept { + xy = x * y; + } + }; +} + +// adapters.hpp: Line 317 +LIBSEMIGROUPS_TEST_CASE("docs", "8", "adapters.hpp", "[docs][quick]") { + template <> + struct Inverse { + inline BMat8 operator()(BMat8 const& x) const noexcept { + LIBSEMIGROUPS_ASSERT(x * x.transpose() == x.one()); + return x.transpose(); + } + }; +} + +// adapters.hpp: Line 349 +LIBSEMIGROUPS_TEST_CASE("docs", "9", "adapters.hpp", "[docs][quick]") { + template <> + struct ImageLeftAction { + void operator()(BMat8& res, BMat8 pt, BMat8 x) const noexcept { + res = (x * pt).col_space_basis(); + } + }; +} + +// adapters.hpp: Line 391 +LIBSEMIGROUPS_TEST_CASE("docs", "10", "adapters.hpp", "[docs][quick]") { + template <> + struct ImageLeftAction { + void operator()(BMat8& res, BMat8 pt, BMat8 x) const noexcept { + res = (x * pt).row_space_basis(); + } + }; +} + +// cong-class.hpp: Line 148 +LIBSEMIGROUPS_TEST_CASE("docs", "11", "cong-class.hpp", "[docs][quick]") { + Presentation p; + p.alphabet(2) + presentation::add_rule(p, {0, 1}, {}); + Congruence cong(congruence_kind::twosided, p); + is_obviously_infinite(cong); // true + congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); + cong.number_of_classes(); // 3 +} + +// freeband.hpp: Line 76 +LIBSEMIGROUPS_TEST_CASE("docs", "12", "freeband.hpp", "[docs][quick]") { + freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, + {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true + freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false + freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}) // true + freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, + {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false + freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true + freeband_equal_to({0, 1, 2, 3, 0, 1}, + {0, 1, 2, 3, 3, 2, 2, 1, 0, 2, 1, 0, 2, 3, + 0, 2, 1, 3, 2, 1, 2, 3, 2, 1, 0, 2, 0, 1, + 0, 2, 0, 3, 2, 0, 1, 2, 2, 3, 0, 1}); // true +} + +// froidure-pin-base.hpp: Line 1337 +LIBSEMIGROUPS_TEST_CASE("docs", "13", "froidure-pin-base.hpp", "[docs][quick]") { + FroidurePin S; + S.add_generator(BMat8({{1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}})); + S.add_generator(BMat8({{0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}})); + S.add_generator(BMat8({{0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}})); + S.add_generator(BMat8({{0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}})); + S.size(); // 4 + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} +} + +// froidure-pin-base.hpp: Line 1441 +LIBSEMIGROUPS_TEST_CASE("docs", "14", "froidure-pin-base.hpp", "[docs][quick]") { + FroidurePin S; + S.add_generator(BMat8({{1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}})); + S.add_generator(BMat8({{0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}})); + S.add_generator(BMat8({{0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}})); + S.add_generator(BMat8({{0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}})); + S.size(); // 4 + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} +} + +// froidure-pin.hpp: Line 137 +LIBSEMIGROUPS_TEST_CASE("docs", "15", "froidure-pin.hpp", "[docs][quick]") { + template <> + struct Complexity { + constexpr size_t operator()(int) const noexcept { + return 0; + } + }; + + template <> + struct Degree { + constexpr size_t operator()(int) const noexcept { + return 0; + } + }; + + template <> + struct IncreaseDegree { + int operator()(int x) const noexcept { + return x; + } + }; + + template <> + struct One { + constexpr int operator()(int) const noexcept { + return 1; + } + }; + + template <> + struct Product { + void operator()(int& xy, + int x, + int y, + size_t = 0) const noexcept { + xy = x * y; + } + }; + + FroidurePin S({2}); + S.size(); // 32 + S.number_of_idempotents() // 1 + *S.cbegin(); // 2 + + FroidurePin T({2, 3}); + T.size() // 130 + T.number_of_idempotents() // 2 + *T.cbegin_idempotents(); // 0 + *T.cbegin_idempotents() + 1; // 1 +} + +// is_specialization_of.hpp: Line 44 +LIBSEMIGROUPS_TEST_CASE("docs", "16", "is_specialization_of.hpp", "[docs][quick]") { + is_specialization_of, std::vector>::value // true + is_specialization_of, std::unordered_map>::value + // false +} + +// is_specialization_of.hpp: Line 74 +LIBSEMIGROUPS_TEST_CASE("docs", "17", "is_specialization_of.hpp", "[docs][quick]") { + is_specialization_of_v, std::vector> // true + is_specialization_of_v, std::unordered_map> // false +} + +// knuth-bendix-class.hpp: Line 72 +LIBSEMIGROUPS_TEST_CASE("docs", "18", "knuth-bendix-class.hpp", "[docs][quick]") { + Presentation p; + p.contains_empty_word(true); + p.alphabet("abcd"); + presentation::add_rule_no_checks(p, "ab", ""); + presentation::add_rule_no_checks(p, "ba", ""); + presentation::add_rule_no_checks(p, "cd", ""); + presentation::add_rule_no_checks(p, "dc", ""); + + KnuthBendix kb(twosided, p); + + !kb.confluent(); // true + kb.run(); + kb.number_of_active_rules(); // 8 + kb.confluent(); // true + kb.number_of_classes(); // POSITIVE_INFINITY +} + +// konieczny.hpp: Line 70 +LIBSEMIGROUPS_TEST_CASE("docs", "19", "konieczny.hpp", "[docs][quick]") { + auto S = make({ + BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), + BMat8({{1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}})}); + S.size(); // returns 63'904 + S.number_of_idempotents(); //returns 2'360 +} + +// konieczny.hpp: Line 1908 +LIBSEMIGROUPS_TEST_CASE("docs", "20", "konieczny.hpp", "[docs][quick]") { + make(gens); +} + +// konieczny.hpp: Line 1952 +LIBSEMIGROUPS_TEST_CASE("docs", "21", "konieczny.hpp", "[docs][quick]") { + make(gens); +} + +// matrix.hpp: Line 1964 +LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { + Mat m({{1, 1}, {0, 0}}); +} + +// matrix.hpp: Line 2866 +LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { + Mat m(2, 3); // construct a 2 x 3 matrix +} + +// matrix.hpp: Line 2888 +LIBSEMIGROUPS_TEST_CASE("docs", "24", "matrix.hpp", "[docs][quick]") { + Mat m({1, 1, 0, 0}); +} + +// matrix.hpp: Line 2910 +LIBSEMIGROUPS_TEST_CASE("docs", "25", "matrix.hpp", "[docs][quick]") { + Mat m({{1, 1}, {0, 0}}); +} + +// matrix.hpp: Line 3814 +LIBSEMIGROUPS_TEST_CASE("docs", "26", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + BMat<3> m; + // construct an uninitialized 4 x 4 dynamic matrix + BMat<> m(4, 4); +} + +// matrix.hpp: Line 4121 +LIBSEMIGROUPS_TEST_CASE("docs", "27", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + IntMat<3> m; + // construct an uninitialized 4 x 4 dynamic matrix + IntMat<> m(4, 4); +} + +// matrix.hpp: Line 4411 +LIBSEMIGROUPS_TEST_CASE("docs", "28", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + MaxPlusMat<3> m; + // construct an uninitialized 4 x 4 dynamic matrix + MaxPlusMat<> m(4, 4); +} + +// matrix.hpp: Line 4720 +LIBSEMIGROUPS_TEST_CASE("docs", "29", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + MinPlusMat<3> m; + // construct an uninitialized 4 x 4 dynamic matrix + MinPlusMat<> m(4, 4); +} + +// matrix.hpp: Line 5039 +LIBSEMIGROUPS_TEST_CASE("docs", "30", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + MaxPlusTruncMat<11, 3> m; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MaxPlusTruncMat<11> m(4, 4); + // construct a truncated max-plus semiring with threshold 11 + MaxPlusTruncSemiring sr(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MaxPlusTruncMat<> m(sr, 5, 5); +} + +// matrix.hpp: Line 5520 +LIBSEMIGROUPS_TEST_CASE("docs", "31", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + MinPlusTruncMat<11, 3> m; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MinPlusTruncMat<11> m(4, 4); + // construct a truncated min-plus semiring with threshold 11 + MinPlusTruncSemiring sr(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MinPlusTruncMat<> m(sr, 5, 5); +} + +// matrix.hpp: Line 6006 +LIBSEMIGROUPS_TEST_CASE("docs", "32", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold + // 11, period 2 + NTPMat<11, 2, 3> m; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, + // period 2 + NTPMat<11, 2> m(4, 4); + // construct an ntp semiring with threshold 11, period 2 + NTPSemiring sr(11, 2); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, + // period 2 + NTPMat<> m(sr, 5, 5); +} + +// matrix.hpp: Line 6984 +LIBSEMIGROUPS_TEST_CASE("docs", "33", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + ProjMaxPlusMat<3> m; + // construct an uninitialized 4 x 4 dynamic matrix + ProjMaxPlusMat<> m(4, 4); +} + +// matrix.hpp: Line 7149 +LIBSEMIGROUPS_TEST_CASE("docs", "34", "matrix.hpp", "[docs][quick]") { + auto x == make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, + 1}})); + // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} + matrix::pow(x, 100); +} + +// matrix.hpp: Line 7897 +LIBSEMIGROUPS_TEST_CASE("docs", "35", "matrix.hpp", "[docs][quick]") { + auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); + matrix::row_space_size(x); // returns 7 +} + +// order.hpp: Line 98 +LIBSEMIGROUPS_TEST_CASE("docs", "36", "order.hpp", "[docs][quick]") { + std::lexicographical_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); +} + +// order.hpp: Line 131 +LIBSEMIGROUPS_TEST_CASE("docs", "37", "order.hpp", "[docs][quick]") { + lexicographical_compare( + x->cbegin(), x->cend(), y->cbegin(), y->cend()); +} + +// order.hpp: Line 261 +LIBSEMIGROUPS_TEST_CASE("docs", "38", "order.hpp", "[docs][quick]") { + template + bool shortlex_compare(T const& first1, + T const& last1, + S const& first2, + S const& last2) { + return (last1 - first1) < (last2 - first2) + || ((last1 - first1) == (last2 - first2) + && std::lexicographical_compare + (first1, last1, first2, last2)); + } +} + +// order.hpp: Line 305 +LIBSEMIGROUPS_TEST_CASE("docs", "39", "order.hpp", "[docs][quick]") { + shortlex_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); +} + +// order.hpp: Line 339 +LIBSEMIGROUPS_TEST_CASE("docs", "40", "order.hpp", "[docs][quick]") { + shortlex_compare( + x->cbegin(), x->cend(), y->cbegin(), y->cend()); +} + +// order.hpp: Line 473 +LIBSEMIGROUPS_TEST_CASE("docs", "41", "order.hpp", "[docs][quick]") { + recursive_path_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); +} + +// order.hpp: Line 505 +LIBSEMIGROUPS_TEST_CASE("docs", "42", "order.hpp", "[docs][quick]") { + recursive_path_compare( + x->cbegin(), x->cend(), y->cbegin(), y->cend()); +} + +// presentation.hpp: Line 863 +LIBSEMIGROUPS_TEST_CASE("docs", "43", "presentation.hpp", "[docs][quick]") { + Presentation p; + presentation::to_report_string(p) + // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" +} + +// ranges.hpp: Line 87 +LIBSEMIGROUPS_TEST_CASE("docs", "44", "ranges.hpp", "[docs][quick]") { + auto wg = make>(4, [[0, 1], [1, 0], [2, 2]]); + Paths p(wg); + p.source(0).max(10); + p.count(); // returns 1023 + (p | Random()).get(); // returns random path in p +} + +// schreier-sims.hpp: Line 166 +LIBSEMIGROUPS_TEST_CASE("docs", "45", "schreier-sims.hpp", "[docs][quick]") { + SchreierSims<5> S; + using Perm = decltype(S)::element_type; + S.add_generator(Perm({1, 0, 2, 3, 4})); + S.add_generator(Perm({1, 2, 3, 4, 0})); + S.size(); // 120 +} + +// sims.hpp: Line 2254 +LIBSEMIGROUPS_TEST_CASE("docs", "46", "sims.hpp", "[docs][quick]") { + .min_nodes(1) + .max_nodes(best) + .target_size(target_size()) + .word_graph(); +} + +// to-cong.hpp: Line 52 +LIBSEMIGROUPS_TEST_CASE("docs", "47", "to-cong.hpp", "[docs][quick]") { + to>(knd, fpb, wg); +} + +// to-froidure-pin.hpp: Line 89 +LIBSEMIGROUPS_TEST_CASE("docs", "48", "to-froidure-pin.hpp", "[docs][quick]") { + to(cong); +} + +// to-froidure-pin.hpp: Line 121 +LIBSEMIGROUPS_TEST_CASE("docs", "49", "to-froidure-pin.hpp", "[docs][quick]") { + to(k); +} + +// to-froidure-pin.hpp: Line 159 +LIBSEMIGROUPS_TEST_CASE("docs", "50", "to-froidure-pin.hpp", "[docs][quick]") { + to(kb); +} + +// to-froidure-pin.hpp: Line 193 +LIBSEMIGROUPS_TEST_CASE("docs", "51", "to-froidure-pin.hpp", "[docs][quick]") { + to(k); +} + +// to-froidure-pin.hpp: Line 226 +LIBSEMIGROUPS_TEST_CASE("docs", "52", "to-froidure-pin.hpp", "[docs][quick]") { + to(kb); +} + +// to-froidure-pin.hpp: Line 266 +LIBSEMIGROUPS_TEST_CASE("docs", "53", "to-froidure-pin.hpp", "[docs][quick]") { + to>(wg, 0, 10); +} + +// to-knuth-bendix.hpp: Line 61 +LIBSEMIGROUPS_TEST_CASE("docs", "54", "to-knuth-bendix.hpp", "[docs][quick]") { + to>(knd, fpb); +} + +// to-knuth-bendix.hpp: Line 96 +LIBSEMIGROUPS_TEST_CASE("docs", "55", "to-knuth-bendix.hpp", "[docs][quick]") { + to(knd, tc); +} + +// to-knuth-bendix.hpp: Line 131 +LIBSEMIGROUPS_TEST_CASE("docs", "56", "to-knuth-bendix.hpp", "[docs][quick]") { + to>(knd, tc); +} + +// to-presentation.hpp: Line 65 +LIBSEMIGROUPS_TEST_CASE("docs", "57", "to-presentation.hpp", "[docs][quick]") { + to>(fp); +} + +// to-presentation.hpp: Line 105 +LIBSEMIGROUPS_TEST_CASE("docs", "58", "to-presentation.hpp", "[docs][quick]") { + to>(kb); +} + +// to-presentation.hpp: Line 153 +LIBSEMIGROUPS_TEST_CASE("docs", "59", "to-presentation.hpp", "[docs][quick]") { + to(kb); +} + +// to-presentation.hpp: Line 213 +LIBSEMIGROUPS_TEST_CASE("docs", "60", "to-presentation.hpp", "[docs][quick]") { + to>(k); +} + +// to-presentation.hpp: Line 266 +LIBSEMIGROUPS_TEST_CASE("docs", "61", "to-presentation.hpp", "[docs][quick]") { + to>(p, func); +} + +// to-presentation.hpp: Line 317 +LIBSEMIGROUPS_TEST_CASE("docs", "62", "to-presentation.hpp", "[docs][quick]") { + to>(p, func); +} + +// to-presentation.hpp: Line 369 +LIBSEMIGROUPS_TEST_CASE("docs", "63", "to-presentation.hpp", "[docs][quick]") { + to>(p, func); +} + +// to-presentation.hpp: Line 436 +LIBSEMIGROUPS_TEST_CASE("docs", "64", "to-presentation.hpp", "[docs][quick]") { + to>(ip); +} + +// to-presentation.hpp: Line 504 +LIBSEMIGROUPS_TEST_CASE("docs", "65", "to-presentation.hpp", "[docs][quick]") { + to(p); +} + +// to-todd-coxeter.hpp: Line 62 +LIBSEMIGROUPS_TEST_CASE("docs", "66", "to-todd-coxeter.hpp", "[docs][quick]") { + to>(knd, fpb, wg); +} + +// to-todd-coxeter.hpp: Line 112 +LIBSEMIGROUPS_TEST_CASE("docs", "67", "to-todd-coxeter.hpp", "[docs][quick]") { + to(kb); +} + +// todd-coxeter-class.hpp: Line 80 +LIBSEMIGROUPS_TEST_CASE("docs", "68", "todd-coxeter-class.hpp", "[docs][quick]") { + Presentation p; + p.alphabet(2); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 0_w, 1_w); + ToddCoxeter tc(congruence_kind::onesided, p); + tc.strategy(options::strategy::felsch); + tc.number_of_classes(); + tc.contains(0000_w, 00_w); + tc.index_of(0000_w); +} + +// todd-coxeter-class.hpp: Line 93 +LIBSEMIGROUPS_TEST_CASE("docs", "69", "todd-coxeter-class.hpp", "[docs][quick]") { + Presentation p; + p.alphabet(4); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 10_w, 1_w); + presentation::add_rule(p, 01_w, 1_w); + presentation::add_rule(p, 20_w, 2_w); + presentation::add_rule(p, 02_w, 2_w); + presentation::add_rule(p, 30_w, 3_w); + presentation::add_rule(p, 03_w, 3_w); + presentation::add_rule(p, 11_w, 0_w); + presentation::add_rule(p, 23_w, 0_w); + presentation::add_rule(p, 222_w, 0_w); + presentation::add_rule(p, 12121212121212_w, 0_w); + presentation::add_rule(p, 12131213121312131213121312131213_w, 0_w); + ToddCoxeter tc(congruence_kind::twosided, p); + tc.strategy(options::strategy::hlt) + .lookahead_extent(options::lookahead_extent::partial) + .save(false); + tc.number_of_classes() // 10'752 + tc.standardize(order::recursive); + normal_forms(tc) | rx::take(10) | rx::to_vector() + // {0_w, + // 1_w, + // 2_w, + // 21_w, + // 12_w, + // 121_w, + // 22_w, + // 221_w, + // 212_w, + // 2121_w} + tc.standardize(order::lex); + normal_forms(tc) | rx::take(10) | rx::to_vector() + // {0_w, + // 01_w, + // 012_w, + // 0121_w, + // 01212_w, + // 012121_w, + // 0121212_w, + // 01212121_w, + // 012121212_w, + // 0121212121_w}; +} + +// todd-coxeter-helpers.hpp: Line 95 +LIBSEMIGROUPS_TEST_CASE("docs", "70", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.current_index_of_no_checks(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 118 +LIBSEMIGROUPS_TEST_CASE("docs", "71", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.current_index_of(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 141 +LIBSEMIGROUPS_TEST_CASE("docs", "72", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.index_of_no_checks(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 164 +LIBSEMIGROUPS_TEST_CASE("docs", "73", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.index_of(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 186 +LIBSEMIGROUPS_TEST_CASE("docs", "74", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.current_index_of_no_checks(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 211 +LIBSEMIGROUPS_TEST_CASE("docs", "75", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.current_index_of(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 236 +LIBSEMIGROUPS_TEST_CASE("docs", "76", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.index_of_no_checks(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 261 +LIBSEMIGROUPS_TEST_CASE("docs", "77", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.index_of(std::begin(w), std::end(w)); +} + +// todd-coxeter-helpers.hpp: Line 285 +LIBSEMIGROUPS_TEST_CASE("docs", "78", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.current_index_of_no_checks(w, w + std::strlen(w)); +} + +// todd-coxeter-helpers.hpp: Line 307 +LIBSEMIGROUPS_TEST_CASE("docs", "79", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.current_index_of(w, w + std::strlen(w)); +} + +// todd-coxeter-helpers.hpp: Line 329 +LIBSEMIGROUPS_TEST_CASE("docs", "80", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.index_of_no_checks(w, w + std::strlen(w)); +} + +// todd-coxeter-helpers.hpp: Line 351 +LIBSEMIGROUPS_TEST_CASE("docs", "81", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.index_of(w, w + std::strlen(w)); +} + +// todd-coxeter-helpers.hpp: Line 834 +LIBSEMIGROUPS_TEST_CASE("docs", "82", "todd-coxeter-helpers.hpp", "[docs][quick]") { + Presentation p; + p.alphabet("abcdef"); + p.contains_empty_word(true); + presentation::add_inverse_rules(p, "defabc"); + presentation::add_rule(p, "bbdeaecbffdbaeeccefbccefb", ""); + presentation::add_rule(p, "ccefbfacddecbffaafdcaafdc", ""); + presentation::add_rule(p, "aafdcdbaeefacddbbdeabbdea", ""); + ToddCoxeter tc(congruence_kind.twosided, p); +} + +// todd-coxeter-helpers.hpp: Line 852 +LIBSEMIGROUPS_TEST_CASE("docs", "83", "todd-coxeter-helpers.hpp", "[docs][quick]") { + tc.lookahead_extent(options::lookahead_extent::full) + .lookahead_style(options::lookahead_style::felsch); + + tc.run_for(std::chrono::seconds(1)); + tc.perform_lookahead(true); + + todd_coxeter::perform_lookbehind(tc); + tc.run_for(std::chrono::seconds(1)); + todd_coxeter::perform_lookbehind(tc); + tc.perform_lookahead(true); + tc.number_of_classes(); // returns 1 +} + +// word-graph.hpp: Line 1540 +LIBSEMIGROUPS_TEST_CASE("docs", "84", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(2); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + word_graph::is_acyclic(wg); // returns false +} + +// word-graph.hpp: Line 1583 +LIBSEMIGROUPS_TEST_CASE("docs", "85", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + wg.target(2, 0, 3); + word_graph::is_acyclic(wg); // returns false + word_graph::is_acyclic(wg, 0); // returns false + word_graph::is_acyclic(wg, 1); // returns false + word_graph::is_acyclic(wg, 2); // returns true + word_graph::is_acyclic(wg, 3); // returns true +} + +// word-graph.hpp: Line 1973 +LIBSEMIGROUPS_TEST_CASE("docs", "86", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(1); + wg.target(0, 1, 0); + wg.target(1, 0, 0); + wg.target(2, 3, 0); + word_graph::is_reachable_no_checks(wg, 0, 1); // returns true + word_graph::is_reachable_no_checks(wg, 1, 0); // returns true + word_graph::is_reachable_no_checks(wg, 1, 2); // returns false + word_graph::is_reachable_no_checks(wg, 2, 3); // returns true + word_graph::is_reachable_no_checks(wg, 3, 2); // returns false +} + +// word-graph.hpp: Line 2053 +LIBSEMIGROUPS_TEST_CASE("docs", "87", "word-graph.hpp", "[docs][quick]") { + auto wg = make>( + 5, {{0, 0}, {1, 1}, {2}, {3, 3}}); + word_graph::is_strictly_cyclic(wg); // returns false +} + +// word-graph.hpp: Line 2793 +LIBSEMIGROUPS_TEST_CASE("docs", "88", "word-graph.hpp", "[docs][quick]") { + // Construct a word graph with 5 nodes and 10 edges (7 specified) + make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); +} + +// word-range.hpp: Line 183 +LIBSEMIGROUPS_TEST_CASE("docs", "89", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), + cend_wilo(2, 3, {0}, {1, 1, 1})); + // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; +} + +// word-range.hpp: Line 253 +LIBSEMIGROUPS_TEST_CASE("docs", "90", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), + cend_wislo(2, {0}, {0, 0, 0})); + // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; +} + +// word-range.hpp: Line 313 +LIBSEMIGROUPS_TEST_CASE("docs", "91", "word-range.hpp", "[docs][quick]") { + WordRange words; + words.order(Order::shortlex) // words in shortlex order + .alphabet_size(2) // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 +} + +// word-range.hpp: Line 762 +LIBSEMIGROUPS_TEST_CASE("docs", "92", "word-range.hpp", "[docs][quick]") { + ToWord toword("bac"); + toword("bac"); // returns {0, 1, 2} + toword("bababbbcbc"); // returns { 0, 1, 0, 1, 0, 0, 0, 2, 0, 2} + + toword.init(); + toword("bac"); // returns {1, 0, 2} +} + +// word-range.hpp: Line 1051 +LIBSEMIGROUPS_TEST_CASE("docs", "93", "word-range.hpp", "[docs][quick]") { + StringRange strings; + strings.alphabet("ab").first("a").last("bbbb"); + auto words = (strings | ToWord("ba")); + // contains the words + // {1_w, 0_w, 11_w, 10_w, 01_w, 00_w, 111_w, + // 110_w, 101_w, 100_w, 011_w, 010_w, 001_w, 000_w, + // 1111_w, 1110_w, 1101_w, 1100_w, 1011_w, 1010_w, 1001_w, + // 1000_w, 0111_w, 0110_w, 0101_w, 0100_w, 0011_w, 0010_w, + // 0001_w})); +} + +// word-range.hpp: Line 1151 +LIBSEMIGROUPS_TEST_CASE("docs", "94", "word-range.hpp", "[docs][quick]") { + ToString tostring("bac"); + tostring(word_type({1, 0, 2})); // returns "abc" + tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})); // returns "baabaabc" + + tostring.init(); + tostring(word_type({1, 0, 2})); // returns "bac" +} + +// word-range.hpp: Line 1402 +LIBSEMIGROUPS_TEST_CASE("docs", "95", "word-range.hpp", "[docs][quick]") { + WordRange words; + words.alphabet_size(1).min(0).max(10); + + auto strings = (words | ToString("a")); + // Contains the strings + // {"", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", + // "aaaaaaaa", "aaaaaaaaa"}; +} + +// word-range.hpp: Line 1595 +LIBSEMIGROUPS_TEST_CASE("docs", "96", "word-range.hpp", "[docs][quick]") { + StringRange strings; + strings.order(Order::shortlex) // strings in shortlex order + .alphabet("ab") // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 +} + +// word-range.hpp: Line 2008 +LIBSEMIGROUPS_TEST_CASE("docs", "97", "word-range.hpp", "[docs][quick]") { + 012_w // same as word_type({0, 1, 2}) + "abc"_w // also same as word_type({0, 1, 2}) + "(ab)^3"_p // same as "ababab" +} + +// word-range.hpp: Line 2089 +LIBSEMIGROUPS_TEST_CASE("docs", "98", "word-range.hpp", "[docs][quick]") { + using namespace words; + pow("a", 5) // same as "aaaaa" + 01_w + 2 // same as 012_w + 01_w + 01_w // same as 0101_w + prod(0123_w, 0, 16, 3) // same as 032103_w +} + +// word-range.hpp: Line 2304 +LIBSEMIGROUPS_TEST_CASE("docs", "99", "word-range.hpp", "[docs][quick]") { + using namespace words; + word_type w = 012345_w + prod(w, 0, 5, 2) // {0, 2, 4} + prod(w, 1, 9, 2) // {1, 3, 5, 1} + prod("abcde", 4, 1, -1) // "edc" + prod({"aba", "xyz"}, 0, 4, 1) // "abaxyzabaxyz" +} + + +} \ No newline at end of file From 11120f11edc0a40387b043d6a1a861fdb7dc46f5 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 15 Oct 2025 15:32:31 +0100 Subject: [PATCH 03/11] Implemented \skip-test command for non-executable code examples Fix Identity -> One Include \skip-test for definition examples --- etc/extract-doc-examples.py | 23 +++++++++++++++++++---- include/libsemigroups/action.hpp | 4 ++-- include/libsemigroups/adapters.hpp | 9 +++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index 8aa9fae97..b090eca3e 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -98,6 +98,7 @@ def extract_code_blocks(file_path): try: with open(file_path, "r", encoding="utf-8", errors="ignore") as file: in_code_block = False + ignore_this_block = False current_block = [] for line_num, line in enumerate(file, 1): @@ -123,7 +124,7 @@ def extract_code_blocks(file_path): file_path }:{line_num}" ) - else: + elif not ignore_this_block: code_blocks.append( { "content": "\n".join(current_block), @@ -131,18 +132,32 @@ def extract_code_blocks(file_path): } ) in_code_block = False + ignore_this_block = False current_block = [] continue if in_code_block: if "using namespace libsemigroups" in line: continue - current_block.append(line) + + # If line contains non-executable statements, + # skip this block. + if "\\skip-test" in line: + ignore_this_block = True + current_block = [] + __bold( + f"Note: Example code block skipped in {file_path} at line { + line_num + }" + ) + continue + + if not ignore_this_block: + current_block.append(line) # discard unclosed code blocks if in_code_block and current_block: - __error( - f"Warning: Unclosed code block at end of file {file_path}") + __error(f"Warning: Unclosed code block at end of file {file_path}") except Exception as e: print(f"Error reading file {file_path}: {e}") diff --git a/include/libsemigroups/action.hpp b/include/libsemigroups/action.hpp index 550dca3fe..c80cfe69a 100644 --- a/include/libsemigroups/action.hpp +++ b/include/libsemigroups/action.hpp @@ -59,7 +59,7 @@ namespace libsemigroups { //! using namespace libsemigroups; //! RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> //! o; - //! o.add_seed(PPerm<16>::identity(16)); + //! o.add_seed(PPerm<16>::one(16)); //! o.add_generator( //! PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, //! {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, @@ -143,7 +143,7 @@ namespace libsemigroups { //! auto rg = ReportGuard(true); //! RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> //! o; - //! o.add_seed(PPerm<16>::identity(16)); + //! o.add_seed(PPerm<16>::one(16)); //! o.add_generator( //! PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, //! {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, diff --git a/include/libsemigroups/adapters.hpp b/include/libsemigroups/adapters.hpp index df7ed8d7c..7394d94b2 100644 --- a/include/libsemigroups/adapters.hpp +++ b/include/libsemigroups/adapters.hpp @@ -117,6 +117,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template <> //! struct Complexity { //! constexpr size_t operator()(KBE const&) const noexcept { @@ -155,6 +156,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template <> //! struct Degree { //! constexpr inline size_t operator()(BMat8 const&) const noexcept { @@ -193,6 +195,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template //! struct IncreaseDegree< //! Integral, @@ -220,6 +223,7 @@ namespace libsemigroups { //! 2. `Element operator()(T const&) const` (possibly `noexcept`, //! `inline` and/or `constexpr` also). This could be implemented as: //! \code + //! \skip-test //! Element operator()(Element const& x) const noexcept { //! return this->operator()(Degree()(x)); //! } @@ -236,6 +240,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template //! struct One< //! T, @@ -279,6 +284,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template <> //! struct Product { //! void operator()(size_t& xy, size_t x, size_t y, size_t = 0) const @@ -314,6 +320,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template <> //! struct Inverse { //! inline BMat8 operator()(BMat8 const& x) const noexcept { @@ -346,6 +353,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template <> //! struct ImageLeftAction { //! void operator()(BMat8& res, BMat8 pt, BMat8 x) const noexcept { @@ -388,6 +396,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template <> //! struct ImageLeftAction { //! void operator()(BMat8& res, BMat8 pt, BMat8 x) const noexcept { From e2c36cbc116b67dabb79de631cc91115c3fe83e4 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 26 Oct 2025 19:28:35 +0000 Subject: [PATCH 04/11] Exclude from code example extraction --- etc/extract-doc-examples.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index b090eca3e..c13dd450e 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -51,6 +51,7 @@ def __parse_args() -> argparse.Namespace: python3 extract_code.py <-- Process specific folder Flags: -r | Process folder recursively + -e | Exclude the following files """, ) @@ -69,7 +70,14 @@ def __parse_args() -> argparse.Namespace: ) parser.add_argument( - "--version", action="version", version="Code Block Extractor 1.0" + "-e", + "--exclude", + nargs="+", + help="Files to exclude from docs code example colleciton", + ) + + parser.add_argument( + "--version", action="version", version="Example Code Block Capture 1.0.0" ) args = parser.parse_args() @@ -165,7 +173,7 @@ def extract_code_blocks(file_path): return code_blocks -def process_folder(folder_path, recursive=False): +def process_folder(folder_path, recursive=False, exclude=[]): """ Process all files in a folder to find code examples. @@ -210,7 +218,15 @@ def process_folder(folder_path, recursive=False): for file_path in sorted(files): # Extract example code - code_blocks = extract_code_blocks(file_path) + if (Path(file_path).name in exclude) or (file_path in exclude): + code_blocks = [] + __bold( + f"Note: Excluded { + file_path + } from example code block extraction." + ) + else: + code_blocks = extract_code_blocks(file_path) # Write to cpp test file if code_blocks: @@ -246,7 +262,7 @@ def process_folder(folder_path, recursive=False): def main(): args = __parse_args() - process_folder(args.folder_path, args.recursive) + process_folder(args.folder_path, args.recursive, args.exclude) if __name__ == "__main__": From 4cd40ac37c4728e2ee64e9ae37ddd74763d94db1 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 26 Oct 2025 20:52:23 +0000 Subject: [PATCH 05/11] Example Code Fixes & Skips --- etc/extract-doc-examples.py | 14 +++ include/libsemigroups/cong-class.hpp | 2 +- include/libsemigroups/freeband.hpp | 2 +- include/libsemigroups/froidure-pin.hpp | 17 ++-- .../libsemigroups/is_specialization_of.hpp | 8 +- include/libsemigroups/knuth-bendix-class.hpp | 2 +- include/libsemigroups/konieczny.hpp | 2 + include/libsemigroups/order.hpp | 19 +++- include/libsemigroups/presentation.hpp | 2 +- include/libsemigroups/sims.hpp | 8 +- include/libsemigroups/to-cong.hpp | 1 + include/libsemigroups/to-froidure-pin.hpp | 6 ++ include/libsemigroups/to-knuth-bendix.hpp | 3 + include/libsemigroups/to-presentation.hpp | 95 ++++++++++--------- include/libsemigroups/to-todd-coxeter.hpp | 46 ++++----- include/libsemigroups/word-range.hpp | 21 ++-- 16 files changed, 152 insertions(+), 96 deletions(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index c13dd450e..9f137b207 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -24,9 +24,23 @@ // along with this program. If not, see . // +#include // for size_t +#include // for uint64_t, uint8_t +#include // for initializer_list +#include // for numeric_limits +#include // for basic_string +#include // for string_view +#include // for enable_if_t +#include // for vector, operator== +#include // for forward +#include // for visit, operator== +#include // for vector, operator== + #include "Catch2-3.8.0/catch_amalgamated.hpp" // for REQUIRE, REQUIRE_NOTHROW, REQUIRE_THROWS_AS #include "libsemigroups/libsemigroups.hpp" // for * #include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE + +using namespace libsemigroups::literals; """ ######################################################################## diff --git a/include/libsemigroups/cong-class.hpp b/include/libsemigroups/cong-class.hpp index b14b56382..367110341 100644 --- a/include/libsemigroups/cong-class.hpp +++ b/include/libsemigroups/cong-class.hpp @@ -146,7 +146,7 @@ namespace libsemigroups { //! \par Example //! \code //! Presentation p; - //! p.alphabet(2) + //! p.alphabet(2); //! presentation::add_rule(p, {0, 1}, {}); //! Congruence cong(congruence_kind::twosided, p); //! is_obviously_infinite(cong); // true diff --git a/include/libsemigroups/freeband.hpp b/include/libsemigroups/freeband.hpp index 4632221e6..74e7d748a 100644 --- a/include/libsemigroups/freeband.hpp +++ b/include/libsemigroups/freeband.hpp @@ -76,7 +76,7 @@ namespace libsemigroups { //! freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, //! {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true //! freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false - //! freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}) // true + //! freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true //! freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, //! {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false //! freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true diff --git a/include/libsemigroups/froidure-pin.hpp b/include/libsemigroups/froidure-pin.hpp index 68e0ea400..e6a37d7be 100644 --- a/include/libsemigroups/froidure-pin.hpp +++ b/include/libsemigroups/froidure-pin.hpp @@ -134,6 +134,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! \skip-test //! template <> //! struct Complexity { //! constexpr size_t operator()(int) const noexcept { @@ -171,15 +172,17 @@ namespace libsemigroups { //! xy = x * y; //! } //! }; - //! + //! \endcode + //! \code + //! using namespace froidure_pin; //! FroidurePin S({2}); //! S.size(); // 32 - //! S.number_of_idempotents() // 1 + //! S.number_of_idempotents(); // 1 //! *S.cbegin(); // 2 //! //! FroidurePin T({2, 3}); - //! T.size() // 130 - //! T.number_of_idempotents() // 2 + //! T.size(); // 130 + //! T.number_of_idempotents(); // 2 //! *T.cbegin_idempotents(); // 0 //! *T.cbegin_idempotents() + 1; // 1 //! \endcode @@ -313,7 +316,7 @@ namespace libsemigroups { private: template static constexpr bool IsState - = ((!std::is_void_v) &&std::is_same_v); + = ((!std::is_void_v) && std::is_same_v); //////////////////////////////////////////////////////////////////////// // FroidurePin - data - private @@ -1383,8 +1386,8 @@ namespace libsemigroups { void expand(size_type); void is_one(internal_const_element_type x, element_index_type) noexcept( - std::is_nothrow_default_constructible_v&& noexcept( - std::declval()(x, x))); + std::is_nothrow_default_constructible_v + && noexcept(std::declval()(x, x))); void copy_generators_from_elements(size_t); void closure_update(element_index_type, diff --git a/include/libsemigroups/is_specialization_of.hpp b/include/libsemigroups/is_specialization_of.hpp index 33431f689..43b15d48d 100644 --- a/include/libsemigroups/is_specialization_of.hpp +++ b/include/libsemigroups/is_specialization_of.hpp @@ -41,8 +41,8 @@ namespace libsemigroups { //! //! \par Example //! \code - //! is_specialization_of, std::vector>::value // true - //! is_specialization_of, std::unordered_map>::value + //! is_specialization_of, std::vector>::value; // true + //! is_specialization_of, std::unordered_map>::value; //! // false //! \endcode //! @@ -71,8 +71,8 @@ namespace libsemigroups { //! //! \par Example //! \code - //! is_specialization_of_v, std::vector> // true - //! is_specialization_of_v, std::unordered_map> // false + //! is_specialization_of_v, std::vector>; // true + //! is_specialization_of_v, std::unordered_map>; // false //! \endcode //! //! \note The template parameters of \p Primary must be types, so, for diff --git a/include/libsemigroups/knuth-bendix-class.hpp b/include/libsemigroups/knuth-bendix-class.hpp index 01183de73..af7d03663 100644 --- a/include/libsemigroups/knuth-bendix-class.hpp +++ b/include/libsemigroups/knuth-bendix-class.hpp @@ -77,7 +77,7 @@ namespace libsemigroups { //! presentation::add_rule_no_checks(p, "cd", ""); //! presentation::add_rule_no_checks(p, "dc", ""); //! - //! KnuthBendix kb(twosided, p); + //! KnuthBendix kb(congruence_kind::twosided, p); //! //! !kb.confluent(); // true //! kb.run(); diff --git a/include/libsemigroups/konieczny.hpp b/include/libsemigroups/konieczny.hpp index b97659b4d..1a458687f 100644 --- a/include/libsemigroups/konieczny.hpp +++ b/include/libsemigroups/konieczny.hpp @@ -1905,6 +1905,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! make(gens); //! \endcode //! @@ -1949,6 +1950,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! make(gens); //! \endcode //! diff --git a/include/libsemigroups/order.hpp b/include/libsemigroups/order.hpp index e0a3bf97c..ee92f34c4 100644 --- a/include/libsemigroups/order.hpp +++ b/include/libsemigroups/order.hpp @@ -95,6 +95,8 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code + //! word_type x = random_word(5, 10); + //! word_type y = random_word(5, 10); //! std::lexicographical_compare( //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); //! \endcode @@ -128,8 +130,10 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code + //! word_type x = random_word(5, 10); + //! word_type y = random_word(5, 10); //! lexicographical_compare( - //! x->cbegin(), x->cend(), y->cbegin(), y->cend()); + //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); //! \endcode template bool lexicographical_compare(T* const x, T* const y) { @@ -258,6 +262,7 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code + //! \skip-test //! template //! bool shortlex_compare(T const& first1, //! T const& last1, @@ -302,6 +307,8 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code + //! word_type x = random_word(5, 10); + //! word_type y = random_word(5, 10); //! shortlex_compare( //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); //! \endcode @@ -336,8 +343,10 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code + //! word_type x = random_word(5, 10); + //! word_type y = random_word(5, 10); //! shortlex_compare( - //! x->cbegin(), x->cend(), y->cbegin(), y->cend()); + //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); //! \endcode //! //! \sa @@ -470,6 +479,8 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code + //! word_type x = random_word(5, 10); + //! word_type y = random_word(5, 10); //! recursive_path_compare( //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); //! \endcode @@ -502,8 +513,10 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code + //! word_type x = random_word(5, 10); + //! word_type y = random_word(5, 10); //! recursive_path_compare( - //! x->cbegin(), x->cend(), y->cbegin(), y->cend()); + //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); //! \endcode //! //! \sa diff --git a/include/libsemigroups/presentation.hpp b/include/libsemigroups/presentation.hpp index b8316d43d..6c390a0b7 100644 --- a/include/libsemigroups/presentation.hpp +++ b/include/libsemigroups/presentation.hpp @@ -861,7 +861,7 @@ namespace libsemigroups { //! \par Example //! \code //! Presentation p; - //! presentation::to_report_string(p) + //! presentation::to_report_string(p); //! // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" //! \endcode template diff --git a/include/libsemigroups/sims.hpp b/include/libsemigroups/sims.hpp index fc4e0dacf..a0f4f2001 100644 --- a/include/libsemigroups/sims.hpp +++ b/include/libsemigroups/sims.hpp @@ -1485,7 +1485,7 @@ namespace libsemigroups { uint64_t number_of_congruences(size_type n) const; }; // SimsBase - } // namespace detail + } // namespace detail namespace sims { class const_cgp_iterator; @@ -1967,7 +1967,7 @@ namespace libsemigroups { using SimsBase::IteratorBase::stats; }; // class iterator_base - }; // class Sims2 + }; // class Sims2 //! \ingroup sims_group //! @@ -2250,7 +2250,9 @@ namespace libsemigroups { //! returned (with `0` nodes and `0` edges). //! //! The algorithm implemented by this function repeatedly runs: - //! \code RepOrc(*this) + //! \code + //! \skip-test + //! RepOrc(*this) //! .min_nodes(1) //! .max_nodes(best) //! .target_size(target_size()) diff --git a/include/libsemigroups/to-cong.hpp b/include/libsemigroups/to-cong.hpp index e7cf16320..b457a33ea 100644 --- a/include/libsemigroups/to-cong.hpp +++ b/include/libsemigroups/to-cong.hpp @@ -49,6 +49,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to>(knd, fpb, wg); //! \endcode //! diff --git a/include/libsemigroups/to-froidure-pin.hpp b/include/libsemigroups/to-froidure-pin.hpp index dc316a5b6..43cc2d0e5 100644 --- a/include/libsemigroups/to-froidure-pin.hpp +++ b/include/libsemigroups/to-froidure-pin.hpp @@ -86,6 +86,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to(cong); //! \endcode //! @@ -118,6 +119,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to(k); //! \endcode //! @@ -156,6 +158,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to(kb); //! \endcode //! @@ -190,6 +193,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to(k); //! \endcode //! @@ -223,6 +227,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to(kb); //! \endcode //! @@ -263,6 +268,7 @@ namespace libsemigroups { //! as follows (for example): //! //! \code + //! \skip-test //! to>(wg, 0, 10); //! \endcode //! diff --git a/include/libsemigroups/to-knuth-bendix.hpp b/include/libsemigroups/to-knuth-bendix.hpp index 871de945a..621709582 100644 --- a/include/libsemigroups/to-knuth-bendix.hpp +++ b/include/libsemigroups/to-knuth-bendix.hpp @@ -58,6 +58,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to>(knd, fpb); //! \endcode //! @@ -93,6 +94,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to(knd, tc); //! \endcode //! @@ -128,6 +130,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to>(knd, tc); //! \endcode //! diff --git a/include/libsemigroups/to-presentation.hpp b/include/libsemigroups/to-presentation.hpp index 3785be437..402d616f1 100644 --- a/include/libsemigroups/to-presentation.hpp +++ b/include/libsemigroups/to-presentation.hpp @@ -62,6 +62,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to>(fp); //! \endcode //! @@ -102,6 +103,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to>(kb); //! \endcode //! @@ -150,31 +152,32 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code - //! to(kb); - //! \endcode - //! - //! This function constructs and returns a Presentation object using the - //! currently active rules of \p kb. - //! - //! No enumeration of the argument \p kb is performed, so it might be the - //! case that the resulting presentation does not define the same - //! semigroup/monoid as \p kb. To ensure that the resulting presentation - //! defines the same semigroup as \p kb, run \ref KnuthBendix::run (or any - //! other function that fully enumerates \p kb) prior to calling this - //! function. - //! - //! \tparam Thing used for SFINAE, must be Presentation. - //! \tparam Word the type of the rules in the presentation of the - //! \ref_knuth_bendix object \p kb. - //! \tparam Rewriter the second template parameter for \ref_knuth_bendix. - //! \tparam ReductionOrder the third template parameter for \ref_knuth_bendix. - //! - //! \param kb the \ref_knuth_bendix object from which to obtain the rules. - //! - //! \returns An object of type \c Presentation. - //! - //! \exceptions - //! \no_libsemigroups_except +//! \skip-test +//! to(kb); +//! \endcode +//! +//! This function constructs and returns a Presentation object using the +//! currently active rules of \p kb. +//! +//! No enumeration of the argument \p kb is performed, so it might be the +//! case that the resulting presentation does not define the same +//! semigroup/monoid as \p kb. To ensure that the resulting presentation +//! defines the same semigroup as \p kb, run \ref KnuthBendix::run (or any +//! other function that fully enumerates \p kb) prior to calling this +//! function. +//! +//! \tparam Thing used for SFINAE, must be Presentation. +//! \tparam Word the type of the rules in the presentation of the +//! \ref_knuth_bendix object \p kb. +//! \tparam Rewriter the second template parameter for \ref_knuth_bendix. +//! \tparam ReductionOrder the third template parameter for \ref_knuth_bendix. +//! +//! \param kb the \ref_knuth_bendix object from which to obtain the rules. +//! +//! \returns An object of type \c Presentation. +//! +//! \exceptions +//! \no_libsemigroups_except #ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN // FIXME(1) this is the same hack as elsewhere (deliberately introducing a // typo) because Doxygen conflates functions with trailing return type but the @@ -210,6 +213,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to>(k); //! \endcode //! @@ -263,6 +267,7 @@ namespace libsemigroups { //! follows: //! //! \code + //! \skip-test //! to>(p, func); //! \endcode //! @@ -314,6 +319,7 @@ namespace libsemigroups { //! follows: //! //! \code + //! \skip-test //! to>(p, func); //! \endcode //! @@ -366,6 +372,7 @@ namespace libsemigroups { //! follows: //! //! \code + //! \skip-test //! to>(p, func); //! \endcode //! @@ -433,6 +440,7 @@ namespace libsemigroups { //! follows: //! //! \code + //! \skip-test //! to>(ip); //! \endcode //! @@ -501,24 +509,25 @@ namespace libsemigroups { //! follows: //! //! \code - //! to(p); - //! \endcode - //! - //! This function returns an inverse presentation with rules equivalent to - //! those of the input presentation, but over a normalised alphabet. If the - //! alphabet of \p p is \f$\{a_0, a_1, \dots, a_{n-1}\}\f$, then the - //! alphabet of the returned inverse presentation will be - //! \f$\{0, 1, \dots, n-1, n, \dots, 2n-1\}\f$, where the inverse of letter - //! \f$i\f$ is the letter \f$i + n\, (\text{mod }2n)\f$. - //! - //! \tparam Thing used for SFINAE, must be InversePresentation. - //! \tparam Word the type of the words in the input presentation. - //! \param p the input presentation. - //! - //! \returns A value of type `InversePresentation`. - //! - //! \throws LibsemigroupsException if `p.throw_if_bad_alphabet_or_rules()` - //! throws. +//! \skip-test +//! to(p); +//! \endcode +//! +//! This function returns an inverse presentation with rules equivalent to +//! those of the input presentation, but over a normalised alphabet. If the +//! alphabet of \p p is \f$\{a_0, a_1, \dots, a_{n-1}\}\f$, then the +//! alphabet of the returned inverse presentation will be +//! \f$\{0, 1, \dots, n-1, n, \dots, 2n-1\}\f$, where the inverse of letter +//! \f$i\f$ is the letter \f$i + n\, (\text{mod }2n)\f$. +//! +//! \tparam Thing used for SFINAE, must be InversePresentation. +//! \tparam Word the type of the words in the input presentation. +//! \param p the input presentation. +//! +//! \returns A value of type `InversePresentation`. +//! +//! \throws LibsemigroupsException if `p.throw_if_bad_alphabet_or_rules()` +//! throws. //! //! \note This function will be moved from the header `to-presentation.hpp` to //! `presentation.hpp` in v4 of libsemigroups. diff --git a/include/libsemigroups/to-todd-coxeter.hpp b/include/libsemigroups/to-todd-coxeter.hpp index ad91c88be..8ace14c53 100644 --- a/include/libsemigroups/to-todd-coxeter.hpp +++ b/include/libsemigroups/to-todd-coxeter.hpp @@ -59,28 +59,29 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code - //! to>(knd, fpb, wg); - //! \endcode - //! - //! This function converts the \ref FroidurePin object \p fpb into a - //! \ref_todd_coxeter object using the WordGraph \p wg (which should be either - //! the \ref FroidurePinBase::left_cayley_graph or the - //! \ref FroidurePinBase::right_cayley_graph of \p fpb). - //! - //! \tparam Result used for SFINAE, the return type of this function, must be - //! \c ToddCoxeter for some type \c Word. - //! \tparam Node the type of the nodes in the WordGraph \p wg. - //! - //! \param knd the kind of the congruence being constructed. - //! \param fpb the FroidurePin instance to be converted. - //! \param wg the left or right Cayley graph of \p fpb. - //! - //! \returns A \ref_todd_coxeter object representing the trivial congruence - //! over the semigroup defined by \p fpb. - //! - //! \throws LibsemigroupsException if \p wg is not the - //! \ref FroidurePinBase::left_cayley_graph or the - //! \ref FroidurePinBase::right_cayley_graph of \p fpb. +//! \skip-test +//! to>(knd, fpb, wg); +//! \endcode +//! +//! This function converts the \ref FroidurePin object \p fpb into a +//! \ref_todd_coxeter object using the WordGraph \p wg (which should be either +//! the \ref FroidurePinBase::left_cayley_graph or the +//! \ref FroidurePinBase::right_cayley_graph of \p fpb). +//! +//! \tparam Result used for SFINAE, the return type of this function, must be +//! \c ToddCoxeter for some type \c Word. +//! \tparam Node the type of the nodes in the WordGraph \p wg. +//! +//! \param knd the kind of the congruence being constructed. +//! \param fpb the FroidurePin instance to be converted. +//! \param wg the left or right Cayley graph of \p fpb. +//! +//! \returns A \ref_todd_coxeter object representing the trivial congruence +//! over the semigroup defined by \p fpb. +//! +//! \throws LibsemigroupsException if \p wg is not the +//! \ref FroidurePinBase::left_cayley_graph or the +//! \ref FroidurePinBase::right_cayley_graph of \p fpb. #ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN // FIXME(1) doxygen conflates this version of "to" with the one of the same // signature in "to-cong.hpp" and so we misspell one of the types of the @@ -109,6 +110,7 @@ namespace libsemigroups { //! Despite the hideous signature, this function should be invoked as follows: //! //! \code + //! \skip-test //! to(kb); //! \endcode //! diff --git a/include/libsemigroups/word-range.hpp b/include/libsemigroups/word-range.hpp index 1d6b8c6f3..6ad5b4523 100644 --- a/include/libsemigroups/word-range.hpp +++ b/include/libsemigroups/word-range.hpp @@ -354,8 +354,7 @@ namespace libsemigroups { //! function could be anything. [[nodiscard]] output_type get() const noexcept { set_iterator(); - return std::visit( - [](auto& it) -> auto const& { return *it; }, _current); + return std::visit([](auto& it) -> auto const& { return *it; }, _current); } //! \brief Advance to the next value. @@ -985,7 +984,7 @@ namespace libsemigroups { //! * \ref literals [[nodiscard]] word_type operator()(From const& input) const { word_type output; - operator()(output, input); + operator()(output, input); return output; } @@ -1360,7 +1359,7 @@ namespace libsemigroups { //! * \ref literals [[nodiscard]] std::string operator()(word_type const& input) const { std::string output; - operator()(output, input); + operator()(output, input); return output; } @@ -1385,7 +1384,7 @@ namespace libsemigroups { operator()(std::initializer_list input) const { static_assert(std::is_integral_v); word_type copy(input.begin(), input.end()); - return operator()(copy); + return operator()(copy); } template @@ -2005,6 +2004,7 @@ namespace libsemigroups { //! in a compact form. //! \par Example //! \code + //! \skip-test //! 012_w // same as word_type({0, 1, 2}) //! "abc"_w // also same as word_type({0, 1, 2}) //! "(ab)^3"_p // same as "ababab" @@ -2086,6 +2086,7 @@ namespace libsemigroups { //! in a compact form. //! \par Example //! \code + //! \skip-test //! using namespace words; //! pow("a", 5) // same as "aaaaa" //! 01_w + 2 // same as 012_w @@ -2302,11 +2303,11 @@ namespace libsemigroups { //! \par Examples //! \code //! using namespace words; - //! word_type w = 012345_w - //! prod(w, 0, 5, 2) // {0, 2, 4} - //! prod(w, 1, 9, 2) // {1, 3, 5, 1} - //! prod("abcde", 4, 1, -1) // "edc" - //! prod({"aba", "xyz"}, 0, 4, 1) // "abaxyzabaxyz" + //! word_type w = 012345_w; + //! prod(w, 0, 5, 2); // {0, 2, 4} + //! prod(w, 1, 9, 2); // {1, 3, 5, 1} + //! prod("abcde", 4, 1, -1); // "edc" + //! prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" //! \endcode template Word prod(Container const& elts, int first, int last, int step = 1); From de191409dd336b0e9192d778cbd16327b8bb5328 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 29 Oct 2025 15:40:23 +0000 Subject: [PATCH 06/11] Paths pipe operator not implemented for Random? --- include/libsemigroups/ranges.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/libsemigroups/ranges.hpp b/include/libsemigroups/ranges.hpp index b84171537..386c6dd4c 100644 --- a/include/libsemigroups/ranges.hpp +++ b/include/libsemigroups/ranges.hpp @@ -84,11 +84,13 @@ namespace libsemigroups { //! //! \par Example //! \code - //! auto wg = make>(4, [[0, 1], [1, 0], [2, 2]]); + //! using rx::operator|; + //! auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); //! Paths p(wg); //! p.source(0).max(10); //! p.count(); // returns 1023 - //! (p | Random()).get(); // returns random path in p + //! // (p | Random()).get(); // returns random path in p (Pipe operator not + //! // implemented for Paths?) //! \endcode // TODO(2) this should be able to emit any number of random items not only // one. From e3ef9ec7e905ae9bed82f78e41fd1242382ae843 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 2 Nov 2025 22:45:52 +0000 Subject: [PATCH 07/11] small fix for empty file exclude cl args --- etc/extract-doc-examples.py | 18 +- include/libsemigroups/froidure-pin.hpp | 1 + tests/test-docs-code-examples.cpp | 510 ++++++------------------- 3 files changed, 117 insertions(+), 412 deletions(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index 9f137b207..63a94e736 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -24,18 +24,6 @@ // along with this program. If not, see . // -#include // for size_t -#include // for uint64_t, uint8_t -#include // for initializer_list -#include // for numeric_limits -#include // for basic_string -#include // for string_view -#include // for enable_if_t -#include // for vector, operator== -#include // for forward -#include // for visit, operator== -#include // for vector, operator== - #include "Catch2-3.8.0/catch_amalgamated.hpp" // for REQUIRE, REQUIRE_NOTHROW, REQUIRE_THROWS_AS #include "libsemigroups/libsemigroups.hpp" // for * #include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE @@ -179,7 +167,8 @@ def extract_code_blocks(file_path): # discard unclosed code blocks if in_code_block and current_block: - __error(f"Warning: Unclosed code block at end of file {file_path}") + __error( + f"Warning: Unclosed code block at end of file {file_path}") except Exception as e: print(f"Error reading file {file_path}: {e}") @@ -276,7 +265,8 @@ def process_folder(folder_path, recursive=False, exclude=[]): def main(): args = __parse_args() - process_folder(args.folder_path, args.recursive, args.exclude) + exclude = args.exclude if not args.exclude is None else [] + process_folder(args.folder_path, args.recursive, exclude) if __name__ == "__main__": diff --git a/include/libsemigroups/froidure-pin.hpp b/include/libsemigroups/froidure-pin.hpp index e6a37d7be..1900fe86a 100644 --- a/include/libsemigroups/froidure-pin.hpp +++ b/include/libsemigroups/froidure-pin.hpp @@ -174,6 +174,7 @@ namespace libsemigroups { //! }; //! \endcode //! \code + //! \skip-test This is closer to a style guide. //! using namespace froidure_pin; //! FroidurePin S({2}); //! S.size(); // 32 diff --git a/tests/test-docs-code-examples.cpp b/tests/test-docs-code-examples.cpp index 0d395fc26..649e361a2 100644 --- a/tests/test-docs-code-examples.cpp +++ b/tests/test-docs-code-examples.cpp @@ -19,6 +19,8 @@ #include "libsemigroups/libsemigroups.hpp" // for * #include "test-main.hpp" // for LIBSEMIGROUPS_TEST_CASE +using namespace libsemigroups::literals; + namespace libsemigroups { // action.hpp: Line 60 LIBSEMIGROUPS_TEST_CASE("docs", "0", "action.hpp", "[docs][quick]") { @@ -72,107 +74,10 @@ LIBSEMIGROUPS_TEST_CASE("docs", "1", "action.hpp", "[docs][quick]") { o.scc().number_of_components(); // 17 } -// adapters.hpp: Line 120 -LIBSEMIGROUPS_TEST_CASE("docs", "2", "adapters.hpp", "[docs][quick]") { - template <> - struct Complexity { - constexpr size_t operator()(KBE const&) const noexcept { - return LIMIT_MAX; - } - }; -} - -// adapters.hpp: Line 158 -LIBSEMIGROUPS_TEST_CASE("docs", "3", "adapters.hpp", "[docs][quick]") { - template <> - struct Degree { - constexpr inline size_t operator()(BMat8 const&) const noexcept { - return 8; - } - }; -} - -// adapters.hpp: Line 196 -LIBSEMIGROUPS_TEST_CASE("docs", "4", "adapters.hpp", "[docs][quick]") { - template - struct IncreaseDegree< - Integral, - typename std::enable_if::value>::type> - { - void operator()(Integral&, size_t) const noexcept { - } - }; -} - -// adapters.hpp: Line 223 -LIBSEMIGROUPS_TEST_CASE("docs", "5", "adapters.hpp", "[docs][quick]") { - Element operator()(Element const& x) const noexcept { - return this->operator()(Degree()(x)); - } -} - -// adapters.hpp: Line 239 -LIBSEMIGROUPS_TEST_CASE("docs", "6", "adapters.hpp", "[docs][quick]") { - template - struct One< - T, - typename std::enable_if::value>::type> { - T operator()(size_t = 0) const noexcept { - return T::one(); - } - - T operator()(T const&) const noexcept { - return T::one(); - } - }; -} - -// adapters.hpp: Line 282 -LIBSEMIGROUPS_TEST_CASE("docs", "7", "adapters.hpp", "[docs][quick]") { - template <> - struct Product { - void operator()(size_t& xy, size_t x, size_t y, size_t = 0) const - noexcept { - xy = x * y; - } - }; -} - -// adapters.hpp: Line 317 -LIBSEMIGROUPS_TEST_CASE("docs", "8", "adapters.hpp", "[docs][quick]") { - template <> - struct Inverse { - inline BMat8 operator()(BMat8 const& x) const noexcept { - LIBSEMIGROUPS_ASSERT(x * x.transpose() == x.one()); - return x.transpose(); - } - }; -} - -// adapters.hpp: Line 349 -LIBSEMIGROUPS_TEST_CASE("docs", "9", "adapters.hpp", "[docs][quick]") { - template <> - struct ImageLeftAction { - void operator()(BMat8& res, BMat8 pt, BMat8 x) const noexcept { - res = (x * pt).col_space_basis(); - } - }; -} - -// adapters.hpp: Line 391 -LIBSEMIGROUPS_TEST_CASE("docs", "10", "adapters.hpp", "[docs][quick]") { - template <> - struct ImageLeftAction { - void operator()(BMat8& res, BMat8 pt, BMat8 x) const noexcept { - res = (x * pt).row_space_basis(); - } - }; -} - // cong-class.hpp: Line 148 -LIBSEMIGROUPS_TEST_CASE("docs", "11", "cong-class.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "2", "cong-class.hpp", "[docs][quick]") { Presentation p; - p.alphabet(2) + p.alphabet(2); presentation::add_rule(p, {0, 1}, {}); Congruence cong(congruence_kind::twosided, p); is_obviously_infinite(cong); // true @@ -181,11 +86,11 @@ LIBSEMIGROUPS_TEST_CASE("docs", "11", "cong-class.hpp", "[docs][quick]") { } // freeband.hpp: Line 76 -LIBSEMIGROUPS_TEST_CASE("docs", "12", "freeband.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "3", "freeband.hpp", "[docs][quick]") { freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false - freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}) // true + freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true @@ -196,7 +101,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "12", "freeband.hpp", "[docs][quick]") { } // froidure-pin-base.hpp: Line 1337 -LIBSEMIGROUPS_TEST_CASE("docs", "13", "froidure-pin-base.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "4", "froidure-pin-base.hpp", "[docs][quick]") { FroidurePin S; S.add_generator(BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, @@ -235,7 +140,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "13", "froidure-pin-base.hpp", "[docs][quick]") } // froidure-pin-base.hpp: Line 1441 -LIBSEMIGROUPS_TEST_CASE("docs", "14", "froidure-pin-base.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "5", "froidure-pin-base.hpp", "[docs][quick]") { FroidurePin S; S.add_generator(BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, @@ -273,73 +178,21 @@ LIBSEMIGROUPS_TEST_CASE("docs", "14", "froidure-pin-base.hpp", "[docs][quick]") // {{3, 3}, {3}}} } -// froidure-pin.hpp: Line 137 -LIBSEMIGROUPS_TEST_CASE("docs", "15", "froidure-pin.hpp", "[docs][quick]") { - template <> - struct Complexity { - constexpr size_t operator()(int) const noexcept { - return 0; - } - }; - - template <> - struct Degree { - constexpr size_t operator()(int) const noexcept { - return 0; - } - }; - - template <> - struct IncreaseDegree { - int operator()(int x) const noexcept { - return x; - } - }; - - template <> - struct One { - constexpr int operator()(int) const noexcept { - return 1; - } - }; - - template <> - struct Product { - void operator()(int& xy, - int x, - int y, - size_t = 0) const noexcept { - xy = x * y; - } - }; - - FroidurePin S({2}); - S.size(); // 32 - S.number_of_idempotents() // 1 - *S.cbegin(); // 2 - - FroidurePin T({2, 3}); - T.size() // 130 - T.number_of_idempotents() // 2 - *T.cbegin_idempotents(); // 0 - *T.cbegin_idempotents() + 1; // 1 -} - // is_specialization_of.hpp: Line 44 -LIBSEMIGROUPS_TEST_CASE("docs", "16", "is_specialization_of.hpp", "[docs][quick]") { - is_specialization_of, std::vector>::value // true - is_specialization_of, std::unordered_map>::value +LIBSEMIGROUPS_TEST_CASE("docs", "6", "is_specialization_of.hpp", "[docs][quick]") { + is_specialization_of, std::vector>::value; // true + is_specialization_of, std::unordered_map>::value; // false } // is_specialization_of.hpp: Line 74 -LIBSEMIGROUPS_TEST_CASE("docs", "17", "is_specialization_of.hpp", "[docs][quick]") { - is_specialization_of_v, std::vector> // true - is_specialization_of_v, std::unordered_map> // false +LIBSEMIGROUPS_TEST_CASE("docs", "7", "is_specialization_of.hpp", "[docs][quick]") { + is_specialization_of_v, std::vector>; // true + is_specialization_of_v, std::unordered_map>; // false } // knuth-bendix-class.hpp: Line 72 -LIBSEMIGROUPS_TEST_CASE("docs", "18", "knuth-bendix-class.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "8", "knuth-bendix-class.hpp", "[docs][quick]") { Presentation p; p.contains_empty_word(true); p.alphabet("abcd"); @@ -348,7 +201,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "18", "knuth-bendix-class.hpp", "[docs][quick]") presentation::add_rule_no_checks(p, "cd", ""); presentation::add_rule_no_checks(p, "dc", ""); - KnuthBendix kb(twosided, p); + KnuthBendix kb(congruence_kind::twosided, p); !kb.confluent(); // true kb.run(); @@ -358,7 +211,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "18", "knuth-bendix-class.hpp", "[docs][quick]") } // konieczny.hpp: Line 70 -LIBSEMIGROUPS_TEST_CASE("docs", "19", "konieczny.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "9", "konieczny.hpp", "[docs][quick]") { auto S = make({ BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), @@ -368,38 +221,28 @@ LIBSEMIGROUPS_TEST_CASE("docs", "19", "konieczny.hpp", "[docs][quick]") { S.number_of_idempotents(); //returns 2'360 } -// konieczny.hpp: Line 1908 -LIBSEMIGROUPS_TEST_CASE("docs", "20", "konieczny.hpp", "[docs][quick]") { - make(gens); -} - -// konieczny.hpp: Line 1952 -LIBSEMIGROUPS_TEST_CASE("docs", "21", "konieczny.hpp", "[docs][quick]") { - make(gens); -} - // matrix.hpp: Line 1964 -LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "10", "matrix.hpp", "[docs][quick]") { Mat m({{1, 1}, {0, 0}}); } // matrix.hpp: Line 2866 -LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "11", "matrix.hpp", "[docs][quick]") { Mat m(2, 3); // construct a 2 x 3 matrix } // matrix.hpp: Line 2888 -LIBSEMIGROUPS_TEST_CASE("docs", "24", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "12", "matrix.hpp", "[docs][quick]") { Mat m({1, 1, 0, 0}); } // matrix.hpp: Line 2910 -LIBSEMIGROUPS_TEST_CASE("docs", "25", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "13", "matrix.hpp", "[docs][quick]") { Mat m({{1, 1}, {0, 0}}); } // matrix.hpp: Line 3814 -LIBSEMIGROUPS_TEST_CASE("docs", "26", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "14", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix BMat<3> m; // construct an uninitialized 4 x 4 dynamic matrix @@ -407,7 +250,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "26", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 4121 -LIBSEMIGROUPS_TEST_CASE("docs", "27", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "15", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix IntMat<3> m; // construct an uninitialized 4 x 4 dynamic matrix @@ -415,7 +258,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "27", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 4411 -LIBSEMIGROUPS_TEST_CASE("docs", "28", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "16", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix MaxPlusMat<3> m; // construct an uninitialized 4 x 4 dynamic matrix @@ -423,7 +266,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "28", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 4720 -LIBSEMIGROUPS_TEST_CASE("docs", "29", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "17", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix MinPlusMat<3> m; // construct an uninitialized 4 x 4 dynamic matrix @@ -431,7 +274,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "29", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 5039 -LIBSEMIGROUPS_TEST_CASE("docs", "30", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "18", "matrix.hpp", "[docs][quick]") { // construct an uninitialized 3 x 3 static matrix with threshold 11 MaxPlusTruncMat<11, 3> m; // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 @@ -444,7 +287,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "30", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 5520 -LIBSEMIGROUPS_TEST_CASE("docs", "31", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "19", "matrix.hpp", "[docs][quick]") { // construct an uninitialized 3 x 3 static matrix with threshold 11 MinPlusTruncMat<11, 3> m; // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 @@ -457,7 +300,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "31", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 6006 -LIBSEMIGROUPS_TEST_CASE("docs", "32", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "20", "matrix.hpp", "[docs][quick]") { // construct an uninitialized 3 x 3 static matrix with threshold // 11, period 2 NTPMat<11, 2, 3> m; @@ -472,7 +315,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "32", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 6984 -LIBSEMIGROUPS_TEST_CASE("docs", "33", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "21", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix ProjMaxPlusMat<3> m; // construct an uninitialized 4 x 4 dynamic matrix @@ -480,7 +323,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "33", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 7149 -LIBSEMIGROUPS_TEST_CASE("docs", "34", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { auto x == make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, 1}})); // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} @@ -488,79 +331,79 @@ LIBSEMIGROUPS_TEST_CASE("docs", "34", "matrix.hpp", "[docs][quick]") { } // matrix.hpp: Line 7897 -LIBSEMIGROUPS_TEST_CASE("docs", "35", "matrix.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); matrix::row_space_size(x); // returns 7 } // order.hpp: Line 98 -LIBSEMIGROUPS_TEST_CASE("docs", "36", "order.hpp", "[docs][quick]") { - std::lexicographical_compare( +LIBSEMIGROUPS_TEST_CASE("docs", "24", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + std::lexicographical_compare( x.cbegin(), x.cend(), y.cbegin(), y.cend()); } -// order.hpp: Line 131 -LIBSEMIGROUPS_TEST_CASE("docs", "37", "order.hpp", "[docs][quick]") { - lexicographical_compare( - x->cbegin(), x->cend(), y->cbegin(), y->cend()); -} - -// order.hpp: Line 261 -LIBSEMIGROUPS_TEST_CASE("docs", "38", "order.hpp", "[docs][quick]") { - template - bool shortlex_compare(T const& first1, - T const& last1, - S const& first2, - S const& last2) { - return (last1 - first1) < (last2 - first2) - || ((last1 - first1) == (last2 - first2) - && std::lexicographical_compare - (first1, last1, first2, last2)); - } +// order.hpp: Line 133 +LIBSEMIGROUPS_TEST_CASE("docs", "25", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + lexicographical_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); } -// order.hpp: Line 305 -LIBSEMIGROUPS_TEST_CASE("docs", "39", "order.hpp", "[docs][quick]") { - shortlex_compare( +// order.hpp: Line 310 +LIBSEMIGROUPS_TEST_CASE("docs", "26", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare( x.cbegin(), x.cend(), y.cbegin(), y.cend()); } -// order.hpp: Line 339 -LIBSEMIGROUPS_TEST_CASE("docs", "40", "order.hpp", "[docs][quick]") { - shortlex_compare( - x->cbegin(), x->cend(), y->cbegin(), y->cend()); +// order.hpp: Line 346 +LIBSEMIGROUPS_TEST_CASE("docs", "27", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); } -// order.hpp: Line 473 -LIBSEMIGROUPS_TEST_CASE("docs", "41", "order.hpp", "[docs][quick]") { - recursive_path_compare( +// order.hpp: Line 482 +LIBSEMIGROUPS_TEST_CASE("docs", "28", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare( x.cbegin(), x.cend(), y.cbegin(), y.cend()); } -// order.hpp: Line 505 -LIBSEMIGROUPS_TEST_CASE("docs", "42", "order.hpp", "[docs][quick]") { - recursive_path_compare( - x->cbegin(), x->cend(), y->cbegin(), y->cend()); +// order.hpp: Line 516 +LIBSEMIGROUPS_TEST_CASE("docs", "29", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); } // presentation.hpp: Line 863 -LIBSEMIGROUPS_TEST_CASE("docs", "43", "presentation.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "30", "presentation.hpp", "[docs][quick]") { Presentation p; - presentation::to_report_string(p) + presentation::to_report_string(p); // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" } // ranges.hpp: Line 87 -LIBSEMIGROUPS_TEST_CASE("docs", "44", "ranges.hpp", "[docs][quick]") { - auto wg = make>(4, [[0, 1], [1, 0], [2, 2]]); +LIBSEMIGROUPS_TEST_CASE("docs", "31", "ranges.hpp", "[docs][quick]") { + using rx::operator|; + auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); Paths p(wg); p.source(0).max(10); p.count(); // returns 1023 - (p | Random()).get(); // returns random path in p + // (p | Random()).get(); // returns random path in p (Pipe operator not + // implemented for Paths?) } // schreier-sims.hpp: Line 166 -LIBSEMIGROUPS_TEST_CASE("docs", "45", "schreier-sims.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "32", "schreier-sims.hpp", "[docs][quick]") { SchreierSims<5> S; using Perm = decltype(S)::element_type; S.add_generator(Perm({1, 0, 2, 3, 4})); @@ -568,121 +411,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "45", "schreier-sims.hpp", "[docs][quick]") { S.size(); // 120 } -// sims.hpp: Line 2254 -LIBSEMIGROUPS_TEST_CASE("docs", "46", "sims.hpp", "[docs][quick]") { - .min_nodes(1) - .max_nodes(best) - .target_size(target_size()) - .word_graph(); -} - -// to-cong.hpp: Line 52 -LIBSEMIGROUPS_TEST_CASE("docs", "47", "to-cong.hpp", "[docs][quick]") { - to>(knd, fpb, wg); -} - -// to-froidure-pin.hpp: Line 89 -LIBSEMIGROUPS_TEST_CASE("docs", "48", "to-froidure-pin.hpp", "[docs][quick]") { - to(cong); -} - -// to-froidure-pin.hpp: Line 121 -LIBSEMIGROUPS_TEST_CASE("docs", "49", "to-froidure-pin.hpp", "[docs][quick]") { - to(k); -} - -// to-froidure-pin.hpp: Line 159 -LIBSEMIGROUPS_TEST_CASE("docs", "50", "to-froidure-pin.hpp", "[docs][quick]") { - to(kb); -} - -// to-froidure-pin.hpp: Line 193 -LIBSEMIGROUPS_TEST_CASE("docs", "51", "to-froidure-pin.hpp", "[docs][quick]") { - to(k); -} - -// to-froidure-pin.hpp: Line 226 -LIBSEMIGROUPS_TEST_CASE("docs", "52", "to-froidure-pin.hpp", "[docs][quick]") { - to(kb); -} - -// to-froidure-pin.hpp: Line 266 -LIBSEMIGROUPS_TEST_CASE("docs", "53", "to-froidure-pin.hpp", "[docs][quick]") { - to>(wg, 0, 10); -} - -// to-knuth-bendix.hpp: Line 61 -LIBSEMIGROUPS_TEST_CASE("docs", "54", "to-knuth-bendix.hpp", "[docs][quick]") { - to>(knd, fpb); -} - -// to-knuth-bendix.hpp: Line 96 -LIBSEMIGROUPS_TEST_CASE("docs", "55", "to-knuth-bendix.hpp", "[docs][quick]") { - to(knd, tc); -} - -// to-knuth-bendix.hpp: Line 131 -LIBSEMIGROUPS_TEST_CASE("docs", "56", "to-knuth-bendix.hpp", "[docs][quick]") { - to>(knd, tc); -} - -// to-presentation.hpp: Line 65 -LIBSEMIGROUPS_TEST_CASE("docs", "57", "to-presentation.hpp", "[docs][quick]") { - to>(fp); -} - -// to-presentation.hpp: Line 105 -LIBSEMIGROUPS_TEST_CASE("docs", "58", "to-presentation.hpp", "[docs][quick]") { - to>(kb); -} - -// to-presentation.hpp: Line 153 -LIBSEMIGROUPS_TEST_CASE("docs", "59", "to-presentation.hpp", "[docs][quick]") { - to(kb); -} - -// to-presentation.hpp: Line 213 -LIBSEMIGROUPS_TEST_CASE("docs", "60", "to-presentation.hpp", "[docs][quick]") { - to>(k); -} - -// to-presentation.hpp: Line 266 -LIBSEMIGROUPS_TEST_CASE("docs", "61", "to-presentation.hpp", "[docs][quick]") { - to>(p, func); -} - -// to-presentation.hpp: Line 317 -LIBSEMIGROUPS_TEST_CASE("docs", "62", "to-presentation.hpp", "[docs][quick]") { - to>(p, func); -} - -// to-presentation.hpp: Line 369 -LIBSEMIGROUPS_TEST_CASE("docs", "63", "to-presentation.hpp", "[docs][quick]") { - to>(p, func); -} - -// to-presentation.hpp: Line 436 -LIBSEMIGROUPS_TEST_CASE("docs", "64", "to-presentation.hpp", "[docs][quick]") { - to>(ip); -} - -// to-presentation.hpp: Line 504 -LIBSEMIGROUPS_TEST_CASE("docs", "65", "to-presentation.hpp", "[docs][quick]") { - to(p); -} - -// to-todd-coxeter.hpp: Line 62 -LIBSEMIGROUPS_TEST_CASE("docs", "66", "to-todd-coxeter.hpp", "[docs][quick]") { - to>(knd, fpb, wg); -} - -// to-todd-coxeter.hpp: Line 112 -LIBSEMIGROUPS_TEST_CASE("docs", "67", "to-todd-coxeter.hpp", "[docs][quick]") { - to(kb); -} - // todd-coxeter-class.hpp: Line 80 -LIBSEMIGROUPS_TEST_CASE("docs", "68", "todd-coxeter-class.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "33", "todd-coxeter-class.hpp", "[docs][quick]") { Presentation p; p.alphabet(2); presentation::add_rule(p, 00_w, 0_w); @@ -695,7 +425,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "68", "todd-coxeter-class.hpp", "[docs][quick]") } // todd-coxeter-class.hpp: Line 93 -LIBSEMIGROUPS_TEST_CASE("docs", "69", "todd-coxeter-class.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") { Presentation p; p.alphabet(4); presentation::add_rule(p, 00_w, 0_w); @@ -742,67 +472,67 @@ LIBSEMIGROUPS_TEST_CASE("docs", "69", "todd-coxeter-class.hpp", "[docs][quick]") } // todd-coxeter-helpers.hpp: Line 95 -LIBSEMIGROUPS_TEST_CASE("docs", "70", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "35", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.current_index_of_no_checks(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 118 -LIBSEMIGROUPS_TEST_CASE("docs", "71", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "36", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.current_index_of(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 141 -LIBSEMIGROUPS_TEST_CASE("docs", "72", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "37", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.index_of_no_checks(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 164 -LIBSEMIGROUPS_TEST_CASE("docs", "73", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "38", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.index_of(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 186 -LIBSEMIGROUPS_TEST_CASE("docs", "74", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "39", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.current_index_of_no_checks(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 211 -LIBSEMIGROUPS_TEST_CASE("docs", "75", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "40", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.current_index_of(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 236 -LIBSEMIGROUPS_TEST_CASE("docs", "76", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "41", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.index_of_no_checks(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 261 -LIBSEMIGROUPS_TEST_CASE("docs", "77", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "42", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.index_of(std::begin(w), std::end(w)); } // todd-coxeter-helpers.hpp: Line 285 -LIBSEMIGROUPS_TEST_CASE("docs", "78", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "43", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.current_index_of_no_checks(w, w + std::strlen(w)); } // todd-coxeter-helpers.hpp: Line 307 -LIBSEMIGROUPS_TEST_CASE("docs", "79", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "44", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.current_index_of(w, w + std::strlen(w)); } // todd-coxeter-helpers.hpp: Line 329 -LIBSEMIGROUPS_TEST_CASE("docs", "80", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "45", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.index_of_no_checks(w, w + std::strlen(w)); } // todd-coxeter-helpers.hpp: Line 351 -LIBSEMIGROUPS_TEST_CASE("docs", "81", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "46", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.index_of(w, w + std::strlen(w)); } // todd-coxeter-helpers.hpp: Line 834 -LIBSEMIGROUPS_TEST_CASE("docs", "82", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "47", "todd-coxeter-helpers.hpp", "[docs][quick]") { Presentation p; p.alphabet("abcdef"); p.contains_empty_word(true); @@ -814,7 +544,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "82", "todd-coxeter-helpers.hpp", "[docs][quick] } // todd-coxeter-helpers.hpp: Line 852 -LIBSEMIGROUPS_TEST_CASE("docs", "83", "todd-coxeter-helpers.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "48", "todd-coxeter-helpers.hpp", "[docs][quick]") { tc.lookahead_extent(options::lookahead_extent::full) .lookahead_style(options::lookahead_style::felsch); @@ -829,7 +559,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "83", "todd-coxeter-helpers.hpp", "[docs][quick] } // word-graph.hpp: Line 1540 -LIBSEMIGROUPS_TEST_CASE("docs", "84", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "49", "word-graph.hpp", "[docs][quick]") { WordGraph wg; wg.add_nodes(2); wg.add_to_out_degree(1); @@ -839,7 +569,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "84", "word-graph.hpp", "[docs][quick]") { } // word-graph.hpp: Line 1583 -LIBSEMIGROUPS_TEST_CASE("docs", "85", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "50", "word-graph.hpp", "[docs][quick]") { WordGraph wg; wg.add_nodes(4); wg.add_to_out_degree(1); @@ -854,7 +584,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "85", "word-graph.hpp", "[docs][quick]") { } // word-graph.hpp: Line 1973 -LIBSEMIGROUPS_TEST_CASE("docs", "86", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "51", "word-graph.hpp", "[docs][quick]") { WordGraph wg; wg.add_nodes(4); wg.add_to_out_degree(1); @@ -869,34 +599,34 @@ LIBSEMIGROUPS_TEST_CASE("docs", "86", "word-graph.hpp", "[docs][quick]") { } // word-graph.hpp: Line 2053 -LIBSEMIGROUPS_TEST_CASE("docs", "87", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "52", "word-graph.hpp", "[docs][quick]") { auto wg = make>( 5, {{0, 0}, {1, 1}, {2}, {3, 3}}); word_graph::is_strictly_cyclic(wg); // returns false } // word-graph.hpp: Line 2793 -LIBSEMIGROUPS_TEST_CASE("docs", "88", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "53", "word-graph.hpp", "[docs][quick]") { // Construct a word graph with 5 nodes and 10 edges (7 specified) make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); } // word-range.hpp: Line 183 -LIBSEMIGROUPS_TEST_CASE("docs", "89", "word-range.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "54", "word-range.hpp", "[docs][quick]") { std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), cend_wilo(2, 3, {0}, {1, 1, 1})); // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; } // word-range.hpp: Line 253 -LIBSEMIGROUPS_TEST_CASE("docs", "90", "word-range.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "55", "word-range.hpp", "[docs][quick]") { std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), cend_wislo(2, {0}, {0, 0, 0})); // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; } // word-range.hpp: Line 313 -LIBSEMIGROUPS_TEST_CASE("docs", "91", "word-range.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "56", "word-range.hpp", "[docs][quick]") { WordRange words; words.order(Order::shortlex) // words in shortlex order .alphabet_size(2) // on 2 letters @@ -904,8 +634,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "91", "word-range.hpp", "[docs][quick]") { .max(5); // to 5 } -// word-range.hpp: Line 762 -LIBSEMIGROUPS_TEST_CASE("docs", "92", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 761 +LIBSEMIGROUPS_TEST_CASE("docs", "57", "word-range.hpp", "[docs][quick]") { ToWord toword("bac"); toword("bac"); // returns {0, 1, 2} toword("bababbbcbc"); // returns { 0, 1, 0, 1, 0, 0, 0, 2, 0, 2} @@ -914,8 +644,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "92", "word-range.hpp", "[docs][quick]") { toword("bac"); // returns {1, 0, 2} } -// word-range.hpp: Line 1051 -LIBSEMIGROUPS_TEST_CASE("docs", "93", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 1050 +LIBSEMIGROUPS_TEST_CASE("docs", "58", "word-range.hpp", "[docs][quick]") { StringRange strings; strings.alphabet("ab").first("a").last("bbbb"); auto words = (strings | ToWord("ba")); @@ -927,8 +657,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "93", "word-range.hpp", "[docs][quick]") { // 0001_w})); } -// word-range.hpp: Line 1151 -LIBSEMIGROUPS_TEST_CASE("docs", "94", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 1150 +LIBSEMIGROUPS_TEST_CASE("docs", "59", "word-range.hpp", "[docs][quick]") { ToString tostring("bac"); tostring(word_type({1, 0, 2})); // returns "abc" tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})); // returns "baabaabc" @@ -937,8 +667,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "94", "word-range.hpp", "[docs][quick]") { tostring(word_type({1, 0, 2})); // returns "bac" } -// word-range.hpp: Line 1402 -LIBSEMIGROUPS_TEST_CASE("docs", "95", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 1401 +LIBSEMIGROUPS_TEST_CASE("docs", "60", "word-range.hpp", "[docs][quick]") { WordRange words; words.alphabet_size(1).min(0).max(10); @@ -948,8 +678,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "95", "word-range.hpp", "[docs][quick]") { // "aaaaaaaa", "aaaaaaaaa"}; } -// word-range.hpp: Line 1595 -LIBSEMIGROUPS_TEST_CASE("docs", "96", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 1594 +LIBSEMIGROUPS_TEST_CASE("docs", "61", "word-range.hpp", "[docs][quick]") { StringRange strings; strings.order(Order::shortlex) // strings in shortlex order .alphabet("ab") // on 2 letters @@ -957,30 +687,14 @@ LIBSEMIGROUPS_TEST_CASE("docs", "96", "word-range.hpp", "[docs][quick]") { .max(5); // to 5 } -// word-range.hpp: Line 2008 -LIBSEMIGROUPS_TEST_CASE("docs", "97", "word-range.hpp", "[docs][quick]") { - 012_w // same as word_type({0, 1, 2}) - "abc"_w // also same as word_type({0, 1, 2}) - "(ab)^3"_p // same as "ababab" -} - -// word-range.hpp: Line 2089 -LIBSEMIGROUPS_TEST_CASE("docs", "98", "word-range.hpp", "[docs][quick]") { - using namespace words; - pow("a", 5) // same as "aaaaa" - 01_w + 2 // same as 012_w - 01_w + 01_w // same as 0101_w - prod(0123_w, 0, 16, 3) // same as 032103_w -} - -// word-range.hpp: Line 2304 -LIBSEMIGROUPS_TEST_CASE("docs", "99", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 2305 +LIBSEMIGROUPS_TEST_CASE("docs", "62", "word-range.hpp", "[docs][quick]") { using namespace words; - word_type w = 012345_w - prod(w, 0, 5, 2) // {0, 2, 4} - prod(w, 1, 9, 2) // {1, 3, 5, 1} - prod("abcde", 4, 1, -1) // "edc" - prod({"aba", "xyz"}, 0, 4, 1) // "abaxyzabaxyz" + word_type w = 012345_w; + prod(w, 0, 5, 2); // {0, 2, 4} + prod(w, 1, 9, 2); // {1, 3, 5, 1} + prod("abcde", 4, 1, -1); // "edc" + prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" } From fefce8544183b449764c97a5c60509c75bcf4086 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 5 Nov 2025 15:21:08 +0000 Subject: [PATCH 08/11] Variety of Fixes - Most Tests Passing See special exclusion of todd-coxeter-helpers.hpp slow test. --- include/libsemigroups/matrix.hpp | 64 ++--- include/libsemigroups/todd-coxeter-class.hpp | 21 +- .../libsemigroups/todd-coxeter-helpers.hpp | 36 ++- include/libsemigroups/word-range.hpp | 2 + tests/test-docs-code-examples.cpp | 242 ++++++------------ 5 files changed, 158 insertions(+), 207 deletions(-) diff --git a/include/libsemigroups/matrix.hpp b/include/libsemigroups/matrix.hpp index 0c120690d..fc1203152 100644 --- a/include/libsemigroups/matrix.hpp +++ b/include/libsemigroups/matrix.hpp @@ -1524,8 +1524,8 @@ namespace libsemigroups { private: using DynamicMatrix_ = DynamicMatrix; using RowViewCommon = detail::RowViewCommon< - DynamicMatrix_, - DynamicRowView>; + DynamicMatrix_, + DynamicRowView>; friend RowViewCommon; public: @@ -1961,6 +1961,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! using Mat = BMat8; //! Mat m({{1, 1}, {0, 0}}); //! \endcode explicit StaticMatrix( @@ -2780,9 +2781,9 @@ namespace libsemigroups { MatrixStaticArithmetic { using MatrixDynamicDim = ::libsemigroups::detail::MatrixDynamicDim; using MatrixCommon = ::libsemigroups::detail::MatrixCommon< - std::vector, - DynamicMatrix, - DynamicRowView>; + std::vector, + DynamicMatrix, + DynamicRowView>; friend MatrixCommon; public: @@ -2863,6 +2864,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! using Mat = IntMat<>; //! Mat m(2, 3); // construct a 2 x 3 matrix //! \endcode DynamicMatrix(size_t r, size_t c) : MatrixDynamicDim(r, c), MatrixCommon() { @@ -2885,6 +2887,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! using Mat = BMat<>; //! Mat m({1, 1, 0, 0}); //! \endcode explicit DynamicMatrix(std::initializer_list const& c) @@ -2907,6 +2910,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! using Mat = IntMat<>; //! Mat m({{1, 1}, {0, 0}}); //! \endcode explicit DynamicMatrix( @@ -3812,9 +3816,9 @@ namespace libsemigroups { //! \par Example //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! BMat<3> m; + //! BMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix - //! BMat<> m(4, 4); + //! BMat<> m4(4, 4); //! \endcode //! \ingroup bmat_group @@ -4119,9 +4123,9 @@ namespace libsemigroups { //! \par Example //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! IntMat<3> m; + //! IntMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix - //! IntMat<> m(4, 4); + //! IntMat<> m4(4, 4); //! \endcode //! \ingroup intmat_group @@ -4409,9 +4413,9 @@ namespace libsemigroups { //! \par Example //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! MaxPlusMat<3> m; + //! MaxPlusMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix - //! MaxPlusMat<> m(4, 4); + //! MaxPlusMat<> m4(4, 4); //! \endcode //! \ingroup maxplusmat_group @@ -4718,9 +4722,9 @@ namespace libsemigroups { //! //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! MinPlusMat<3> m; + //! MinPlusMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix - //! MinPlusMat<> m(4, 4); + //! MinPlusMat<> m4(4, 4); //! \endcode //! \ingroup minplusmat_group @@ -5037,14 +5041,14 @@ namespace libsemigroups { //! \par Example //! \code //! // construct an uninitialized 3 x 3 static matrix with threshold 11 - //! MaxPlusTruncMat<11, 3> m; + //! MaxPlusTruncMat<11, 3> m3_11; //! // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - //! MaxPlusTruncMat<11> m(4, 4); + //! MaxPlusTruncMat<11> m4_11(4, 4); //! // construct a truncated max-plus semiring with threshold 11 - //! MaxPlusTruncSemiring sr(11); + //! MaxPlusTruncSemiring sr_11(11); //! // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 //! // (defined at run time) - //! MaxPlusTruncMat<> m(sr, 5, 5); + //! MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); //! \endcode //! \ingroup maxplustruncmat_group @@ -5518,14 +5522,14 @@ namespace libsemigroups { //! \par Example //! \code //! // construct an uninitialized 3 x 3 static matrix with threshold 11 - //! MinPlusTruncMat<11, 3> m; + //! MinPlusTruncMat<11, 3> m3_11; //! // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - //! MinPlusTruncMat<11> m(4, 4); + //! MinPlusTruncMat<11> m4_11(4, 4); //! // construct a truncated min-plus semiring with threshold 11 - //! MinPlusTruncSemiring sr(11); + //! MinPlusTruncSemiring sr_11(11); //! // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 //! // (defined at run time) - //! MinPlusTruncMat<> m(sr, 5, 5); + //! MinPlusTruncMat<> m5_11(&sr_11, 5, 5); //! \endcode //! \ingroup minplustruncmat_group @@ -6005,15 +6009,15 @@ namespace libsemigroups { //! \code //! // construct an uninitialized 3 x 3 static matrix with threshold //! // 11, period 2 - //! NTPMat<11, 2, 3> m; + //! NTPMat<11, 2, 3> m3_11_2; //! // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, //! // period 2 - //! NTPMat<11, 2> m(4, 4); + //! NTPMat<11, 2> m4_11_2(4, 4); //! // construct an ntp semiring with threshold 11, period 2 - //! NTPSemiring sr(11, 2); + //! NTPSemiring<> sr_11_2(11, 2); //! // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, //! // period 2 - //! NTPMat<> m(sr, 5, 5); + //! NTPMat<> m_5_11_2(&sr_11_2, 5, 5); //! \endcode namespace detail { @@ -6678,7 +6682,7 @@ namespace libsemigroups { ProjMaxPlusMat( std::initializer_list> const& m) : ProjMaxPlusMat( - std::vector>(m.begin(), m.end())) {} + std::vector>(m.begin(), m.end())) {} ~ProjMaxPlusMat() = default; @@ -6982,9 +6986,9 @@ namespace libsemigroups { //! \par Example //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! ProjMaxPlusMat<3> m; + //! ProjMaxPlusMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix - //! ProjMaxPlusMat<> m(4, 4); + //! ProjMaxPlusMat<> m4(4, 4); //! \endcode //! \ingroup projmaxplus_group @@ -7146,8 +7150,8 @@ namespace libsemigroups { //! \par Example //! //! \code - //! auto x == make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, - //! 1}})); + //! auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, + //! 1}}); //! // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} //! matrix::pow(x, 100); //! \endcode diff --git a/include/libsemigroups/todd-coxeter-class.hpp b/include/libsemigroups/todd-coxeter-class.hpp index 39f2dbd7e..f8805e200 100644 --- a/include/libsemigroups/todd-coxeter-class.hpp +++ b/include/libsemigroups/todd-coxeter-class.hpp @@ -77,6 +77,8 @@ namespace libsemigroups { //! //! \par Example 1 //! \code + //! using options = detail::ToddCoxeterImpl::options; + //! //! Presentation p; //! p.alphabet(2); //! presentation::add_rule(p, 00_w, 0_w); @@ -84,12 +86,17 @@ namespace libsemigroups { //! ToddCoxeter tc(congruence_kind::onesided, p); //! tc.strategy(options::strategy::felsch); //! tc.number_of_classes(); - //! tc.contains(0000_w, 00_w); - //! tc.index_of(0000_w); + //! + //! auto w1 = 0000_w; + //! auto w2 = 00_w; + //! todd_coxeter::contains(tc, w1, w2); + //! todd_coxeter::index_of(tc, w1); //! \endcode //! //! \par Example 2 //! \code + //! using options = detail::ToddCoxeterImpl::options; + //! //! Presentation p; //! p.alphabet(4); //! presentation::add_rule(p, 00_w, 0_w); @@ -108,9 +115,9 @@ namespace libsemigroups { //! tc.strategy(options::strategy::hlt) //! .lookahead_extent(options::lookahead_extent::partial) //! .save(false); - //! tc.number_of_classes() // 10'752 - //! tc.standardize(order::recursive); - //! normal_forms(tc) | rx::take(10) | rx::to_vector() + //! tc.number_of_classes(); // 10'752 + //! tc.standardize(Order::recursive); + //! todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); //! // {0_w, //! // 1_w, //! // 2_w, @@ -121,8 +128,8 @@ namespace libsemigroups { //! // 221_w, //! // 212_w, //! // 2121_w} - //! tc.standardize(order::lex); - //! normal_forms(tc) | rx::take(10) | rx::to_vector() + //! tc.standardize(Order::lex); + //! todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); //! // {0_w, //! // 01_w, //! // 012_w, diff --git a/include/libsemigroups/todd-coxeter-helpers.hpp b/include/libsemigroups/todd-coxeter-helpers.hpp index 3a3a17c6b..bccba9d42 100644 --- a/include/libsemigroups/todd-coxeter-helpers.hpp +++ b/include/libsemigroups/todd-coxeter-helpers.hpp @@ -92,6 +92,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.current_index_of_no_checks(std::begin(w), std::end(w)); //! \endcode //! @@ -115,6 +116,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.current_index_of(std::begin(w), std::end(w)); //! \endcode //! @@ -138,6 +140,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.index_of_no_checks(std::begin(w), std::end(w)); //! \endcode //! @@ -161,6 +164,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.index_of(std::begin(w), std::end(w)); //! \endcode //! @@ -183,6 +187,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.current_index_of_no_checks(std::begin(w), std::end(w)); //! \endcode //! @@ -208,6 +213,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.current_index_of(std::begin(w), std::end(w)); //! \endcode //! @@ -233,6 +239,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.index_of_no_checks(std::begin(w), std::end(w)); //! \endcode //! @@ -258,6 +265,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.index_of(std::begin(w), std::end(w)); //! \endcode //! @@ -282,6 +290,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.current_index_of_no_checks(w, w + std::strlen(w)); //! \endcode //! @@ -304,6 +313,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.current_index_of(w, w + std::strlen(w)); //! \endcode //! @@ -326,6 +336,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.index_of_no_checks(w, w + std::strlen(w)); //! \endcode //! @@ -348,6 +359,7 @@ namespace libsemigroups { //! //! This function just calls //! \code + //! \skip-test //! tc.index_of(w, w + std::strlen(w)); //! \endcode //! @@ -831,6 +843,10 @@ namespace libsemigroups { //! Neumann for the trivial group: //! //! \code + //! \skip-test + //! \\ TODO : Long running test. Check if meant to be this slow? + //! + //! using options = detail::ToddCoxeterImpl::options; //! Presentation p; //! p.alphabet("abcdef"); //! p.contains_empty_word(true); @@ -838,17 +854,8 @@ namespace libsemigroups { //! presentation::add_rule(p, "bbdeaecbffdbaeeccefbccefb", ""); //! presentation::add_rule(p, "ccefbfacddecbffaafdcaafdc", ""); //! presentation::add_rule(p, "aafdcdbaeefacddbbdeabbdea", ""); - //! ToddCoxeter tc(congruence_kind.twosided, p); - //! \endcode - //! - //! Then running \p tc will simply grow the underlying word graph until - //! your computer runs out of memory. The authors of ``libsemigroups`` were - //! not able to find any combination of the many settings for - //! \ref_todd_coxeter where running \p tc returned an answer. We also tried - //! with GAP and ACE but neither of these seemed able to return an answer - //! either. But doing the following: + //! ToddCoxeter tc(congruence_kind::twosided, p); //! - //! \code //! tc.lookahead_extent(options::lookahead_extent::full) //! .lookahead_style(options::lookahead_style::felsch); //! @@ -861,9 +868,14 @@ namespace libsemigroups { //! tc.perform_lookahead(true); //! tc.number_of_classes(); // returns 1 //! \endcode + //!! + //! Running \p tc will simply grow the underlying word graph until + //! your computer runs out of memory. The authors of ``libsemigroups`` were + //! not able to find any combination of the many settings for + //! \ref_todd_coxeter where running \p tc returned an answer. We also tried + //! with GAP and ACE but neither of these seemed able to return an answer + //! either. But doing the following: //! - //! returns the correct answer in about 22 seconds (on a 2024 Macbook Pro M4 - //! Pro). //! //! \param tc the \ref_todd_coxeter instance. //! diff --git a/include/libsemigroups/word-range.hpp b/include/libsemigroups/word-range.hpp index 6ad5b4523..e9af89705 100644 --- a/include/libsemigroups/word-range.hpp +++ b/include/libsemigroups/word-range.hpp @@ -1047,6 +1047,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! using namespace rx; //! StringRange strings; //! strings.alphabet("ab").first("a").last("bbbb"); //! auto words = (strings | ToWord("ba")); @@ -1398,6 +1399,7 @@ namespace libsemigroups { //! //! \par Example //! \code + //! using namespace rx; //! WordRange words; //! words.alphabet_size(1).min(0).max(10); //! diff --git a/tests/test-docs-code-examples.cpp b/tests/test-docs-code-examples.cpp index 649e361a2..3877ff88c 100644 --- a/tests/test-docs-code-examples.cpp +++ b/tests/test-docs-code-examples.cpp @@ -223,114 +223,118 @@ LIBSEMIGROUPS_TEST_CASE("docs", "9", "konieczny.hpp", "[docs][quick]") { // matrix.hpp: Line 1964 LIBSEMIGROUPS_TEST_CASE("docs", "10", "matrix.hpp", "[docs][quick]") { - Mat m({{1, 1}, {0, 0}}); + using Mat = BMat8; + Mat m({{1, 1}, {0, 0}}); } -// matrix.hpp: Line 2866 +// matrix.hpp: Line 2867 LIBSEMIGROUPS_TEST_CASE("docs", "11", "matrix.hpp", "[docs][quick]") { - Mat m(2, 3); // construct a 2 x 3 matrix + using Mat = IntMat<>; + Mat m(2, 3); // construct a 2 x 3 matrix } -// matrix.hpp: Line 2888 +// matrix.hpp: Line 2890 LIBSEMIGROUPS_TEST_CASE("docs", "12", "matrix.hpp", "[docs][quick]") { - Mat m({1, 1, 0, 0}); + using Mat = BMat<>; + Mat m({1, 1, 0, 0}); } -// matrix.hpp: Line 2910 +// matrix.hpp: Line 2913 LIBSEMIGROUPS_TEST_CASE("docs", "13", "matrix.hpp", "[docs][quick]") { - Mat m({{1, 1}, {0, 0}}); + using Mat = IntMat<>; + Mat m({{1, 1}, {0, 0}}); } -// matrix.hpp: Line 3814 +// matrix.hpp: Line 3818 LIBSEMIGROUPS_TEST_CASE("docs", "14", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix - BMat<3> m; + BMat<3> m3; // construct an uninitialized 4 x 4 dynamic matrix - BMat<> m(4, 4); + BMat<> m4(4, 4); } -// matrix.hpp: Line 4121 +// matrix.hpp: Line 4125 LIBSEMIGROUPS_TEST_CASE("docs", "15", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix - IntMat<3> m; + IntMat<3> m3; // construct an uninitialized 4 x 4 dynamic matrix - IntMat<> m(4, 4); + IntMat<> m4(4, 4); } -// matrix.hpp: Line 4411 +// matrix.hpp: Line 4415 LIBSEMIGROUPS_TEST_CASE("docs", "16", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix - MaxPlusMat<3> m; + MaxPlusMat<3> m3; // construct an uninitialized 4 x 4 dynamic matrix - MaxPlusMat<> m(4, 4); + MaxPlusMat<> m4(4, 4); } -// matrix.hpp: Line 4720 +// matrix.hpp: Line 4724 LIBSEMIGROUPS_TEST_CASE("docs", "17", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix - MinPlusMat<3> m; + MinPlusMat<3> m3; // construct an uninitialized 4 x 4 dynamic matrix - MinPlusMat<> m(4, 4); + MinPlusMat<> m4(4, 4); } -// matrix.hpp: Line 5039 +// matrix.hpp: Line 5043 LIBSEMIGROUPS_TEST_CASE("docs", "18", "matrix.hpp", "[docs][quick]") { // construct an uninitialized 3 x 3 static matrix with threshold 11 - MaxPlusTruncMat<11, 3> m; + MaxPlusTruncMat<11, 3> m3_11; // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MaxPlusTruncMat<11> m(4, 4); + MaxPlusTruncMat<11> m4_11(4, 4); // construct a truncated max-plus semiring with threshold 11 - MaxPlusTruncSemiring sr(11); + MaxPlusTruncSemiring sr_11(11); // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 // (defined at run time) - MaxPlusTruncMat<> m(sr, 5, 5); + MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); } -// matrix.hpp: Line 5520 +// matrix.hpp: Line 5524 LIBSEMIGROUPS_TEST_CASE("docs", "19", "matrix.hpp", "[docs][quick]") { // construct an uninitialized 3 x 3 static matrix with threshold 11 - MinPlusTruncMat<11, 3> m; + MinPlusTruncMat<11, 3> m3_11; // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MinPlusTruncMat<11> m(4, 4); + MinPlusTruncMat<11> m4_11(4, 4); // construct a truncated min-plus semiring with threshold 11 - MinPlusTruncSemiring sr(11); + MinPlusTruncSemiring sr_11(11); // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 // (defined at run time) - MinPlusTruncMat<> m(sr, 5, 5); + MinPlusTruncMat<> m5_11(&sr_11, 5, 5); } -// matrix.hpp: Line 6006 +// matrix.hpp: Line 6010 LIBSEMIGROUPS_TEST_CASE("docs", "20", "matrix.hpp", "[docs][quick]") { // construct an uninitialized 3 x 3 static matrix with threshold // 11, period 2 - NTPMat<11, 2, 3> m; + NTPMat<11, 2, 3> m3_11_2; // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, // period 2 - NTPMat<11, 2> m(4, 4); + NTPMat<11, 2> m4_11_2(4, 4); // construct an ntp semiring with threshold 11, period 2 - NTPSemiring sr(11, 2); + NTPSemiring<> sr_11_2(11, 2); // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, // period 2 - NTPMat<> m(sr, 5, 5); + NTPMat<> m_5_11_2(&sr_11_2, 5, 5); } -// matrix.hpp: Line 6984 +// matrix.hpp: Line 6988 LIBSEMIGROUPS_TEST_CASE("docs", "21", "matrix.hpp", "[docs][quick]") { // default construct an uninitialized 3 x 3 static matrix - ProjMaxPlusMat<3> m; + ProjMaxPlusMat<3> m3; // construct an uninitialized 4 x 4 dynamic matrix - ProjMaxPlusMat<> m(4, 4); + ProjMaxPlusMat<> m4(4, 4); } -// matrix.hpp: Line 7149 +// matrix.hpp: Line 7153 LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { - auto x == make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, - 1}})); + auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, + 1}}); // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} matrix::pow(x, 100); } -// matrix.hpp: Line 7897 +// matrix.hpp: Line 7901 LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); matrix::row_space_size(x); // returns 7 @@ -413,20 +417,27 @@ LIBSEMIGROUPS_TEST_CASE("docs", "32", "schreier-sims.hpp", "[docs][quick]") { // todd-coxeter-class.hpp: Line 80 LIBSEMIGROUPS_TEST_CASE("docs", "33", "todd-coxeter-class.hpp", "[docs][quick]") { - Presentation p; + using options = detail::ToddCoxeterImpl::options; + + Presentation p; p.alphabet(2); presentation::add_rule(p, 00_w, 0_w); presentation::add_rule(p, 0_w, 1_w); ToddCoxeter tc(congruence_kind::onesided, p); tc.strategy(options::strategy::felsch); tc.number_of_classes(); - tc.contains(0000_w, 00_w); - tc.index_of(0000_w); + + auto w1 = 0000_w; + auto w2 = 00_w; + todd_coxeter::contains(tc, w1, w2); + todd_coxeter::index_of(tc, w1); } -// todd-coxeter-class.hpp: Line 93 +// todd-coxeter-class.hpp: Line 98 LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") { - Presentation p; + using options = detail::ToddCoxeterImpl::options; + + Presentation p; p.alphabet(4); presentation::add_rule(p, 00_w, 0_w); presentation::add_rule(p, 10_w, 1_w); @@ -444,9 +455,9 @@ LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") tc.strategy(options::strategy::hlt) .lookahead_extent(options::lookahead_extent::partial) .save(false); - tc.number_of_classes() // 10'752 - tc.standardize(order::recursive); - normal_forms(tc) | rx::take(10) | rx::to_vector() + tc.number_of_classes(); // 10'752 + tc.standardize(Order::recursive); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); // {0_w, // 1_w, // 2_w, @@ -457,8 +468,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") // 221_w, // 212_w, // 2121_w} - tc.standardize(order::lex); - normal_forms(tc) | rx::take(10) | rx::to_vector() + tc.standardize(Order::lex); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); // {0_w, // 01_w, // 012_w, @@ -471,95 +482,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") // 0121212121_w}; } -// todd-coxeter-helpers.hpp: Line 95 -LIBSEMIGROUPS_TEST_CASE("docs", "35", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.current_index_of_no_checks(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 118 -LIBSEMIGROUPS_TEST_CASE("docs", "36", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.current_index_of(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 141 -LIBSEMIGROUPS_TEST_CASE("docs", "37", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.index_of_no_checks(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 164 -LIBSEMIGROUPS_TEST_CASE("docs", "38", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.index_of(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 186 -LIBSEMIGROUPS_TEST_CASE("docs", "39", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.current_index_of_no_checks(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 211 -LIBSEMIGROUPS_TEST_CASE("docs", "40", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.current_index_of(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 236 -LIBSEMIGROUPS_TEST_CASE("docs", "41", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.index_of_no_checks(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 261 -LIBSEMIGROUPS_TEST_CASE("docs", "42", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.index_of(std::begin(w), std::end(w)); -} - -// todd-coxeter-helpers.hpp: Line 285 -LIBSEMIGROUPS_TEST_CASE("docs", "43", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.current_index_of_no_checks(w, w + std::strlen(w)); -} - -// todd-coxeter-helpers.hpp: Line 307 -LIBSEMIGROUPS_TEST_CASE("docs", "44", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.current_index_of(w, w + std::strlen(w)); -} - -// todd-coxeter-helpers.hpp: Line 329 -LIBSEMIGROUPS_TEST_CASE("docs", "45", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.index_of_no_checks(w, w + std::strlen(w)); -} - -// todd-coxeter-helpers.hpp: Line 351 -LIBSEMIGROUPS_TEST_CASE("docs", "46", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.index_of(w, w + std::strlen(w)); -} - -// todd-coxeter-helpers.hpp: Line 834 -LIBSEMIGROUPS_TEST_CASE("docs", "47", "todd-coxeter-helpers.hpp", "[docs][quick]") { - Presentation p; - p.alphabet("abcdef"); - p.contains_empty_word(true); - presentation::add_inverse_rules(p, "defabc"); - presentation::add_rule(p, "bbdeaecbffdbaeeccefbccefb", ""); - presentation::add_rule(p, "ccefbfacddecbffaafdcaafdc", ""); - presentation::add_rule(p, "aafdcdbaeefacddbbdeabbdea", ""); - ToddCoxeter tc(congruence_kind.twosided, p); -} - -// todd-coxeter-helpers.hpp: Line 852 -LIBSEMIGROUPS_TEST_CASE("docs", "48", "todd-coxeter-helpers.hpp", "[docs][quick]") { - tc.lookahead_extent(options::lookahead_extent::full) - .lookahead_style(options::lookahead_style::felsch); - - tc.run_for(std::chrono::seconds(1)); - tc.perform_lookahead(true); - - todd_coxeter::perform_lookbehind(tc); - tc.run_for(std::chrono::seconds(1)); - todd_coxeter::perform_lookbehind(tc); - tc.perform_lookahead(true); - tc.number_of_classes(); // returns 1 -} - // word-graph.hpp: Line 1540 -LIBSEMIGROUPS_TEST_CASE("docs", "49", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "35", "word-graph.hpp", "[docs][quick]") { WordGraph wg; wg.add_nodes(2); wg.add_to_out_degree(1); @@ -569,7 +493,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "49", "word-graph.hpp", "[docs][quick]") { } // word-graph.hpp: Line 1583 -LIBSEMIGROUPS_TEST_CASE("docs", "50", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "36", "word-graph.hpp", "[docs][quick]") { WordGraph wg; wg.add_nodes(4); wg.add_to_out_degree(1); @@ -584,7 +508,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "50", "word-graph.hpp", "[docs][quick]") { } // word-graph.hpp: Line 1973 -LIBSEMIGROUPS_TEST_CASE("docs", "51", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "37", "word-graph.hpp", "[docs][quick]") { WordGraph wg; wg.add_nodes(4); wg.add_to_out_degree(1); @@ -599,34 +523,34 @@ LIBSEMIGROUPS_TEST_CASE("docs", "51", "word-graph.hpp", "[docs][quick]") { } // word-graph.hpp: Line 2053 -LIBSEMIGROUPS_TEST_CASE("docs", "52", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "38", "word-graph.hpp", "[docs][quick]") { auto wg = make>( 5, {{0, 0}, {1, 1}, {2}, {3, 3}}); word_graph::is_strictly_cyclic(wg); // returns false } // word-graph.hpp: Line 2793 -LIBSEMIGROUPS_TEST_CASE("docs", "53", "word-graph.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "39", "word-graph.hpp", "[docs][quick]") { // Construct a word graph with 5 nodes and 10 edges (7 specified) make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); } // word-range.hpp: Line 183 -LIBSEMIGROUPS_TEST_CASE("docs", "54", "word-range.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "40", "word-range.hpp", "[docs][quick]") { std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), cend_wilo(2, 3, {0}, {1, 1, 1})); // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; } // word-range.hpp: Line 253 -LIBSEMIGROUPS_TEST_CASE("docs", "55", "word-range.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "41", "word-range.hpp", "[docs][quick]") { std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), cend_wislo(2, {0}, {0, 0, 0})); // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; } // word-range.hpp: Line 313 -LIBSEMIGROUPS_TEST_CASE("docs", "56", "word-range.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "42", "word-range.hpp", "[docs][quick]") { WordRange words; words.order(Order::shortlex) // words in shortlex order .alphabet_size(2) // on 2 letters @@ -635,7 +559,7 @@ LIBSEMIGROUPS_TEST_CASE("docs", "56", "word-range.hpp", "[docs][quick]") { } // word-range.hpp: Line 761 -LIBSEMIGROUPS_TEST_CASE("docs", "57", "word-range.hpp", "[docs][quick]") { +LIBSEMIGROUPS_TEST_CASE("docs", "43", "word-range.hpp", "[docs][quick]") { ToWord toword("bac"); toword("bac"); // returns {0, 1, 2} toword("bababbbcbc"); // returns { 0, 1, 0, 1, 0, 0, 0, 2, 0, 2} @@ -645,8 +569,9 @@ LIBSEMIGROUPS_TEST_CASE("docs", "57", "word-range.hpp", "[docs][quick]") { } // word-range.hpp: Line 1050 -LIBSEMIGROUPS_TEST_CASE("docs", "58", "word-range.hpp", "[docs][quick]") { - StringRange strings; +LIBSEMIGROUPS_TEST_CASE("docs", "44", "word-range.hpp", "[docs][quick]") { + using namespace rx; + StringRange strings; strings.alphabet("ab").first("a").last("bbbb"); auto words = (strings | ToWord("ba")); // contains the words @@ -657,8 +582,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "58", "word-range.hpp", "[docs][quick]") { // 0001_w})); } -// word-range.hpp: Line 1150 -LIBSEMIGROUPS_TEST_CASE("docs", "59", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 1151 +LIBSEMIGROUPS_TEST_CASE("docs", "45", "word-range.hpp", "[docs][quick]") { ToString tostring("bac"); tostring(word_type({1, 0, 2})); // returns "abc" tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})); // returns "baabaabc" @@ -667,9 +592,10 @@ LIBSEMIGROUPS_TEST_CASE("docs", "59", "word-range.hpp", "[docs][quick]") { tostring(word_type({1, 0, 2})); // returns "bac" } -// word-range.hpp: Line 1401 -LIBSEMIGROUPS_TEST_CASE("docs", "60", "word-range.hpp", "[docs][quick]") { - WordRange words; +// word-range.hpp: Line 1402 +LIBSEMIGROUPS_TEST_CASE("docs", "46", "word-range.hpp", "[docs][quick]") { + using namespace rx; + WordRange words; words.alphabet_size(1).min(0).max(10); auto strings = (words | ToString("a")); @@ -678,8 +604,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "60", "word-range.hpp", "[docs][quick]") { // "aaaaaaaa", "aaaaaaaaa"}; } -// word-range.hpp: Line 1594 -LIBSEMIGROUPS_TEST_CASE("docs", "61", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 1596 +LIBSEMIGROUPS_TEST_CASE("docs", "47", "word-range.hpp", "[docs][quick]") { StringRange strings; strings.order(Order::shortlex) // strings in shortlex order .alphabet("ab") // on 2 letters @@ -687,8 +613,8 @@ LIBSEMIGROUPS_TEST_CASE("docs", "61", "word-range.hpp", "[docs][quick]") { .max(5); // to 5 } -// word-range.hpp: Line 2305 -LIBSEMIGROUPS_TEST_CASE("docs", "62", "word-range.hpp", "[docs][quick]") { +// word-range.hpp: Line 2307 +LIBSEMIGROUPS_TEST_CASE("docs", "48", "word-range.hpp", "[docs][quick]") { using namespace words; word_type w = 012345_w; prod(w, 0, 5, 2); // {0, 2, 4} From 4f8297045413f3ab60f63fab2c4f794d245bf77c Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 11 Nov 2025 15:52:13 +0000 Subject: [PATCH 09/11] Semantic "return" comment tests: //-> --- etc/extract-doc-examples.py | 20 +- include/libsemigroups/action.hpp | 6 +- include/libsemigroups/cong-class.hpp | 2 +- include/libsemigroups/froidure-pin-base.hpp | 4 +- .../libsemigroups/is_specialization_of.hpp | 12 +- include/libsemigroups/knuth-bendix-class.hpp | 8 +- include/libsemigroups/order.hpp | 6 +- include/libsemigroups/ranges.hpp | 2 +- include/libsemigroups/schreier-sims.hpp | 9 +- include/libsemigroups/todd-coxeter-class.hpp | 8 +- include/libsemigroups/word-graph.hpp | 30 +- include/libsemigroups/word-range.hpp | 12 +- tests/test-docs-code-examples.cpp | 1207 +++++++++-------- 13 files changed, 671 insertions(+), 655 deletions(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index 63a94e736..0d2f8132a 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -162,13 +162,29 @@ def extract_code_blocks(file_path): ) continue + # If line contains a function call with a return value + # labelled by '//-> ' + # where ::= | + if "//->" in line: + parts = line.split("//->") + function_call = parts[0].strip().strip(";") + function_returns = parts[1].strip() + + #  validate format of return + #  TODO: This + + #  Add require value eq + current_block.append( + f" REQUIRE({function_call} == {function_returns});" + ) + continue + if not ignore_this_block: current_block.append(line) # discard unclosed code blocks if in_code_block and current_block: - __error( - f"Warning: Unclosed code block at end of file {file_path}") + __error(f"Warning: Unclosed code block at end of file {file_path}") except Exception as e: print(f"Error reading file {file_path}: {e}") diff --git a/include/libsemigroups/action.hpp b/include/libsemigroups/action.hpp index c80cfe69a..0ccd6e0f0 100644 --- a/include/libsemigroups/action.hpp +++ b/include/libsemigroups/action.hpp @@ -77,7 +77,7 @@ namespace libsemigroups { //! {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, //! 16)); //! o.reserve(70000); - //! o.size(); // returns 65536 + //! o.size(); //-> 65536 //! \endcode //! \ingroup types_group @@ -161,8 +161,8 @@ namespace libsemigroups { //! {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, //! 16)); //! o.reserve(70000); - //! o.size(); // 65536 - //! o.scc().number_of_components(); // 17 + //! o.size(); //-> 65536 + //! o.scc().number_of_components(); //-> 17 //! \endcode //! //! \par Complexity diff --git a/include/libsemigroups/cong-class.hpp b/include/libsemigroups/cong-class.hpp index 367110341..b9b60c580 100644 --- a/include/libsemigroups/cong-class.hpp +++ b/include/libsemigroups/cong-class.hpp @@ -151,7 +151,7 @@ namespace libsemigroups { //! Congruence cong(congruence_kind::twosided, p); //! is_obviously_infinite(cong); // true //! congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); - //! cong.number_of_classes(); // 3 + //! cong.number_of_classes(); //-> 3 //! \endcode template class Congruence : public detail::CongruenceCommon, diff --git a/include/libsemigroups/froidure-pin-base.hpp b/include/libsemigroups/froidure-pin-base.hpp index 45a82e0ab..6bd6e17be 100644 --- a/include/libsemigroups/froidure-pin-base.hpp +++ b/include/libsemigroups/froidure-pin-base.hpp @@ -1351,7 +1351,7 @@ namespace libsemigroups { //! {0, 0, 0, 1}, //! {0, 0, 0, 1}, //! {0, 0, 0, 1}})); - //! S.size(); // 4 + //! S.size(); //-> 4 //! std::vector(S.cbegin_rules(), S.cend_rules()); //! // {{{0, 0}, {0}}, //! // {{0, 1}, {1}}, @@ -1455,7 +1455,7 @@ namespace libsemigroups { //! {0, 0, 0, 1}, //! {0, 0, 0, 1}, //! {0, 0, 0, 1}})); - //! S.size(); // 4 + //! S.size(); //-> 4 //! std::vector(S.cbegin_rules(), S.cend_rules()); //! // {{{0, 0}, {0}}, //! // {{0, 1}, {1}}, diff --git a/include/libsemigroups/is_specialization_of.hpp b/include/libsemigroups/is_specialization_of.hpp index 43b15d48d..cb756f4ae 100644 --- a/include/libsemigroups/is_specialization_of.hpp +++ b/include/libsemigroups/is_specialization_of.hpp @@ -41,9 +41,11 @@ namespace libsemigroups { //! //! \par Example //! \code - //! is_specialization_of, std::vector>::value; // true - //! is_specialization_of, std::unordered_map>::value; - //! // false + //! using iso_1= is_specialization_of, std::vector>; + //! iso_1::value; //-> true + //! using iso_2 = is_specialization_of,std::unordered_map>; + //! iso_2::value; //-> false + //! //! \endcode //! //! \note The template parameters of \p Primary must be types, so, for @@ -71,8 +73,8 @@ namespace libsemigroups { //! //! \par Example //! \code - //! is_specialization_of_v, std::vector>; // true - //! is_specialization_of_v, std::unordered_map>; // false + //! is_specialization_of_v, std::vector>; //-> true + //! is_specialization_of_v, std::unordered_map>; //-> false //! \endcode //! //! \note The template parameters of \p Primary must be types, so, for diff --git a/include/libsemigroups/knuth-bendix-class.hpp b/include/libsemigroups/knuth-bendix-class.hpp index af7d03663..3bd71ce86 100644 --- a/include/libsemigroups/knuth-bendix-class.hpp +++ b/include/libsemigroups/knuth-bendix-class.hpp @@ -79,11 +79,11 @@ namespace libsemigroups { //! //! KnuthBendix kb(congruence_kind::twosided, p); //! - //! !kb.confluent(); // true + //! !kb.confluent(); //-> true //! kb.run(); - //! kb.number_of_active_rules(); // 8 - //! kb.confluent(); // true - //! kb.number_of_classes(); // POSITIVE_INFINITY + //! kb.number_of_active_rules(); //-> 8 + //! kb.confluent(); //-> true + //! kb.number_of_classes(); //-> POSITIVE_INFINITY //! \endcode //! //! \warning At present it is only possible to create KnuthBendix objects from diff --git a/include/libsemigroups/order.hpp b/include/libsemigroups/order.hpp index ee92f34c4..ff3b7afc4 100644 --- a/include/libsemigroups/order.hpp +++ b/include/libsemigroups/order.hpp @@ -97,8 +97,7 @@ namespace libsemigroups { //! \code //! word_type x = random_word(5, 10); //! word_type y = random_word(5, 10); - //! std::lexicographical_compare( - //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); + //! lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend());//->true //! \endcode template >> bool lexicographical_compare(T const& x, T const& y) { @@ -132,8 +131,7 @@ namespace libsemigroups { //! \code //! word_type x = random_word(5, 10); //! word_type y = random_word(5, 10); - //! lexicographical_compare( - //! x.cbegin(), x.cend(), y.cbegin(), y.cend()); + //! lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend());//->true //! \endcode template bool lexicographical_compare(T* const x, T* const y) { diff --git a/include/libsemigroups/ranges.hpp b/include/libsemigroups/ranges.hpp index 386c6dd4c..b290f1a58 100644 --- a/include/libsemigroups/ranges.hpp +++ b/include/libsemigroups/ranges.hpp @@ -88,7 +88,7 @@ namespace libsemigroups { //! auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); //! Paths p(wg); //! p.source(0).max(10); - //! p.count(); // returns 1023 + //! p.count(); //-> 1023 //! // (p | Random()).get(); // returns random path in p (Pipe operator not //! // implemented for Paths?) //! \endcode diff --git a/include/libsemigroups/schreier-sims.hpp b/include/libsemigroups/schreier-sims.hpp index 7d9e931a1..85c617fe2 100644 --- a/include/libsemigroups/schreier-sims.hpp +++ b/include/libsemigroups/schreier-sims.hpp @@ -167,7 +167,7 @@ namespace libsemigroups { //! using Perm = decltype(S)::element_type; //! S.add_generator(Perm({1, 0, 2, 3, 4})); //! S.add_generator(Perm({1, 2, 3, 4, 0})); - //! S.size(); // 120 + //! S.size(); //-> 120 //! \endcode template ::type, @@ -933,10 +933,9 @@ namespace libsemigroups { bool internal_equal_to(internal_const_element_type x, internal_const_element_type y) const - noexcept(noexcept( - EqualTo()(this->to_external_const(x), - this->to_external_const( - y)) && noexcept(this->to_external_const(x)))) { + noexcept(noexcept(EqualTo()(this->to_external_const(x), + this->to_external_const(y)) + && noexcept(this->to_external_const(x)))) { return EqualTo()(this->to_external_const(x), this->to_external_const(y)); } diff --git a/include/libsemigroups/todd-coxeter-class.hpp b/include/libsemigroups/todd-coxeter-class.hpp index f8805e200..05bd86bc3 100644 --- a/include/libsemigroups/todd-coxeter-class.hpp +++ b/include/libsemigroups/todd-coxeter-class.hpp @@ -85,12 +85,12 @@ namespace libsemigroups { //! presentation::add_rule(p, 0_w, 1_w); //! ToddCoxeter tc(congruence_kind::onesided, p); //! tc.strategy(options::strategy::felsch); - //! tc.number_of_classes(); + //! tc.number_of_classes(); //-> 1 //! //! auto w1 = 0000_w; //! auto w2 = 00_w; - //! todd_coxeter::contains(tc, w1, w2); - //! todd_coxeter::index_of(tc, w1); + //! todd_coxeter::contains(tc, w1, w2); //-> true + //! todd_coxeter::index_of(tc, w1); //-> 0 //! \endcode //! //! \par Example 2 @@ -115,7 +115,7 @@ namespace libsemigroups { //! tc.strategy(options::strategy::hlt) //! .lookahead_extent(options::lookahead_extent::partial) //! .save(false); - //! tc.number_of_classes(); // 10'752 + //! tc.number_of_classes(); //-> 10752 //! tc.standardize(Order::recursive); //! todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); //! // {0_w, diff --git a/include/libsemigroups/word-graph.hpp b/include/libsemigroups/word-graph.hpp index a1f0b0284..1ca37ec5f 100644 --- a/include/libsemigroups/word-graph.hpp +++ b/include/libsemigroups/word-graph.hpp @@ -1542,7 +1542,7 @@ namespace libsemigroups { //! wg.add_to_out_degree(1); //! wg.target(0, 0, 1); //! wg.target(1, 0, 0); - //! word_graph::is_acyclic(wg); // returns false + //! word_graph::is_acyclic(wg); //-> false //! \endcode // Not noexcept because detail::is_acyclic isn't template @@ -1586,11 +1586,11 @@ namespace libsemigroups { //! wg.target(0, 0, 1); //! wg.target(1, 0, 0); //! wg.target(2, 0, 3); - //! word_graph::is_acyclic(wg); // returns false - //! word_graph::is_acyclic(wg, 0); // returns false - //! word_graph::is_acyclic(wg, 1); // returns false - //! word_graph::is_acyclic(wg, 2); // returns true - //! word_graph::is_acyclic(wg, 3); // returns true + //! word_graph::is_acyclic(wg); //-> false + //! word_graph::is_acyclic(wg, 0); //-> false + //! word_graph::is_acyclic(wg, 1); //-> false + //! word_graph::is_acyclic(wg, 2); //-> true + //! word_graph::is_acyclic(wg, 3); //-> true //! \endcode // Not noexcept because detail::is_acyclic isn't template @@ -1976,11 +1976,11 @@ namespace libsemigroups { //! wg.target(0, 1, 0); //! wg.target(1, 0, 0); //! wg.target(2, 3, 0); - //! word_graph::is_reachable_no_checks(wg, 0, 1); // returns true - //! word_graph::is_reachable_no_checks(wg, 1, 0); // returns true - //! word_graph::is_reachable_no_checks(wg, 1, 2); // returns false - //! word_graph::is_reachable_no_checks(wg, 2, 3); // returns true - //! word_graph::is_reachable_no_checks(wg, 3, 2); // returns false + //! word_graph::is_reachable_no_checks(wg, 0, 1); //-> true + //! word_graph::is_reachable_no_checks(wg, 1, 0); //-> true + //! word_graph::is_reachable_no_checks(wg, 1, 2); //-> false + //! word_graph::is_reachable_no_checks(wg, 2, 3); //-> true + //! word_graph::is_reachable_no_checks(wg, 3, 2); //-> false //! \endcode template [[nodiscard]] bool is_reachable_no_checks(WordGraph const& wg, @@ -2052,7 +2052,7 @@ namespace libsemigroups { //! \code //! auto wg = make>( //! 5, {{0, 0}, {1, 1}, {2}, {3, 3}}); - //! word_graph::is_strictly_cyclic(wg); // returns false + //! word_graph::is_strictly_cyclic(wg); //-> false //! \endcode // TODO(1) should have a version that returns the node that everything is // reachable from @@ -2791,7 +2791,7 @@ namespace libsemigroups { //! \par Example //! \code //! // Construct a word graph with 5 nodes and 10 edges (7 specified) - //! make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); + //! auto wg = make>(5,{{0, 0},{1, 1},{2},{3, 3}}); //! \endcode // Passing the 2nd parameter "targets" by value disambiguates it from the // other make. @@ -2880,7 +2880,7 @@ namespace libsemigroups { // always have an odd number of arguments, so we check that it's even // here (the argument x and an odd number of further arguments). WordGraph xy; - operator()(xy, x, std::forward(args)...); + operator()(xy, x, std::forward(args)...); return xy; } @@ -2915,7 +2915,7 @@ namespace libsemigroups { return is_subrelation(x, static_cast(0), y, static_cast(0)); } }; // JoinerMeeterCommon - } // namespace detail + } // namespace detail //! \ingroup word_graph_group //! \brief Class for taking joins of word graphs. diff --git a/include/libsemigroups/word-range.hpp b/include/libsemigroups/word-range.hpp index e9af89705..8325f3bf5 100644 --- a/include/libsemigroups/word-range.hpp +++ b/include/libsemigroups/word-range.hpp @@ -759,11 +759,11 @@ namespace libsemigroups { //! \par Example //! \code //! ToWord toword("bac"); - //! toword("bac"); // returns {0, 1, 2} - //! toword("bababbbcbc"); // returns { 0, 1, 0, 1, 0, 0, 0, 2, 0, 2} + //! toword("bac"); //->std::vector{0,1,2} + //! toword("bababbbcbc");//->std::vector{0,1,0,1,0,0,0,2,0,2} //! //! toword.init(); - //! toword("bac"); // returns {1, 0, 2} + //! toword("bac"); //-> std::vector{1, 0, 2} //! \endcode // TODO (later) a version that takes a word_type, so that we can permute the // letters in a word @@ -1149,11 +1149,11 @@ namespace libsemigroups { //! \par Example //! \code //! ToString tostring("bac"); - //! tostring(word_type({1, 0, 2})); // returns "abc" - //! tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})); // returns "baabaabc" + //! tostring(word_type({1, 0, 2})); //-> "abc" + //! tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})); //-> "baabaabc" //! //! tostring.init(); - //! tostring(word_type({1, 0, 2})); // returns "bac" + //! tostring(word_type({1, 0, 2})); //-> "bac" //! \endcode class ToString { public: diff --git a/tests/test-docs-code-examples.cpp b/tests/test-docs-code-examples.cpp index 3877ff88c..c3140c04c 100644 --- a/tests/test-docs-code-examples.cpp +++ b/tests/test-docs-code-examples.cpp @@ -22,606 +22,607 @@ using namespace libsemigroups::literals; namespace libsemigroups { -// action.hpp: Line 60 -LIBSEMIGROUPS_TEST_CASE("docs", "0", "action.hpp", "[docs][quick]") { - RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> - o; - o.add_seed(PPerm<16>::one(16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.add_generator( - PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.reserve(70000); - o.size(); // returns 65536 -} - -// action.hpp: Line 143 -LIBSEMIGROUPS_TEST_CASE("docs", "1", "action.hpp", "[docs][quick]") { - auto rg = ReportGuard(true); - RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> - o; - o.add_seed(PPerm<16>::one(16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.add_generator( - PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.reserve(70000); - o.size(); // 65536 - o.scc().number_of_components(); // 17 -} - -// cong-class.hpp: Line 148 -LIBSEMIGROUPS_TEST_CASE("docs", "2", "cong-class.hpp", "[docs][quick]") { - Presentation p; - p.alphabet(2); - presentation::add_rule(p, {0, 1}, {}); - Congruence cong(congruence_kind::twosided, p); - is_obviously_infinite(cong); // true - congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); - cong.number_of_classes(); // 3 -} - -// freeband.hpp: Line 76 -LIBSEMIGROUPS_TEST_CASE("docs", "3", "freeband.hpp", "[docs][quick]") { - freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, - {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true - freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false - freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true - freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, - {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false - freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true - freeband_equal_to({0, 1, 2, 3, 0, 1}, - {0, 1, 2, 3, 3, 2, 2, 1, 0, 2, 1, 0, 2, 3, - 0, 2, 1, 3, 2, 1, 2, 3, 2, 1, 0, 2, 0, 1, - 0, 2, 0, 3, 2, 0, 1, 2, 2, 3, 0, 1}); // true -} - -// froidure-pin-base.hpp: Line 1337 -LIBSEMIGROUPS_TEST_CASE("docs", "4", "froidure-pin-base.hpp", "[docs][quick]") { - FroidurePin S; - S.add_generator(BMat8({{1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}})); - S.add_generator(BMat8({{0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}})); - S.add_generator(BMat8({{0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}})); - S.add_generator(BMat8({{0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}})); - S.size(); // 4 - std::vector(S.cbegin_rules(), S.cend_rules()); - // {{{0, 0}, {0}}, - // {{0, 1}, {1}}, - // {{0, 2}, {2}}, - // {{0, 3}, {3}}, - // {{1, 0}, {0}}, - // {{1, 1}, {1}}, - // {{1, 2}, {2}}, - // {{1, 3}, {3}}, - // {{2, 0}, {0}}, - // {{2, 1}, {1}}, - // {{2, 2}, {2}}, - // {{2, 3}, {3}}, - // {{3, 0}, {0}}, - // {{3, 1}, {1}}, - // {{3, 2}, {2}}, - // {{3, 3}, {3}}} -} - -// froidure-pin-base.hpp: Line 1441 -LIBSEMIGROUPS_TEST_CASE("docs", "5", "froidure-pin-base.hpp", "[docs][quick]") { - FroidurePin S; - S.add_generator(BMat8({{1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}})); - S.add_generator(BMat8({{0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}})); - S.add_generator(BMat8({{0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}})); - S.add_generator(BMat8({{0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}})); - S.size(); // 4 - std::vector(S.cbegin_rules(), S.cend_rules()); - // {{{0, 0}, {0}}, - // {{0, 1}, {1}}, - // {{0, 2}, {2}}, - // {{0, 3}, {3}}, - // {{1, 0}, {0}}, - // {{1, 1}, {1}}, - // {{1, 2}, {2}}, - // {{1, 3}, {3}}, - // {{2, 0}, {0}}, - // {{2, 1}, {1}}, - // {{2, 2}, {2}}, - // {{2, 3}, {3}}, - // {{3, 0}, {0}}, - // {{3, 1}, {1}}, - // {{3, 2}, {2}}, - // {{3, 3}, {3}}} -} - -// is_specialization_of.hpp: Line 44 -LIBSEMIGROUPS_TEST_CASE("docs", "6", "is_specialization_of.hpp", "[docs][quick]") { - is_specialization_of, std::vector>::value; // true - is_specialization_of, std::unordered_map>::value; - // false -} - -// is_specialization_of.hpp: Line 74 -LIBSEMIGROUPS_TEST_CASE("docs", "7", "is_specialization_of.hpp", "[docs][quick]") { - is_specialization_of_v, std::vector>; // true - is_specialization_of_v, std::unordered_map>; // false -} - -// knuth-bendix-class.hpp: Line 72 -LIBSEMIGROUPS_TEST_CASE("docs", "8", "knuth-bendix-class.hpp", "[docs][quick]") { - Presentation p; - p.contains_empty_word(true); - p.alphabet("abcd"); - presentation::add_rule_no_checks(p, "ab", ""); - presentation::add_rule_no_checks(p, "ba", ""); - presentation::add_rule_no_checks(p, "cd", ""); - presentation::add_rule_no_checks(p, "dc", ""); - - KnuthBendix kb(congruence_kind::twosided, p); - - !kb.confluent(); // true - kb.run(); - kb.number_of_active_rules(); // 8 - kb.confluent(); // true - kb.number_of_classes(); // POSITIVE_INFINITY -} - -// konieczny.hpp: Line 70 -LIBSEMIGROUPS_TEST_CASE("docs", "9", "konieczny.hpp", "[docs][quick]") { - auto S = make({ - BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), - BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), - BMat8({{1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), - BMat8({{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}})}); - S.size(); // returns 63'904 - S.number_of_idempotents(); //returns 2'360 -} - -// matrix.hpp: Line 1964 -LIBSEMIGROUPS_TEST_CASE("docs", "10", "matrix.hpp", "[docs][quick]") { - using Mat = BMat8; - Mat m({{1, 1}, {0, 0}}); -} - -// matrix.hpp: Line 2867 -LIBSEMIGROUPS_TEST_CASE("docs", "11", "matrix.hpp", "[docs][quick]") { - using Mat = IntMat<>; - Mat m(2, 3); // construct a 2 x 3 matrix -} - -// matrix.hpp: Line 2890 -LIBSEMIGROUPS_TEST_CASE("docs", "12", "matrix.hpp", "[docs][quick]") { - using Mat = BMat<>; - Mat m({1, 1, 0, 0}); -} - -// matrix.hpp: Line 2913 -LIBSEMIGROUPS_TEST_CASE("docs", "13", "matrix.hpp", "[docs][quick]") { - using Mat = IntMat<>; - Mat m({{1, 1}, {0, 0}}); -} - -// matrix.hpp: Line 3818 -LIBSEMIGROUPS_TEST_CASE("docs", "14", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - BMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - BMat<> m4(4, 4); -} - -// matrix.hpp: Line 4125 -LIBSEMIGROUPS_TEST_CASE("docs", "15", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - IntMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - IntMat<> m4(4, 4); -} - -// matrix.hpp: Line 4415 -LIBSEMIGROUPS_TEST_CASE("docs", "16", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - MaxPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - MaxPlusMat<> m4(4, 4); -} - -// matrix.hpp: Line 4724 -LIBSEMIGROUPS_TEST_CASE("docs", "17", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - MinPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - MinPlusMat<> m4(4, 4); -} - -// matrix.hpp: Line 5043 -LIBSEMIGROUPS_TEST_CASE("docs", "18", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold 11 - MaxPlusTruncMat<11, 3> m3_11; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MaxPlusTruncMat<11> m4_11(4, 4); - // construct a truncated max-plus semiring with threshold 11 - MaxPlusTruncSemiring sr_11(11); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 - // (defined at run time) - MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); -} - -// matrix.hpp: Line 5524 -LIBSEMIGROUPS_TEST_CASE("docs", "19", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold 11 - MinPlusTruncMat<11, 3> m3_11; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MinPlusTruncMat<11> m4_11(4, 4); - // construct a truncated min-plus semiring with threshold 11 - MinPlusTruncSemiring sr_11(11); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 - // (defined at run time) - MinPlusTruncMat<> m5_11(&sr_11, 5, 5); -} - -// matrix.hpp: Line 6010 -LIBSEMIGROUPS_TEST_CASE("docs", "20", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold - // 11, period 2 - NTPMat<11, 2, 3> m3_11_2; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, - // period 2 - NTPMat<11, 2> m4_11_2(4, 4); - // construct an ntp semiring with threshold 11, period 2 - NTPSemiring<> sr_11_2(11, 2); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, - // period 2 - NTPMat<> m_5_11_2(&sr_11_2, 5, 5); -} - -// matrix.hpp: Line 6988 -LIBSEMIGROUPS_TEST_CASE("docs", "21", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - ProjMaxPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - ProjMaxPlusMat<> m4(4, 4); -} - -// matrix.hpp: Line 7153 -LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { - auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, - 1}}); - // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} - matrix::pow(x, 100); -} - -// matrix.hpp: Line 7901 -LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { - auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); - matrix::row_space_size(x); // returns 7 -} - -// order.hpp: Line 98 -LIBSEMIGROUPS_TEST_CASE("docs", "24", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - std::lexicographical_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 133 -LIBSEMIGROUPS_TEST_CASE("docs", "25", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - lexicographical_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 310 -LIBSEMIGROUPS_TEST_CASE("docs", "26", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - shortlex_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 346 -LIBSEMIGROUPS_TEST_CASE("docs", "27", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - shortlex_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 482 -LIBSEMIGROUPS_TEST_CASE("docs", "28", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - recursive_path_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 516 -LIBSEMIGROUPS_TEST_CASE("docs", "29", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - recursive_path_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// presentation.hpp: Line 863 -LIBSEMIGROUPS_TEST_CASE("docs", "30", "presentation.hpp", "[docs][quick]") { - Presentation p; - presentation::to_report_string(p); - // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" -} - -// ranges.hpp: Line 87 -LIBSEMIGROUPS_TEST_CASE("docs", "31", "ranges.hpp", "[docs][quick]") { - using rx::operator|; - auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); - Paths p(wg); - p.source(0).max(10); - p.count(); // returns 1023 - // (p | Random()).get(); // returns random path in p (Pipe operator not - // implemented for Paths?) -} - -// schreier-sims.hpp: Line 166 -LIBSEMIGROUPS_TEST_CASE("docs", "32", "schreier-sims.hpp", "[docs][quick]") { - SchreierSims<5> S; - using Perm = decltype(S)::element_type; - S.add_generator(Perm({1, 0, 2, 3, 4})); - S.add_generator(Perm({1, 2, 3, 4, 0})); - S.size(); // 120 -} - -// todd-coxeter-class.hpp: Line 80 -LIBSEMIGROUPS_TEST_CASE("docs", "33", "todd-coxeter-class.hpp", "[docs][quick]") { - using options = detail::ToddCoxeterImpl::options; - - Presentation p; - p.alphabet(2); - presentation::add_rule(p, 00_w, 0_w); - presentation::add_rule(p, 0_w, 1_w); - ToddCoxeter tc(congruence_kind::onesided, p); - tc.strategy(options::strategy::felsch); - tc.number_of_classes(); - - auto w1 = 0000_w; - auto w2 = 00_w; - todd_coxeter::contains(tc, w1, w2); - todd_coxeter::index_of(tc, w1); -} - -// todd-coxeter-class.hpp: Line 98 -LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") { - using options = detail::ToddCoxeterImpl::options; - - Presentation p; - p.alphabet(4); - presentation::add_rule(p, 00_w, 0_w); - presentation::add_rule(p, 10_w, 1_w); - presentation::add_rule(p, 01_w, 1_w); - presentation::add_rule(p, 20_w, 2_w); - presentation::add_rule(p, 02_w, 2_w); - presentation::add_rule(p, 30_w, 3_w); - presentation::add_rule(p, 03_w, 3_w); - presentation::add_rule(p, 11_w, 0_w); - presentation::add_rule(p, 23_w, 0_w); - presentation::add_rule(p, 222_w, 0_w); - presentation::add_rule(p, 12121212121212_w, 0_w); - presentation::add_rule(p, 12131213121312131213121312131213_w, 0_w); - ToddCoxeter tc(congruence_kind::twosided, p); - tc.strategy(options::strategy::hlt) - .lookahead_extent(options::lookahead_extent::partial) - .save(false); - tc.number_of_classes(); // 10'752 - tc.standardize(Order::recursive); - todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); - // {0_w, - // 1_w, - // 2_w, - // 21_w, - // 12_w, - // 121_w, - // 22_w, - // 221_w, - // 212_w, - // 2121_w} - tc.standardize(Order::lex); - todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); - // {0_w, - // 01_w, - // 012_w, - // 0121_w, - // 01212_w, - // 012121_w, - // 0121212_w, - // 01212121_w, - // 012121212_w, - // 0121212121_w}; -} - -// word-graph.hpp: Line 1540 -LIBSEMIGROUPS_TEST_CASE("docs", "35", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(2); - wg.add_to_out_degree(1); - wg.target(0, 0, 1); - wg.target(1, 0, 0); - word_graph::is_acyclic(wg); // returns false -} - -// word-graph.hpp: Line 1583 -LIBSEMIGROUPS_TEST_CASE("docs", "36", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(4); - wg.add_to_out_degree(1); - wg.target(0, 0, 1); - wg.target(1, 0, 0); - wg.target(2, 0, 3); - word_graph::is_acyclic(wg); // returns false - word_graph::is_acyclic(wg, 0); // returns false - word_graph::is_acyclic(wg, 1); // returns false - word_graph::is_acyclic(wg, 2); // returns true - word_graph::is_acyclic(wg, 3); // returns true -} - -// word-graph.hpp: Line 1973 -LIBSEMIGROUPS_TEST_CASE("docs", "37", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(4); - wg.add_to_out_degree(1); - wg.target(0, 1, 0); - wg.target(1, 0, 0); - wg.target(2, 3, 0); - word_graph::is_reachable_no_checks(wg, 0, 1); // returns true - word_graph::is_reachable_no_checks(wg, 1, 0); // returns true - word_graph::is_reachable_no_checks(wg, 1, 2); // returns false - word_graph::is_reachable_no_checks(wg, 2, 3); // returns true - word_graph::is_reachable_no_checks(wg, 3, 2); // returns false -} - -// word-graph.hpp: Line 2053 -LIBSEMIGROUPS_TEST_CASE("docs", "38", "word-graph.hpp", "[docs][quick]") { - auto wg = make>( - 5, {{0, 0}, {1, 1}, {2}, {3, 3}}); - word_graph::is_strictly_cyclic(wg); // returns false -} - -// word-graph.hpp: Line 2793 -LIBSEMIGROUPS_TEST_CASE("docs", "39", "word-graph.hpp", "[docs][quick]") { - // Construct a word graph with 5 nodes and 10 edges (7 specified) - make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); -} - -// word-range.hpp: Line 183 -LIBSEMIGROUPS_TEST_CASE("docs", "40", "word-range.hpp", "[docs][quick]") { - std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), - cend_wilo(2, 3, {0}, {1, 1, 1})); - // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; -} - -// word-range.hpp: Line 253 -LIBSEMIGROUPS_TEST_CASE("docs", "41", "word-range.hpp", "[docs][quick]") { - std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), - cend_wislo(2, {0}, {0, 0, 0})); - // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; -} - -// word-range.hpp: Line 313 -LIBSEMIGROUPS_TEST_CASE("docs", "42", "word-range.hpp", "[docs][quick]") { - WordRange words; - words.order(Order::shortlex) // words in shortlex order - .alphabet_size(2) // on 2 letters - .min(1) // of length in the range from 1 - .max(5); // to 5 -} - -// word-range.hpp: Line 761 -LIBSEMIGROUPS_TEST_CASE("docs", "43", "word-range.hpp", "[docs][quick]") { - ToWord toword("bac"); - toword("bac"); // returns {0, 1, 2} - toword("bababbbcbc"); // returns { 0, 1, 0, 1, 0, 0, 0, 2, 0, 2} - - toword.init(); - toword("bac"); // returns {1, 0, 2} -} - -// word-range.hpp: Line 1050 -LIBSEMIGROUPS_TEST_CASE("docs", "44", "word-range.hpp", "[docs][quick]") { - using namespace rx; - StringRange strings; - strings.alphabet("ab").first("a").last("bbbb"); - auto words = (strings | ToWord("ba")); - // contains the words - // {1_w, 0_w, 11_w, 10_w, 01_w, 00_w, 111_w, - // 110_w, 101_w, 100_w, 011_w, 010_w, 001_w, 000_w, - // 1111_w, 1110_w, 1101_w, 1100_w, 1011_w, 1010_w, 1001_w, - // 1000_w, 0111_w, 0110_w, 0101_w, 0100_w, 0011_w, 0010_w, - // 0001_w})); -} - -// word-range.hpp: Line 1151 -LIBSEMIGROUPS_TEST_CASE("docs", "45", "word-range.hpp", "[docs][quick]") { - ToString tostring("bac"); - tostring(word_type({1, 0, 2})); // returns "abc" - tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})); // returns "baabaabc" - - tostring.init(); - tostring(word_type({1, 0, 2})); // returns "bac" -} - -// word-range.hpp: Line 1402 -LIBSEMIGROUPS_TEST_CASE("docs", "46", "word-range.hpp", "[docs][quick]") { - using namespace rx; - WordRange words; - words.alphabet_size(1).min(0).max(10); - - auto strings = (words | ToString("a")); - // Contains the strings - // {"", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", - // "aaaaaaaa", "aaaaaaaaa"}; -} - -// word-range.hpp: Line 1596 -LIBSEMIGROUPS_TEST_CASE("docs", "47", "word-range.hpp", "[docs][quick]") { - StringRange strings; - strings.order(Order::shortlex) // strings in shortlex order - .alphabet("ab") // on 2 letters - .min(1) // of length in the range from 1 - .max(5); // to 5 -} - -// word-range.hpp: Line 2307 -LIBSEMIGROUPS_TEST_CASE("docs", "48", "word-range.hpp", "[docs][quick]") { - using namespace words; - word_type w = 012345_w; - prod(w, 0, 5, 2); // {0, 2, 4} - prod(w, 1, 9, 2); // {1, 3, 5, 1} - prod("abcde", 4, 1, -1); // "edc" - prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" -} - - -} \ No newline at end of file + // action.hpp: Line 60 + LIBSEMIGROUPS_TEST_CASE("docs", "0", "action.hpp", "[docs][quick]") { + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + REQUIRE(o.size() == 65536); + } + + // action.hpp: Line 143 + LIBSEMIGROUPS_TEST_CASE("docs", "1", "action.hpp", "[docs][quick]") { + auto rg = ReportGuard(true); + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + REQUIRE(o.size() == 65536); + REQUIRE(o.scc().number_of_components() == 17); + } + + // cong-class.hpp: Line 148 + LIBSEMIGROUPS_TEST_CASE("docs", "2", "cong-class.hpp", "[docs][quick]") { + Presentation p; + p.alphabet(2); + presentation::add_rule(p, {0, 1}, {}); + Congruence cong(congruence_kind::twosided, p); + is_obviously_infinite(cong); // true + congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); + REQUIRE(cong.number_of_classes() == 3); + } + + // freeband.hpp: Line 76 + LIBSEMIGROUPS_TEST_CASE("docs", "3", "freeband.hpp", "[docs][quick]") { + freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, + {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true + freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false + freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true + freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, + {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false + freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true + freeband_equal_to({0, 1, 2, 3, 0, 1}, + {0, 1, 2, 3, 3, 2, 2, 1, 0, 2, 1, 0, 2, 3, + 0, 2, 1, 3, 2, 1, 2, 3, 2, 1, 0, 2, 0, 1, + 0, 2, 0, 3, 2, 0, 1, 2, 2, 3, 0, 1}); // true + } + + // froidure-pin-base.hpp: Line 1337 + LIBSEMIGROUPS_TEST_CASE("docs", + "4", + "froidure-pin-base.hpp", + "[docs][quick]") { + FroidurePin S; + S.add_generator( + BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}})); + S.add_generator( + BMat8({{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}})); + S.add_generator( + BMat8({{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}})); + S.add_generator( + BMat8({{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}})); + REQUIRE(S.size() == 4); + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} + } + + // froidure-pin-base.hpp: Line 1441 + LIBSEMIGROUPS_TEST_CASE("docs", + "5", + "froidure-pin-base.hpp", + "[docs][quick]") { + FroidurePin S; + S.add_generator( + BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}})); + S.add_generator( + BMat8({{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}})); + S.add_generator( + BMat8({{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}})); + S.add_generator( + BMat8({{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}})); + REQUIRE(S.size() == 4); + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} + } + + // is_specialization_of.hpp: Line 44 + LIBSEMIGROUPS_TEST_CASE("docs", + "6", + "is_specialization_of.hpp", + "[docs][quick]") { + using iso_1 = is_specialization_of, std::vector>; + REQUIRE(iso_1::value == true); + using iso_2 = is_specialization_of, std::unordered_map>; + REQUIRE(iso_2::value == false); + } + + // is_specialization_of.hpp: Line 76 + LIBSEMIGROUPS_TEST_CASE("docs", + "7", + "is_specialization_of.hpp", + "[docs][quick]") { + REQUIRE(is_specialization_of_v, std::vector> == true); + REQUIRE(is_specialization_of_v, std::unordered_map> + == false); + } + + // knuth-bendix-class.hpp: Line 72 + LIBSEMIGROUPS_TEST_CASE("docs", + "8", + "knuth-bendix-class.hpp", + "[docs][quick]") { + Presentation p; + p.contains_empty_word(true); + p.alphabet("abcd"); + presentation::add_rule_no_checks(p, "ab", ""); + presentation::add_rule_no_checks(p, "ba", ""); + presentation::add_rule_no_checks(p, "cd", ""); + presentation::add_rule_no_checks(p, "dc", ""); + + KnuthBendix kb(congruence_kind::twosided, p); + + REQUIRE(!kb.confluent() == true); + kb.run(); + REQUIRE(kb.number_of_active_rules() == 8); + REQUIRE(kb.confluent() == true); + REQUIRE(kb.number_of_classes() == POSITIVE_INFINITY); + } + + // konieczny.hpp: Line 70 + LIBSEMIGROUPS_TEST_CASE("docs", "9", "konieczny.hpp", "[docs][quick]") { + auto S = make( + {BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), + BMat8({{1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}})}); + S.size(); // returns 63'904 + S.number_of_idempotents(); // returns 2'360 + } + + // matrix.hpp: Line 1964 + LIBSEMIGROUPS_TEST_CASE("docs", "10", "matrix.hpp", "[docs][quick]") { + using Mat = BMat8; + Mat m({{1, 1}, {0, 0}}); + } + + // matrix.hpp: Line 2867 + LIBSEMIGROUPS_TEST_CASE("docs", "11", "matrix.hpp", "[docs][quick]") { + using Mat = IntMat<>; + Mat m(2, 3); // construct a 2 x 3 matrix + } + + // matrix.hpp: Line 2890 + LIBSEMIGROUPS_TEST_CASE("docs", "12", "matrix.hpp", "[docs][quick]") { + using Mat = BMat<>; + Mat m({1, 1, 0, 0}); + } + + // matrix.hpp: Line 2913 + LIBSEMIGROUPS_TEST_CASE("docs", "13", "matrix.hpp", "[docs][quick]") { + using Mat = IntMat<>; + Mat m({{1, 1}, {0, 0}}); + } + + // matrix.hpp: Line 3818 + LIBSEMIGROUPS_TEST_CASE("docs", "14", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + BMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + BMat<> m4(4, 4); + } + + // matrix.hpp: Line 4125 + LIBSEMIGROUPS_TEST_CASE("docs", "15", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + IntMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + IntMat<> m4(4, 4); + } + + // matrix.hpp: Line 4415 + LIBSEMIGROUPS_TEST_CASE("docs", "16", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + MaxPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + MaxPlusMat<> m4(4, 4); + } + + // matrix.hpp: Line 4724 + LIBSEMIGROUPS_TEST_CASE("docs", "17", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + MinPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + MinPlusMat<> m4(4, 4); + } + + // matrix.hpp: Line 5043 + LIBSEMIGROUPS_TEST_CASE("docs", "18", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + MaxPlusTruncMat<11, 3> m3_11; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MaxPlusTruncMat<11> m4_11(4, 4); + // construct a truncated max-plus semiring with threshold 11 + MaxPlusTruncSemiring sr_11(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); + } + + // matrix.hpp: Line 5524 + LIBSEMIGROUPS_TEST_CASE("docs", "19", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + MinPlusTruncMat<11, 3> m3_11; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MinPlusTruncMat<11> m4_11(4, 4); + // construct a truncated min-plus semiring with threshold 11 + MinPlusTruncSemiring sr_11(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MinPlusTruncMat<> m5_11(&sr_11, 5, 5); + } + + // matrix.hpp: Line 6010 + LIBSEMIGROUPS_TEST_CASE("docs", "20", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold + // 11, period 2 + NTPMat<11, 2, 3> m3_11_2; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, + // period 2 + NTPMat<11, 2> m4_11_2(4, 4); + // construct an ntp semiring with threshold 11, period 2 + NTPSemiring<> sr_11_2(11, 2); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, + // period 2 + NTPMat<> m_5_11_2(&sr_11_2, 5, 5); + } + + // matrix.hpp: Line 6988 + LIBSEMIGROUPS_TEST_CASE("docs", "21", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + ProjMaxPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + ProjMaxPlusMat<> m4(4, 4); + } + + // matrix.hpp: Line 7153 + LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { + auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, 1}}); + // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} + matrix::pow(x, 100); + } + + // matrix.hpp: Line 7901 + LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { + auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); + matrix::row_space_size(x); // returns 7 + } + + // order.hpp: Line 98 + LIBSEMIGROUPS_TEST_CASE("docs", "24", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + REQUIRE(lexicographical_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()) + == true); + } + + // order.hpp: Line 132 + LIBSEMIGROUPS_TEST_CASE("docs", "25", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + REQUIRE(lexicographical_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()) + == true); + } + + // order.hpp: Line 308 + LIBSEMIGROUPS_TEST_CASE("docs", "26", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // order.hpp: Line 344 + LIBSEMIGROUPS_TEST_CASE("docs", "27", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // order.hpp: Line 480 + LIBSEMIGROUPS_TEST_CASE("docs", "28", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // order.hpp: Line 514 + LIBSEMIGROUPS_TEST_CASE("docs", "29", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // presentation.hpp: Line 863 + LIBSEMIGROUPS_TEST_CASE("docs", "30", "presentation.hpp", "[docs][quick]") { + Presentation p; + presentation::to_report_string(p); + // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" + } + + // ranges.hpp: Line 87 + LIBSEMIGROUPS_TEST_CASE("docs", "31", "ranges.hpp", "[docs][quick]") { + using rx::operator|; + auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); + Paths p(wg); + p.source(0).max(10); + REQUIRE(p.count() == 1023); + // (p | Random()).get(); // returns random path in p (Pipe operator not + // implemented for Paths?) + } + + // schreier-sims.hpp: Line 166 + LIBSEMIGROUPS_TEST_CASE("docs", "32", "schreier-sims.hpp", "[docs][quick]") { + SchreierSims<5> S; + using Perm = decltype(S)::element_type; + S.add_generator(Perm({1, 0, 2, 3, 4})); + S.add_generator(Perm({1, 2, 3, 4, 0})); + REQUIRE(S.size() == 120); + } + + // todd-coxeter-class.hpp: Line 80 + LIBSEMIGROUPS_TEST_CASE("docs", + "33", + "todd-coxeter-class.hpp", + "[docs][quick]") { + using options = detail::ToddCoxeterImpl::options; + + Presentation p; + p.alphabet(2); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 0_w, 1_w); + ToddCoxeter tc(congruence_kind::onesided, p); + tc.strategy(options::strategy::felsch); + REQUIRE(tc.number_of_classes() == 1); + + auto w1 = 0000_w; + auto w2 = 00_w; + REQUIRE(todd_coxeter::contains(tc, w1, w2) == true); + REQUIRE(todd_coxeter::index_of(tc, w1) == 0); + } + + // todd-coxeter-class.hpp: Line 98 + LIBSEMIGROUPS_TEST_CASE("docs", + "34", + "todd-coxeter-class.hpp", + "[docs][quick]") { + using options = detail::ToddCoxeterImpl::options; + + Presentation p; + p.alphabet(4); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 10_w, 1_w); + presentation::add_rule(p, 01_w, 1_w); + presentation::add_rule(p, 20_w, 2_w); + presentation::add_rule(p, 02_w, 2_w); + presentation::add_rule(p, 30_w, 3_w); + presentation::add_rule(p, 03_w, 3_w); + presentation::add_rule(p, 11_w, 0_w); + presentation::add_rule(p, 23_w, 0_w); + presentation::add_rule(p, 222_w, 0_w); + presentation::add_rule(p, 12121212121212_w, 0_w); + presentation::add_rule(p, 12131213121312131213121312131213_w, 0_w); + ToddCoxeter tc(congruence_kind::twosided, p); + tc.strategy(options::strategy::hlt) + .lookahead_extent(options::lookahead_extent::partial) + .save(false); + REQUIRE(tc.number_of_classes() == 10752); + tc.standardize(Order::recursive); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); + // {0_w, + // 1_w, + // 2_w, + // 21_w, + // 12_w, + // 121_w, + // 22_w, + // 221_w, + // 212_w, + // 2121_w} + tc.standardize(Order::lex); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); + // {0_w, + // 01_w, + // 012_w, + // 0121_w, + // 01212_w, + // 012121_w, + // 0121212_w, + // 01212121_w, + // 012121212_w, + // 0121212121_w}; + } + + // word-graph.hpp: Line 1540 + LIBSEMIGROUPS_TEST_CASE("docs", "35", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(2); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + REQUIRE(word_graph::is_acyclic(wg) == false); + } + + // word-graph.hpp: Line 1583 + LIBSEMIGROUPS_TEST_CASE("docs", "36", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + wg.target(2, 0, 3); + REQUIRE(word_graph::is_acyclic(wg) == false); + REQUIRE(word_graph::is_acyclic(wg, 0) == false); + REQUIRE(word_graph::is_acyclic(wg, 1) == false); + REQUIRE(word_graph::is_acyclic(wg, 2) == true); + REQUIRE(word_graph::is_acyclic(wg, 3) == true); + } + + // word-graph.hpp: Line 1973 + LIBSEMIGROUPS_TEST_CASE("docs", "37", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(1); + wg.target(0, 1, 0); + wg.target(1, 0, 0); + wg.target(2, 3, 0); + REQUIRE(word_graph::is_reachable_no_checks(wg, 0, 1) == true); + REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 0) == true); + REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 2) == false); + REQUIRE(word_graph::is_reachable_no_checks(wg, 2, 3) == true); + REQUIRE(word_graph::is_reachable_no_checks(wg, 3, 2) == false); + } + + // word-graph.hpp: Line 2053 + LIBSEMIGROUPS_TEST_CASE("docs", "38", "word-graph.hpp", "[docs][quick]") { + auto wg = make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); + REQUIRE(word_graph::is_strictly_cyclic(wg) == false); + } + + // word-graph.hpp: Line 2793 + LIBSEMIGROUPS_TEST_CASE("docs", "39", "word-graph.hpp", "[docs][quick]") { + // Construct a word graph with 5 nodes and 10 edges (7 specified) + auto wg = make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); + } + + // word-range.hpp: Line 183 + LIBSEMIGROUPS_TEST_CASE("docs", "40", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), + cend_wilo(2, 3, {0}, {1, 1, 1})); + // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; + } + + // word-range.hpp: Line 253 + LIBSEMIGROUPS_TEST_CASE("docs", "41", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), + cend_wislo(2, {0}, {0, 0, 0})); + // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; + } + + // word-range.hpp: Line 313 + LIBSEMIGROUPS_TEST_CASE("docs", "42", "word-range.hpp", "[docs][quick]") { + WordRange words; + words + .order(Order::shortlex) // words in shortlex order + .alphabet_size(2) // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 + } + + // word-range.hpp: Line 761 + LIBSEMIGROUPS_TEST_CASE("docs", "43", "word-range.hpp", "[docs][quick]") { + ToWord toword("bac"); + REQUIRE(toword("bac") == std::vector{0, 1, 2}); + REQUIRE(toword("bababbbcbc") + == std::vector{0, 1, 0, 1, 0, 0, 0, 2, 0, 2}); + + toword.init(); + REQUIRE(toword("bac") == std::vector{1, 0, 2}); + } + + // word-range.hpp: Line 1050 + LIBSEMIGROUPS_TEST_CASE("docs", "44", "word-range.hpp", "[docs][quick]") { + using namespace rx; + StringRange strings; + strings.alphabet("ab").first("a").last("bbbb"); + auto words = (strings | ToWord("ba")); + // contains the words + // {1_w, 0_w, 11_w, 10_w, 01_w, 00_w, 111_w, + // 110_w, 101_w, 100_w, 011_w, 010_w, 001_w, 000_w, + // 1111_w, 1110_w, 1101_w, 1100_w, 1011_w, 1010_w, 1001_w, + // 1000_w, 0111_w, 0110_w, 0101_w, 0100_w, 0011_w, 0010_w, + // 0001_w})); + } + + // word-range.hpp: Line 1151 + LIBSEMIGROUPS_TEST_CASE("docs", "45", "word-range.hpp", "[docs][quick]") { + ToString tostring("bac"); + REQUIRE(tostring(word_type({1, 0, 2})) == "abc"); + REQUIRE(tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})) == "baabaabc"); + + tostring.init(); + REQUIRE(tostring(word_type({1, 0, 2})) == "bac"); + } + + // word-range.hpp: Line 1402 + LIBSEMIGROUPS_TEST_CASE("docs", "46", "word-range.hpp", "[docs][quick]") { + using namespace rx; + WordRange words; + words.alphabet_size(1).min(0).max(10); + + auto strings = (words | ToString("a")); + // Contains the strings + // {"", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", + // "aaaaaaaa", "aaaaaaaaa"}; + } + + // word-range.hpp: Line 1596 + LIBSEMIGROUPS_TEST_CASE("docs", "47", "word-range.hpp", "[docs][quick]") { + StringRange strings; + strings + .order(Order::shortlex) // strings in shortlex order + .alphabet("ab") // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 + } + + // word-range.hpp: Line 2307 + LIBSEMIGROUPS_TEST_CASE("docs", "48", "word-range.hpp", "[docs][quick]") { + using namespace words; + word_type w = 012345_w; + prod(w, 0, 5, 2); // {0, 2, 4} + prod(w, 1, 9, 2); // {1, 3, 5, 1} + prod("abcde", 4, 1, -1); // "edc" + prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" + } + +} // namespace libsemigroups From 4b17a5dc3feec6613b8edd6bc4d41d6af3f710ab Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 12 Nov 2025 14:57:03 +0000 Subject: [PATCH 10/11] All tests passing. Job Done! --- etc/extract-doc-examples.py | 29 +- include/libsemigroups/cong-class.hpp | 2 + include/libsemigroups/knuth-bendix-class.hpp | 6 +- include/libsemigroups/matrix.hpp | 14 +- include/libsemigroups/order.hpp | 13 +- include/libsemigroups/word-graph.hpp | 6 +- tests/test-docs-code-examples.cpp | 1214 +++++++++--------- 7 files changed, 655 insertions(+), 629 deletions(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index 0d2f8132a..d19c2af0d 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -1,10 +1,13 @@ -import os +""" +Automated code block extraction from documentation for testing. +""" + import sys import argparse from pathlib import Path ######################################################################## -# CONSTANTS +# Constants ######################################################################## HEADER_TEXT = """// libsemigroups - C++ library for semigroups and monoids @@ -32,7 +35,7 @@ """ ######################################################################## -# INTERNAL +# Internal ######################################################################## @@ -52,8 +55,8 @@ def __parse_args() -> argparse.Namespace: Examples: python3 extract_code.py <-- Process specific folder Flags: - -r | Process folder recursively - -e | Exclude the following files + -r | Process folder recursively + -e | Exclude the following files """, ) @@ -79,7 +82,10 @@ def __parse_args() -> argparse.Namespace: ) parser.add_argument( - "--version", action="version", version="Example Code Block Capture 1.0.0" + "-v", + "--version", + action="version", + version="Documentation Code Block Extraction 0.1.0", ) args = parser.parse_args() @@ -88,7 +94,7 @@ def __parse_args() -> argparse.Namespace: ######################################################################## -# CODE BLOCK EXTRACTION +# Code block extraction ######################################################################## @@ -116,6 +122,7 @@ def extract_code_blocks(file_path): line = line.removeprefix("//!") line = line.rstrip("\n\r") + # Code Block Open if "\\code" in line: if in_code_block: __error( @@ -127,6 +134,7 @@ def extract_code_blocks(file_path): current_block = [] continue + #  Code Block Close if "\\endcode" in line: if not in_code_block: __error( @@ -192,6 +200,11 @@ def extract_code_blocks(file_path): return code_blocks +######################################################################## +# File Iteration +######################################################################## + + def process_folder(folder_path, recursive=False, exclude=[]): """ Process all files in a folder to find code examples. @@ -275,7 +288,7 @@ def process_folder(folder_path, recursive=False, exclude=[]): ######################################################################## -# MAIN +# Main ######################################################################### diff --git a/include/libsemigroups/cong-class.hpp b/include/libsemigroups/cong-class.hpp index b9b60c580..4d9414fa0 100644 --- a/include/libsemigroups/cong-class.hpp +++ b/include/libsemigroups/cong-class.hpp @@ -147,7 +147,9 @@ namespace libsemigroups { //! \code //! Presentation p; //! p.alphabet(2); + //! p.contains_empty_word(true); //! presentation::add_rule(p, {0, 1}, {}); + //! //! Congruence cong(congruence_kind::twosided, p); //! is_obviously_infinite(cong); // true //! congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); diff --git a/include/libsemigroups/knuth-bendix-class.hpp b/include/libsemigroups/knuth-bendix-class.hpp index 3bd71ce86..7e5c092aa 100644 --- a/include/libsemigroups/knuth-bendix-class.hpp +++ b/include/libsemigroups/knuth-bendix-class.hpp @@ -79,9 +79,11 @@ namespace libsemigroups { //! //! KnuthBendix kb(congruence_kind::twosided, p); //! - //! !kb.confluent(); //-> true + //! kb.number_of_active_rules(); //-> 0 + //! kb.number_of_pending_rules(); //-> 4 //! kb.run(); - //! kb.number_of_active_rules(); //-> 8 + //! kb.number_of_active_rules(); //-> 4 + //! kb.number_of_pending_rules(); //-> 0 //! kb.confluent(); //-> true //! kb.number_of_classes(); //-> POSITIVE_INFINITY //! \endcode diff --git a/include/libsemigroups/matrix.hpp b/include/libsemigroups/matrix.hpp index fc1203152..f3fef2c25 100644 --- a/include/libsemigroups/matrix.hpp +++ b/include/libsemigroups/matrix.hpp @@ -3816,7 +3816,7 @@ namespace libsemigroups { //! \par Example //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! BMat<3> m3; + //! [[maybe_unused]] BMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix //! BMat<> m4(4, 4); //! \endcode @@ -4123,7 +4123,7 @@ namespace libsemigroups { //! \par Example //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! IntMat<3> m3; + //! [[maybe_unused]] IntMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix //! IntMat<> m4(4, 4); //! \endcode @@ -4413,7 +4413,7 @@ namespace libsemigroups { //! \par Example //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! MaxPlusMat<3> m3; + //! [[maybe_unused]] MaxPlusMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix //! MaxPlusMat<> m4(4, 4); //! \endcode @@ -4722,7 +4722,7 @@ namespace libsemigroups { //! //! \code //! // default construct an uninitialized 3 x 3 static matrix - //! MinPlusMat<3> m3; + //! [[maybe_unused]] MinPlusMat<3> m3; //! // construct an uninitialized 4 x 4 dynamic matrix //! MinPlusMat<> m4(4, 4); //! \endcode @@ -5041,7 +5041,7 @@ namespace libsemigroups { //! \par Example //! \code //! // construct an uninitialized 3 x 3 static matrix with threshold 11 - //! MaxPlusTruncMat<11, 3> m3_11; + //! [[maybe_unused]] MaxPlusTruncMat<11, 3> m3_11; //! // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 //! MaxPlusTruncMat<11> m4_11(4, 4); //! // construct a truncated max-plus semiring with threshold 11 @@ -5522,7 +5522,7 @@ namespace libsemigroups { //! \par Example //! \code //! // construct an uninitialized 3 x 3 static matrix with threshold 11 - //! MinPlusTruncMat<11, 3> m3_11; + //! [[maybe_unused]] MinPlusTruncMat<11, 3> m3_11; //! // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 //! MinPlusTruncMat<11> m4_11(4, 4); //! // construct a truncated min-plus semiring with threshold 11 @@ -6009,7 +6009,7 @@ namespace libsemigroups { //! \code //! // construct an uninitialized 3 x 3 static matrix with threshold //! // 11, period 2 - //! NTPMat<11, 2, 3> m3_11_2; + //! [[maybe_unused]] NTPMat<11, 2, 3> m3_11_2; //! // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, //! // period 2 //! NTPMat<11, 2> m4_11_2(4, 4); diff --git a/include/libsemigroups/order.hpp b/include/libsemigroups/order.hpp index ff3b7afc4..07a71d606 100644 --- a/include/libsemigroups/order.hpp +++ b/include/libsemigroups/order.hpp @@ -95,9 +95,11 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code - //! word_type x = random_word(5, 10); - //! word_type y = random_word(5, 10); - //! lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend());//->true + //! word_type x = 1101_w; + //! word_type y = 1001_w; + //! + //! // x > y + //! lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend());//->false //! \endcode template >> bool lexicographical_compare(T const& x, T const& y) { @@ -129,8 +131,9 @@ namespace libsemigroups { //! //! \par Possible Implementation //! \code - //! word_type x = random_word(5, 10); - //! word_type y = random_word(5, 10); + //! word_type x = 0001_w; + //! word_type y = 0010_w; + //! // x < y //! lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend());//->true //! \endcode template diff --git a/include/libsemigroups/word-graph.hpp b/include/libsemigroups/word-graph.hpp index 1ca37ec5f..926dd6b9d 100644 --- a/include/libsemigroups/word-graph.hpp +++ b/include/libsemigroups/word-graph.hpp @@ -1972,14 +1972,14 @@ namespace libsemigroups { //! \code //! WordGraph wg; //! wg.add_nodes(4); - //! wg.add_to_out_degree(1); + //! wg.add_to_out_degree(4); //! wg.target(0, 1, 0); //! wg.target(1, 0, 0); //! wg.target(2, 3, 0); - //! word_graph::is_reachable_no_checks(wg, 0, 1); //-> true + //! word_graph::is_reachable_no_checks(wg, 0, 1); //-> false //! word_graph::is_reachable_no_checks(wg, 1, 0); //-> true //! word_graph::is_reachable_no_checks(wg, 1, 2); //-> false - //! word_graph::is_reachable_no_checks(wg, 2, 3); //-> true + //! word_graph::is_reachable_no_checks(wg, 2, 3); //-> false //! word_graph::is_reachable_no_checks(wg, 3, 2); //-> false //! \endcode template diff --git a/tests/test-docs-code-examples.cpp b/tests/test-docs-code-examples.cpp index c3140c04c..c0ead1b64 100644 --- a/tests/test-docs-code-examples.cpp +++ b/tests/test-docs-code-examples.cpp @@ -22,607 +22,613 @@ using namespace libsemigroups::literals; namespace libsemigroups { - // action.hpp: Line 60 - LIBSEMIGROUPS_TEST_CASE("docs", "0", "action.hpp", "[docs][quick]") { - RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> o; - o.add_seed(PPerm<16>::one(16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.add_generator( - PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.reserve(70000); - REQUIRE(o.size() == 65536); - } - - // action.hpp: Line 143 - LIBSEMIGROUPS_TEST_CASE("docs", "1", "action.hpp", "[docs][quick]") { - auto rg = ReportGuard(true); - RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> o; - o.add_seed(PPerm<16>::one(16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.add_generator( - PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.reserve(70000); - REQUIRE(o.size() == 65536); - REQUIRE(o.scc().number_of_components() == 17); - } - - // cong-class.hpp: Line 148 - LIBSEMIGROUPS_TEST_CASE("docs", "2", "cong-class.hpp", "[docs][quick]") { - Presentation p; - p.alphabet(2); - presentation::add_rule(p, {0, 1}, {}); - Congruence cong(congruence_kind::twosided, p); - is_obviously_infinite(cong); // true - congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); - REQUIRE(cong.number_of_classes() == 3); - } - - // freeband.hpp: Line 76 - LIBSEMIGROUPS_TEST_CASE("docs", "3", "freeband.hpp", "[docs][quick]") { - freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, - {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true - freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false - freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true - freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, - {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false - freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true - freeband_equal_to({0, 1, 2, 3, 0, 1}, - {0, 1, 2, 3, 3, 2, 2, 1, 0, 2, 1, 0, 2, 3, - 0, 2, 1, 3, 2, 1, 2, 3, 2, 1, 0, 2, 0, 1, - 0, 2, 0, 3, 2, 0, 1, 2, 2, 3, 0, 1}); // true - } - - // froidure-pin-base.hpp: Line 1337 - LIBSEMIGROUPS_TEST_CASE("docs", - "4", - "froidure-pin-base.hpp", - "[docs][quick]") { - FroidurePin S; - S.add_generator( - BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}})); - S.add_generator( - BMat8({{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}})); - S.add_generator( - BMat8({{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}})); - S.add_generator( - BMat8({{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}})); - REQUIRE(S.size() == 4); - std::vector(S.cbegin_rules(), S.cend_rules()); - // {{{0, 0}, {0}}, - // {{0, 1}, {1}}, - // {{0, 2}, {2}}, - // {{0, 3}, {3}}, - // {{1, 0}, {0}}, - // {{1, 1}, {1}}, - // {{1, 2}, {2}}, - // {{1, 3}, {3}}, - // {{2, 0}, {0}}, - // {{2, 1}, {1}}, - // {{2, 2}, {2}}, - // {{2, 3}, {3}}, - // {{3, 0}, {0}}, - // {{3, 1}, {1}}, - // {{3, 2}, {2}}, - // {{3, 3}, {3}}} - } - - // froidure-pin-base.hpp: Line 1441 - LIBSEMIGROUPS_TEST_CASE("docs", - "5", - "froidure-pin-base.hpp", - "[docs][quick]") { - FroidurePin S; - S.add_generator( - BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}})); - S.add_generator( - BMat8({{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}})); - S.add_generator( - BMat8({{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}})); - S.add_generator( - BMat8({{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}})); - REQUIRE(S.size() == 4); - std::vector(S.cbegin_rules(), S.cend_rules()); - // {{{0, 0}, {0}}, - // {{0, 1}, {1}}, - // {{0, 2}, {2}}, - // {{0, 3}, {3}}, - // {{1, 0}, {0}}, - // {{1, 1}, {1}}, - // {{1, 2}, {2}}, - // {{1, 3}, {3}}, - // {{2, 0}, {0}}, - // {{2, 1}, {1}}, - // {{2, 2}, {2}}, - // {{2, 3}, {3}}, - // {{3, 0}, {0}}, - // {{3, 1}, {1}}, - // {{3, 2}, {2}}, - // {{3, 3}, {3}}} - } - - // is_specialization_of.hpp: Line 44 - LIBSEMIGROUPS_TEST_CASE("docs", - "6", - "is_specialization_of.hpp", - "[docs][quick]") { - using iso_1 = is_specialization_of, std::vector>; - REQUIRE(iso_1::value == true); - using iso_2 = is_specialization_of, std::unordered_map>; - REQUIRE(iso_2::value == false); - } - - // is_specialization_of.hpp: Line 76 - LIBSEMIGROUPS_TEST_CASE("docs", - "7", - "is_specialization_of.hpp", - "[docs][quick]") { - REQUIRE(is_specialization_of_v, std::vector> == true); - REQUIRE(is_specialization_of_v, std::unordered_map> - == false); - } - - // knuth-bendix-class.hpp: Line 72 - LIBSEMIGROUPS_TEST_CASE("docs", - "8", - "knuth-bendix-class.hpp", - "[docs][quick]") { - Presentation p; - p.contains_empty_word(true); - p.alphabet("abcd"); - presentation::add_rule_no_checks(p, "ab", ""); - presentation::add_rule_no_checks(p, "ba", ""); - presentation::add_rule_no_checks(p, "cd", ""); - presentation::add_rule_no_checks(p, "dc", ""); - - KnuthBendix kb(congruence_kind::twosided, p); - - REQUIRE(!kb.confluent() == true); - kb.run(); - REQUIRE(kb.number_of_active_rules() == 8); - REQUIRE(kb.confluent() == true); - REQUIRE(kb.number_of_classes() == POSITIVE_INFINITY); - } - - // konieczny.hpp: Line 70 - LIBSEMIGROUPS_TEST_CASE("docs", "9", "konieczny.hpp", "[docs][quick]") { - auto S = make( - {BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), - BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), - BMat8({{1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), - BMat8({{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}})}); - S.size(); // returns 63'904 - S.number_of_idempotents(); // returns 2'360 - } - - // matrix.hpp: Line 1964 - LIBSEMIGROUPS_TEST_CASE("docs", "10", "matrix.hpp", "[docs][quick]") { - using Mat = BMat8; - Mat m({{1, 1}, {0, 0}}); - } - - // matrix.hpp: Line 2867 - LIBSEMIGROUPS_TEST_CASE("docs", "11", "matrix.hpp", "[docs][quick]") { - using Mat = IntMat<>; - Mat m(2, 3); // construct a 2 x 3 matrix - } - - // matrix.hpp: Line 2890 - LIBSEMIGROUPS_TEST_CASE("docs", "12", "matrix.hpp", "[docs][quick]") { - using Mat = BMat<>; - Mat m({1, 1, 0, 0}); - } - - // matrix.hpp: Line 2913 - LIBSEMIGROUPS_TEST_CASE("docs", "13", "matrix.hpp", "[docs][quick]") { - using Mat = IntMat<>; - Mat m({{1, 1}, {0, 0}}); - } - - // matrix.hpp: Line 3818 - LIBSEMIGROUPS_TEST_CASE("docs", "14", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - BMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - BMat<> m4(4, 4); - } - - // matrix.hpp: Line 4125 - LIBSEMIGROUPS_TEST_CASE("docs", "15", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - IntMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - IntMat<> m4(4, 4); - } - - // matrix.hpp: Line 4415 - LIBSEMIGROUPS_TEST_CASE("docs", "16", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - MaxPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - MaxPlusMat<> m4(4, 4); - } - - // matrix.hpp: Line 4724 - LIBSEMIGROUPS_TEST_CASE("docs", "17", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - MinPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - MinPlusMat<> m4(4, 4); - } - - // matrix.hpp: Line 5043 - LIBSEMIGROUPS_TEST_CASE("docs", "18", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold 11 - MaxPlusTruncMat<11, 3> m3_11; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MaxPlusTruncMat<11> m4_11(4, 4); - // construct a truncated max-plus semiring with threshold 11 - MaxPlusTruncSemiring sr_11(11); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 - // (defined at run time) - MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); - } - - // matrix.hpp: Line 5524 - LIBSEMIGROUPS_TEST_CASE("docs", "19", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold 11 - MinPlusTruncMat<11, 3> m3_11; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MinPlusTruncMat<11> m4_11(4, 4); - // construct a truncated min-plus semiring with threshold 11 - MinPlusTruncSemiring sr_11(11); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 - // (defined at run time) - MinPlusTruncMat<> m5_11(&sr_11, 5, 5); - } - - // matrix.hpp: Line 6010 - LIBSEMIGROUPS_TEST_CASE("docs", "20", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold - // 11, period 2 - NTPMat<11, 2, 3> m3_11_2; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, - // period 2 - NTPMat<11, 2> m4_11_2(4, 4); - // construct an ntp semiring with threshold 11, period 2 - NTPSemiring<> sr_11_2(11, 2); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, - // period 2 - NTPMat<> m_5_11_2(&sr_11_2, 5, 5); - } - - // matrix.hpp: Line 6988 - LIBSEMIGROUPS_TEST_CASE("docs", "21", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - ProjMaxPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - ProjMaxPlusMat<> m4(4, 4); - } - - // matrix.hpp: Line 7153 - LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { - auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, 1}}); - // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} - matrix::pow(x, 100); - } - - // matrix.hpp: Line 7901 - LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { - auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); - matrix::row_space_size(x); // returns 7 - } - - // order.hpp: Line 98 - LIBSEMIGROUPS_TEST_CASE("docs", "24", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - REQUIRE(lexicographical_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()) - == true); - } - - // order.hpp: Line 132 - LIBSEMIGROUPS_TEST_CASE("docs", "25", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - REQUIRE(lexicographical_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()) - == true); - } - - // order.hpp: Line 308 - LIBSEMIGROUPS_TEST_CASE("docs", "26", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - shortlex_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); - } - - // order.hpp: Line 344 - LIBSEMIGROUPS_TEST_CASE("docs", "27", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - shortlex_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); - } - - // order.hpp: Line 480 - LIBSEMIGROUPS_TEST_CASE("docs", "28", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - recursive_path_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); - } - - // order.hpp: Line 514 - LIBSEMIGROUPS_TEST_CASE("docs", "29", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - recursive_path_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); - } - - // presentation.hpp: Line 863 - LIBSEMIGROUPS_TEST_CASE("docs", "30", "presentation.hpp", "[docs][quick]") { - Presentation p; - presentation::to_report_string(p); - // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" - } - - // ranges.hpp: Line 87 - LIBSEMIGROUPS_TEST_CASE("docs", "31", "ranges.hpp", "[docs][quick]") { - using rx::operator|; - auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); - Paths p(wg); - p.source(0).max(10); - REQUIRE(p.count() == 1023); - // (p | Random()).get(); // returns random path in p (Pipe operator not - // implemented for Paths?) - } - - // schreier-sims.hpp: Line 166 - LIBSEMIGROUPS_TEST_CASE("docs", "32", "schreier-sims.hpp", "[docs][quick]") { - SchreierSims<5> S; - using Perm = decltype(S)::element_type; - S.add_generator(Perm({1, 0, 2, 3, 4})); - S.add_generator(Perm({1, 2, 3, 4, 0})); - REQUIRE(S.size() == 120); - } - - // todd-coxeter-class.hpp: Line 80 - LIBSEMIGROUPS_TEST_CASE("docs", - "33", - "todd-coxeter-class.hpp", - "[docs][quick]") { - using options = detail::ToddCoxeterImpl::options; - - Presentation p; - p.alphabet(2); - presentation::add_rule(p, 00_w, 0_w); - presentation::add_rule(p, 0_w, 1_w); - ToddCoxeter tc(congruence_kind::onesided, p); - tc.strategy(options::strategy::felsch); - REQUIRE(tc.number_of_classes() == 1); - - auto w1 = 0000_w; - auto w2 = 00_w; - REQUIRE(todd_coxeter::contains(tc, w1, w2) == true); - REQUIRE(todd_coxeter::index_of(tc, w1) == 0); - } - - // todd-coxeter-class.hpp: Line 98 - LIBSEMIGROUPS_TEST_CASE("docs", - "34", - "todd-coxeter-class.hpp", - "[docs][quick]") { - using options = detail::ToddCoxeterImpl::options; - - Presentation p; - p.alphabet(4); - presentation::add_rule(p, 00_w, 0_w); - presentation::add_rule(p, 10_w, 1_w); - presentation::add_rule(p, 01_w, 1_w); - presentation::add_rule(p, 20_w, 2_w); - presentation::add_rule(p, 02_w, 2_w); - presentation::add_rule(p, 30_w, 3_w); - presentation::add_rule(p, 03_w, 3_w); - presentation::add_rule(p, 11_w, 0_w); - presentation::add_rule(p, 23_w, 0_w); - presentation::add_rule(p, 222_w, 0_w); - presentation::add_rule(p, 12121212121212_w, 0_w); - presentation::add_rule(p, 12131213121312131213121312131213_w, 0_w); - ToddCoxeter tc(congruence_kind::twosided, p); - tc.strategy(options::strategy::hlt) - .lookahead_extent(options::lookahead_extent::partial) - .save(false); - REQUIRE(tc.number_of_classes() == 10752); - tc.standardize(Order::recursive); - todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); - // {0_w, - // 1_w, - // 2_w, - // 21_w, - // 12_w, - // 121_w, - // 22_w, - // 221_w, - // 212_w, - // 2121_w} - tc.standardize(Order::lex); - todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); - // {0_w, - // 01_w, - // 012_w, - // 0121_w, - // 01212_w, - // 012121_w, - // 0121212_w, - // 01212121_w, - // 012121212_w, - // 0121212121_w}; - } - - // word-graph.hpp: Line 1540 - LIBSEMIGROUPS_TEST_CASE("docs", "35", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(2); - wg.add_to_out_degree(1); - wg.target(0, 0, 1); - wg.target(1, 0, 0); - REQUIRE(word_graph::is_acyclic(wg) == false); - } - - // word-graph.hpp: Line 1583 - LIBSEMIGROUPS_TEST_CASE("docs", "36", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(4); - wg.add_to_out_degree(1); - wg.target(0, 0, 1); - wg.target(1, 0, 0); - wg.target(2, 0, 3); - REQUIRE(word_graph::is_acyclic(wg) == false); - REQUIRE(word_graph::is_acyclic(wg, 0) == false); - REQUIRE(word_graph::is_acyclic(wg, 1) == false); - REQUIRE(word_graph::is_acyclic(wg, 2) == true); - REQUIRE(word_graph::is_acyclic(wg, 3) == true); - } - - // word-graph.hpp: Line 1973 - LIBSEMIGROUPS_TEST_CASE("docs", "37", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(4); - wg.add_to_out_degree(1); - wg.target(0, 1, 0); - wg.target(1, 0, 0); - wg.target(2, 3, 0); - REQUIRE(word_graph::is_reachable_no_checks(wg, 0, 1) == true); - REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 0) == true); - REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 2) == false); - REQUIRE(word_graph::is_reachable_no_checks(wg, 2, 3) == true); - REQUIRE(word_graph::is_reachable_no_checks(wg, 3, 2) == false); - } - - // word-graph.hpp: Line 2053 - LIBSEMIGROUPS_TEST_CASE("docs", "38", "word-graph.hpp", "[docs][quick]") { - auto wg = make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); - REQUIRE(word_graph::is_strictly_cyclic(wg) == false); - } - - // word-graph.hpp: Line 2793 - LIBSEMIGROUPS_TEST_CASE("docs", "39", "word-graph.hpp", "[docs][quick]") { - // Construct a word graph with 5 nodes and 10 edges (7 specified) - auto wg = make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); - } - - // word-range.hpp: Line 183 - LIBSEMIGROUPS_TEST_CASE("docs", "40", "word-range.hpp", "[docs][quick]") { - std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), - cend_wilo(2, 3, {0}, {1, 1, 1})); - // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; - } - - // word-range.hpp: Line 253 - LIBSEMIGROUPS_TEST_CASE("docs", "41", "word-range.hpp", "[docs][quick]") { - std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), - cend_wislo(2, {0}, {0, 0, 0})); - // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; - } - - // word-range.hpp: Line 313 - LIBSEMIGROUPS_TEST_CASE("docs", "42", "word-range.hpp", "[docs][quick]") { - WordRange words; - words - .order(Order::shortlex) // words in shortlex order - .alphabet_size(2) // on 2 letters - .min(1) // of length in the range from 1 - .max(5); // to 5 - } - - // word-range.hpp: Line 761 - LIBSEMIGROUPS_TEST_CASE("docs", "43", "word-range.hpp", "[docs][quick]") { - ToWord toword("bac"); - REQUIRE(toword("bac") == std::vector{0, 1, 2}); - REQUIRE(toword("bababbbcbc") - == std::vector{0, 1, 0, 1, 0, 0, 0, 2, 0, 2}); - - toword.init(); - REQUIRE(toword("bac") == std::vector{1, 0, 2}); - } - - // word-range.hpp: Line 1050 - LIBSEMIGROUPS_TEST_CASE("docs", "44", "word-range.hpp", "[docs][quick]") { - using namespace rx; - StringRange strings; - strings.alphabet("ab").first("a").last("bbbb"); - auto words = (strings | ToWord("ba")); - // contains the words - // {1_w, 0_w, 11_w, 10_w, 01_w, 00_w, 111_w, - // 110_w, 101_w, 100_w, 011_w, 010_w, 001_w, 000_w, - // 1111_w, 1110_w, 1101_w, 1100_w, 1011_w, 1010_w, 1001_w, - // 1000_w, 0111_w, 0110_w, 0101_w, 0100_w, 0011_w, 0010_w, - // 0001_w})); - } - - // word-range.hpp: Line 1151 - LIBSEMIGROUPS_TEST_CASE("docs", "45", "word-range.hpp", "[docs][quick]") { - ToString tostring("bac"); - REQUIRE(tostring(word_type({1, 0, 2})) == "abc"); - REQUIRE(tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})) == "baabaabc"); - - tostring.init(); - REQUIRE(tostring(word_type({1, 0, 2})) == "bac"); - } - - // word-range.hpp: Line 1402 - LIBSEMIGROUPS_TEST_CASE("docs", "46", "word-range.hpp", "[docs][quick]") { - using namespace rx; - WordRange words; - words.alphabet_size(1).min(0).max(10); - - auto strings = (words | ToString("a")); - // Contains the strings - // {"", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", - // "aaaaaaaa", "aaaaaaaaa"}; - } - - // word-range.hpp: Line 1596 - LIBSEMIGROUPS_TEST_CASE("docs", "47", "word-range.hpp", "[docs][quick]") { - StringRange strings; - strings - .order(Order::shortlex) // strings in shortlex order - .alphabet("ab") // on 2 letters - .min(1) // of length in the range from 1 - .max(5); // to 5 - } - - // word-range.hpp: Line 2307 - LIBSEMIGROUPS_TEST_CASE("docs", "48", "word-range.hpp", "[docs][quick]") { - using namespace words; - word_type w = 012345_w; - prod(w, 0, 5, 2); // {0, 2, 4} - prod(w, 1, 9, 2); // {1, 3, 5, 1} - prod("abcde", 4, 1, -1); // "edc" - prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" - } - -} // namespace libsemigroups +// action.hpp: Line 60 +LIBSEMIGROUPS_TEST_CASE("docs", "0", "action.hpp", "[docs][quick]") { + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> + o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + REQUIRE(o.size() == 65536); +} + +// action.hpp: Line 143 +LIBSEMIGROUPS_TEST_CASE("docs", "1", "action.hpp", "[docs][quick]") { + auto rg = ReportGuard(true); + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> + o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + REQUIRE(o.size() == 65536); + REQUIRE(o.scc().number_of_components() == 17); +} + +// cong-class.hpp: Line 148 +LIBSEMIGROUPS_TEST_CASE("docs", "2", "cong-class.hpp", "[docs][quick]") { + Presentation p; + p.alphabet(2); + p.contains_empty_word(true); + presentation::add_rule(p, {0, 1}, {}); + + Congruence cong(congruence_kind::twosided, p); + is_obviously_infinite(cong); // true + congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); + REQUIRE(cong.number_of_classes() == 3); +} + +// freeband.hpp: Line 76 +LIBSEMIGROUPS_TEST_CASE("docs", "3", "freeband.hpp", "[docs][quick]") { + freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, + {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true + freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false + freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true + freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, + {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false + freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true + freeband_equal_to({0, 1, 2, 3, 0, 1}, + {0, 1, 2, 3, 3, 2, 2, 1, 0, 2, 1, 0, 2, 3, + 0, 2, 1, 3, 2, 1, 2, 3, 2, 1, 0, 2, 0, 1, + 0, 2, 0, 3, 2, 0, 1, 2, 2, 3, 0, 1}); // true +} + +// froidure-pin-base.hpp: Line 1337 +LIBSEMIGROUPS_TEST_CASE("docs", "4", "froidure-pin-base.hpp", "[docs][quick]") { + FroidurePin S; + S.add_generator(BMat8({{1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}})); + S.add_generator(BMat8({{0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}})); + S.add_generator(BMat8({{0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}})); + S.add_generator(BMat8({{0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}})); + REQUIRE(S.size() == 4); + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} +} + +// froidure-pin-base.hpp: Line 1441 +LIBSEMIGROUPS_TEST_CASE("docs", "5", "froidure-pin-base.hpp", "[docs][quick]") { + FroidurePin S; + S.add_generator(BMat8({{1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}, + {1, 0, 0, 0}})); + S.add_generator(BMat8({{0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 1, 0, 0}})); + S.add_generator(BMat8({{0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}})); + S.add_generator(BMat8({{0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}, + {0, 0, 0, 1}})); + REQUIRE(S.size() == 4); + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} +} + +// is_specialization_of.hpp: Line 44 +LIBSEMIGROUPS_TEST_CASE("docs", "6", "is_specialization_of.hpp", "[docs][quick]") { + using iso_1= is_specialization_of, std::vector>; + REQUIRE(iso_1::value == true); + using iso_2 = is_specialization_of,std::unordered_map>; + REQUIRE(iso_2::value == false); + +} + +// is_specialization_of.hpp: Line 76 +LIBSEMIGROUPS_TEST_CASE("docs", "7", "is_specialization_of.hpp", "[docs][quick]") { + REQUIRE(is_specialization_of_v, std::vector> == true); + REQUIRE(is_specialization_of_v, std::unordered_map> == false); +} + +// knuth-bendix-class.hpp: Line 72 +LIBSEMIGROUPS_TEST_CASE("docs", "8", "knuth-bendix-class.hpp", "[docs][quick]") { + Presentation p; + p.contains_empty_word(true); + p.alphabet("abcd"); + presentation::add_rule_no_checks(p, "ab", ""); + presentation::add_rule_no_checks(p, "ba", ""); + presentation::add_rule_no_checks(p, "cd", ""); + presentation::add_rule_no_checks(p, "dc", ""); + + KnuthBendix kb(congruence_kind::twosided, p); + + REQUIRE(kb.number_of_active_rules() == 0); + REQUIRE(kb.number_of_pending_rules() == 4); + kb.run(); + REQUIRE(kb.number_of_active_rules() == 4); + REQUIRE(kb.number_of_pending_rules() == 0); + REQUIRE(kb.confluent() == true); + REQUIRE(kb.number_of_classes() == POSITIVE_INFINITY); +} + +// konieczny.hpp: Line 70 +LIBSEMIGROUPS_TEST_CASE("docs", "9", "konieczny.hpp", "[docs][quick]") { + auto S = make({ + BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), + BMat8({{1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}})}); + S.size(); // returns 63'904 + S.number_of_idempotents(); //returns 2'360 +} + +// matrix.hpp: Line 1964 +LIBSEMIGROUPS_TEST_CASE("docs", "10", "matrix.hpp", "[docs][quick]") { + using Mat = BMat8; + Mat m({{1, 1}, {0, 0}}); +} + +// matrix.hpp: Line 2867 +LIBSEMIGROUPS_TEST_CASE("docs", "11", "matrix.hpp", "[docs][quick]") { + using Mat = IntMat<>; + Mat m(2, 3); // construct a 2 x 3 matrix +} + +// matrix.hpp: Line 2890 +LIBSEMIGROUPS_TEST_CASE("docs", "12", "matrix.hpp", "[docs][quick]") { + using Mat = BMat<>; + Mat m({1, 1, 0, 0}); +} + +// matrix.hpp: Line 2913 +LIBSEMIGROUPS_TEST_CASE("docs", "13", "matrix.hpp", "[docs][quick]") { + using Mat = IntMat<>; + Mat m({{1, 1}, {0, 0}}); +} + +// matrix.hpp: Line 3818 +LIBSEMIGROUPS_TEST_CASE("docs", "14", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] BMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + BMat<> m4(4, 4); +} + +// matrix.hpp: Line 4125 +LIBSEMIGROUPS_TEST_CASE("docs", "15", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] IntMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + IntMat<> m4(4, 4); +} + +// matrix.hpp: Line 4415 +LIBSEMIGROUPS_TEST_CASE("docs", "16", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] MaxPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + MaxPlusMat<> m4(4, 4); +} + +// matrix.hpp: Line 4724 +LIBSEMIGROUPS_TEST_CASE("docs", "17", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] MinPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + MinPlusMat<> m4(4, 4); +} + +// matrix.hpp: Line 5043 +LIBSEMIGROUPS_TEST_CASE("docs", "18", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + [[maybe_unused]] MaxPlusTruncMat<11, 3> m3_11; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MaxPlusTruncMat<11> m4_11(4, 4); + // construct a truncated max-plus semiring with threshold 11 + MaxPlusTruncSemiring sr_11(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); +} + +// matrix.hpp: Line 5524 +LIBSEMIGROUPS_TEST_CASE("docs", "19", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + [[maybe_unused]] MinPlusTruncMat<11, 3> m3_11; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MinPlusTruncMat<11> m4_11(4, 4); + // construct a truncated min-plus semiring with threshold 11 + MinPlusTruncSemiring sr_11(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MinPlusTruncMat<> m5_11(&sr_11, 5, 5); +} + +// matrix.hpp: Line 6010 +LIBSEMIGROUPS_TEST_CASE("docs", "20", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold + // 11, period 2 + [[maybe_unused]] NTPMat<11, 2, 3> m3_11_2; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, + // period 2 + NTPMat<11, 2> m4_11_2(4, 4); + // construct an ntp semiring with threshold 11, period 2 + NTPSemiring<> sr_11_2(11, 2); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, + // period 2 + NTPMat<> m_5_11_2(&sr_11_2, 5, 5); +} + +// matrix.hpp: Line 6988 +LIBSEMIGROUPS_TEST_CASE("docs", "21", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + ProjMaxPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + ProjMaxPlusMat<> m4(4, 4); +} + +// matrix.hpp: Line 7153 +LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { + auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, + 1}}); + // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} + matrix::pow(x, 100); +} + +// matrix.hpp: Line 7901 +LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { + auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); + matrix::row_space_size(x); // returns 7 +} + +// order.hpp: Line 98 +LIBSEMIGROUPS_TEST_CASE("docs", "24", "order.hpp", "[docs][quick]") { + word_type x = 1101_w; + word_type y = 1001_w; + + // x > y + REQUIRE(lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend()) == false); +} + +// order.hpp: Line 134 +LIBSEMIGROUPS_TEST_CASE("docs", "25", "order.hpp", "[docs][quick]") { + word_type x = 0001_w; + word_type y = 0010_w; + // x < y + REQUIRE(lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend()) == true); +} + +// order.hpp: Line 311 +LIBSEMIGROUPS_TEST_CASE("docs", "26", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); +} + +// order.hpp: Line 347 +LIBSEMIGROUPS_TEST_CASE("docs", "27", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); +} + +// order.hpp: Line 483 +LIBSEMIGROUPS_TEST_CASE("docs", "28", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); +} + +// order.hpp: Line 517 +LIBSEMIGROUPS_TEST_CASE("docs", "29", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare( + x.cbegin(), x.cend(), y.cbegin(), y.cend()); +} + +// presentation.hpp: Line 863 +LIBSEMIGROUPS_TEST_CASE("docs", "30", "presentation.hpp", "[docs][quick]") { + Presentation p; + presentation::to_report_string(p); + // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" +} + +// ranges.hpp: Line 87 +LIBSEMIGROUPS_TEST_CASE("docs", "31", "ranges.hpp", "[docs][quick]") { + using rx::operator|; + auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); + Paths p(wg); + p.source(0).max(10); + REQUIRE(p.count() == 1023); + // (p | Random()).get(); // returns random path in p (Pipe operator not + // implemented for Paths?) +} + +// schreier-sims.hpp: Line 166 +LIBSEMIGROUPS_TEST_CASE("docs", "32", "schreier-sims.hpp", "[docs][quick]") { + SchreierSims<5> S; + using Perm = decltype(S)::element_type; + S.add_generator(Perm({1, 0, 2, 3, 4})); + S.add_generator(Perm({1, 2, 3, 4, 0})); + REQUIRE(S.size() == 120); +} + +// todd-coxeter-class.hpp: Line 80 +LIBSEMIGROUPS_TEST_CASE("docs", "33", "todd-coxeter-class.hpp", "[docs][quick]") { + using options = detail::ToddCoxeterImpl::options; + + Presentation p; + p.alphabet(2); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 0_w, 1_w); + ToddCoxeter tc(congruence_kind::onesided, p); + tc.strategy(options::strategy::felsch); + REQUIRE(tc.number_of_classes() == 1); + + auto w1 = 0000_w; + auto w2 = 00_w; + REQUIRE(todd_coxeter::contains(tc, w1, w2) == true); + REQUIRE(todd_coxeter::index_of(tc, w1) == 0); +} + +// todd-coxeter-class.hpp: Line 98 +LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") { + using options = detail::ToddCoxeterImpl::options; + + Presentation p; + p.alphabet(4); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 10_w, 1_w); + presentation::add_rule(p, 01_w, 1_w); + presentation::add_rule(p, 20_w, 2_w); + presentation::add_rule(p, 02_w, 2_w); + presentation::add_rule(p, 30_w, 3_w); + presentation::add_rule(p, 03_w, 3_w); + presentation::add_rule(p, 11_w, 0_w); + presentation::add_rule(p, 23_w, 0_w); + presentation::add_rule(p, 222_w, 0_w); + presentation::add_rule(p, 12121212121212_w, 0_w); + presentation::add_rule(p, 12131213121312131213121312131213_w, 0_w); + ToddCoxeter tc(congruence_kind::twosided, p); + tc.strategy(options::strategy::hlt) + .lookahead_extent(options::lookahead_extent::partial) + .save(false); + REQUIRE(tc.number_of_classes() == 10752); + tc.standardize(Order::recursive); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); + // {0_w, + // 1_w, + // 2_w, + // 21_w, + // 12_w, + // 121_w, + // 22_w, + // 221_w, + // 212_w, + // 2121_w} + tc.standardize(Order::lex); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); + // {0_w, + // 01_w, + // 012_w, + // 0121_w, + // 01212_w, + // 012121_w, + // 0121212_w, + // 01212121_w, + // 012121212_w, + // 0121212121_w}; +} + +// word-graph.hpp: Line 1540 +LIBSEMIGROUPS_TEST_CASE("docs", "35", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(2); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + REQUIRE(word_graph::is_acyclic(wg) == false); +} + +// word-graph.hpp: Line 1583 +LIBSEMIGROUPS_TEST_CASE("docs", "36", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + wg.target(2, 0, 3); + REQUIRE(word_graph::is_acyclic(wg) == false); + REQUIRE(word_graph::is_acyclic(wg, 0) == false); + REQUIRE(word_graph::is_acyclic(wg, 1) == false); + REQUIRE(word_graph::is_acyclic(wg, 2) == true); + REQUIRE(word_graph::is_acyclic(wg, 3) == true); +} + +// word-graph.hpp: Line 1973 +LIBSEMIGROUPS_TEST_CASE("docs", "37", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(4); + wg.target(0, 1, 0); + wg.target(1, 0, 0); + wg.target(2, 3, 0); + REQUIRE(word_graph::is_reachable_no_checks(wg, 0, 1) == false); + REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 0) == true); + REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 2) == false); + REQUIRE(word_graph::is_reachable_no_checks(wg, 2, 3) == false); + REQUIRE(word_graph::is_reachable_no_checks(wg, 3, 2) == false); +} + +// word-graph.hpp: Line 2053 +LIBSEMIGROUPS_TEST_CASE("docs", "38", "word-graph.hpp", "[docs][quick]") { + auto wg = make>( + 5, {{0, 0}, {1, 1}, {2}, {3, 3}}); + REQUIRE(word_graph::is_strictly_cyclic(wg) == false); +} + +// word-graph.hpp: Line 2793 +LIBSEMIGROUPS_TEST_CASE("docs", "39", "word-graph.hpp", "[docs][quick]") { + // Construct a word graph with 5 nodes and 10 edges (7 specified) + auto wg = make>(5,{{0, 0},{1, 1},{2},{3, 3}}); +} + +// word-range.hpp: Line 183 +LIBSEMIGROUPS_TEST_CASE("docs", "40", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), + cend_wilo(2, 3, {0}, {1, 1, 1})); + // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; +} + +// word-range.hpp: Line 253 +LIBSEMIGROUPS_TEST_CASE("docs", "41", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), + cend_wislo(2, {0}, {0, 0, 0})); + // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; +} + +// word-range.hpp: Line 313 +LIBSEMIGROUPS_TEST_CASE("docs", "42", "word-range.hpp", "[docs][quick]") { + WordRange words; + words.order(Order::shortlex) // words in shortlex order + .alphabet_size(2) // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 +} + +// word-range.hpp: Line 761 +LIBSEMIGROUPS_TEST_CASE("docs", "43", "word-range.hpp", "[docs][quick]") { + ToWord toword("bac"); + REQUIRE(toword("bac") == std::vector{0,1,2}); + REQUIRE(toword("bababbbcbc") == std::vector{0,1,0,1,0,0,0,2,0,2}); + + toword.init(); + REQUIRE(toword("bac") == std::vector{1, 0, 2}); +} + +// word-range.hpp: Line 1050 +LIBSEMIGROUPS_TEST_CASE("docs", "44", "word-range.hpp", "[docs][quick]") { + using namespace rx; + StringRange strings; + strings.alphabet("ab").first("a").last("bbbb"); + auto words = (strings | ToWord("ba")); + // contains the words + // {1_w, 0_w, 11_w, 10_w, 01_w, 00_w, 111_w, + // 110_w, 101_w, 100_w, 011_w, 010_w, 001_w, 000_w, + // 1111_w, 1110_w, 1101_w, 1100_w, 1011_w, 1010_w, 1001_w, + // 1000_w, 0111_w, 0110_w, 0101_w, 0100_w, 0011_w, 0010_w, + // 0001_w})); +} + +// word-range.hpp: Line 1151 +LIBSEMIGROUPS_TEST_CASE("docs", "45", "word-range.hpp", "[docs][quick]") { + ToString tostring("bac"); + REQUIRE(tostring(word_type({1, 0, 2})) == "abc"); + REQUIRE(tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})) == "baabaabc"); + + tostring.init(); + REQUIRE(tostring(word_type({1, 0, 2})) == "bac"); +} + +// word-range.hpp: Line 1402 +LIBSEMIGROUPS_TEST_CASE("docs", "46", "word-range.hpp", "[docs][quick]") { + using namespace rx; + WordRange words; + words.alphabet_size(1).min(0).max(10); + + auto strings = (words | ToString("a")); + // Contains the strings + // {"", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", + // "aaaaaaaa", "aaaaaaaaa"}; +} + +// word-range.hpp: Line 1596 +LIBSEMIGROUPS_TEST_CASE("docs", "47", "word-range.hpp", "[docs][quick]") { + StringRange strings; + strings.order(Order::shortlex) // strings in shortlex order + .alphabet("ab") // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 +} + +// word-range.hpp: Line 2307 +LIBSEMIGROUPS_TEST_CASE("docs", "48", "word-range.hpp", "[docs][quick]") { + using namespace words; + word_type w = 012345_w; + prod(w, 0, 5, 2); // {0, 2, 4} + prod(w, 1, 9, 2); // {1, 3, 5, 1} + prod("abcde", 4, 1, -1); // "edc" + prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" +} + + +} \ No newline at end of file From 550c79a6e6e226acf519bddd98dcd2fb20696f04 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 19 Nov 2025 11:33:22 +0000 Subject: [PATCH 11/11] Auto clang-format@15 with assertions & small style changes --- etc/extract-doc-examples.py | 63 +- tests/test-docs-code-examples.cpp | 1221 +++++++++++++++-------------- 2 files changed, 670 insertions(+), 614 deletions(-) diff --git a/etc/extract-doc-examples.py b/etc/extract-doc-examples.py index d19c2af0d..799440c9f 100644 --- a/etc/extract-doc-examples.py +++ b/etc/extract-doc-examples.py @@ -4,6 +4,8 @@ import sys import argparse +import subprocess +import re from pathlib import Path ######################################################################## @@ -34,6 +36,7 @@ using namespace libsemigroups::literals; """ +TEST_FILEPATH = "./tests/test-docs-code-examples.cpp" ######################################################################## # Internal ######################################################################## @@ -183,7 +186,8 @@ def extract_code_blocks(file_path): #  Add require value eq current_block.append( - f" REQUIRE({function_call} == {function_returns});" + f" REQUIRE({function_call} == { + function_returns});" ) continue @@ -192,7 +196,8 @@ def extract_code_blocks(file_path): # discard unclosed code blocks if in_code_block and current_block: - __error(f"Warning: Unclosed code block at end of file {file_path}") + __error( + f"Warning: Unclosed code block at end of file {file_path}") except Exception as e: print(f"Error reading file {file_path}: {e}") @@ -244,7 +249,7 @@ def process_folder(folder_path, recursive=False, exclude=[]): total_blocks = 0 try: - with open("./tests/test-docs-code-examples.cpp", "w") as testfile: + with open(TEST_FILEPATH, "w") as testfile: testfile.write(f"{HEADER_TEXT}\n") testfile.write("namespace libsemigroups {\n") # Open namespace @@ -266,7 +271,9 @@ def process_folder(folder_path, recursive=False, exclude=[]): testfile.write( f'// {file_path.relative_to(folder)}: Line { block["start_line"] - }\nLIBSEMIGROUPS_TEST_CASE("docs", "{total_blocks}", "{ + }\nLIBSEMIGROUPS_TEST_CASE("docs", "{ + "{:03}".format(total_blocks) + }", "{ file_path.relative_to(folder) }", "[docs][quick]") {{\n' ) @@ -287,6 +294,52 @@ def process_folder(folder_path, recursive=False, exclude=[]): print(f"Total code blocks found: {total_blocks}") +######################################################################## +# File Formatting +######################################################################### + + +def check_clang_format_version() -> bool: + """Check that clang-format@15 is installed.""" + try: + res = subprocess.run( + ["clang-format", "--version"], capture_output=True, text=True, check=True + ) + version_check = re.search(r"version\s+(\d+)", res.stdout) + + if not version_check: + __error("Could not match clang-format --version") + return False + + ver = int(version_check.group(1)) + + if ver != 15: + __error("clang-format@15 is required") + return False + else: + return True + except FileNotFoundError: + __error("clang-format@15 is not installed") + return False + except subprocess.CalledProcessError as e: + __error(f"clang-format --version error: {e}") + return False + + +def format_file(filepath): + if not check_clang_format_version(): + __error("Unable to format file, see clang-format related error") + return + + try: + subprocess.run(["clang-format", "-i", filepath], check=True) + print(f"\n Formatted {filepath}") + except subprocess.CalledProcessError as e: + __error(f"Failed to format file {filepath} : {e}") + except FileNotFoundError: + __error(f"Could not find file {filepath} to format") + + ######################################################################## # Main ######################################################################### @@ -296,6 +349,8 @@ def main(): args = __parse_args() exclude = args.exclude if not args.exclude is None else [] process_folder(args.folder_path, args.recursive, exclude) + format_file(TEST_FILEPATH) + print("\n Docs code block extraction completed successfully. Exiting.") if __name__ == "__main__": diff --git a/tests/test-docs-code-examples.cpp b/tests/test-docs-code-examples.cpp index c0ead1b64..ceda60bfb 100644 --- a/tests/test-docs-code-examples.cpp +++ b/tests/test-docs-code-examples.cpp @@ -22,613 +22,614 @@ using namespace libsemigroups::literals; namespace libsemigroups { -// action.hpp: Line 60 -LIBSEMIGROUPS_TEST_CASE("docs", "0", "action.hpp", "[docs][quick]") { - RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> - o; - o.add_seed(PPerm<16>::one(16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.add_generator( - PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.reserve(70000); - REQUIRE(o.size() == 65536); -} - -// action.hpp: Line 143 -LIBSEMIGROUPS_TEST_CASE("docs", "1", "action.hpp", "[docs][quick]") { - auto rg = ReportGuard(true); - RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> - o; - o.add_seed(PPerm<16>::one(16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.add_generator( - PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - 16)); - o.add_generator( - PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - 16)); - o.reserve(70000); - REQUIRE(o.size() == 65536); - REQUIRE(o.scc().number_of_components() == 17); -} - -// cong-class.hpp: Line 148 -LIBSEMIGROUPS_TEST_CASE("docs", "2", "cong-class.hpp", "[docs][quick]") { - Presentation p; - p.alphabet(2); - p.contains_empty_word(true); - presentation::add_rule(p, {0, 1}, {}); - - Congruence cong(congruence_kind::twosided, p); - is_obviously_infinite(cong); // true - congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); - REQUIRE(cong.number_of_classes() == 3); -} - -// freeband.hpp: Line 76 -LIBSEMIGROUPS_TEST_CASE("docs", "3", "freeband.hpp", "[docs][quick]") { - freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, - {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true - freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false - freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true - freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, - {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false - freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true - freeband_equal_to({0, 1, 2, 3, 0, 1}, - {0, 1, 2, 3, 3, 2, 2, 1, 0, 2, 1, 0, 2, 3, - 0, 2, 1, 3, 2, 1, 2, 3, 2, 1, 0, 2, 0, 1, - 0, 2, 0, 3, 2, 0, 1, 2, 2, 3, 0, 1}); // true -} - -// froidure-pin-base.hpp: Line 1337 -LIBSEMIGROUPS_TEST_CASE("docs", "4", "froidure-pin-base.hpp", "[docs][quick]") { - FroidurePin S; - S.add_generator(BMat8({{1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}})); - S.add_generator(BMat8({{0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}})); - S.add_generator(BMat8({{0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}})); - S.add_generator(BMat8({{0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}})); - REQUIRE(S.size() == 4); - std::vector(S.cbegin_rules(), S.cend_rules()); - // {{{0, 0}, {0}}, - // {{0, 1}, {1}}, - // {{0, 2}, {2}}, - // {{0, 3}, {3}}, - // {{1, 0}, {0}}, - // {{1, 1}, {1}}, - // {{1, 2}, {2}}, - // {{1, 3}, {3}}, - // {{2, 0}, {0}}, - // {{2, 1}, {1}}, - // {{2, 2}, {2}}, - // {{2, 3}, {3}}, - // {{3, 0}, {0}}, - // {{3, 1}, {1}}, - // {{3, 2}, {2}}, - // {{3, 3}, {3}}} -} - -// froidure-pin-base.hpp: Line 1441 -LIBSEMIGROUPS_TEST_CASE("docs", "5", "froidure-pin-base.hpp", "[docs][quick]") { - FroidurePin S; - S.add_generator(BMat8({{1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}, - {1, 0, 0, 0}})); - S.add_generator(BMat8({{0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 1, 0, 0}})); - S.add_generator(BMat8({{0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}, - {0, 0, 1, 0}})); - S.add_generator(BMat8({{0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}, - {0, 0, 0, 1}})); - REQUIRE(S.size() == 4); - std::vector(S.cbegin_rules(), S.cend_rules()); - // {{{0, 0}, {0}}, - // {{0, 1}, {1}}, - // {{0, 2}, {2}}, - // {{0, 3}, {3}}, - // {{1, 0}, {0}}, - // {{1, 1}, {1}}, - // {{1, 2}, {2}}, - // {{1, 3}, {3}}, - // {{2, 0}, {0}}, - // {{2, 1}, {1}}, - // {{2, 2}, {2}}, - // {{2, 3}, {3}}, - // {{3, 0}, {0}}, - // {{3, 1}, {1}}, - // {{3, 2}, {2}}, - // {{3, 3}, {3}}} -} - -// is_specialization_of.hpp: Line 44 -LIBSEMIGROUPS_TEST_CASE("docs", "6", "is_specialization_of.hpp", "[docs][quick]") { - using iso_1= is_specialization_of, std::vector>; - REQUIRE(iso_1::value == true); - using iso_2 = is_specialization_of,std::unordered_map>; - REQUIRE(iso_2::value == false); - -} - -// is_specialization_of.hpp: Line 76 -LIBSEMIGROUPS_TEST_CASE("docs", "7", "is_specialization_of.hpp", "[docs][quick]") { - REQUIRE(is_specialization_of_v, std::vector> == true); - REQUIRE(is_specialization_of_v, std::unordered_map> == false); -} - -// knuth-bendix-class.hpp: Line 72 -LIBSEMIGROUPS_TEST_CASE("docs", "8", "knuth-bendix-class.hpp", "[docs][quick]") { - Presentation p; - p.contains_empty_word(true); - p.alphabet("abcd"); - presentation::add_rule_no_checks(p, "ab", ""); - presentation::add_rule_no_checks(p, "ba", ""); - presentation::add_rule_no_checks(p, "cd", ""); - presentation::add_rule_no_checks(p, "dc", ""); - - KnuthBendix kb(congruence_kind::twosided, p); - - REQUIRE(kb.number_of_active_rules() == 0); - REQUIRE(kb.number_of_pending_rules() == 4); - kb.run(); - REQUIRE(kb.number_of_active_rules() == 4); - REQUIRE(kb.number_of_pending_rules() == 0); - REQUIRE(kb.confluent() == true); - REQUIRE(kb.number_of_classes() == POSITIVE_INFINITY); -} - -// konieczny.hpp: Line 70 -LIBSEMIGROUPS_TEST_CASE("docs", "9", "konieczny.hpp", "[docs][quick]") { - auto S = make({ - BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), - BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), - BMat8({{1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), - BMat8({{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}})}); - S.size(); // returns 63'904 - S.number_of_idempotents(); //returns 2'360 -} - -// matrix.hpp: Line 1964 -LIBSEMIGROUPS_TEST_CASE("docs", "10", "matrix.hpp", "[docs][quick]") { - using Mat = BMat8; - Mat m({{1, 1}, {0, 0}}); -} - -// matrix.hpp: Line 2867 -LIBSEMIGROUPS_TEST_CASE("docs", "11", "matrix.hpp", "[docs][quick]") { - using Mat = IntMat<>; - Mat m(2, 3); // construct a 2 x 3 matrix -} - -// matrix.hpp: Line 2890 -LIBSEMIGROUPS_TEST_CASE("docs", "12", "matrix.hpp", "[docs][quick]") { - using Mat = BMat<>; - Mat m({1, 1, 0, 0}); -} - -// matrix.hpp: Line 2913 -LIBSEMIGROUPS_TEST_CASE("docs", "13", "matrix.hpp", "[docs][quick]") { - using Mat = IntMat<>; - Mat m({{1, 1}, {0, 0}}); -} - -// matrix.hpp: Line 3818 -LIBSEMIGROUPS_TEST_CASE("docs", "14", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - [[maybe_unused]] BMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - BMat<> m4(4, 4); -} - -// matrix.hpp: Line 4125 -LIBSEMIGROUPS_TEST_CASE("docs", "15", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - [[maybe_unused]] IntMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - IntMat<> m4(4, 4); -} - -// matrix.hpp: Line 4415 -LIBSEMIGROUPS_TEST_CASE("docs", "16", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - [[maybe_unused]] MaxPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - MaxPlusMat<> m4(4, 4); -} - -// matrix.hpp: Line 4724 -LIBSEMIGROUPS_TEST_CASE("docs", "17", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - [[maybe_unused]] MinPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - MinPlusMat<> m4(4, 4); -} - -// matrix.hpp: Line 5043 -LIBSEMIGROUPS_TEST_CASE("docs", "18", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold 11 - [[maybe_unused]] MaxPlusTruncMat<11, 3> m3_11; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MaxPlusTruncMat<11> m4_11(4, 4); - // construct a truncated max-plus semiring with threshold 11 - MaxPlusTruncSemiring sr_11(11); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 - // (defined at run time) - MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); -} - -// matrix.hpp: Line 5524 -LIBSEMIGROUPS_TEST_CASE("docs", "19", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold 11 - [[maybe_unused]] MinPlusTruncMat<11, 3> m3_11; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 - MinPlusTruncMat<11> m4_11(4, 4); - // construct a truncated min-plus semiring with threshold 11 - MinPlusTruncSemiring sr_11(11); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 - // (defined at run time) - MinPlusTruncMat<> m5_11(&sr_11, 5, 5); -} - -// matrix.hpp: Line 6010 -LIBSEMIGROUPS_TEST_CASE("docs", "20", "matrix.hpp", "[docs][quick]") { - // construct an uninitialized 3 x 3 static matrix with threshold - // 11, period 2 - [[maybe_unused]] NTPMat<11, 2, 3> m3_11_2; - // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, - // period 2 - NTPMat<11, 2> m4_11_2(4, 4); - // construct an ntp semiring with threshold 11, period 2 - NTPSemiring<> sr_11_2(11, 2); - // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, - // period 2 - NTPMat<> m_5_11_2(&sr_11_2, 5, 5); -} - -// matrix.hpp: Line 6988 -LIBSEMIGROUPS_TEST_CASE("docs", "21", "matrix.hpp", "[docs][quick]") { - // default construct an uninitialized 3 x 3 static matrix - ProjMaxPlusMat<3> m3; - // construct an uninitialized 4 x 4 dynamic matrix - ProjMaxPlusMat<> m4(4, 4); -} - -// matrix.hpp: Line 7153 -LIBSEMIGROUPS_TEST_CASE("docs", "22", "matrix.hpp", "[docs][quick]") { - auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, - 1}}); - // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} - matrix::pow(x, 100); -} - -// matrix.hpp: Line 7901 -LIBSEMIGROUPS_TEST_CASE("docs", "23", "matrix.hpp", "[docs][quick]") { - auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); - matrix::row_space_size(x); // returns 7 -} - -// order.hpp: Line 98 -LIBSEMIGROUPS_TEST_CASE("docs", "24", "order.hpp", "[docs][quick]") { - word_type x = 1101_w; - word_type y = 1001_w; - - // x > y - REQUIRE(lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend()) == false); -} - -// order.hpp: Line 134 -LIBSEMIGROUPS_TEST_CASE("docs", "25", "order.hpp", "[docs][quick]") { - word_type x = 0001_w; - word_type y = 0010_w; - // x < y - REQUIRE(lexicographical_compare(x.cbegin(),x.cend(),y.cbegin(),y.cend()) == true); -} - -// order.hpp: Line 311 -LIBSEMIGROUPS_TEST_CASE("docs", "26", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - shortlex_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 347 -LIBSEMIGROUPS_TEST_CASE("docs", "27", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - shortlex_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 483 -LIBSEMIGROUPS_TEST_CASE("docs", "28", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - recursive_path_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// order.hpp: Line 517 -LIBSEMIGROUPS_TEST_CASE("docs", "29", "order.hpp", "[docs][quick]") { - word_type x = random_word(5, 10); - word_type y = random_word(5, 10); - recursive_path_compare( - x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -// presentation.hpp: Line 863 -LIBSEMIGROUPS_TEST_CASE("docs", "30", "presentation.hpp", "[docs][quick]") { - Presentation p; - presentation::to_report_string(p); - // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" -} - -// ranges.hpp: Line 87 -LIBSEMIGROUPS_TEST_CASE("docs", "31", "ranges.hpp", "[docs][quick]") { - using rx::operator|; - auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); - Paths p(wg); - p.source(0).max(10); - REQUIRE(p.count() == 1023); - // (p | Random()).get(); // returns random path in p (Pipe operator not - // implemented for Paths?) -} - -// schreier-sims.hpp: Line 166 -LIBSEMIGROUPS_TEST_CASE("docs", "32", "schreier-sims.hpp", "[docs][quick]") { - SchreierSims<5> S; - using Perm = decltype(S)::element_type; - S.add_generator(Perm({1, 0, 2, 3, 4})); - S.add_generator(Perm({1, 2, 3, 4, 0})); - REQUIRE(S.size() == 120); -} - -// todd-coxeter-class.hpp: Line 80 -LIBSEMIGROUPS_TEST_CASE("docs", "33", "todd-coxeter-class.hpp", "[docs][quick]") { - using options = detail::ToddCoxeterImpl::options; - - Presentation p; - p.alphabet(2); - presentation::add_rule(p, 00_w, 0_w); - presentation::add_rule(p, 0_w, 1_w); - ToddCoxeter tc(congruence_kind::onesided, p); - tc.strategy(options::strategy::felsch); - REQUIRE(tc.number_of_classes() == 1); - - auto w1 = 0000_w; - auto w2 = 00_w; - REQUIRE(todd_coxeter::contains(tc, w1, w2) == true); - REQUIRE(todd_coxeter::index_of(tc, w1) == 0); -} - -// todd-coxeter-class.hpp: Line 98 -LIBSEMIGROUPS_TEST_CASE("docs", "34", "todd-coxeter-class.hpp", "[docs][quick]") { - using options = detail::ToddCoxeterImpl::options; - - Presentation p; - p.alphabet(4); - presentation::add_rule(p, 00_w, 0_w); - presentation::add_rule(p, 10_w, 1_w); - presentation::add_rule(p, 01_w, 1_w); - presentation::add_rule(p, 20_w, 2_w); - presentation::add_rule(p, 02_w, 2_w); - presentation::add_rule(p, 30_w, 3_w); - presentation::add_rule(p, 03_w, 3_w); - presentation::add_rule(p, 11_w, 0_w); - presentation::add_rule(p, 23_w, 0_w); - presentation::add_rule(p, 222_w, 0_w); - presentation::add_rule(p, 12121212121212_w, 0_w); - presentation::add_rule(p, 12131213121312131213121312131213_w, 0_w); - ToddCoxeter tc(congruence_kind::twosided, p); - tc.strategy(options::strategy::hlt) - .lookahead_extent(options::lookahead_extent::partial) - .save(false); - REQUIRE(tc.number_of_classes() == 10752); - tc.standardize(Order::recursive); - todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); - // {0_w, - // 1_w, - // 2_w, - // 21_w, - // 12_w, - // 121_w, - // 22_w, - // 221_w, - // 212_w, - // 2121_w} - tc.standardize(Order::lex); - todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); - // {0_w, - // 01_w, - // 012_w, - // 0121_w, - // 01212_w, - // 012121_w, - // 0121212_w, - // 01212121_w, - // 012121212_w, - // 0121212121_w}; -} - -// word-graph.hpp: Line 1540 -LIBSEMIGROUPS_TEST_CASE("docs", "35", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(2); - wg.add_to_out_degree(1); - wg.target(0, 0, 1); - wg.target(1, 0, 0); - REQUIRE(word_graph::is_acyclic(wg) == false); -} - -// word-graph.hpp: Line 1583 -LIBSEMIGROUPS_TEST_CASE("docs", "36", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(4); - wg.add_to_out_degree(1); - wg.target(0, 0, 1); - wg.target(1, 0, 0); - wg.target(2, 0, 3); - REQUIRE(word_graph::is_acyclic(wg) == false); - REQUIRE(word_graph::is_acyclic(wg, 0) == false); - REQUIRE(word_graph::is_acyclic(wg, 1) == false); - REQUIRE(word_graph::is_acyclic(wg, 2) == true); - REQUIRE(word_graph::is_acyclic(wg, 3) == true); -} - -// word-graph.hpp: Line 1973 -LIBSEMIGROUPS_TEST_CASE("docs", "37", "word-graph.hpp", "[docs][quick]") { - WordGraph wg; - wg.add_nodes(4); - wg.add_to_out_degree(4); - wg.target(0, 1, 0); - wg.target(1, 0, 0); - wg.target(2, 3, 0); - REQUIRE(word_graph::is_reachable_no_checks(wg, 0, 1) == false); - REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 0) == true); - REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 2) == false); - REQUIRE(word_graph::is_reachable_no_checks(wg, 2, 3) == false); - REQUIRE(word_graph::is_reachable_no_checks(wg, 3, 2) == false); -} - -// word-graph.hpp: Line 2053 -LIBSEMIGROUPS_TEST_CASE("docs", "38", "word-graph.hpp", "[docs][quick]") { - auto wg = make>( - 5, {{0, 0}, {1, 1}, {2}, {3, 3}}); - REQUIRE(word_graph::is_strictly_cyclic(wg) == false); -} - -// word-graph.hpp: Line 2793 -LIBSEMIGROUPS_TEST_CASE("docs", "39", "word-graph.hpp", "[docs][quick]") { - // Construct a word graph with 5 nodes and 10 edges (7 specified) - auto wg = make>(5,{{0, 0},{1, 1},{2},{3, 3}}); -} - -// word-range.hpp: Line 183 -LIBSEMIGROUPS_TEST_CASE("docs", "40", "word-range.hpp", "[docs][quick]") { - std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), - cend_wilo(2, 3, {0}, {1, 1, 1})); - // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; -} - -// word-range.hpp: Line 253 -LIBSEMIGROUPS_TEST_CASE("docs", "41", "word-range.hpp", "[docs][quick]") { - std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), - cend_wislo(2, {0}, {0, 0, 0})); - // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; -} - -// word-range.hpp: Line 313 -LIBSEMIGROUPS_TEST_CASE("docs", "42", "word-range.hpp", "[docs][quick]") { - WordRange words; - words.order(Order::shortlex) // words in shortlex order - .alphabet_size(2) // on 2 letters - .min(1) // of length in the range from 1 - .max(5); // to 5 -} - -// word-range.hpp: Line 761 -LIBSEMIGROUPS_TEST_CASE("docs", "43", "word-range.hpp", "[docs][quick]") { - ToWord toword("bac"); - REQUIRE(toword("bac") == std::vector{0,1,2}); - REQUIRE(toword("bababbbcbc") == std::vector{0,1,0,1,0,0,0,2,0,2}); - - toword.init(); - REQUIRE(toword("bac") == std::vector{1, 0, 2}); -} - -// word-range.hpp: Line 1050 -LIBSEMIGROUPS_TEST_CASE("docs", "44", "word-range.hpp", "[docs][quick]") { - using namespace rx; - StringRange strings; - strings.alphabet("ab").first("a").last("bbbb"); - auto words = (strings | ToWord("ba")); - // contains the words - // {1_w, 0_w, 11_w, 10_w, 01_w, 00_w, 111_w, - // 110_w, 101_w, 100_w, 011_w, 010_w, 001_w, 000_w, - // 1111_w, 1110_w, 1101_w, 1100_w, 1011_w, 1010_w, 1001_w, - // 1000_w, 0111_w, 0110_w, 0101_w, 0100_w, 0011_w, 0010_w, - // 0001_w})); -} - -// word-range.hpp: Line 1151 -LIBSEMIGROUPS_TEST_CASE("docs", "45", "word-range.hpp", "[docs][quick]") { - ToString tostring("bac"); - REQUIRE(tostring(word_type({1, 0, 2})) == "abc"); - REQUIRE(tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})) == "baabaabc"); - - tostring.init(); - REQUIRE(tostring(word_type({1, 0, 2})) == "bac"); -} - -// word-range.hpp: Line 1402 -LIBSEMIGROUPS_TEST_CASE("docs", "46", "word-range.hpp", "[docs][quick]") { - using namespace rx; - WordRange words; - words.alphabet_size(1).min(0).max(10); - - auto strings = (words | ToString("a")); - // Contains the strings - // {"", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", - // "aaaaaaaa", "aaaaaaaaa"}; -} - -// word-range.hpp: Line 1596 -LIBSEMIGROUPS_TEST_CASE("docs", "47", "word-range.hpp", "[docs][quick]") { - StringRange strings; - strings.order(Order::shortlex) // strings in shortlex order - .alphabet("ab") // on 2 letters - .min(1) // of length in the range from 1 - .max(5); // to 5 -} - -// word-range.hpp: Line 2307 -LIBSEMIGROUPS_TEST_CASE("docs", "48", "word-range.hpp", "[docs][quick]") { - using namespace words; - word_type w = 012345_w; - prod(w, 0, 5, 2); // {0, 2, 4} - prod(w, 1, 9, 2); // {1, 3, 5, 1} - prod("abcde", 4, 1, -1); // "edc" - prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" -} - - -} \ No newline at end of file + // action.hpp: Line 60 + LIBSEMIGROUPS_TEST_CASE("docs", "000", "action.hpp", "[docs][quick]") { + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + REQUIRE(o.size() == 65536); + } + + // action.hpp: Line 143 + LIBSEMIGROUPS_TEST_CASE("docs", "001", "action.hpp", "[docs][quick]") { + auto rg = ReportGuard(true); + RightAction, PPerm<16>, ImageRightAction, PPerm<16>>> o; + o.add_seed(PPerm<16>::one(16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.add_generator( + PPerm<16>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + 16)); + o.add_generator( + PPerm<16>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + 16)); + o.reserve(70000); + REQUIRE(o.size() == 65536); + REQUIRE(o.scc().number_of_components() == 17); + } + + // cong-class.hpp: Line 148 + LIBSEMIGROUPS_TEST_CASE("docs", "002", "cong-class.hpp", "[docs][quick]") { + Presentation p; + p.alphabet(2); + p.contains_empty_word(true); + presentation::add_rule(p, {0, 1}, {}); + + Congruence cong(congruence_kind::twosided, p); + is_obviously_infinite(cong); // true + congruence_common::add_generating_pair(cong, {0, 0, 0}, {}); + REQUIRE(cong.number_of_classes() == 3); + } + + // freeband.hpp: Line 76 + LIBSEMIGROUPS_TEST_CASE("docs", "003", "freeband.hpp", "[docs][quick]") { + freeband_equal_to({0, 1, 2, 3, 2, 1, 0}, + {0, 1, 2, 3, 2, 3, 2, 1, 0}); // true + freeband_equal_to({1, 2, 3}, {0, 1, 2}); // false + freeband_equal_to({1, 4, 2, 3, 10}, {1, 4, 1, 4, 2, 3, 10}); // true + freeband_equal_to({0, 1, 2, 3, 4, 0, 1, 2, 3, 4}, + {4, 3, 2, 1, 0, 4, 3, 2, 1, 0}); // false + freeband_equal_to({0, 1, 2, 1, 0, 1, 2}, {0, 1, 2}); // true + freeband_equal_to({0, 1, 2, 3, 0, 1}, + {0, 1, 2, 3, 3, 2, 2, 1, 0, 2, 1, 0, 2, 3, + 0, 2, 1, 3, 2, 1, 2, 3, 2, 1, 0, 2, 0, 1, + 0, 2, 0, 3, 2, 0, 1, 2, 2, 3, 0, 1}); // true + } + + // froidure-pin-base.hpp: Line 1337 + LIBSEMIGROUPS_TEST_CASE("docs", + "004", + "froidure-pin-base.hpp", + "[docs][quick]") { + FroidurePin S; + S.add_generator( + BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}})); + S.add_generator( + BMat8({{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}})); + S.add_generator( + BMat8({{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}})); + S.add_generator( + BMat8({{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}})); + REQUIRE(S.size() == 4); + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} + } + + // froidure-pin-base.hpp: Line 1441 + LIBSEMIGROUPS_TEST_CASE("docs", + "005", + "froidure-pin-base.hpp", + "[docs][quick]") { + FroidurePin S; + S.add_generator( + BMat8({{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0}})); + S.add_generator( + BMat8({{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}})); + S.add_generator( + BMat8({{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}})); + S.add_generator( + BMat8({{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}})); + REQUIRE(S.size() == 4); + std::vector(S.cbegin_rules(), S.cend_rules()); + // {{{0, 0}, {0}}, + // {{0, 1}, {1}}, + // {{0, 2}, {2}}, + // {{0, 3}, {3}}, + // {{1, 0}, {0}}, + // {{1, 1}, {1}}, + // {{1, 2}, {2}}, + // {{1, 3}, {3}}, + // {{2, 0}, {0}}, + // {{2, 1}, {1}}, + // {{2, 2}, {2}}, + // {{2, 3}, {3}}, + // {{3, 0}, {0}}, + // {{3, 1}, {1}}, + // {{3, 2}, {2}}, + // {{3, 3}, {3}}} + } + + // is_specialization_of.hpp: Line 44 + LIBSEMIGROUPS_TEST_CASE("docs", + "006", + "is_specialization_of.hpp", + "[docs][quick]") { + using iso_1 = is_specialization_of, std::vector>; + REQUIRE(iso_1::value == true); + using iso_2 = is_specialization_of, std::unordered_map>; + REQUIRE(iso_2::value == false); + } + + // is_specialization_of.hpp: Line 76 + LIBSEMIGROUPS_TEST_CASE("docs", + "007", + "is_specialization_of.hpp", + "[docs][quick]") { + REQUIRE(is_specialization_of_v, std::vector> == true); + REQUIRE(is_specialization_of_v, std::unordered_map> + == false); + } + + // knuth-bendix-class.hpp: Line 72 + LIBSEMIGROUPS_TEST_CASE("docs", + "008", + "knuth-bendix-class.hpp", + "[docs][quick]") { + Presentation p; + p.contains_empty_word(true); + p.alphabet("abcd"); + presentation::add_rule_no_checks(p, "ab", ""); + presentation::add_rule_no_checks(p, "ba", ""); + presentation::add_rule_no_checks(p, "cd", ""); + presentation::add_rule_no_checks(p, "dc", ""); + + KnuthBendix kb(congruence_kind::twosided, p); + + REQUIRE(kb.number_of_active_rules() == 0); + REQUIRE(kb.number_of_pending_rules() == 4); + kb.run(); + REQUIRE(kb.number_of_active_rules() == 4); + REQUIRE(kb.number_of_pending_rules() == 0); + REQUIRE(kb.confluent() == true); + REQUIRE(kb.number_of_classes() == POSITIVE_INFINITY); + } + + // konieczny.hpp: Line 70 + LIBSEMIGROUPS_TEST_CASE("docs", "009", "konieczny.hpp", "[docs][quick]") { + auto S = make( + {BMat8({{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}}), + BMat8({{1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}), + BMat8({{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}})}); + S.size(); // returns 63'904 + S.number_of_idempotents(); // returns 2'360 + } + + // matrix.hpp: Line 1964 + LIBSEMIGROUPS_TEST_CASE("docs", "010", "matrix.hpp", "[docs][quick]") { + using Mat = BMat8; + Mat m({{1, 1}, {0, 0}}); + } + + // matrix.hpp: Line 2867 + LIBSEMIGROUPS_TEST_CASE("docs", "011", "matrix.hpp", "[docs][quick]") { + using Mat = IntMat<>; + Mat m(2, 3); // construct a 2 x 3 matrix + } + + // matrix.hpp: Line 2890 + LIBSEMIGROUPS_TEST_CASE("docs", "012", "matrix.hpp", "[docs][quick]") { + using Mat = BMat<>; + Mat m({1, 1, 0, 0}); + } + + // matrix.hpp: Line 2913 + LIBSEMIGROUPS_TEST_CASE("docs", "013", "matrix.hpp", "[docs][quick]") { + using Mat = IntMat<>; + Mat m({{1, 1}, {0, 0}}); + } + + // matrix.hpp: Line 3818 + LIBSEMIGROUPS_TEST_CASE("docs", "014", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] BMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + BMat<> m4(4, 4); + } + + // matrix.hpp: Line 4125 + LIBSEMIGROUPS_TEST_CASE("docs", "015", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] IntMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + IntMat<> m4(4, 4); + } + + // matrix.hpp: Line 4415 + LIBSEMIGROUPS_TEST_CASE("docs", "016", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] MaxPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + MaxPlusMat<> m4(4, 4); + } + + // matrix.hpp: Line 4724 + LIBSEMIGROUPS_TEST_CASE("docs", "017", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + [[maybe_unused]] MinPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + MinPlusMat<> m4(4, 4); + } + + // matrix.hpp: Line 5043 + LIBSEMIGROUPS_TEST_CASE("docs", "018", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + [[maybe_unused]] MaxPlusTruncMat<11, 3> m3_11; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MaxPlusTruncMat<11> m4_11(4, 4); + // construct a truncated max-plus semiring with threshold 11 + MaxPlusTruncSemiring sr_11(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MaxPlusTruncMat<> m5_11(&sr_11, 5, 5); + } + + // matrix.hpp: Line 5524 + LIBSEMIGROUPS_TEST_CASE("docs", "019", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold 11 + [[maybe_unused]] MinPlusTruncMat<11, 3> m3_11; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11 + MinPlusTruncMat<11> m4_11(4, 4); + // construct a truncated min-plus semiring with threshold 11 + MinPlusTruncSemiring sr_11(11); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11 + // (defined at run time) + MinPlusTruncMat<> m5_11(&sr_11, 5, 5); + } + + // matrix.hpp: Line 6010 + LIBSEMIGROUPS_TEST_CASE("docs", "020", "matrix.hpp", "[docs][quick]") { + // construct an uninitialized 3 x 3 static matrix with threshold + // 11, period 2 + [[maybe_unused]] NTPMat<11, 2, 3> m3_11_2; + // construct an uninitialized 4 x 4 dynamic matrix with threshold 11, + // period 2 + NTPMat<11, 2> m4_11_2(4, 4); + // construct an ntp semiring with threshold 11, period 2 + NTPSemiring<> sr_11_2(11, 2); + // construct an uninitialized 5 x 5 dynamic matrix with threshold 11, + // period 2 + NTPMat<> m_5_11_2(&sr_11_2, 5, 5); + } + + // matrix.hpp: Line 6988 + LIBSEMIGROUPS_TEST_CASE("docs", "021", "matrix.hpp", "[docs][quick]") { + // default construct an uninitialized 3 x 3 static matrix + ProjMaxPlusMat<3> m3; + // construct an uninitialized 4 x 4 dynamic matrix + ProjMaxPlusMat<> m4(4, 4); + } + + // matrix.hpp: Line 7153 + LIBSEMIGROUPS_TEST_CASE("docs", "022", "matrix.hpp", "[docs][quick]") { + auto x = make>({{-2, 2, 0}, {-1, 0, 0}, {1, -3, 1}}); + // returns {{-1, 0, -1}, {-2, -1, -2}, {-1, 0, -1}} + matrix::pow(x, 100); + } + + // matrix.hpp: Line 7901 + LIBSEMIGROUPS_TEST_CASE("docs", "023", "matrix.hpp", "[docs][quick]") { + auto x = make>({{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}); + matrix::row_space_size(x); // returns 7 + } + + // order.hpp: Line 98 + LIBSEMIGROUPS_TEST_CASE("docs", "024", "order.hpp", "[docs][quick]") { + word_type x = 1101_w; + word_type y = 1001_w; + + // x > y + REQUIRE(lexicographical_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()) + == false); + } + + // order.hpp: Line 134 + LIBSEMIGROUPS_TEST_CASE("docs", "025", "order.hpp", "[docs][quick]") { + word_type x = 0001_w; + word_type y = 0010_w; + // x < y + REQUIRE(lexicographical_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()) + == true); + } + + // order.hpp: Line 311 + LIBSEMIGROUPS_TEST_CASE("docs", "026", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // order.hpp: Line 347 + LIBSEMIGROUPS_TEST_CASE("docs", "027", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + shortlex_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // order.hpp: Line 483 + LIBSEMIGROUPS_TEST_CASE("docs", "028", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // order.hpp: Line 517 + LIBSEMIGROUPS_TEST_CASE("docs", "029", "order.hpp", "[docs][quick]") { + word_type x = random_word(5, 10); + word_type y = random_word(5, 10); + recursive_path_compare(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + // presentation.hpp: Line 863 + LIBSEMIGROUPS_TEST_CASE("docs", "030", "presentation.hpp", "[docs][quick]") { + Presentation p; + presentation::to_report_string(p); + // "|A| = 0, |R| = 0, |u| + |v| ∈ [0, 0], ∑(|u| + |v|) = 0" + } + + // ranges.hpp: Line 87 + LIBSEMIGROUPS_TEST_CASE("docs", "031", "ranges.hpp", "[docs][quick]") { + using rx::operator|; + auto wg = make>(4, {{0, 1}, {1, 0}, {2, 2}}); + Paths p(wg); + p.source(0).max(10); + REQUIRE(p.count() == 1023); + // (p | Random()).get(); // returns random path in p (Pipe operator not + // implemented for Paths?) + } + + // schreier-sims.hpp: Line 166 + LIBSEMIGROUPS_TEST_CASE("docs", "032", "schreier-sims.hpp", "[docs][quick]") { + SchreierSims<5> S; + using Perm = decltype(S)::element_type; + S.add_generator(Perm({1, 0, 2, 3, 4})); + S.add_generator(Perm({1, 2, 3, 4, 0})); + REQUIRE(S.size() == 120); + } + + // todd-coxeter-class.hpp: Line 80 + LIBSEMIGROUPS_TEST_CASE("docs", + "033", + "todd-coxeter-class.hpp", + "[docs][quick]") { + using options = detail::ToddCoxeterImpl::options; + + Presentation p; + p.alphabet(2); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 0_w, 1_w); + ToddCoxeter tc(congruence_kind::onesided, p); + tc.strategy(options::strategy::felsch); + REQUIRE(tc.number_of_classes() == 1); + + auto w1 = 0000_w; + auto w2 = 00_w; + REQUIRE(todd_coxeter::contains(tc, w1, w2) == true); + REQUIRE(todd_coxeter::index_of(tc, w1) == 0); + } + + // todd-coxeter-class.hpp: Line 98 + LIBSEMIGROUPS_TEST_CASE("docs", + "034", + "todd-coxeter-class.hpp", + "[docs][quick]") { + using options = detail::ToddCoxeterImpl::options; + + Presentation p; + p.alphabet(4); + presentation::add_rule(p, 00_w, 0_w); + presentation::add_rule(p, 10_w, 1_w); + presentation::add_rule(p, 01_w, 1_w); + presentation::add_rule(p, 20_w, 2_w); + presentation::add_rule(p, 02_w, 2_w); + presentation::add_rule(p, 30_w, 3_w); + presentation::add_rule(p, 03_w, 3_w); + presentation::add_rule(p, 11_w, 0_w); + presentation::add_rule(p, 23_w, 0_w); + presentation::add_rule(p, 222_w, 0_w); + presentation::add_rule(p, 12121212121212_w, 0_w); + presentation::add_rule(p, 12131213121312131213121312131213_w, 0_w); + ToddCoxeter tc(congruence_kind::twosided, p); + tc.strategy(options::strategy::hlt) + .lookahead_extent(options::lookahead_extent::partial) + .save(false); + REQUIRE(tc.number_of_classes() == 10752); + tc.standardize(Order::recursive); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); + // {0_w, + // 1_w, + // 2_w, + // 21_w, + // 12_w, + // 121_w, + // 22_w, + // 221_w, + // 212_w, + // 2121_w} + tc.standardize(Order::lex); + todd_coxeter::normal_forms(tc) | rx::take(10) | rx::to_vector(); + // {0_w, + // 01_w, + // 012_w, + // 0121_w, + // 01212_w, + // 012121_w, + // 0121212_w, + // 01212121_w, + // 012121212_w, + // 0121212121_w}; + } + + // word-graph.hpp: Line 1540 + LIBSEMIGROUPS_TEST_CASE("docs", "035", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(2); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + REQUIRE(word_graph::is_acyclic(wg) == false); + } + + // word-graph.hpp: Line 1583 + LIBSEMIGROUPS_TEST_CASE("docs", "036", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(1); + wg.target(0, 0, 1); + wg.target(1, 0, 0); + wg.target(2, 0, 3); + REQUIRE(word_graph::is_acyclic(wg) == false); + REQUIRE(word_graph::is_acyclic(wg, 0) == false); + REQUIRE(word_graph::is_acyclic(wg, 1) == false); + REQUIRE(word_graph::is_acyclic(wg, 2) == true); + REQUIRE(word_graph::is_acyclic(wg, 3) == true); + } + + // word-graph.hpp: Line 1973 + LIBSEMIGROUPS_TEST_CASE("docs", "037", "word-graph.hpp", "[docs][quick]") { + WordGraph wg; + wg.add_nodes(4); + wg.add_to_out_degree(4); + wg.target(0, 1, 0); + wg.target(1, 0, 0); + wg.target(2, 3, 0); + REQUIRE(word_graph::is_reachable_no_checks(wg, 0, 1) == false); + REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 0) == true); + REQUIRE(word_graph::is_reachable_no_checks(wg, 1, 2) == false); + REQUIRE(word_graph::is_reachable_no_checks(wg, 2, 3) == false); + REQUIRE(word_graph::is_reachable_no_checks(wg, 3, 2) == false); + } + + // word-graph.hpp: Line 2053 + LIBSEMIGROUPS_TEST_CASE("docs", "038", "word-graph.hpp", "[docs][quick]") { + auto wg = make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); + REQUIRE(word_graph::is_strictly_cyclic(wg) == false); + } + + // word-graph.hpp: Line 2793 + LIBSEMIGROUPS_TEST_CASE("docs", "039", "word-graph.hpp", "[docs][quick]") { + // Construct a word graph with 5 nodes and 10 edges (7 specified) + auto wg = make>(5, {{0, 0}, {1, 1}, {2}, {3, 3}}); + } + + // word-range.hpp: Line 183 + LIBSEMIGROUPS_TEST_CASE("docs", "040", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wilo(2, 3, {0}, {1, 1, 1}), + cend_wilo(2, 3, {0}, {1, 1, 1})); + // {{0}, {0, 0}, {0, 1}, {1}, {1, 0}, {1, 1}}; + } + + // word-range.hpp: Line 253 + LIBSEMIGROUPS_TEST_CASE("docs", "041", "word-range.hpp", "[docs][quick]") { + std::vector(cbegin_wislo(2, {0}, {0, 0, 0}), + cend_wislo(2, {0}, {0, 0, 0})); + // {{0}, {1}, {0, 0}, {0, 1}, {1, 0}, {1, 1}}; + } + + // word-range.hpp: Line 313 + LIBSEMIGROUPS_TEST_CASE("docs", "042", "word-range.hpp", "[docs][quick]") { + WordRange words; + words + .order(Order::shortlex) // words in shortlex order + .alphabet_size(2) // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 + } + + // word-range.hpp: Line 761 + LIBSEMIGROUPS_TEST_CASE("docs", "043", "word-range.hpp", "[docs][quick]") { + ToWord toword("bac"); + REQUIRE(toword("bac") == std::vector{0, 1, 2}); + REQUIRE(toword("bababbbcbc") + == std::vector{0, 1, 0, 1, 0, 0, 0, 2, 0, 2}); + + toword.init(); + REQUIRE(toword("bac") == std::vector{1, 0, 2}); + } + + // word-range.hpp: Line 1050 + LIBSEMIGROUPS_TEST_CASE("docs", "044", "word-range.hpp", "[docs][quick]") { + using namespace rx; + StringRange strings; + strings.alphabet("ab").first("a").last("bbbb"); + auto words = (strings | ToWord("ba")); + // contains the words + // {1_w, 0_w, 11_w, 10_w, 01_w, 00_w, 111_w, + // 110_w, 101_w, 100_w, 011_w, 010_w, 001_w, 000_w, + // 1111_w, 1110_w, 1101_w, 1100_w, 1011_w, 1010_w, 1001_w, + // 1000_w, 0111_w, 0110_w, 0101_w, 0100_w, 0011_w, 0010_w, + // 0001_w})); + } + + // word-range.hpp: Line 1151 + LIBSEMIGROUPS_TEST_CASE("docs", "045", "word-range.hpp", "[docs][quick]") { + ToString tostring("bac"); + REQUIRE(tostring(word_type({1, 0, 2})) == "abc"); + REQUIRE(tostring(word_type({0, 1, 1, 0, 1, 1, 0, 2})) == "baabaabc"); + + tostring.init(); + REQUIRE(tostring(word_type({1, 0, 2})) == "bac"); + } + + // word-range.hpp: Line 1402 + LIBSEMIGROUPS_TEST_CASE("docs", "046", "word-range.hpp", "[docs][quick]") { + using namespace rx; + WordRange words; + words.alphabet_size(1).min(0).max(10); + + auto strings = (words | ToString("a")); + // Contains the strings + // {"", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", + // "aaaaaaaa", "aaaaaaaaa"}; + } + + // word-range.hpp: Line 1596 + LIBSEMIGROUPS_TEST_CASE("docs", "047", "word-range.hpp", "[docs][quick]") { + StringRange strings; + strings + .order(Order::shortlex) // strings in shortlex order + .alphabet("ab") // on 2 letters + .min(1) // of length in the range from 1 + .max(5); // to 5 + } + + // word-range.hpp: Line 2307 + LIBSEMIGROUPS_TEST_CASE("docs", "048", "word-range.hpp", "[docs][quick]") { + using namespace words; + word_type w = 012345_w; + prod(w, 0, 5, 2); // {0, 2, 4} + prod(w, 1, 9, 2); // {1, 3, 5, 1} + prod("abcde", 4, 1, -1); // "edc" + prod({"aba", "xyz"}, 0, 4, 1); // "abaxyzabaxyz" + } + +} // namespace libsemigroups \ No newline at end of file