diff --git a/docs/source/conf.py b/docs/source/conf.py
index d85408a4..51ec0357 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -189,7 +189,7 @@
# Python code that is treated like it were put in a testsetup directive for
# every file that is tested, and for every group.
doctest_global_setup = """from libsemigroups_pybind11 import ReportGuard
-ReportGuard(False)"""
+rg = ReportGuard(False)"""
############ intersphinx ############
diff --git a/docs/source/data-structures/presentations/alphabet-helpers.rst b/docs/source/data-structures/presentations/alphabet-helpers.rst
new file mode 100644
index 00000000..81e7eaac
--- /dev/null
+++ b/docs/source/data-structures/presentations/alphabet-helpers.rst
@@ -0,0 +1,21 @@
+Alphabet Helpers
+----------------
+
+.. currentmodule:: libsemigroups_pybind11.alphabet
+
+This page contains the documentation for the ``alphabet`` subpackage, that contains
+helper functions for the :any:`Alphabet` class.
+
+.. TODO "validate" is really in libsemigroups namespace and as such should be
+ on its own page probably, like "to"
+
+.. autosummary::
+ :signatures: short
+
+ first_unused_letter
+ validate
+
+.. automodule:: libsemigroups_pybind11.alphabet
+ :members:
+ :imported-members:
+ :exclude-members: Alphabet
diff --git a/docs/source/data-structures/presentations/alphabet.rst b/docs/source/data-structures/presentations/alphabet.rst
new file mode 100644
index 00000000..b70f176c
--- /dev/null
+++ b/docs/source/data-structures/presentations/alphabet.rst
@@ -0,0 +1,53 @@
+..
+ Copyright (c) 2026 J. D. Mitchell
+
+ Distributed under the terms of the GPL license version 3.
+
+ The full license is in the file LICENSE, distributed with this software.
+
+.. currentmodule:: libsemigroups_pybind11
+
+The Alphabet class
+==================
+
+.. autoclass:: Alphabet
+ :doc-only:
+
+.. Types
+
+ -----
+
+ In what follows, we use the following pseudo-types:
+
+ - ``Letter`` for ``str | int``
+ - ``Word`` for ``str | list[int]``
+
+ Recall that, once an alphabet has been constructed, the type of its letters and
+ words are fixed.
+
+Contents
+--------
+
+.. autosummary::
+ :signatures: short
+
+ ~Alphabet
+ Alphabet.add_letter
+ Alphabet.copy
+ Alphabet.contains
+ Alphabet.empty
+ Alphabet.index
+ Alphabet.init
+ Alphabet.letter
+ Alphabet.letters
+ Alphabet.remove_letter
+ Alphabet.throw_if_duplicate_letters
+ Alphabet.throw_if_letter_not_in_alphabet
+
+Full API
+--------
+
+.. autoclass:: Alphabet
+ :class-doc-from: init
+ :members:
+
diff --git a/docs/source/data-structures/presentations/index.rst b/docs/source/data-structures/presentations/index.rst
index 34117135..d2a19bfb 100644
--- a/docs/source/data-structures/presentations/index.rst
+++ b/docs/source/data-structures/presentations/index.rst
@@ -36,10 +36,13 @@ semigroups and monoids are:
.. toctree::
:maxdepth: 1
+ alphabet
present
inverse-present
+ alphabet-helpers
present-helpers
examples
+ to-alphabet
to-present
to-inverse-present
obvinf
diff --git a/docs/source/data-structures/presentations/to-alphabet.rst b/docs/source/data-structures/presentations/to-alphabet.rst
new file mode 100644
index 00000000..fa1afe52
--- /dev/null
+++ b/docs/source/data-structures/presentations/to-alphabet.rst
@@ -0,0 +1,85 @@
+..
+ Copyright (c) 2026 J. D. Mitchell
+
+ Distributed under the terms of the GPL license version 3.
+
+ The full license is in the file LICENSE, distributed with this software.
+
+.. currentmodule:: libsemigroups_pybind11
+
+Converting to an Alphabet
+=========================
+
+This page contains documentation relating to converting
+``libsemigroups_pybind11`` objects into :any:`Alphabet` instances using the
+:any:`to` function.
+
+.. seealso::
+
+ :doc:`/data-structures/to-function` for an overview of possible conversions
+ between ``libsemigroups_pybind11`` types.
+
+Various uses
+------------
+
+Recall that the signature for the :any:`to` function is ``to(*args, rtype)``.
+In what follows, we explain how different values of *args* and *rtype* may be
+used to construct :any:`Alphabet` objects.
+
+.. _alphabet-to-alphabet:
+
+Converting an :any:`Alphabet` to an :any:`Alphabet`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To construct an :any:`Alphabet` from an :any:`Alphabet`, specify the following
+values for *args*:
+
+ - **alphabet** (:any:`Alphabet`) -- the :any:`Alphabet` to convert.
+
+Additionally, specify one of the following for *rtype*:
+
+ - ``(Alphabet, str)`` for constructing an :any:`Alphabet` over words of type
+ ``str``.
+ - ``(Alphabet, list[int])`` for constructing an :any:`Alphabet` over words
+ of type ``list[int]``.
+
+This function behaves in one of two ways, depending on the type of words in
+*alphabet*, and the type of words specified in *rtype*:
+
+ 1. When the type of words in *alphabet* and type of words specified in
+ *rtype* are not the same, this function returns an :any:`Alphabet`
+ equivalent to the input :any:`Alphabet` *alphabet* but with words a
+ different type (for example, can be used to convert from ``str`` to
+ ``list[int]``).
+ 2. When the type of words in *alphabet* and type of words specified in
+ *rtype* are the same, this function effectively just returns its argument
+ *alphabet*, and is included solely for the purpose of simplifying certain
+ client code, where alphabets must be converted from one type to another
+ sometimes, but not other times.
+
+If *alphabet* has letters :math:`\{a_0, a_1, \dots a_{n-1}\}`, where each
+letter is of type ``str``, then the conversion from one type to another is
+:math:`a_i \mapsto` ``human_readable_index(a_i)``. Conversely, if each letter is
+of type ``int``, then the conversion from one type to another is
+:math:`a_i \mapsto` ``human_readable_letter(a_i)``.
+
+.. seealso::
+
+ - :any:`words.human_readable_index`;
+ - :any:`words.human_readable_letter`; and
+ - :any:`Alphabet.throw_if_duplicate_letters`.
+
+.. doctest:: Python
+
+ >>> from libsemigroups_pybind11 import Alphabet, to
+
+ >>> a = Alphabet("abcdef")
+ >>> a == to(a, rtype=(Alphabet, str))
+ True
+
+ >>> b = to(a, rtype=(Alphabet, list[int]))
+ >>> b.letters()
+ [0, 1, 2, 3, 4, 5]
+
+ >>> to(b, rtype=(Alphabet, str)) == a
+ True
diff --git a/docs/source/data-structures/presentations/to-inverse-present.rst b/docs/source/data-structures/presentations/to-inverse-present.rst
index 5070b987..1348525d 100644
--- a/docs/source/data-structures/presentations/to-inverse-present.rst
+++ b/docs/source/data-structures/presentations/to-inverse-present.rst
@@ -98,7 +98,7 @@ Additionally, specify one of the following for *rtype*:
- ``(InversePresentation, list[int])`` for constructing an
:any:`InversePresentation` over words of type ``list[int]``.
-This function behaves in one of two ways, depending on type of words in *ip*, and
+This function behaves in one of two ways, depending on the type of words in *ip*, and
the type of words specified in *rtype*:
1. When the type of words in *ip* and type of words specified in *rtype*
diff --git a/docs/source/data-structures/presentations/to-present.rst b/docs/source/data-structures/presentations/to-present.rst
index 315f19f6..81acb4a4 100644
--- a/docs/source/data-structures/presentations/to-present.rst
+++ b/docs/source/data-structures/presentations/to-present.rst
@@ -53,7 +53,7 @@ Additionally, specify one of the following for *rtype*:
- ``(Presentation, list[int])`` for constructing a :any:`Presentation` over
words of type ``list[int]``.
-This function behaves in one of two ways, depending on type of words in *p*, and
+This function behaves in one of two ways, depending on the type of words in *p*, and
the type of words specified in *rtype*:
1. When the type of words in *p* and type of words specified in *rtype* are
diff --git a/src/alphabet.cpp b/src/alphabet.cpp
new file mode 100644
index 00000000..03c6448a
--- /dev/null
+++ b/src/alphabet.cpp
@@ -0,0 +1,639 @@
+//
+// libsemigroups - C++ library for semigroups and monoids
+// Copyright (C) 2026 James D. Mitchell
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+
+// libsemigroups headers
+#include
+
+// pybind11....
+#include
+#include
+#include
+
+// libsemigroups_pybind11....
+#include "main.hpp" // for init_alphabet
+
+namespace py = pybind11;
+
+namespace libsemigroups {
+
+ namespace {
+ template
+ void bind_alphabet(py::module& m, std::string name) {
+ using Alphabet_ = Alphabet;
+
+ using size_type = typename Alphabet_::size_type;
+ using native_word_type = typename Alphabet_::native_word_type;
+ using native_letter_type = typename Alphabet_::native_letter_type;
+
+ py::class_ thing(m,
+ name.c_str(),
+ R"pbdoc(
+Class for storing and indexing an alphabet.
+
+An :any:`Alphabet` object stores an ordered list of distinct letters and
+maintains a map from each letter to its position in that list. The order of the
+letters is significant: it is the order used by :any:`letter` and
+:any:`Alphabet.index`.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("abc")
+ >>> list(a)
+ ['a', 'b', 'c']
+ >>> a.index("b")
+ 1)pbdoc");
+
+ ////////////////////////////////////////////////////////////////////////
+ // Operators
+ ////////////////////////////////////////////////////////////////////////
+
+ thing.def("__repr__", [](Alphabet_ const& thing) {
+ return to_human_readable_repr(thing);
+ });
+
+ thing.def("__str__", [](Alphabet_ const& self) {
+ return to_input_string(self, "[]");
+ });
+
+ thing.def("__len__", &Alphabet_::size);
+
+ thing.def("__copy__",
+ [](Alphabet_ const& self) { return Alphabet(self); });
+
+ thing.def(
+ "__iter__",
+ [](Alphabet_ const& self) {
+ return py::make_iterator(self.letters().begin(),
+ self.letters().end());
+ },
+ py::keep_alive<0, 1>());
+
+ thing.def(py::self == py::self);
+ thing.def(py::self != py::self);
+
+ ////////////////////////////////////////////////////////////////////////
+ // Constructors + initializers
+ ////////////////////////////////////////////////////////////////////////
+
+ thing.def(py::init<>(), R"pbdoc(
+:sig=(self: Alphabet, *, word: type) -> None:
+::only-document-once:
+Create an empty alphabet.
+
+This function creates an empty alphabet.
+
+:Keyword Arguments:
+ * **word** (*type*) -- the type of words to use. Must be either ``str`` or
+ ``list[int]``.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet(word=str).empty()
+ True
+ >>> Alphabet(word=list[int]).empty()
+ True)pbdoc");
+
+ thing.def(
+ "init",
+ [](Alphabet_& self) -> Alphabet_& { return self.init(); },
+ R"pbdoc(
+:sig=(self: Alphabet) -> Alphabet:
+
+Remove all letters.
+
+This function clears the alphabet, putting it back into the state it would be in
+if it was newly created.
+
+:returns: ``self``.
+:rtype: Alphabet
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("abc")
+ >>> a.init() is a
+ True
+ >>> a.empty()
+ True
+)pbdoc");
+
+ thing.def(py::init(), R"pbdoc(
+:sig=(self: Alphabet, letters: str | list[int]) -> None:
+::only-document-once:
+Create from letters.
+
+This function creates an alphabet with the letters in *letters*.
+
+:param letters: the alphabet.
+:type letters: str | list[int]
+
+:raises LibsemigroupsError: if there are duplicate letters in *letters*.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet("abc").letters()
+ 'abc'
+ >>> Alphabet([0, 2]).letters()
+ [0, 2]
+)pbdoc");
+
+ thing.def(
+ "init",
+ [](Alphabet_& self, native_word_type const& letters) -> Alphabet_& {
+ return self.init(letters);
+ },
+ py::arg("letters"),
+ R"pbdoc(
+:sig=(self: Alphabet, letters: str | list[int]) -> Alphabet:
+
+Re-initialize from letters.
+
+This function sets the alphabet to be the letters in *letters*.
+
+:param letters: the alphabet.
+:type letters: str | list[int]
+
+:returns: ``self``.
+:rtype: Alphabet
+
+:raises LibsemigroupsError: if there are duplicate letters in *letters*.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("abc")
+ >>> a.init("de") is a
+ True
+ >>> a.letters()
+ 'de'
+)pbdoc");
+
+ thing.def(py::init(), R"pbdoc(
+:sig=(self: Alphabet, n: int, *, word: type) -> None:
+::only-document-once:
+
+Create an alphabet by size.
+
+This function creates an alphabet containing the first *n* human-readable
+letters if the keyword argument *word* is ``str`` and the integers in the interval :math:`[0, n)` if *word* is ``list[int]``.
+
+:param n: the size of the alphabet.
+:type n: int
+
+:Keyword Arguments:
+ * **word** (*type*) -- the type of words to use. Must be either ``str`` or
+ ``list[int]``.
+
+:raises LibsemigroupsError:
+ if the value of *n* is greater than the maximum number of supported
+ letters.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet(3, word=str).letters()
+ 'abc'
+ >>> Alphabet(3, word=list[int]).letters()
+ [0, 1, 2]
+)pbdoc");
+
+ thing.def(
+ "init",
+ [](Alphabet_& self, size_type n) -> Alphabet_& {
+ return self.init(n);
+ },
+ py::arg("n"),
+ R"pbdoc(
+:sig=(self: Alphabet, n: int) -> Alphabet:
+
+Re-initialize the alphabet by size.
+
+This function replaces the alphabet by the first *n* human-readable letters.
+
+:param n: the size of the alphabet.
+:type n: int
+
+:returns: ``self``.
+:rtype: Alphabet
+
+:raises LibsemigroupsError:
+ if the value of *n* is greater than the maximum number of supported
+ letters.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("abc")
+ >>> a.init(2) is a
+ True
+ >>> a.letters()
+ 'ab'
+)pbdoc");
+
+ thing.def(
+ "copy",
+ [](Alphabet_ const& self) { return Alphabet(self); },
+ R"pbdoc(
+:sig=(self: Alphabet) -> Alphabet:
+
+Copy a :any:`Alphabet` object.
+
+:returns: A copy.
+:rtype: Alphabet
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("abc")
+ >>> b = a.copy()
+ >>> b == a
+ True
+ >>> b is a
+ False
+)pbdoc");
+
+ ////////////////////////////////////////////////////////////////////////
+ // Mem fns
+ ////////////////////////////////////////////////////////////////////////
+
+ thing.def("add_letter",
+ &Alphabet_::add_letter,
+ py::arg("x"),
+ R"pbdoc(
+:sig=(self: Alphabet, x: str | int) -> Alphabet:
+
+Add a letter.
+
+This function adds the letter *x* to the alphabet.
+
+:param x: the letter to add.
+:type x: str | int
+
+:returns: ``self``.
+:rtype: Alphabet
+
+:raises LibsemigroupsError: if *x* is in :any:`letters`.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("ab")
+ >>> a.add_letter("c") is a
+ True
+ >>> a.letters()
+ 'abc'
+)pbdoc");
+
+ thing.def("contains",
+ &Alphabet_::contains,
+ py::arg("x"),
+ R"pbdoc(
+:sig=(self: Alphabet, x: str | int) -> bool:
+
+Check if a letter belongs to the alphabet or not.
+
+This function checks whether *x* belongs to the alphabet.
+
+:param x: the letter to check.
+:type x: str | int
+
+:returns: Whether or not *x* belongs to the alphabet.
+:rtype: bool
+
+:complexity: Constant on average, worst case linear in the size of the alphabet.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("abc")
+ >>> a.contains("a")
+ True
+ >>> a.contains("d")
+ False
+)pbdoc");
+
+ thing.def("empty",
+ &Alphabet_::empty,
+ R"pbdoc(
+:sig=(self: Alphabet) -> bool:
+
+Check if the alphabet is empty.
+
+This function returns ``True`` if the alphabet contains no letters, and
+``False`` otherwise.
+
+:returns: Whether or not the alphabet is empty.
+:rtype: bool
+
+:complexity: Constant.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet(word=str).empty()
+ True
+ >>> Alphabet("abc").empty()
+ False
+)pbdoc");
+
+ thing.def("index",
+ &Alphabet_::index,
+ py::arg("x"),
+ R"pbdoc(
+:sig=(self: Alphabet, x: str | int) -> int:
+
+Return the index of a letter in the alphabet.
+
+After checking that *x* is in the alphabet, this function returns the index
+of *x* in the alphabet.
+
+:param x: the possible letter to check.
+:type x: str | int
+
+:returns: The index of *x* in the alphabet.
+:rtype: int
+
+:raises LibsemigroupsError: if ``x`` does not belong to the alphabet.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet("abc").index("b")
+ 1
+ >>> Alphabet([4, 2]).index(2)
+ 1
+)pbdoc");
+
+ thing.def("letter",
+ &Alphabet_::letter,
+ py::arg("i"),
+ R"pbdoc(
+:sig=(self: Alphabet, i: int) -> str | int:
+
+Return a letter in the alphabet by index.
+
+After checking that *i* is in the range :math:`[0, n)`, where :math:`n` is
+the length of the alphabet, this function returns the letter with index *i*.
+
+:param i: the index.
+:type i: int
+
+:returns: The letter with index *i*.
+:rtype: str | int
+
+:raises LibsemigroupsError: if *i* is not in the range :math:`[0, n)`.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet("abc").letter(2)
+ 'c'
+ >>> Alphabet([4, 2]).letter(0)
+ 4
+)pbdoc");
+
+ thing.def("letters",
+ &Alphabet_::letters,
+ R"pbdoc(
+:sig=(self: Alphabet) -> str | list[int]:
+Return the letters of the alphabet.
+
+This function returns the letters of the alphabet.
+
+:returns: The letters of the alphabet.
+:rtype: str | list[int]
+
+:complexity: Constant.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet("abc").letters()
+ 'abc'
+ >>> Alphabet([0, 2]).letters()
+ [0, 2]
+)pbdoc");
+
+ thing.def("remove_letter",
+ &Alphabet_::remove_letter,
+ py::arg("x"),
+ R"pbdoc(
+:sig=(self: Alphabet, x: str | int) -> Alphabet:
+
+Remove a letter.
+
+This function removes the letter *x* from the alphabet.
+
+:param x: the letter to remove.
+:type x: str | int
+
+:returns: ``self``.
+:rtype: Alphabet
+
+:raises LibsemigroupsError: if *x* is not in :any`letters`.
+
+:complexity:
+ Average case: linear in the length of the alphabet, worst case: quadratic in
+ the length of the alphabet.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> a = Alphabet("abc")
+ >>> a.remove_letter("b") is a
+ True
+ >>> a.letters()
+ 'ac'
+)pbdoc");
+
+ thing.def(
+ "throw_if_duplicate_letters",
+ [](Alphabet_ const& self) {
+ return self.throw_if_duplicate_letters();
+ },
+ R"pbdoc(
+:sig=(self: Alphabet) -> None:
+
+Check if the alphabet contains duplicates.
+
+This function checks if the alphabet contains duplicates..
+
+:raises LibsemigroupsError: if there are duplicate letters in the alphabet.
+
+:complexity: Linear in the length of the alphabet.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet("abc").throw_if_duplicate_letters() is None
+ True)pbdoc");
+ // thing.def(
+ // "throw_if_letter_not_in_alphabet",
+ // [](Alphabet_ const& self, Iterator1 first, Iterator2 last) {
+ // return self.throw_if_letter_not_in_alphabet(first, last);
+ // },
+ // py::arg("first"),
+ // py::arg("last"),
+ // R"pbdoc(
+ // Check if every letter in a range belongs to the alphabet.
+ //
+ // :param first: iterator pointing at the first letter to check.
+ // :type first: Iterator1
+ //
+ // :param last: iterator pointing one beyond the last letter to check.
+ // :type last: Iterator2
+ // Checks whether every letter in the range ``[first, last)`` belongs to
+ // the alphabet.
+ //
+ // :raises LibsemigroupsError: if any letter in ``[first, last)`` does
+ // not belong to the alphabet.
+ //
+ // :complexity: Linear in the length of the range on average, worst case
+ // proportional to the product of the length of the range and the size of
+ // the alphabet.
+ //
+ // Example
+ // -------
+ //
+ // .. doctest:: python
+ //
+ // >>> from libsemigroups_pybind11 import Alphabet
+ // >>> Alphabet("abc").throw_if_letter_not_in_alphabet("a") is None
+ // True)pbdoc");
+ thing.def(
+ "throw_if_letter_not_in_alphabet",
+ [](Alphabet_ const& self, native_letter_type x) {
+ return self.throw_if_letter_not_in_alphabet(x);
+ },
+ py::arg("x"),
+ R"pbdoc(
+:sig=(self: Alphabet, x : str | int) -> None:
+
+Check if a letter belongs to the alphabet or not.
+
+This function checks whether or not *x* belongs to the alphabet.
+
+:param x: the letter to check.
+:type x: str | int
+
+:raises LibsemigroupsError: if *x* does not belong to the alphabet.
+
+:complexity: Constant on average, worst case linear in the size of the alphabet.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet("abc").throw_if_letter_not_in_alphabet("a") is None
+ True)pbdoc");
+
+ ////////////////////////////////////////////////////////////////////////
+ // Helpers in libsemigroups namespace
+ ////////////////////////////////////////////////////////////////////////
+
+ m.def(
+ "validate",
+ [](Alphabet const& alphabet) { return validate(alphabet); },
+ py::arg("alphabet"),
+ R"pbdoc(
+:sig=(alphabet: Alphabet) -> None:
+::only-document-once:
+
+Check if an alphabet is valid.
+
+This function checks whether the parameter *alphabet* is valid.
+
+:param alphabet: the alphabet to validate.
+:type alphabet: Alphabet
+
+:raises LibsemigroupsError: if *alphabet* contains duplicate letters.
+
+:complexity: Linear in the size of *alphabet*.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet, alphabet
+ >>> alphabet.validate(Alphabet("abc")) is None
+ True)pbdoc");
+
+ ////////////////////////////////////////////////////////////////////////
+ // Helpers in alphabet namespace
+ ////////////////////////////////////////////////////////////////////////
+
+ m.def(
+ "alphabet_first_unused_letter",
+ [](Alphabet const& alphabet) {
+ return alphabet::first_unused_letter(alphabet);
+ },
+ py::arg("alphabet"),
+ R"pbdoc(
+:sig=(alphabet: Alphabet) -> str | int:
+::only-document-once:
+
+Return the first letter not in the alphabet.
+
+This function returns ``words.human_readable_letter(i)``, where ``i`` is the
+least possible value such that the returned letter does not belong to
+*alphabet*.
+
+:param alphabet: the alphabet.
+:type alphabet: Alphabet
+
+:returns: The first unused letter.
+:rtype: str | int
+
+:raises LibsemigroupsError:
+ if ``alphabet`` already contains the maximum possible number of supported
+ letters.
+
+.. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet, alphabet
+ >>> alphabet.first_unused_letter(Alphabet("abc"))
+ 'd'
+)pbdoc");
+ } // bind_alphabet
+
+ template
+ void bind_to_alphabet(py::module& m, std::string const& name) {
+ std::string fn_name = std::string("to_alphabet_") + name;
+ // NOTE: the following prevents the _cxx_obj of a python Alphabet from
+ // being copied here, but doesn't prevent the python Alphabet itself from
+ // being copied.
+ using Result = std::conditional_t,
+ Alphabet const&,
+ Alphabet>;
+
+ m.def(fn_name.c_str(), [](Alphabet const& p) -> Result {
+ return to>(p);
+ });
+ }
+ } // namespace
+
+ void init_alphabet(py::module& m) {
+ bind_alphabet(m, "AlphabetString");
+ bind_alphabet(m, "AlphabetWord");
+
+ bind_to_alphabet(m, "string");
+ bind_to_alphabet(m, "string");
+ bind_to_alphabet(m, "word");
+ bind_to_alphabet(m, "word");
+ }
+} // namespace libsemigroups
diff --git a/src/libsemigroups_pybind11/__init__.py b/src/libsemigroups_pybind11/__init__.py
index 132396e2..d75c4998 100644
--- a/src/libsemigroups_pybind11/__init__.py
+++ b/src/libsemigroups_pybind11/__init__.py
@@ -10,6 +10,7 @@
action,
adapters,
aho_corasick,
+ alphabet,
bipartition,
blocks,
bmat8,
@@ -36,6 +37,7 @@
from ._version import __version__
from .action import Action, LeftAction, RightAction
from .adapters import ImageLeftAction, ImageRightAction
+from .alphabet import Alphabet, validate
from .bipartition import Bipartition
from .blocks import Blocks
from .congruence import Congruence
@@ -169,6 +171,7 @@
"action",
"adapters",
"aho_corasick",
+ "alphabet",
"bipartition",
"blocks",
"bmat8",
@@ -193,6 +196,7 @@
"words",
# Classes defined in submodules
"Action",
+ "Alphabet",
"Bipartition",
"Blocks",
"Congruence",
@@ -225,8 +229,9 @@
"ToddCoxeter",
"Transf",
# Free functions from submodules
- "to",
"is_obviously_infinite",
+ "to",
+ "validate",
]
if LIBSEMIGROUPS_HPCOMBI_ENABLED:
diff --git a/src/libsemigroups_pybind11/alphabet.py b/src/libsemigroups_pybind11/alphabet.py
new file mode 100644
index 00000000..a5aeafde
--- /dev/null
+++ b/src/libsemigroups_pybind11/alphabet.py
@@ -0,0 +1,139 @@
+# Copyright (c) 2026 J. D. Mitchell
+#
+# Distributed under the terms of the GPL license version 3.
+#
+# The full license is in the file LICENSE, distributed with this software.
+
+# No doc string, this file is documented in alphabet-helpers.rst
+
+# pylint: disable=missing-module-docstring
+
+import collections
+
+from typing_extensions import Self as _Self
+
+from _libsemigroups_pybind11 import (
+ AlphabetString as _AlphabetString,
+ AlphabetWord as _AlphabetWord,
+ alphabet_first_unused_letter as _alphabet_first_unused_letter,
+ validate as _validate,
+)
+
+from .detail.cxx_wrapper import (
+ CxxWrapper as _CxxWrapper,
+ copy_cxx_mem_fns as _copy_cxx_mem_fns,
+ register_cxx_wrapped_type as _register_cxx_wrapped_type,
+ to_cxx as _to_cxx,
+ wrap_cxx_free_fn as _wrap_cxx_free_fn,
+)
+from .detail.decorators import copydoc as _copydoc
+
+
+class Alphabet(_CxxWrapper):
+ __doc__ = _AlphabetString.__doc__
+
+ _py_template_params_to_cxx_type = {(str,): _AlphabetString, (list[int],): _AlphabetWord}
+
+ _cxx_type_to_py_template_params = dict(
+ zip(
+ _py_template_params_to_cxx_type.values(),
+ _py_template_params_to_cxx_type.keys(),
+ strict=True,
+ )
+ )
+
+ _all_wrapped_cxx_types = {*_py_template_params_to_cxx_type.values()}
+
+ @staticmethod
+ def _validate_word_type(word: type) -> None:
+ if word not in (str, list[int]):
+ raise ValueError(
+ f'the keyword argument "word" must be str or list[int], but found {word}'
+ )
+
+ @_copydoc(_AlphabetString.__init__, _AlphabetWord.__init__)
+ def __init__(self: _Self, *args, **kwargs) -> None:
+ """__init__(self: Alphabet, *, word: type) -> None
+
+ Construct an empty alphabet.
+
+ :Keyword Arguments:
+ * **word** (*type*) -- the type of words to use. Must be either
+ ``str`` or ``list[int]``.
+
+ .. doctest:: python
+
+ >>> from libsemigroups_pybind11 import Alphabet
+ >>> Alphabet(word=str).empty()
+ True
+ >>> Alphabet(word=list[int]).empty()
+ True
+ """
+ super().__init__(*args, optional_kwargs=("word",), **kwargs)
+ if _to_cxx(self) is not None:
+ return
+
+ if len(args) > 1:
+ raise TypeError(f"expected at most 1 positional argument, found {len(args)}")
+
+ if len(args) == 1 and "word" in kwargs and not isinstance(args[0], int):
+ raise TypeError(
+ 'expected either 1 positional argument or the keyword argument "word" '
+ f"but found both, with argument type {type(args[0])}"
+ )
+
+ if len(args) == 0:
+ if "word" not in kwargs:
+ raise TypeError(
+ f'expected the keyword argument "word", but found {tuple(kwargs.keys())}'
+ )
+ self._validate_word_type(kwargs["word"])
+ self.py_template_params = (kwargs["word"],)
+ self.init_cxx_obj()
+ return
+
+ if isinstance(args[0], Alphabet):
+ self.py_template_params = args[0].py_template_params
+ elif isinstance(args[0], str):
+ self.py_template_params = (str,)
+ elif isinstance(args[0], list):
+ if not all(isinstance(x, int) for x in args[0]):
+ raise TypeError("expected the argument to consist of int values")
+ self.py_template_params = (list[int],)
+ elif isinstance(args[0], int):
+ if "word" not in kwargs:
+ raise TypeError('expected the keyword argument "word" when constructing by size')
+ self._validate_word_type(kwargs["word"])
+ self.py_template_params = (kwargs["word"],)
+ else:
+ raise TypeError(
+ f"expected the argument to have type one of (str, list[int], int) "
+ f"but found {type(args[0])}"
+ )
+
+ self.init_cxx_obj(*args)
+
+ def __contains__(self: _Self, val: str | int) -> bool:
+ return _to_cxx(self).contains(val)
+
+ def __eq__(self: _Self, other: _Self) -> bool:
+ return _to_cxx(self) == _to_cxx(other)
+
+ def __len__(self: _Self) -> int:
+ return len(_to_cxx(self))
+
+ def __str__(self: _Self) -> str:
+ return str(_to_cxx(self))
+
+ def __iter__(self: _Self) -> collections.abc.Iterator[int | str]:
+ return iter(_to_cxx(self))
+
+
+_copy_cxx_mem_fns(_AlphabetString, Alphabet)
+_register_cxx_wrapped_type(_AlphabetString, Alphabet)
+_register_cxx_wrapped_type(_AlphabetWord, Alphabet)
+
+first_unused_letter = _wrap_cxx_free_fn(_alphabet_first_unused_letter)
+validate = _wrap_cxx_free_fn(_validate)
+
+__all__ = ["Alphabet", "first_unused_letter", "validate"]
diff --git a/src/libsemigroups_pybind11/to.py b/src/libsemigroups_pybind11/to.py
index 7a1c71cf..f195a4c7 100644
--- a/src/libsemigroups_pybind11/to.py
+++ b/src/libsemigroups_pybind11/to.py
@@ -12,6 +12,8 @@
from _libsemigroups_pybind11 import (
Order as _Order,
+ to_alphabet_string as _to_alphabet_string,
+ to_alphabet_word as _to_alphabet_word,
to_congruence_string as _to_congruence_string,
to_congruence_word as _to_congruence_word,
to_froidure_pin as _to_froidure_pin,
@@ -39,6 +41,7 @@
to_todd_coxeter_word as _to_todd_coxeter_word,
)
+from .alphabet import Alphabet as _Alphabet
from .congruence import Congruence as _Congruence
from .detail.cxx_wrapper import to_cxx as _to_cxx
from .froidure_pin import FroidurePin as _FroidurePin
@@ -70,8 +73,10 @@ def _nice_name(type_list):
_RETURN_TYPE_TO_CONVERTER_FUNCTION = {
- (_Congruence, str): _to_congruence_string,
+ (_Alphabet, str): _to_alphabet_string,
+ (_Alphabet, list[int]): _to_alphabet_word,
(_Congruence, list[int]): _to_congruence_word,
+ (_Congruence, str): _to_congruence_string,
(_FroidurePin,): _to_froidure_pin,
(_InversePresentation,): _to_inverse_presentation,
(_InversePresentation, list[int]): _to_inverse_presentation_word,
@@ -118,6 +123,7 @@ def to(*args, rtype: tuple):
See the following pages for a detailed description of the various use
cases of this function:
+ * :doc:`/data-structures/presentations/to-alphabet`;
* :doc:`/main-algorithms/congruence/to-cong`;
* :doc:`/main-algorithms/froidure-pin/to-froidure-pin`;
* :doc:`/data-structures/presentations/to-inverse-present`;
diff --git a/src/main.cpp b/src/main.cpp
index fe397bef..c67bbdcf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -76,6 +76,7 @@ namespace libsemigroups {
init_runner(m);
// Must be before cong classes
+ init_alphabet(m);
init_present(m);
init_inverse_present(m);
diff --git a/src/main.hpp b/src/main.hpp
index a098df62..0f9742a4 100644
--- a/src/main.hpp
+++ b/src/main.hpp
@@ -38,6 +38,7 @@ namespace libsemigroups {
void init_action(py::module&);
void init_aho_corasick(py::module&);
+ void init_alphabet(py::module&);
void init_bipart(py::module&);
void init_blocks(py::module&);
void init_bmat8(py::module&);
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 00000000..e5c6fb4b
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,13 @@
+"""This file contains the configuration for pytest."""
+
+import pytest
+
+from libsemigroups_pybind11 import ReportGuard
+
+
+@pytest.fixture(autouse=True)
+def setup_each_test():
+ """Avoid having to write ReportGuard(false) in every test case"""
+ rg = ReportGuard(False)
+ yield
+ del rg
diff --git a/tests/runner.py b/tests/runner.py
index 6af59e25..e974b8f8 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -10,15 +10,12 @@
from datetime import timedelta
-from libsemigroups_pybind11 import ReportGuard
-
N = 0 # pylint: disable=invalid-name
def check_runner(x, t=timedelta(microseconds=1000)): # pylint: disable=missing-function-docstring
global N # pylint: disable=global-statement
N = 0
- ReportGuard(False)
assert not x.stopped()
assert not x.finished()
diff --git a/tests/test_alphabet.py b/tests/test_alphabet.py
new file mode 100644
index 00000000..8659c5eb
--- /dev/null
+++ b/tests/test_alphabet.py
@@ -0,0 +1,319 @@
+# Copyright (c) 2026 J. D. Mitchell
+#
+# Distributed under the terms of the GPL license version 3.
+#
+# The full license is in the file LICENSE, distributed with this software.
+
+"""This module contains some tests for the Alphabet class."""
+
+# pylint: disable=missing-function-docstring
+
+import pytest
+
+from libsemigroups_pybind11 import Alphabet, LibsemigroupsError, alphabet, to
+
+
+def test_string_alphabet():
+ a = Alphabet("abc")
+
+ assert len(a) == 3
+ assert not a.empty()
+ assert "a" in a
+ assert "d" not in a
+ assert a.letters() == "abc"
+ assert a.index("b") == 1
+ assert a.letter(2) == "c"
+ assert alphabet.first_unused_letter(a) == "d"
+ assert alphabet.validate(a) is None
+
+ with pytest.raises(LibsemigroupsError):
+ Alphabet("aa")
+
+
+def test_word_alphabet():
+ a = Alphabet([0, 2])
+
+ assert len(a) == 2
+ assert not a.empty()
+ assert 0 in a
+ assert 1 not in a
+ assert a.letters() == [0, 2]
+ assert a.index(2) == 1
+ assert a.letter(0) == 0
+ assert alphabet.first_unused_letter(a) == 1
+ assert alphabet.validate(a) is None
+
+ with pytest.raises(LibsemigroupsError):
+ Alphabet([0, 0])
+
+
+def test_ambiguous_constructors():
+ with pytest.raises(TypeError):
+ Alphabet()
+
+ assert len(Alphabet(word=str)) == 0
+ assert len(Alphabet(word=list[int])) == 0
+ assert Alphabet(3, word=str).letters() == "abc"
+ assert Alphabet(3, word=list[int]).letters() == [0, 1, 2]
+
+ with pytest.raises(TypeError):
+ Alphabet(3)
+ with pytest.raises(ValueError):
+ Alphabet(word=tuple)
+
+
+def test_add_letter():
+ a = Alphabet("abc")
+
+ with pytest.raises(LibsemigroupsError):
+ a.add_letter("a")
+ with pytest.raises(TypeError):
+ a.add_letter(10)
+ assert a.add_letter("e") is a
+
+ a = Alphabet([0, 3])
+
+ with pytest.raises(LibsemigroupsError):
+ a.add_letter(0)
+ with pytest.raises(TypeError):
+ a.add_letter("a")
+ assert a.add_letter(1) is a
+
+
+def test_contains():
+ a = Alphabet("abc")
+
+ assert "a" in a
+ assert a.contains("a")
+
+ with pytest.raises(TypeError):
+ a.contains(0)
+
+ a = Alphabet([0, 1, 2])
+
+ assert 1 in a
+ assert a.contains(1)
+
+ with pytest.raises(TypeError):
+ a.contains("a")
+
+
+def test_empty():
+ a = Alphabet("abc")
+ assert not a.empty()
+ a.init()
+ assert a.empty()
+
+ a = Alphabet(3, word=list[int])
+ assert not a.empty()
+ a.init()
+ assert a.empty()
+
+
+def test_iter():
+ a = Alphabet("abc")
+ assert list(a) == list(a.letters())
+
+ a = Alphabet([0, 1, 11])
+ assert list(a) == a.letters()
+
+
+def test_index():
+ a = Alphabet("abc")
+ assert [a.index(x) for x in a] == [0, 1, 2]
+
+ with pytest.raises(LibsemigroupsError):
+ a.index("d")
+ with pytest.raises(TypeError):
+ a.index(0)
+
+ a = Alphabet([11, 0, 1])
+ assert [a.index(x) for x in a] == [0, 1, 2]
+
+ with pytest.raises(LibsemigroupsError):
+ a.index(2)
+ with pytest.raises(TypeError):
+ a.index("a")
+
+
+def test_copy():
+ a = Alphabet("abc")
+ b = a.copy()
+
+ assert b == a
+ assert b is not a
+ b.add_letter("d")
+ assert b != a
+ assert a.letters() == "abc"
+ assert b.letters() == "abcd"
+
+ a = Alphabet([0, 2])
+ b = a.copy()
+
+ assert b == a
+ assert b is not a
+ b.add_letter(1)
+ assert b != a
+ assert a.letters() == [0, 2]
+ assert b.letters() == [0, 2, 1]
+
+
+def test_copy_constructor():
+ a = Alphabet("abc")
+ b = a.copy()
+
+ assert b == a
+ assert b is not a
+ assert b.letters() == "abc"
+
+ a = Alphabet([0, 2])
+ b = a.copy()
+
+ assert b == a
+ assert b is not a
+ assert b.letters() == [0, 2]
+
+
+def test_repr_and_str():
+ assert repr(Alphabet("abc")) == ''
+ assert str(Alphabet("abc")) == 'Alphabet("abc")'
+ assert repr(Alphabet([0, 1, 2])) == ""
+ assert str(Alphabet([0, 1, 2])) == "Alphabet([0, 1, 2])"
+
+
+def test_equality():
+ assert Alphabet("abc") == Alphabet("abc")
+ assert Alphabet("abc") != Alphabet("acb")
+ assert Alphabet([0, 1, 2]) == Alphabet([0, 1, 2])
+ assert Alphabet([0, 1, 2]) != Alphabet([0, 2, 1])
+
+
+def test_init_from_letters():
+ a = Alphabet("abc")
+
+ assert a.init("de") is a
+ assert a.letters() == "de"
+ with pytest.raises(LibsemigroupsError):
+ a.init("dd")
+ with pytest.raises(TypeError):
+ a.init([0, 1])
+
+ a = Alphabet([0, 1])
+
+ assert a.init([3, 2]) is a
+ assert a.letters() == [3, 2]
+ with pytest.raises(LibsemigroupsError):
+ a.init([3, 3])
+ with pytest.raises(TypeError):
+ a.init("ab")
+
+
+def test_init_from_size():
+ a = Alphabet("abc")
+
+ assert a.init(2) is a
+ assert a.letters() == "ab"
+
+ a = Alphabet([10, 11])
+
+ assert a.init(3) is a
+ assert a.letters() == [0, 1, 2]
+
+
+def test_letter():
+ a = Alphabet("abc")
+
+ assert [a.letter(i) for i in range(len(a))] == ["a", "b", "c"]
+ with pytest.raises(LibsemigroupsError):
+ a.letter(3)
+ with pytest.raises(TypeError):
+ a.letter("a")
+
+ a = Alphabet([11, 0, 1])
+
+ assert [a.letter(i) for i in range(len(a))] == [11, 0, 1]
+ with pytest.raises(LibsemigroupsError):
+ a.letter(3)
+ with pytest.raises(TypeError):
+ a.letter("a")
+
+
+def test_letters_after_mutation():
+ a = Alphabet("ab")
+
+ a.add_letter("c")
+ assert a.letters() == "abc"
+ a.remove_letter("b")
+ assert a.letters() == "ac"
+
+ a = Alphabet([0, 1])
+
+ a.add_letter(3)
+ assert a.letters() == [0, 1, 3]
+ a.remove_letter(1)
+ assert a.letters() == [0, 3]
+
+
+def test_remove_letter():
+ a = Alphabet("abc")
+
+ assert a.remove_letter("b") is a
+ assert a.letters() == "ac"
+ with pytest.raises(LibsemigroupsError):
+ a.remove_letter("b")
+ with pytest.raises(TypeError):
+ a.remove_letter(0)
+
+ a = Alphabet([0, 1, 2])
+
+ assert a.remove_letter(1) is a
+ assert a.letters() == [0, 2]
+ with pytest.raises(LibsemigroupsError):
+ a.remove_letter(1)
+ with pytest.raises(TypeError):
+ a.remove_letter("a")
+
+
+def test_throw_if_duplicate_letters():
+ assert Alphabet("abc").throw_if_duplicate_letters() is None
+ assert Alphabet([0, 1, 2]).throw_if_duplicate_letters() is None
+
+
+def test_throw_if_letter_not_in_alphabet():
+ a = Alphabet("abc")
+
+ assert a.throw_if_letter_not_in_alphabet("a") is None
+ with pytest.raises(LibsemigroupsError):
+ a.throw_if_letter_not_in_alphabet("d")
+ with pytest.raises(TypeError):
+ a.throw_if_letter_not_in_alphabet(0)
+
+ a = Alphabet([0, 1, 2])
+
+ assert a.throw_if_letter_not_in_alphabet(1) is None
+ with pytest.raises(LibsemigroupsError):
+ a.throw_if_letter_not_in_alphabet(3)
+ with pytest.raises(TypeError):
+ a.throw_if_letter_not_in_alphabet("a")
+
+
+def test_validate():
+ assert alphabet.validate(Alphabet("abc")) is None
+ assert alphabet.validate(Alphabet([0, 1, 2])) is None
+ with pytest.raises(TypeError):
+ alphabet.validate("abc")
+
+
+def test_to_alphabet():
+ a = Alphabet("abc")
+ assert a.letters() == "abc"
+
+ b = to(a, rtype=(Alphabet, str))
+ assert a == b
+
+ # assert b is a
+
+ c = to(a, rtype=(Alphabet, list[int]))
+ assert c.letters() == [0, 1, 2]
+
+ assert to(c, rtype=(Alphabet, str)) == a
diff --git a/tests/test_cong.py b/tests/test_cong.py
index ac3bafc3..ea322083 100644
--- a/tests/test_cong.py
+++ b/tests/test_cong.py
@@ -19,7 +19,6 @@
KnuthBendix,
LibsemigroupsError,
Presentation,
- ReportGuard,
StringRange,
ToddCoxeter,
congruence,
@@ -33,7 +32,6 @@
def test_018():
- ReportGuard(False)
p = Presentation([0, 1, 2])
presentation.add_rule(p, [0, 0], [0, 0])
presentation.add_rule(p, [0, 1], [1, 0])
diff --git a/tests/test_froidure_pin.py b/tests/test_froidure_pin.py
index f0729347..61e45745 100644
--- a/tests/test_froidure_pin.py
+++ b/tests/test_froidure_pin.py
@@ -27,7 +27,6 @@
Perm,
PPerm,
Presentation,
- ReportGuard,
Transf,
congruence_kind,
froidure_pin,
@@ -39,7 +38,6 @@
def check_constructors(coll):
- ReportGuard(False)
# default constructor
S = FroidurePin([coll[0]])
S.add_generators(coll[1:])
@@ -52,7 +50,6 @@ def check_constructors(coll):
def check_generators(coll):
- ReportGuard(False)
S = FroidurePin([coll[0]])
S.add_generators(coll[1:])
for i, x in enumerate(coll):
@@ -82,15 +79,12 @@ def check_generators(coll):
def check_settings(S):
- ReportGuard(False)
assert S.batch_size() == 8192
S.batch_size(S.batch_size())
S.reserve(100)
def check_mem_compare(S):
- ReportGuard(False)
-
with pytest.raises(RuntimeError):
froidure_pin.current_position(S, [0, 0, 0, 0, 0, 0, 0, S.number_of_generators(), 1])
with pytest.raises(RuntimeError):
@@ -122,7 +116,6 @@ def check_mem_compare(S):
def check_accessors(S):
- ReportGuard(False)
# current_size
assert S.current_size() == S.number_of_generators()
S.run()
@@ -138,16 +131,12 @@ def check_accessors(S):
def check_attributes(S):
- ReportGuard(False)
-
S.contains_one()
assert S.is_finite()
S.degree() # just check it doesn't throw
def check_idempotents(S):
- ReportGuard(False)
-
# Suppress TypeError in case no multiplication is provided
with contextlib.suppress(TypeError):
assert all(x * x == x for x in S.idempotents())
@@ -160,8 +149,6 @@ def check_idempotents(S):
def check_cayley_graphs(S):
- ReportGuard(False)
-
gen_names = "abcdefghijklmnopqrstuvwxyz"[: S.number_of_generators()]
d = froidure_pin.dot_current_right_cayley_graph(S)
@@ -208,8 +195,6 @@ def check_cayley_graphs(S):
def check_factor_prod_rels(S):
- ReportGuard(False)
-
# current_length
for i in range(S.number_of_generators()):
assert S.current_length(i) == 1
@@ -245,7 +230,6 @@ def check_factor_prod_rels(S):
def check_prefix_suffix(S):
- ReportGuard(False)
S.run()
for i in range(S.number_of_generators(), S.size()):
@@ -254,7 +238,6 @@ def check_prefix_suffix(S):
def check_froidure_pin_transf1(T):
- ReportGuard(False)
S = FroidurePin(T([1, 7, 2, 6, 0, 4, 1, 5]))
S.add_generator(T([2, 4, 6, 1, 4, 5, 2, 7]))
@@ -364,7 +347,6 @@ def test_runner_pperm():
def test_froidure_pin_perm(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [Perm([1, 0] + list(range(2, 4))), Perm(list(range(1, 4)) + [0])]
assert FroidurePin(gens).size() == 24
@@ -382,7 +364,6 @@ def test_runner_perm():
def test_froidure_pin_bipart(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
T = Bipartition
gens = [T([0, 1, 1, 0]), T([0, 1, 2, 1]), T([0, 0, 0, 0])]
assert FroidurePin(gens).size() == 15
@@ -395,7 +376,6 @@ def test_froidure_pin_bipart(checks_for_froidure_pin, checks_for_generators):
def test_froidure_pin_pbr(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
T = PBR
gens = [T([[], [0]]), T([[0, 1], [0]]), T([[1], []]), T([[1], [0, 1]])]
assert FroidurePin(gens).size() == 15
@@ -408,7 +388,6 @@ def test_froidure_pin_pbr(checks_for_froidure_pin, checks_for_generators):
def test_froidure_pin_bmat(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [
Matrix(MatrixKind.Boolean, [[0, 1], [1, 0]]),
Matrix(MatrixKind.Boolean, [[1, 0], [1, 1]]),
@@ -424,7 +403,6 @@ def test_froidure_pin_bmat(checks_for_froidure_pin, checks_for_generators):
def test_froidure_pin_bmat8(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [BMat8([[0, 1], [1, 0]]), BMat8([[1, 0], [1, 1]]), BMat8([[1, 0], [0, 0]])]
assert FroidurePin(gens).size() == 16
@@ -436,7 +414,6 @@ def test_froidure_pin_bmat8(checks_for_froidure_pin, checks_for_generators):
def test_froidure_pin_int_mat(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [Matrix(MatrixKind.Integer, [[0, -3], [-2, -10]])]
S = FroidurePin(gens)
# This example is probably infinite really, here we are using 64 bit
@@ -451,7 +428,6 @@ def test_froidure_pin_int_mat(checks_for_froidure_pin, checks_for_generators):
def test_froidure_pin_max_plus(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [Matrix(MatrixKind.MaxPlus, [[0, -3], [-2, -10]])]
assert FroidurePin(gens).size() == 2
@@ -463,7 +439,6 @@ def test_froidure_pin_max_plus(checks_for_froidure_pin, checks_for_generators):
def test_froidure_pin_min_plus(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
x = Matrix(MatrixKind.MinPlus, 2, 2)
gens = [Matrix(MatrixKind.MinPlus, [[1, 0], [0, x.scalar_zero()]])]
assert FroidurePin(gens).size() == 3
@@ -476,7 +451,6 @@ def test_froidure_pin_min_plus(checks_for_froidure_pin, checks_for_generators):
def test_froidure_pin_proj_max_plus(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
x = Matrix(MatrixKind.ProjMaxPlus, 2, 2)
gens = [Matrix(MatrixKind.ProjMaxPlus, [[1, 0], [0, x.scalar_zero()]])]
assert FroidurePin(gens).size() == 2
@@ -489,7 +463,6 @@ def test_froidure_pin_proj_max_plus(checks_for_froidure_pin, checks_for_generato
def test_froidure_pin_max_plus_trunc(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [Matrix(MatrixKind.MaxPlusTrunc, 11, [[1, 0], [0, 1]])]
assert FroidurePin(gens).size() == 12
@@ -501,7 +474,6 @@ def test_froidure_pin_max_plus_trunc(checks_for_froidure_pin, checks_for_generat
def test_froidure_pin_min_plus_trunc(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [Matrix(MatrixKind.MinPlusTrunc, 11, [[1, 0], [0, 1]])]
assert FroidurePin(gens).size() == 2
@@ -513,7 +485,6 @@ def test_froidure_pin_min_plus_trunc(checks_for_froidure_pin, checks_for_generat
def test_froidure_pin_ntp(checks_for_froidure_pin, checks_for_generators):
- ReportGuard(False)
gens = [Matrix(MatrixKind.NTP, 5, 7, [[1, 1], [1, 1]])]
assert FroidurePin(gens).size() == 6
diff --git a/tests/test_kambites.py b/tests/test_kambites.py
index af7cac71..d8fb9216 100644
--- a/tests/test_kambites.py
+++ b/tests/test_kambites.py
@@ -12,7 +12,6 @@
POSITIVE_INFINITY,
Kambites,
Presentation,
- ReportGuard,
StringRange,
congruence_kind,
is_obviously_infinite,
@@ -243,7 +242,6 @@ def test_case_006_e():
def test_case_008():
- ReportGuard(False)
p = Presentation("abcdefg")
presentation.add_rule(p, "abcd", "ce")
@@ -275,7 +273,6 @@ def test_case_008():
def test_case_010():
- ReportGuard(False)
p = Presentation("cab")
presentation.add_rule(p, "aabc", "acba")
diff --git a/tests/test_knuth_bendix.py b/tests/test_knuth_bendix.py
index 505dc499..0adef14b 100644
--- a/tests/test_knuth_bendix.py
+++ b/tests/test_knuth_bendix.py
@@ -20,7 +20,6 @@
LibsemigroupsError,
Order,
Presentation,
- ReportGuard,
StringRange,
congruence_kind,
is_obviously_infinite,
@@ -39,7 +38,6 @@ def check_initialisation(*args):
def test_initialisation():
- ReportGuard(False)
kinds = [congruence_kind.twosided, congruence_kind.onesided]
p = Presentation("ba")
@@ -68,7 +66,6 @@ def test_initialisation():
def test_attributes():
- ReportGuard(False)
p = Presentation("abBe")
presentation.add_identity_rules(p, "e")
presentation.add_inverse_rules(p, "aBbe", "e")
@@ -104,7 +101,6 @@ def test_attributes():
def test_operators():
- ReportGuard(False)
p = Presentation("abBe")
presentation.add_identity_rules(p, "e")
presentation.add_inverse_rules(p, "aBbe", "e")
@@ -133,8 +129,6 @@ def test_operators():
def test_running_state():
- ReportGuard(False)
-
p = Presentation("abce")
presentation.add_identity_rules(p, "e")
presentation.add_rule(p, "aa", "e")
diff --git a/tests/test_konieczny.py b/tests/test_konieczny.py
index 154c8720..c90c0885 100644
--- a/tests/test_konieczny.py
+++ b/tests/test_konieczny.py
@@ -20,7 +20,6 @@
Matrix,
MatrixKind,
PPerm,
- ReportGuard,
Transf,
)
@@ -39,7 +38,6 @@ def BMat(x):
def test_case_031():
"""transformations"""
- ReportGuard(False)
k = Konieczny([Transf([1, 0, 2, 3, 4]), Transf([1, 2, 3, 4, 0]), Transf([0, 0, 2, 3, 4])])
assert k.size() == 3125
@@ -56,7 +54,7 @@ def test_case_031():
def test_case_032():
"""transformations - JDM favourite example"""
- ReportGuard(False)
+
S = Konieczny(
[
Transf([1, 7, 2, 6, 0, 4, 1, 5]),
@@ -77,7 +75,7 @@ def test_case_032():
def test_case_033():
"""transformations - large example"""
- ReportGuard(False)
+
gens = [
Transf([2, 1, 0, 4, 2, 1, 1, 8, 0]),
Transf([1, 7, 6, 2, 5, 1, 1, 4, 3]),
@@ -104,7 +102,6 @@ def test_case_033():
def test_case_034():
- ReportGuard(False)
S = Konieczny(
[
Transf([2, 1, 0, 4, 2, 1, 1, 8, 0]),
@@ -120,7 +117,6 @@ def test_case_034():
def test_case_035():
"""transformations - large example with run_until"""
- ReportGuard(False)
S = Konieczny(
[
@@ -141,7 +137,7 @@ def test_case_035():
def test_case_038():
"""transformations: contains"""
- ReportGuard(False)
+
S = Konieczny([Transf([1, 0, 2, 3, 4]), Transf([1, 2, 3, 4, 0]), Transf([0, 0, 2, 3, 4])])
assert S.contains(Transf([1, 0, 2, 3, 4]))
assert S.contains(Transf([1, 2, 3, 4, 0]))
@@ -177,8 +173,6 @@ def test_case_039():
"""transformations Hall monoid 5 (only the first couple of generators so that
the test runs in short amount of time)"""
- ReportGuard(False)
-
K = Konieczny(
[
Transf(
@@ -257,7 +251,6 @@ def test_case_039():
def test_case_040():
- ReportGuard(False)
S = Konieczny(
[
Transf([2, 1, 0, 4, 2, 1, 1, 8, 0]),
@@ -275,7 +268,7 @@ def test_case_040():
def test_case_041():
"""current_number_D_classes"""
- ReportGuard(False)
+
S = Konieczny(
[
Transf([2, 1, 0, 4, 2, 1, 1, 8, 0]),
@@ -294,7 +287,6 @@ def test_case_041():
def check_case_000(Mat):
- ReportGuard(False)
gens = [
Mat([[0, 1, 0, 1], [1, 0, 0, 0], [0, 1, 1, 1], [0, 1, 1, 0]]),
Mat([[0, 1, 1, 1], [1, 1, 0, 0], [0, 0, 0, 0], [1, 1, 1, 1]]),
@@ -310,7 +302,6 @@ def test_case_000():
def check_case_001(Mat):
- ReportGuard(False)
gens = [
Mat([[1, 0, 0, 0], [0, 0, 1, 0], [1, 0, 0, 1], [0, 1, 0, 0]]),
Mat([[1, 0, 0, 1], [1, 0, 0, 1], [1, 1, 1, 1], [0, 1, 1, 0]]),
@@ -329,7 +320,6 @@ def test_case_001():
def check_case_003(Mat):
- ReportGuard(False)
gens = [
Mat([[0, 1, 1, 1, 0], [0, 0, 1, 0, 0], [1, 0, 0, 1, 0], [1, 1, 1, 0, 0], [0, 1, 1, 1, 1]]),
Mat([[0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 1, 0, 1, 1]]),
@@ -348,7 +338,7 @@ def test_case_003():
def test_case_028():
"""partial perm"""
- ReportGuard(False)
+
gens = [
PPerm([0, 2, 3, 7], [1, 6, 7, 3], 9),
PPerm([0, 1, 2, 3, 4, 7], [6, 5, 8, 0, 2, 1], 9),
@@ -370,7 +360,7 @@ def test_case_028():
def test_case_029():
"""symmetric inverse monoid n = 8"""
- ReportGuard(False)
+
S = Konieczny(
[
PPerm([0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], 8),
@@ -386,7 +376,7 @@ def test_case_029():
def test_konieczny_init():
"""symmetric inverse monoid n = 7"""
- ReportGuard(False)
+
S = Konieczny(
[
PPerm([0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], 8),
@@ -405,7 +395,6 @@ def test_konieczny_init():
def test_case_030():
"""exceptions"""
- ReportGuard(False)
gens = [
PPerm([0, 2, 3, 7], [1, 6, 7, 3], 9),
@@ -454,7 +443,6 @@ def test_konieczny_hpcombi_ptranf16():
def test_froidure_pin_max_plus_trunc():
- ReportGuard(False)
K = Konieczny(Matrix(MatrixKind.MaxPlusTrunc, 11, [[1, 0], [0, 1]]))
assert K.size() == 12
assert K.number_of_idempotents() == 1
diff --git a/tests/test_obvinf.py b/tests/test_obvinf.py
index dedfe68a..4429e116 100644
--- a/tests/test_obvinf.py
+++ b/tests/test_obvinf.py
@@ -11,7 +11,6 @@
from libsemigroups_pybind11 import (
KnuthBendix,
Presentation,
- ReportGuard,
congruence_kind,
is_obviously_infinite,
presentation,
@@ -40,8 +39,6 @@ def test_is_obviously_infinite_presentation():
def test_is_obviously_infinite_knuth_bendix():
- ReportGuard(False)
-
p = Presentation("abABe")
p.contains_empty_word(True)
presentation.add_identity_rules(p, "e")
diff --git a/tests/test_presentation_examples.py b/tests/test_presentation_examples.py
index c9321190..eac08925 100644
--- a/tests/test_presentation_examples.py
+++ b/tests/test_presentation_examples.py
@@ -17,7 +17,6 @@
POSITIVE_INFINITY,
LibsemigroupsError,
Presentation,
- ReportGuard,
ToddCoxeter,
congruence_kind,
)
@@ -25,7 +24,6 @@
def check_symmetric_group(min_n, max_n, symmetric_group_implementation):
- ReportGuard(False)
with pytest.raises(RuntimeError):
symmetric_group_implementation(min_n - 1)
for i in range(min_n, max_n):
@@ -36,7 +34,6 @@ def check_symmetric_group(min_n, max_n, symmetric_group_implementation):
def check_full_transformation_monoid(ns, ftm_implementation):
- ReportGuard(False)
with pytest.raises(RuntimeError):
ftm_implementation(ns[0] - 1)
for n in ns:
@@ -47,7 +44,6 @@ def check_full_transformation_monoid(ns, ftm_implementation):
def check_symmetric_inverse_monoid(sim_implementation):
- ReportGuard(False)
n = 5
p = sim_implementation(n)
p.throw_if_bad_alphabet_or_rules()
@@ -63,8 +59,6 @@ def test_semigroup_status():
def test_monoid_status():
- ReportGuard(False)
-
assert examples.alternating_group_Moo97(5).contains_empty_word()
assert examples.brauer_monoid_KM07(5).contains_empty_word()
assert examples.catalan_monoid(5).contains_empty_word()
@@ -136,7 +130,6 @@ def test_symmetric_group_Moo97_b():
def test_alternating_group_Moo97():
- ReportGuard(False)
min_n = 4
max_n = 9
with pytest.raises(LibsemigroupsError):
@@ -165,7 +158,6 @@ def test_full_transformation_monoid():
def test_catalan_monoid():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.catalan_monoid(0)
@@ -178,7 +170,6 @@ def test_catalan_monoid():
def test_partial_transformation_monoid_Shu60():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.partial_transformation_monoid_Shu60(3)
@@ -191,7 +182,6 @@ def test_partial_transformation_monoid_Shu60():
def test_partial_transformation_monoid_MW24():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.partial_transformation_monoid_MW24(1)
@@ -216,7 +206,6 @@ def test_symmetric_inverse_monoid_MW24():
def test_dual_symmetric_inverse_monoid_EEF07():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.dual_symmetric_inverse_monoid_EEF07(2)
@@ -227,7 +216,6 @@ def test_dual_symmetric_inverse_monoid_EEF07():
def test_uniform_block_bijection_monoid_Fit03():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.uniform_block_bijection_monoid_Fit03(2)
@@ -237,7 +225,6 @@ def test_uniform_block_bijection_monoid_Fit03():
def test_partition_monoid_Eas11():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.partition_monoid_Eas11(3)
@@ -247,7 +234,6 @@ def test_partition_monoid_Eas11():
def test_partition_monoid_HR05():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.partition_monoid_HR05(0)
@@ -257,7 +243,6 @@ def test_partition_monoid_HR05():
def test_brauer_monoid_KM07():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.brauer_monoid_KM07(0)
@@ -267,7 +252,6 @@ def test_brauer_monoid_KM07():
def test_rectangular_band_ACOR00():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.rectangular_band_ACOR00(1, 0)
@@ -284,7 +268,6 @@ def test_rectangular_band_ACOR00():
def test_stellar_monoid_GH19():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.stellar_monoid_GH19(0)
@@ -299,7 +282,6 @@ def test_stellar_monoid_GH19():
def test_chinese_monoid_CEKNH01():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.chinese_monoid_CEKNH01(0)
@@ -315,7 +297,6 @@ def test_chinese_monoid_CEKNH01():
def test_monogenic_semigroup():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.monogenic_semigroup(4, 0)
@@ -328,7 +309,6 @@ def test_monogenic_semigroup():
def test_plactic_monoid_Knu70():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.plactic_monoid_Knu70(0)
@@ -343,7 +323,6 @@ def test_plactic_monoid_Knu70():
def test_stylic_monoid_AR22():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.stylic_monoid_AR22(0)
@@ -359,7 +338,6 @@ def test_stylic_monoid_AR22():
def test_fibonacci_semigroup_CRRT94():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.fibonacci_semigroup_CRRT94(0, 1)
@@ -375,7 +353,6 @@ def test_fibonacci_semigroup_CRRT94():
def test_temperley_lieb_monoid_Eas21():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.temperley_lieb_monoid_Eas21(0)
@@ -391,7 +368,6 @@ def test_temperley_lieb_monoid_Eas21():
def test_singular_brauer_monoid_MM07():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.singular_brauer_monoid_MM07(0)
@@ -407,7 +383,6 @@ def test_singular_brauer_monoid_MM07():
def test_orientation_preserving_monoid_AR00():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.orientation_preserving_monoid_AR00(0)
@@ -423,7 +398,6 @@ def test_orientation_preserving_monoid_AR00():
def test_orientation_preserving_reversing_monoid_AR00():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.orientation_preserving_reversing_monoid_AR00(0)
@@ -439,7 +413,6 @@ def test_orientation_preserving_reversing_monoid_AR00():
def test_abacus_jones():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.abacus_jones_monoid(0, 1)
with pytest.raises(LibsemigroupsError):
@@ -461,7 +434,6 @@ def test_abacus_jones():
def test_braid_group():
- ReportGuard(False)
with pytest.raises(LibsemigroupsError):
examples.braid_group(0)
with pytest.raises(LibsemigroupsError):
diff --git a/tests/test_schreier_sims.py b/tests/test_schreier_sims.py
index a6e943e9..1563551b 100644
--- a/tests/test_schreier_sims.py
+++ b/tests/test_schreier_sims.py
@@ -16,12 +16,11 @@
import pytest
-from libsemigroups_pybind11 import LibsemigroupsError, Perm, ReportGuard, SchreierSims
+from libsemigroups_pybind11 import LibsemigroupsError, Perm, SchreierSims
from libsemigroups_pybind11.schreier_sims import intersection
def check_constructors(gens):
- ReportGuard(False)
# default constructor
with pytest.raises(TypeError):
SchreierSims()
@@ -38,7 +37,6 @@ def check_constructors(gens):
def check_generators(gens):
- ReportGuard(False)
S = SchreierSims(gens)
for i, gen in enumerate(gens):
assert S.generator(i) == gen
@@ -56,7 +54,6 @@ def check_generators(gens):
def check_empty(gens):
- ReportGuard(False)
S = SchreierSims(gens)
assert not S.empty()
S.init()
@@ -64,7 +61,6 @@ def check_empty(gens):
def check_finished(gens):
- ReportGuard(False)
S = SchreierSims(gens)
assert not S.finished()
S.run()
@@ -78,7 +74,6 @@ def check_one(n):
def check_elements(n):
- ReportGuard(False)
S = SchreierSims([Perm(range(n))])
S.add_base_point(0)
@@ -329,7 +324,6 @@ def check_elements(n):
def check_sift(gens):
- ReportGuard(False)
S = SchreierSims(gens)
S.run()
for i, gen in enumerate(gens):
@@ -338,7 +332,6 @@ def check_sift(gens):
def check_sift_inplace(gens):
- ReportGuard(False)
S = SchreierSims(gens)
one = S.one()
S.run()
@@ -348,7 +341,6 @@ def check_sift_inplace(gens):
def check_intersection(n):
- ReportGuard(False)
gens_S = [
Perm([1, 3, 7, 5, 2, 0, 4, 6] + list(range(8, n))),
Perm([2, 4, 3, 6, 5, 7, 0, 1] + list(range(8, n))),
@@ -370,7 +362,6 @@ def check_intersection(n):
def check_SchreierSims_001(n):
- ReportGuard(False)
S = SchreierSims([Perm(range(n))])
S.init()
assert S.size() == 1
diff --git a/tests/test_sims.py b/tests/test_sims.py
index 6344ebf9..e8b36623 100644
--- a/tests/test_sims.py
+++ b/tests/test_sims.py
@@ -22,7 +22,6 @@
Order,
Presentation,
RepOrc,
- ReportGuard,
Sims1,
Sims2,
SimsRefinerFaithful,
@@ -77,7 +76,6 @@ def check_meets_and_joins(_):
@pytest.mark.quick
def test_sims1_000():
"""fp example 1"""
- ReportGuard(False)
p = Presentation([0, 1])
p.contains_empty_word(True)
@@ -144,7 +142,7 @@ def test_sims1_000():
@pytest.mark.quick
def test_sims1_001():
"""fp example 2"""
- ReportGuard(False)
+
p = Presentation([0, 1, 2])
p.contains_empty_word(True)
@@ -186,7 +184,7 @@ def test_sims1_001():
@pytest.mark.quick
def test_sims1_002():
"""ToddCoxeter failing example (word_type)"""
- ReportGuard(False)
+
p = Presentation([0, 1, 2, 3, 4, 5, 6])
p.contains_empty_word(False)
@@ -272,7 +270,7 @@ def test_sims1_002():
@pytest.mark.quick
def test_sims1_003():
"""ToddCoxeter failing example (std::string)"""
- ReportGuard(False)
+
p = Presentation("aAbBcCe")
p.contains_empty_word(False)
@@ -290,7 +288,7 @@ def test_sims1_003():
@pytest.mark.quick
def test_sims1_004():
"""partition_monoid(2) right"""
- ReportGuard(False)
+
p = Presentation([0, 1, 2, 3])
p.contains_empty_word(False)
@@ -336,7 +334,6 @@ def test_sims1_004():
@pytest.mark.quick
def test_sims_refiner_faithful_128():
- ReportGuard(True)
p = Presentation([0, 1])
p.contains_empty_word(True)
presentation.add_rule(p, [0, 0, 0], [0])
@@ -364,7 +361,6 @@ def test_sims_refiner_faithful_128():
def test_sims1_901():
- ReportGuard(False)
p = Presentation(list(range(4)))
presentation.add_rule(p, [1, 2, 1], [1, 1])
presentation.add_rule(p, [3, 3], [1, 1])
@@ -381,7 +377,6 @@ def test_sims1_901():
def test_sims1_902():
- ReportGuard(False)
p = Presentation("abcd")
presentation.add_rule(p, "bcb", "bb")
presentation.add_rule(p, "dd", "bb")
@@ -398,7 +393,6 @@ def test_sims1_902():
def test_sims2_901():
- ReportGuard(False)
p = Presentation([0, 1])
presentation.add_rule(p, [0, 1], [1, 0])
@@ -422,7 +416,6 @@ def test_sims2_901():
def test_sims2_902():
- ReportGuard(False)
p = Presentation("ab")
presentation.add_rule(p, "ab", "ba")
diff --git a/tests/test_stephen.py b/tests/test_stephen.py
index 5a76dd45..ae6d4cba 100644
--- a/tests/test_stephen.py
+++ b/tests/test_stephen.py
@@ -21,7 +21,6 @@
InversePresentation,
LibsemigroupsError,
Presentation,
- ReportGuard,
Stephen,
ToddCoxeter,
ToWord,
@@ -110,7 +109,7 @@ def verify_c4_not_equal_to(p, word1, word2):
@pytest.mark.quick
def test_stephen_000():
"""basic test 1"""
- ReportGuard(False)
+
p = Presentation([0, 1])
presentation.add_rule(p, [0], [0, 1])
s = Stephen(p)
@@ -122,7 +121,7 @@ def test_stephen_000():
@pytest.mark.quick
def test_stephen_001():
"""basic test 2"""
- ReportGuard(False)
+
p = Presentation([0, 1])
presentation.add_rule(p, [0, 0, 0], [0])
presentation.add_rule(p, [1, 1, 1], [1])
@@ -188,7 +187,7 @@ def test_stephen_001():
@pytest.mark.quick
def test_stephen_002():
"""full transf monoid"""
- ReportGuard(False)
+
n = 5
p = examples.full_transformation_monoid_II74(n)
@@ -325,7 +324,7 @@ def test_stephen_002():
@pytest.mark.quick
def test_stephen_003():
"""from step_hen 002"""
- ReportGuard(False)
+
to_word = ToWord("ab")
p = Presentation(to_word("ab"))
presentation.add_rule(p, to_word("aaa"), to_word("a"))
@@ -354,7 +353,7 @@ def test_stephen_003():
@pytest.mark.quick
def test_stephen_003_str():
"""from step_hen 002"""
- ReportGuard(False)
+
p = Presentation("ab")
presentation.add_rule(p, "aaa", "a")
presentation.add_rule(p, "bbb", "b")
@@ -382,7 +381,7 @@ def test_stephen_003_str():
@pytest.mark.quick
def test_stephen_004():
"""from step_hen 003"""
- ReportGuard(False)
+
to_word = ToWord("abcdefg")
p = Presentation(to_word("abcdefg"))
presentation.add_rule(p, to_word("aaaeaa"), to_word("abcd"))
@@ -447,7 +446,7 @@ def test_stephen_004():
@pytest.mark.quick
def test_stephen_005():
"""from step_hen 004"""
- ReportGuard(False)
+
to_word = ToWord("abc")
p = Presentation(to_word("abc"))
presentation.add_rule(p, to_word("ab"), to_word("ba"))
@@ -482,7 +481,7 @@ def test_stephen_005():
@pytest.mark.quick
def test_stephen_005_str():
"""from step_hen 004"""
- ReportGuard(False)
+
p = Presentation("abc")
presentation.add_rule(p, "ab", "ba")
presentation.add_rule(p, "ac", "cc")
@@ -516,7 +515,7 @@ def test_stephen_005_str():
@pytest.mark.quick
def test_stephen_006():
"""from step_hen 005"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("bb"), to_word("c"))
@@ -543,7 +542,7 @@ def test_stephen_006():
# def test_stephen_007():
# """Fibonacci(4, 6)"""
# # [stephen][extreme]") {
-# ReportGuard(False);
+
# S = Stephen(examples.fibonacci_semigroup(4, 6))
# S.set_word([0, 1, 2, 3]).run_for(timedelta(seconds=10))
# assert not S.finished()
@@ -552,7 +551,7 @@ def test_stephen_006():
@pytest.mark.quick
def test_stephen_008():
"""C(4) monoid normal form (test_case_knuth_bendix_055)"""
- ReportGuard(False)
+
to_word = ToWord("abcdefg")
p = Presentation(to_word("abcdefg"))
presentation.add_rule(p, to_word("abcd"), to_word("ce"))
@@ -614,7 +613,7 @@ def test_stephen_008():
def test_Stephen_009():
"""C(4) monoid normal form (test_case_gap_smalloverlap_85)"""
# [stephen][quick]") {
- ReportGuard(False)
+
to_word = ToWord("abc")
p = Presentation(to_word("cab"))
presentation.add_rule(p, to_word("aabc"), to_word("acba"))
@@ -639,7 +638,7 @@ def test_Stephen_009():
@pytest.mark.quick
def test_stephen_010():
"""code coverage"""
- ReportGuard(False)
+
to_word = ToWord("abcdefg")
p = Presentation([])
# TODO(2): Once we have make check that this error is thrown
@@ -683,7 +682,7 @@ def test_stephen_010():
@pytest.mark.quick
def test_Stephen_011():
"""C(4) monoid normal form (test_case_gap_smalloverlap_49)"""
- ReportGuard(False)
+
to_word = ToWord("abcdefgh")
p = Presentation(to_word("abcdefgh"))
@@ -704,7 +703,7 @@ def test_Stephen_011():
@pytest.mark.quick
def test_Stephen_012():
"""C(4) monoid normal form (test_case_gap_smalloverlap_63)"""
- ReportGuard(False)
+
to_word = ToWord("abcdefgh")
p = Presentation(to_word("abcdefgh"))
@@ -718,7 +717,7 @@ def test_Stephen_012():
@pytest.mark.quick
def test_Stephen_013():
"""C(4) monoid equal to (test_case_gap_smalloverlap_70)"""
- ReportGuard(False)
+
to_word = ToWord("abcdefghij")
p = Presentation(to_word("abcdefghij"))
@@ -733,7 +732,7 @@ def test_Stephen_013():
@pytest.mark.quick
def test_stephen_014():
"""C(4) monoid normal form (test_case_ex_3_13_14)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("abbba"), to_word("cdc"))
@@ -748,7 +747,7 @@ def test_stephen_014():
@pytest.mark.quick
def test_stephen_015():
"""C(4) monoid normal form (test_case_ex_3_15)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("aabc"), to_word("acba"))
@@ -769,7 +768,7 @@ def test_stephen_015():
@pytest.mark.quick
def test_stephen_016():
"""C(4) monoid normal form (test_case_ex_3_16)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("abcd"), to_word("acca"))
@@ -786,7 +785,7 @@ def test_stephen_016():
@pytest.mark.quick
def test_stephen_017():
"""C(4) monoid normal form (test_case_mt_3)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("abcd"), to_word("accca"))
@@ -798,7 +797,7 @@ def test_stephen_017():
@pytest.mark.quick
def test_stephen_018():
"""C(4) monoid normal form (test_case_mt_5)"""
- ReportGuard(False)
+
to_word = ToWord("abc")
p = Presentation(to_word("abc"))
presentation.add_rule(p, to_word("ac"), to_word("cbbbbc"))
@@ -810,7 +809,7 @@ def test_stephen_018():
@pytest.mark.quick
def test_stephen_019():
"""C(4) monoid normal form (test_case_mt_6)"""
- ReportGuard(False)
+
to_word = ToWord("abc")
p = Presentation(to_word("abc"))
presentation.add_rule(p, to_word("ccab"), to_word("cbac"))
@@ -824,7 +823,7 @@ def test_stephen_019():
@pytest.mark.quick
def test_stephen_020():
"""C(4) monoid normal form (test_case_mt_10)"""
- ReportGuard(False)
+
to_word = ToWord("abcdefghij")
p = Presentation(to_word("abcdefghij"))
presentation.add_rule(p, to_word("afh"), to_word("bgh"))
@@ -838,7 +837,7 @@ def test_stephen_020():
@pytest.mark.quick
def test_stephen_021():
"""C(4) monoid normal form (test_case_mt_13)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("abcd"), to_word("dcba"))
@@ -850,7 +849,7 @@ def test_stephen_021():
@pytest.mark.quick
def test_stephen_022():
"""C(4) monoid normal form (test_case_mt_14)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("abca"), to_word("dcbd"))
@@ -862,7 +861,7 @@ def test_stephen_022():
@pytest.mark.quick
def test_stephen_023():
"""C(4) monoid normal form (test_case_mt_15)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("abcd"), to_word("dcba"))
@@ -875,7 +874,7 @@ def test_stephen_023():
@pytest.mark.quick
def test_stephen_024():
"""C(4) monoid normal form (test_case_mt_16)"""
- ReportGuard(False)
+
to_word = ToWord("abcdefg")
p = Presentation(to_word("abcdefg"))
presentation.add_rule(p, to_word("abcd"), to_word("acca"))
@@ -888,7 +887,7 @@ def test_stephen_024():
@pytest.mark.quick
def test_stephen_025():
"""C(4) monoid normal form (test_case_mt_17)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("ababbabbbabbbb"), to_word("abbbbbabbbbbbabbbbbbbabbbbbbbb"))
@@ -905,7 +904,7 @@ def test_stephen_025():
@pytest.mark.quick
def test_stephen_026():
"""C(4) monoid normal form (test_case_weak_1)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("acba"), to_word("aabc"))
@@ -924,7 +923,7 @@ def test_stephen_026():
@pytest.mark.quick
def test_stephen_027():
"""C(4) monoid normal form (test_case_weak_2)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("acba"), to_word("aabc"))
@@ -938,7 +937,7 @@ def test_stephen_027():
@pytest.mark.quick
def test_stephen_028():
"""C(4) monoid normal form (test_case_weak_3)"""
- ReportGuard(False)
+
to_word = ToWord("abcde")
p = Presentation(to_word("abcde"))
presentation.add_rule(p, to_word("bceac"), to_word("aeebbc"))
@@ -950,7 +949,7 @@ def test_stephen_028():
@pytest.mark.quick
def test_stephen_029():
"""C(4) monoid normal form (test_case_weak_4)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("acba"), to_word("aabc"))
@@ -963,7 +962,7 @@ def test_stephen_029():
@pytest.mark.quick
def test_stephen_030():
"""C(4) monoid normal form (test_case_weak_5)"""
- ReportGuard(False)
+
to_word = ToWord("abcd")
p = Presentation(to_word("abcd"))
presentation.add_rule(p, to_word("acba"), to_word("aabc"))
@@ -975,7 +974,7 @@ def test_stephen_030():
@pytest.mark.quick
def test_stephen_031():
"""Test behaviour when uninitialised"""
- ReportGuard(False)
+
p = Presentation([])
with pytest.raises(LibsemigroupsError):
@@ -1012,7 +1011,7 @@ def test_stephen_031():
@pytest.mark.quick
def test_Stephen_034():
"""(inverse) step_hen test_schutzenbergergraph 001 (string)"""
- ReportGuard(False)
+
to_word = ToWord("abcABC")
p = InversePresentation(to_word("abcABC"))
@@ -1037,7 +1036,7 @@ def test_Stephen_034():
@pytest.mark.quick
def test_Stephen_035():
"""(inverse) step_hen test_schutzenbergergraph 001"""
- ReportGuard(False)
+
to_word = ToWord("abcABC")
p = InversePresentation(to_word("abcABC"))
p.inverses(to_word("ABCabc"))
@@ -1062,7 +1061,7 @@ def test_Stephen_035():
@pytest.mark.quick
def test_Stephen_036():
"""(inverse) step_hen test_schutzenbergergraph 002"""
- ReportGuard(False)
+
to_word = ToWord("abcABC")
p = InversePresentation(to_word("abcABC"))
p.inverses(to_word("ABCabc"))
@@ -1078,7 +1077,7 @@ def test_Stephen_036():
@pytest.mark.quick
def test_Stephen_037():
"""(inverse) step_hen test_schutzenbergergraph 003"""
- ReportGuard(False)
+
to_word = ToWord("xyXY")
p = InversePresentation(to_word("xyXY"))
p.inverses(to_word("XYxy"))
@@ -1095,7 +1094,7 @@ def test_Stephen_037():
@pytest.mark.quick
def test_Stephen_038():
"""(inverse) step_hen test_schutzenbergergraph 004"""
- ReportGuard(False)
+
to_word = ToWord("xyXY")
p = InversePresentation(to_word("xyXY"))
p.inverses(to_word("XYxy"))
@@ -1132,7 +1131,7 @@ def test_Stephen_038():
@pytest.mark.quick
def test_Stephen_039():
"""(inverse) step_hen test_schutzenbergergraph 005"""
- ReportGuard(False)
+
to_word = ToWord("xyXY")
p = InversePresentation(to_word("xyXY"))
p.inverses(to_word("XYxy"))
@@ -1150,7 +1149,7 @@ def test_Stephen_039():
@pytest.mark.quick
def test_Stephen_040():
"""(inverse) step_hen test_schutzenbergergraph 006"""
- ReportGuard(False)
+
to_word = ToWord("abcABC")
p = InversePresentation(to_word("abcABC"))
p.inverses(to_word("ABCabc"))
@@ -1179,7 +1178,7 @@ def test_Stephen_040():
@pytest.mark.quick
def test_stephen_041():
"""corner case"""
- ReportGuard(False)
+
to_word = ToWord("x")
p = Presentation([])
@@ -1199,7 +1198,7 @@ def test_stephen_041():
@pytest.mark.quick
def test_stephen_042():
"""empty word"""
- ReportGuard(False)
+
p = examples.symmetric_inverse_monoid(4)
assert p.contains_empty_word()
assert len(p.alphabet()) == 4
@@ -1220,7 +1219,7 @@ def test_stephen_042():
@pytest.mark.quick
def test_stephen_043():
"""shared_ptr"""
- ReportGuard(False)
+
to_word = ToWord("abcABC")
p = InversePresentation(to_word("abcABC"))
p.inverses(to_word("ABCabc"))
@@ -1249,7 +1248,7 @@ def test_stephen_043():
@pytest.mark.quick
def test_stephen_044():
"""inverse presentation -- operator=="""
- ReportGuard(False)
+
tc = ToddCoxeter(word=list[int])
p = examples.symmetric_inverse_monoid(4)
@@ -1277,7 +1276,7 @@ def test_stephen_044():
@pytest.mark.quick
def test_stephen_046():
"""non-inverse presentation -- operator=="""
- ReportGuard(False)
+
p = examples.symmetric_inverse_monoid(4)
tc = ToddCoxeter(congruence_kind.twosided, p)
@@ -1299,7 +1298,7 @@ def test_stephen_046():
@pytest.mark.quick
def test_stephen_032():
"""Plactic monoid"""
- ReportGuard(False)
+
p = examples.plactic_monoid(4)
p.contains_empty_word(True)
s = Stephen(p)
@@ -1311,7 +1310,7 @@ def test_stephen_032():
# @pytest.mark.fail
# def test_stephen_033():
# """Whyte's 4-relation full transf monoid 8"""
-# rg = ReportGuard(True);
+
# p = Presentation([])
# p.rules = [
# [0, 0],
@@ -1443,7 +1442,7 @@ def test_stephen_032():
@pytest.mark.quick
def test_stephen_045():
"""Munn tree products"""
- ReportGuard(False)
+
to_word = ToWord("abcABC")
p = InversePresentation(to_word("abcABC"))
@@ -1488,7 +1487,7 @@ def test_stephen_045():
@pytest.mark.quick
def test_stephen_048():
"""chinese monoid"""
- ReportGuard(False)
+
p = examples.chinese_monoid(3)
S = Stephen(p)
@@ -1500,7 +1499,7 @@ def test_stephen_048():
@pytest.mark.quick
def test_stephen_049():
"""to_human_readable_repr"""
- ReportGuard(False)
+
p = Presentation([0, 1])
p.contains_empty_word(True)
presentation.add_rule(p, [0, 0, 0], [1, 1])
@@ -1572,7 +1571,6 @@ def test_stephen_049():
@pytest.mark.quick
def test_stephen_051():
"""Incomplete Munn tree products"""
- ReportGuard(False)
p = InversePresentation("abcABC")
p.inverses("ABCabc")
@@ -1602,8 +1600,6 @@ def test_stephen_051():
@pytest.mark.quick
def test_stephen_return_policy():
- ReportGuard(False)
-
p = InversePresentation("abcABC")
p.inverses("ABCabc")
diff --git a/tests/test_to.py b/tests/test_to.py
index 8fd2d966..ba9f1ad1 100644
--- a/tests/test_to.py
+++ b/tests/test_to.py
@@ -37,7 +37,6 @@
KnuthBendix,
Order,
Presentation,
- ReportGuard,
Stephen,
ToddCoxeter,
Transf,
@@ -48,8 +47,6 @@
)
from libsemigroups_pybind11.detail.cxx_wrapper import to_cxx
-ReportGuard(False)
-
###############################################################################
# Helper functions
###############################################################################
diff --git a/tests/test_todd_coxeter.py b/tests/test_todd_coxeter.py
index 1a9a5296..2c9d74cb 100644
--- a/tests/test_todd_coxeter.py
+++ b/tests/test_todd_coxeter.py
@@ -18,7 +18,6 @@
FroidurePin,
Order,
Presentation,
- ReportGuard,
ToddCoxeter,
Transf,
WordRange,
@@ -64,7 +63,6 @@ def test_constructors():
def test_attributes():
- ReportGuard(False)
p = Presentation([0])
presentation.add_rule(p, [0, 0, 0, 0, 0, 0], [0, 0, 0])
tc = ToddCoxeter(congruence_kind.onesided, p)
@@ -102,7 +100,6 @@ def test_attributes():
def test_operators():
- ReportGuard(False)
p = Presentation([0, 1])
presentation.add_rule(p, [0, 0, 0, 0], [1])
presentation.add_rule(p, [1, 1, 1, 1], [1])
@@ -133,7 +130,6 @@ def test_operators():
def test_settings():
- ReportGuard(False)
p = Presentation([0])
presentation.add_rule(p, [0, 0, 0, 0], [0, 0])
tc = ToddCoxeter(congruence_kind.onesided, p)
@@ -188,7 +184,6 @@ def test_settings():
def test_000_iterators():
- ReportGuard(False)
p = Presentation([0, 1])
presentation.add_rule(p, [0, 0, 0, 0], [0])
presentation.add_rule(p, [1, 1, 1, 1], [1])
@@ -237,7 +232,6 @@ def test_000_iterators():
def test_020():
- ReportGuard(False)
p = Presentation([0])
tc = ToddCoxeter(congruence_kind.twosided, p)
tc.strategy(strategy.hlt)
@@ -246,7 +240,6 @@ def test_020():
def test_021():
- ReportGuard(False)
p = Presentation([0, 1, 2, 3, 4])
tc = ToddCoxeter(congruence_kind.twosided, p)
with pytest.raises(RuntimeError):
@@ -254,7 +247,6 @@ def test_021():
def test_033():
- ReportGuard(False)
p = Presentation([0, 1])
presentation.add_rule(p, [0, 0, 0], [0])
presentation.add_rule(p, [0], [1, 1])
@@ -270,7 +262,6 @@ def test_033():
def test_036():
- ReportGuard(False)
S = FroidurePin(Transf([1, 3, 4, 2, 3]), Transf([3, 2, 1, 3, 3]))
tc = ToddCoxeter(congruence_kind.twosided, S.right_cayley_graph())
tc.add_generating_pair([0], [1])
@@ -287,7 +278,6 @@ def test_036():
def test_096():
- ReportGuard(False)
p = Presentation([0, 1])
presentation.add_rule(p, [0], [1])
presentation.add_rule(p, [0, 0], [0])