diff --git a/src/action.cpp b/src/action.cpp index 0508cf504..6f93f9bab 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -229,11 +229,14 @@ Returns an iterator yielding the generators. :rtype: Iterator[Element] )pbdoc"); - thing.def("position", - &Action_::position, - py::arg("pt"), - R"pbdoc( -:sig=(self: Action, pt: Point) -> int: + thing.def( + "position", + [](Action_& self, const_reference_point_type pt) { + return from_int(self.position(pt)); + }, + py::arg("pt"), + R"pbdoc( +:sig=(self: Action, pt: Point) -> int | Undefined: Returns the position of a point in the so far discovered points. @@ -243,7 +246,7 @@ Returns the position of a point in the so far discovered points. :complexity: Constant. :returns: The index of *pt* in ``self`` or :any:`UNDEFINED`. -:rtype: int +:rtype: int | Undefined )pbdoc"); thing.def("empty", &Action_::empty, diff --git a/src/aho-corasick.cpp b/src/aho-corasick.cpp index ee4eef2ef..981f72017 100644 --- a/src/aho-corasick.cpp +++ b/src/aho-corasick.cpp @@ -86,11 +86,16 @@ Copy a :any:`AhoCorasick` object. thing.def("__copy__", [](AhoCorasick const& self) { return AhoCorasick(self); }); - thing.def("child", - &AhoCorasick::child, - py::arg("parent"), - py::arg("letter"), - R"pbdoc( + thing.def( + "child", + [](AhoCorasick const& self, + AhoCorasick::index_type parent, + letter_type letter) { return from_int(self.child(parent, letter)); }, + py::arg("parent"), + py::arg("letter"), + R"pbdoc( +:sig=(self: AhoCorasick, parent: int, letter: int) -> int | Undefined: + Return the child of *parent* with edge-label *letter* This function returns the index of the child of the node with index @@ -104,14 +109,13 @@ This function returns the index of the child of the node with index :type letter: int :returns: the index of the child. -:rtype: int +:rtype: int | Undefined :raises LibsemigroupsError: if ``throw_if_node_index_not_active(parent)`` throws. :complexity: Constant. .. seealso:: :any:`throw_if_node_index_not_active`. - )pbdoc"); thing.def("height", diff --git a/src/cong-common.cpp b/src/cong-common.cpp index edae932aa..1908a1824 100644 --- a/src/cong-common.cpp +++ b/src/cong-common.cpp @@ -52,8 +52,6 @@ namespace libsemigroups { using KnuthBendixWordRewriteFromLeft = KnuthBendix; - using int_or_pos_infty = std::variant; - //////////////////////////////////////////////////////////////////////// // Implementation helpers //////////////////////////////////////////////////////////////////////// @@ -411,13 +409,7 @@ Copy a :any:`{name}` object. doc extra_doc) { thing.def( "number_of_classes", - [](Thing& self) -> std::variant { - auto result = self.number_of_classes(); - if (result != POSITIVE_INFINITY) { - return {result}; - } - return {POSITIVE_INFINITY}; - }, + [](Thing& self) { return from_int(self.number_of_classes()); }, make_doc(R"pbdoc( :sig=(self: {name}) -> int | PositiveInfinity: {only_document_once} diff --git a/src/constants.cpp b/src/constants.cpp index de1088412..73c2b3bc3 100644 --- a/src/constants.cpp +++ b/src/constants.cpp @@ -43,47 +43,6 @@ namespace libsemigroups { return true; }, py::is_operator()) - .def( - "__eq__", - [](Undefined const& lhop, size_t rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](size_t lhop, Undefined const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](Undefined const& lhop, int rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](int lhop, Undefined const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](Undefined const& lhop, uint64_t rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](uint64_t lhop, Undefined const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__int__", - [](Undefined const& x) -> size_t { return static_cast(x); }) - .def("__chr__", - [](Undefined const& x) -> char { return static_cast(x); }) .def("__hash__", [](Undefined const& op) -> int { return std::hash{}(static_cast(op)); }); @@ -113,46 +72,6 @@ namespace libsemigroups { [](PositiveInfinity const& lhop, NegativeInfinity const& rhop) -> bool { return false; }, py::is_operator()) - .def( - "__eq__", - [](int lhop, PositiveInfinity const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](PositiveInfinity const& lhop, int rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](int64_t lhop, PositiveInfinity const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](PositiveInfinity const& lhop, int64_t rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](uint64_t lhop, PositiveInfinity const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](PositiveInfinity const& lhop, uint64_t rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def("to_int", - [](PositiveInfinity const& x) -> int64_t { - return static_cast(x); - }) .def("__hash__", [](PositiveInfinity const& op) -> int { return std::hash{}(static_cast(op)); }); @@ -177,34 +96,6 @@ namespace libsemigroups { [](NegativeInfinity const& lhop, PositiveInfinity const& rhop) -> bool { return lhop == rhop; }, py::is_operator()) - .def( - "__eq__", - [](int lhop, NegativeInfinity const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](NegativeInfinity const& lhop, int rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](int64_t lhop, NegativeInfinity const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](NegativeInfinity const& lhop, int64_t rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def("to_int", - [](NegativeInfinity const& x) -> int64_t { - return static_cast(x); - }) .def("__hash__", [](NegativeInfinity const& op) -> int { return std::hash{}(static_cast(op)); }); @@ -219,46 +110,6 @@ namespace libsemigroups { .def("__repr__", [](LimitMax const& val) -> std::string { return "LIMIT_MAX"; }) .def(pybind11::self < LimitMax()) - .def(pybind11::self < int()) - .def(int() < pybind11::self) - .def( - "__eq__", - [](int lhop, LimitMax const& rhop) -> bool { return lhop == rhop; }, - py::is_operator()) - .def( - "__eq__", - [](LimitMax const& lhop, int rhop) -> bool { return lhop == rhop; }, - py::is_operator()) - .def( - "__eq__", - [](int64_t lhop, LimitMax const& rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__eq__", - [](LimitMax const& lhop, int64_t rhop) -> bool { - return lhop == rhop; - }, - py::is_operator()) - .def( - "__sub__", - [](LimitMax const& lhs, int rhs) { return lhs - rhs; }, - py::is_operator()) - .def( - "__rsub__", - [](LimitMax const& rhs, int lhs) { return lhs - rhs; }, - py::is_operator()) - .def( - "__sub__", - [](LimitMax const& lhs, int64_t rhs) { return lhs - rhs; }, - py::is_operator()) - .def( - "__rsub__", - [](LimitMax const& rhs, int64_t lhs) { return lhs - rhs; }, - py::is_operator()) - .def("to_int", - [](LimitMax const& x) -> int { return static_cast(x); }) .def("__hash__", [](LimitMax const& op) -> int { return std::hash{}(static_cast(op)); }); diff --git a/src/forest.cpp b/src/forest.cpp index 77d5d7413..c793f03e2 100644 --- a/src/forest.cpp +++ b/src/forest.cpp @@ -24,6 +24,7 @@ // libsemigroups.... #include // for Forest +#include // for rx::to_vector // pybind11.... #include // for py::operator @@ -69,11 +70,11 @@ Constructs a forest with *n* nodes, that is initialised so that the )pbdoc"); thing.def( py::init( - [](std::vector> const& - parents, - std::vector> const& - labels) { - return make(to_ints(parents), to_ints(labels)); + [](std::vector> const& parents, + std::vector> const& labels) { + using node_type = node_type; + return make(to_ints(parents), + to_ints(labels)); }), py::arg("parents"), py::arg("labels"), @@ -141,8 +142,8 @@ the same state as if it had just be constructed as ``Forest(n)``. )pbdoc"); thing.def( "label", - [](Forest const& self, - Forest::node_type i) -> std::variant { + [](Forest const& self, + node_type i) -> int_or_unsigned_constant { if (self.label(i) != UNDEFINED) { return {self.label(i)}; } @@ -173,15 +174,15 @@ Returns the label of the edge from a node to its parent. thing.def( "labels", [](Forest const& self) - -> std::vector> { - std::vector> result; - for (auto node : self.labels()) { - if (node != UNDEFINED) { - result.emplace_back(node); - } else { - result.emplace_back(UNDEFINED); - } - } + -> std::vector> { + auto result + = self.labels() + | rx::transform( + [](auto val) -> int_or_unsigned_constant { + return {val}; + }) + | rx::to_vector(); + from_ints(result); return result; }, R"pbdoc( @@ -218,12 +219,9 @@ in the forest. thing.def(py::self == py::self, py::arg("that")); thing.def( "parent", - [](Forest const& self, - Forest::node_type i) -> std::variant { - if (self.parent(i) != UNDEFINED) { - return {self.parent(i)}; - } - return {UNDEFINED}; + [](Forest const& self, + node_type i) -> int_or_unsigned_constant { + return from_int(self.parent(i)); }, py::arg("i"), R"pbdoc( @@ -249,15 +247,15 @@ Returns the parent of a node. thing.def( "parents", [](Forest const& self) - -> std::vector> { - std::vector> result; - for (auto node : self.parents()) { - if (node != UNDEFINED) { - result.emplace_back(node); - } else { - result.emplace_back(UNDEFINED); - } - } + -> std::vector> { + auto result + = self.parents() + | rx::transform( + [](auto val) -> int_or_unsigned_constant { + return {val}; + }) + | rx::to_vector(); + from_ints(result); return result; }, R"pbdoc( diff --git a/src/froidure-pin.cpp b/src/froidure-pin.cpp index 2e1277e61..a822c3a60 100644 --- a/src/froidure-pin.cpp +++ b/src/froidure-pin.cpp @@ -205,13 +205,8 @@ See :any:`add_generator` for a detailed description. thing.def( "current_position", - [](FroidurePin_ const& self, - Element const& x) -> std::variant { - auto result = self.current_position(x); - if (result != UNDEFINED) { - return {result}; - } - return {UNDEFINED}; + [](FroidurePin_ const& self, Element const& x) { + return from_int(self.current_position(x)); }, py::arg("x").noconvert(), R"pbdoc( @@ -717,13 +712,8 @@ elements are sorted, or :any:`UNDEFINED` if *i* is greater than m.def( "froidure_pin_current_position", - [](FroidurePinBase const& fpb, - word_type const& w) -> std::variant { - auto result = froidure_pin::current_position(fpb, w); - if (result != UNDEFINED) { - return {result}; - } - return {UNDEFINED}; + [](FroidurePinBase const& fpb, word_type const& w) { + return from_int(froidure_pin::current_position(fpb, w)); }, py::arg("fpb"), py::arg("w"), diff --git a/src/kambites.cpp b/src/kambites.cpp index 71657d67d..046b62e1c 100644 --- a/src/kambites.cpp +++ b/src/kambites.cpp @@ -139,13 +139,7 @@ is not at least :math:`4`, then an exception is thrown.)pbdoc"sv; thing.def( "small_overlap_class", - [](Kambites_& self) -> std::variant { - auto result = self.small_overlap_class(); - if (result != POSITIVE_INFINITY) { - return {result}; - } - return {POSITIVE_INFINITY}; - }, + [](Kambites_& self) { return from_int(self.small_overlap_class()); }, R"pbdoc( :sig=(self: Kambites) -> int | PositiveInfinity: diff --git a/src/knuth-bendix-impl.cpp b/src/knuth-bendix-impl.cpp index 10965dbe6..9329c016f 100644 --- a/src/knuth-bendix-impl.cpp +++ b/src/knuth-bendix-impl.cpp @@ -203,11 +203,13 @@ system is already confluent. :rtype: KnuthBendix )pbdoc"); - thing.def("max_overlap", - py::overload_cast<>(&KnuthBendixImpl::max_overlap, - py::const_), - R"pbdoc( -:sig=(self: KnuthBendix) -> int: + thing.def( + "max_overlap", + [](KnuthBendixImpl const& self) { + return from_int(self.max_overlap()); + }, + R"pbdoc( +:sig=(self: KnuthBendix) -> int | PositiveInfinity: Return the maximum length of overlaps to be considered. @@ -215,17 +217,19 @@ This function returns the maximum length of the overlap of two left hand sides of rules that should be considered in :any:`Runner.run`. :return: The maximum overlap length -:rtype: int +:rtype: int | PositiveInfinity .. seealso:: :any:`Runner.run`. )pbdoc"); thing.def( "max_overlap", - py::overload_cast(&KnuthBendixImpl::max_overlap), + [](KnuthBendixImpl& self, int_or_constant val) { + return self.max_overlap(to_int(val)); + }, py::arg("val"), R"pbdoc( -:sig=(self: KnuthBendix) -> KnuthBendix: +:sig=(self: KnuthBendix, val: int | PositiveInfinity) -> KnuthBendix: Set the maximum length of overlaps to be considered. @@ -244,11 +248,13 @@ If this value is less than the longest left hand side of a rule, then .. seealso:: :any:`Runner.run`. )pbdoc"); - thing.def("max_rules", - py::overload_cast<>(&KnuthBendixImpl::max_rules, - py::const_), - R"pbdoc( -:sig=(self: KnuthBendix) -> int: + thing.def( + "max_rules", + [](KnuthBendixImpl const& self) { + return from_int(self.max_rules()); + }, + R"pbdoc( +:sig=(self: KnuthBendix) -> int | PositiveInfinity: Return the maximum number of rules. @@ -258,17 +264,19 @@ or :any:`knuth_bendix.by_overlap_length`, then they will terminate and the system may not be confluent. :return: The maximum number of rules the system should contain. -:rtype: int +:rtype: int | PositiveInfinity .. seealso:: :any:`Runner.run`. )pbdoc"); thing.def( "max_rules", - py::overload_cast(&KnuthBendixImpl::max_rules), + [](KnuthBendixImpl& self, int_or_constant val) { + return self.max_rules(to_int(val)); + }, py::arg("val"), R"pbdoc( -:sig=(self: KnuthBendix) -> KnuthBendix: +:sig=(self: KnuthBendix, val: int | PositiveInfinity) -> KnuthBendix: Set the maximum number of rules. @@ -280,7 +288,7 @@ system may not be confluent. By default this value is :any:`POSITIVE_INFINITY`. :param val: The maximum number of rules. -:type val: int +:type val: int | PositiveInfinity :return: ``self``. :rtype: KnuthBendix diff --git a/src/libsemigroups_pybind11/action.py b/src/libsemigroups_pybind11/action.py index 44d81f656..c3947278d 100644 --- a/src/libsemigroups_pybind11/action.py +++ b/src/libsemigroups_pybind11/action.py @@ -175,7 +175,9 @@ class Action(_CxxWrapper): # pylint: disable=missing-class-docstring ######################################################################## # pylint: disable=redefined-outer-name - def __init__(self: _Self, *args, generators=None, seeds=None, func=None, side=None) -> None: + def __init__( + self: _Self, *args, generators=None, seeds=None, func=None, side=None + ) -> None: """ :sig=(self: Action, generators=None, seeds=None, func=None, side=None) -> None: @@ -207,7 +209,9 @@ def __init__(self: _Self, *args, generators=None, seeds=None, func=None, side=No if _to_cxx(self) is not None: return if len(args) != 0: - raise ValueError(f"expected 0 positional arguments, but found {len(args)}") + raise ValueError( + f"expected 0 positional arguments, but found {len(args)}" + ) if not isinstance(generators, list): raise TypeError( "expected the keyword argument 'generators' to be " @@ -270,7 +274,9 @@ def generators(self: _Self) -> Iterator[Element]: _copy_cxx_mem_fns(_RightActionPPerm1PPerm1, Action) -for _type in ( +for ( + _type +) in ( Action._py_template_params_to_cxx_type.values() # pylint: disable=protected-access ): _register_cxx_wrapped_type(_type, Action) diff --git a/src/libsemigroups_pybind11/congruence.py b/src/libsemigroups_pybind11/congruence.py index 21c534b82..5d71e6f94 100644 --- a/src/libsemigroups_pybind11/congruence.py +++ b/src/libsemigroups_pybind11/congruence.py @@ -71,7 +71,9 @@ def __init__(self: _Self, *args, **kwargs) -> None: ) self.init_cxx_obj(*args) - def get(self: _Self, t: type) -> Union[_Kambites, _KnuthBendix, _ToddCoxeter]: + def get( + self: _Self, t: type + ) -> Union[_Kambites, _KnuthBendix, _ToddCoxeter]: """ :sig=(self: Congruence, t: type) -> Kambites | KnuthBendix | ToddCoxeter: Returns the *t* instance used to compute the congruence (if any). diff --git a/src/libsemigroups_pybind11/knuth_bendix.py b/src/libsemigroups_pybind11/knuth_bendix.py index 6a97392c7..113589aaf 100644 --- a/src/libsemigroups_pybind11/knuth_bendix.py +++ b/src/libsemigroups_pybind11/knuth_bendix.py @@ -89,7 +89,9 @@ def __init__(self, *args, Rewriter="RewriteTrie", **kwargs) -> None: return if len(args) == 2: if isinstance(args[1], _Presentation): - self.py_template_params = args[1].py_template_params + (Rewriter,) + self.py_template_params = args[1].py_template_params + ( + Rewriter, + ) else: raise TypeError( f"expected the 2nd argument to be a Presentation, but found {type(args[1])}" diff --git a/src/libsemigroups_pybind11/matrix.py b/src/libsemigroups_pybind11/matrix.py index 20bb51e82..70d16d696 100644 --- a/src/libsemigroups_pybind11/matrix.py +++ b/src/libsemigroups_pybind11/matrix.py @@ -12,7 +12,6 @@ """ from enum import Enum as _Enum -from typing import Union from _libsemigroups_pybind11 import ( # pylint: disable=no-name-in-module,unused-import BMat as _BMat, @@ -28,9 +27,9 @@ PositiveInfinity as _PositiveInfinity, ProjMaxPlusMat as _ProjMaxPlusMat, matrix_row_space_size as row_space_size, - period, # TODO rename matrix_period - row_basis as _row_basis, # TODO rename matrix_period - threshold, # TODO rename matrix_period + matrix_period as period, + matrix_row_basis as row_basis, + matrix_threshold as threshold, ) @@ -63,97 +62,6 @@ class _MatrixKind(_Enum): } -def _convert_matrix_args(*args): - # TODO remove this, sink into C++ - # Convert POSITIVE_INFINITY and NEGATIVE_INFINITY to integers - if len(args) == 0 or not isinstance(args[-1], list): - return args - return ( - *args[:-1], - [ - [ - (z.to_int() if isinstance(z, (_PositiveInfinity, _NegativeInfinity)) else z) - for z in y - ] - for y in args[-1] - ], - ) - - -def _convert_cxx_entry_to_py( - val: int, -) -> Union[int, _PositiveInfinity, _NegativeInfinity]: - # TODO remove this, sink into C++ - # Convert from integers to _POSITIVE_INFINITY and _NEGATIVE_INFINITY - - if val == _POSITIVE_INFINITY: - return _POSITIVE_INFINITY - if val == _NEGATIVE_INFINITY: - return _NEGATIVE_INFINITY - return val - - -def _convert_cxx_row_to_py( - row: list[int], -) -> list[Union[int, _PositiveInfinity, _NegativeInfinity]]: - # TODO remove this, sink into C++ - for i, val in enumerate(row): - row[i] = _convert_cxx_entry_to_py(val) - return row - - -def _convert_cxx_rows_to_py( - rows: list[int], -) -> list[list[Union[int, _PositiveInfinity, _NegativeInfinity]]]: - # TODO remove this, sink into C++ - for i, val in enumerate(rows): - rows[i] = _convert_cxx_row_to_py(val) - return rows - - -def _at(self, arg): - # pylint: disable=protected-access - if isinstance(arg, tuple) and len(arg) == 2: - return _convert_cxx_entry_to_py(self._at(arg)) - if isinstance(arg, int) and arg >= 0: - return _convert_cxx_row_to_py(self._at(arg)) - raise NotImplementedError - - -def _scalar_zero(self) -> Union[int, _PositiveInfinity, _NegativeInfinity]: - # pylint: disable=protected-access - return _convert_cxx_entry_to_py(self._scalar_zero()) - - -def row_basis(x): - """ - Returns a row space basis of a matrix as a list of lists. The matrix *x* which - must be one of: - - * :any:`MatrixKind.Boolean` - * :any:`MatrixKind.MaxPlusTrunc` - - This function returns a row space basis of the matrix *x* as a list of lists - of rows. - - :param x: the matrix. - :type x: Matrix - - :complexity: - :math:`O(r ^ 2 c)` where :math:`r` is the number of rows in ``x`` - and :math:`c` is the number of columns in ``x``. - - :returns: A basis for the row space of *x*. - :rtype: list[list[int | POSITIVE_INFINITY | NEGATIVE_INFINITY]] - """ - return _convert_cxx_rows_to_py(_row_basis(x)) - - -for _Mat in _MatrixKindToCxxType.values(): - _Mat.__getitem__ = _at - _Mat.scalar_zero = _scalar_zero - - # the underscore prefix stops this from appearing in the doc of the # "matrix" submodule. # TODO could update to use kwargs for threshold and period @@ -163,4 +71,4 @@ def _Matrix(kind: _MatrixKind, *args): # pylint: disable=invalid-name """ if not isinstance(kind, _MatrixKind): raise TypeError("the 1st argument must be a _MatrixKind") - return _MatrixKindToCxxType[kind](*_convert_matrix_args(*args)) + return _MatrixKindToCxxType[kind](*args) diff --git a/src/libsemigroups_pybind11/presentation/__init__.py b/src/libsemigroups_pybind11/presentation/__init__.py index 61f79a8b9..2ab15e11d 100644 --- a/src/libsemigroups_pybind11/presentation/__init__.py +++ b/src/libsemigroups_pybind11/presentation/__init__.py @@ -14,7 +14,6 @@ from typing_extensions import Self from _libsemigroups_pybind11 import ( # pylint: disable=no-name-in-module - # TODO(0) balance? InversePresentationString as _InversePresentationString, InversePresentationWord as _InversePresentationWord, PresentationString as _PresentationString, diff --git a/src/libsemigroups_pybind11/sims.py b/src/libsemigroups_pybind11/sims.py index a86ccc8f9..a3b28511c 100644 --- a/src/libsemigroups_pybind11/sims.py +++ b/src/libsemigroups_pybind11/sims.py @@ -50,9 +50,13 @@ def __init__(self: _Self, *args, **kwargs) -> None: if _to_cxx(self) is not None: return if len(args) not in (0, 1): - raise TypeError(f"expected 0 or 1 positional arguments but found {len(args)}") + raise TypeError( + f"expected 0 or 1 positional arguments but found {len(args)}" + ) if len(kwargs) != 0: - raise TypeError(f"expected 0 keyword arguments, but found {len(kwargs)}") + raise TypeError( + f"expected 0 keyword arguments, but found {len(kwargs)}" + ) if len(args) == 0: # self.Word = kwargs["Word"] @@ -218,7 +222,9 @@ def __init__(self: _Self, *args, **kwargs) -> None: ######################################################################## -class SimsRefinerFaithful(_CxxWrapper): # pylint: disable=missing-class-docstring +class SimsRefinerFaithful( + _CxxWrapper +): # pylint: disable=missing-class-docstring __doc__ = _SimsRefinerFaithful.__doc__ _py_template_params_to_cxx_type = { @@ -252,7 +258,9 @@ def __init__(self: _Self, *args, **kwargs) -> None: ): self.py_template_params = (list[int],) else: - raise TypeError("expected the 1st argument to be a list[list[int]]") + raise TypeError( + "expected the 1st argument to be a list[list[int]]" + ) self.init_cxx_obj(*args) diff --git a/src/libsemigroups_pybind11/transf.py b/src/libsemigroups_pybind11/transf.py index f694cf551..e1755ead5 100644 --- a/src/libsemigroups_pybind11/transf.py +++ b/src/libsemigroups_pybind11/transf.py @@ -191,7 +191,9 @@ def __repr__(self: Self) -> str: result = str(self) if len(result) < 72: return result - return f"" + return ( + f"" + ) # We retain a separate __repr__ so that we can distinguish the cxx objects # and their python counterparts. @@ -267,7 +269,9 @@ def __repr__(self: Self) -> str: result = str(self) if len(result) < 72: return result - return f"" + return ( + f"" + ) # We retain a separate __str__ so that we can distinguish the cxx objects # and their python counterparts. @@ -349,7 +353,9 @@ def increase_degree_by(self: Self, n: int) -> Self: @staticmethod @_copydoc(_Perm1.one) def one(n: int) -> Self: - result_type = Perm._py_template_params_to_cxx_type[Perm._py_template_params_from_degree(n)] + result_type = Perm._py_template_params_to_cxx_type[ + Perm._py_template_params_from_degree(n) + ] return _to_py(result_type.one(n)) diff --git a/src/main.hpp b/src/main.hpp index 6967c5152..8f700ee00 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -19,6 +19,7 @@ #ifndef SRC_MAIN_HPP_ #define SRC_MAIN_HPP_ +#include #include // for variant #include @@ -80,29 +81,112 @@ namespace libsemigroups { void init_words(py::module&); template - std::vector - to_ints(std::vector> const& vec) { + using int_or_unsigned_constant + = std::variant; + + template + using int_or_signed_constant = std:: + variant; + + template + using int_or_constant = std::conditional_t, + int_or_signed_constant, + int_or_unsigned_constant>; + + template + Int to_int(int_or_constant val) { + if (std::holds_alternative(val)) { + return std::get<0>(val); + } else if (std::holds_alternative(val)) { + return static_cast(std::get<1>(val)); + } else if (std::holds_alternative(val)) { + return static_cast(std::get<2>(val)); + } else if (std::holds_alternative(val)) { + return static_cast(std::get<3>(val)); + } + if constexpr (std::is_signed_v) { + if (std::holds_alternative(val)) { + return static_cast(std::get<4>(val)); + } + } + } + + template + std::vector to_ints(std::vector> const& vec) { std::vector vec_as_ints; for (auto const& val : vec) { - if (std::holds_alternative(val)) { - vec_as_ints.push_back(std::get<0>(val)); - } else { - vec_as_ints.push_back(static_cast(std::get<1>(val))); - } + vec_as_ints.push_back(to_int(val)); } return vec_as_ints; } template std::vector> - to_ints(std::vector>> const& vec) { + to_ints(std::vector>> const& vec) { std::vector> vec_as_ints; for (auto const& val : vec) { - vec_as_ints.push_back(to_ints(val)); + vec_as_ints.push_back(to_ints(val)); } return vec_as_ints; } + template + int_or_constant from_int(int_or_constant const& val) { + if (std::holds_alternative(val)) { + if constexpr (std::is_signed_v) { + if (std::get<0>(val) == static_cast(NEGATIVE_INFINITY)) { + return {NEGATIVE_INFINITY}; + } + } + if (std::get<0>(val) == static_cast(UNDEFINED)) { + return {UNDEFINED}; + } else if (std::get<0>(val) == static_cast(POSITIVE_INFINITY)) { + return {POSITIVE_INFINITY}; + } else if (std::get<0>(val) == static_cast(LIMIT_MAX)) { + return {LIMIT_MAX}; + } + } + return val; + } + + template + int_or_constant from_int(Int val) { + if constexpr (std::is_signed_v) { + if (val == static_cast(NEGATIVE_INFINITY)) { + return {NEGATIVE_INFINITY}; + } + } + if (val == static_cast(UNDEFINED)) { + return {UNDEFINED}; + } else if (val == static_cast(POSITIVE_INFINITY)) { + return {POSITIVE_INFINITY}; + } else if (val == static_cast(LIMIT_MAX)) { + return {LIMIT_MAX}; + } + return {val}; + } + + template + void from_ints(std::vector>& vec) { + for (auto& val : vec) { + if (std::holds_alternative(val)) { + val = from_int(val); + } + } + } + + template + std::pair, int_or_constant> + from_ints(std::pair const& pair) { + return {from_int(pair.first), from_int(pair.second)}; + } + + template + std::tuple, int_or_constant> + from_ints(std::tuple const& tup) { + return {from_int(std::get<0>(tup)), from_int(std::get<1>(tup))}; + } + } // namespace libsemigroups #endif // SRC_MAIN_HPP_ diff --git a/src/matrix.cpp b/src/matrix.cpp index 7f6ebf720..9369855bd 100644 --- a/src/matrix.cpp +++ b/src/matrix.cpp @@ -157,6 +157,8 @@ namespace libsemigroups { py_type = "NTPMat"; } + using scalar_type = typename Mat::scalar_type; + py::class_ thing(m, py_type.c_str(), R"pbdoc( @@ -168,17 +170,20 @@ above in :any:`MatrixKind`. thing.def("__hash__", &Mat::hash_value); thing.def("__copy__", [](Mat const& x) { return Mat(x); }); thing.def( - "_at", - [](const Mat& mat, py::tuple xy) { - return mat.at(xy[0].cast(), xy[1].cast()); + "__getitem__", + [](Mat const& mat, py::tuple xy) { + return from_int(mat.at(xy[0].cast(), xy[1].cast())); }, py::is_operator()); thing.def( - "_at", + "__getitem__", [](Mat const& thing, size_t i) { try { - auto r = thing.row(i); - return std::vector(r.begin(), r.end()); + auto r = thing.row(i); + std::vector> result(r.begin(), + r.end()); + from_ints(result); + return result; } catch (LibsemigroupsException const& e) { // This is done so that "list" works as expected for a // matrix @@ -188,7 +193,7 @@ above in :any:`MatrixKind`. py::is_operator()); thing.def( "__setitem__", - [](Mat& mat, py::tuple xy, typename Mat::scalar_type val) { + [](Mat& mat, py::tuple xy, scalar_type val) { matrix::throw_if_bad_entry(mat, val); auto r = xy[0].cast(); auto c = xy[1].cast(); @@ -211,9 +216,9 @@ above in :any:`MatrixKind`. py::is_operator()); thing.def( "__setitem__", - [](Mat& mat, - size_t r, - std::vector const& row) { + [](Mat& mat, + size_t r, + std::vector> const& row) { auto rv = mat.row(r); if (row.size() != rv.size()) { LIBSEMIGROUPS_EXCEPTION( @@ -221,10 +226,13 @@ above in :any:`MatrixKind`. rv.size(), row.size()); } - for (auto item : row) { - matrix::throw_if_bad_entry(mat, item); + for (auto& item : row) { + matrix::throw_if_bad_entry(mat, to_int(item)); + } + auto dit = rv.begin(); + for (auto it = row.cbegin(); it != row.cend(); ++it, ++dit) { + *dit = to_int(*it); } - std::copy(row.cbegin(), row.cend(), rv.begin()); }, py::is_operator()); thing.def( @@ -358,10 +366,10 @@ above in :any:`MatrixKind`. }); thing.def("transpose", [](Mat& thing) { thing.transpose(); }); thing.def("swap", &Mat::swap); - thing.def("_scalar_zero", - [](Mat const& thing) { return thing.scalar_zero(); }); + thing.def("scalar_zero", + [](Mat const& thing) { return from_int(thing.scalar_zero()); }); thing.def("scalar_one", - [](Mat const& thing) { return thing.scalar_one(); }); + [](Mat const& thing) { return from_int(thing.scalar_one()); }); thing.def("number_of_rows", [](Mat const& thing) { return thing.number_of_rows(); }); thing.def("degree", @@ -383,20 +391,22 @@ above in :any:`MatrixKind`. template auto bind_matrix_no_semiring(py::module& m) { using scalar_type = typename Mat::scalar_type; - auto thing = bind_matrix_common(m); - thing.def(py::init([](std::vector> const& rows) { - return make(rows); - }), - py::arg("rows"), - R"pbdoc( + auto thing = bind_matrix_common(m); + + thing.def( + py::init( + [](std::vector>> const& + rows) { return make(to_ints(rows)); }), + py::arg("rows"), + R"pbdoc( Construct a matrix from rows. :param kind: specifies the underlying semiring. :type kind: MatrixKind :param rows: the rows of the matrix. -:type rows: list[list[int | POSITIVE_INFINITY | NEGATIVE_INFINITY]] +:type rows: list[list[int | PositiveInfinity | NegativeInfinity]] :raise RunTimeError: if *kind* is :py:attr:`MatrixKind.MaxPlusTrunc`, @@ -404,11 +414,11 @@ Construct a matrix from rows. :py:attr:`MatrixKind.NTP`. :raise LibsemigroupsError: - if the entries in *rows* are not of equal length. + if the entries in *rows* are not of equal length. :raise LibsemigroupsError: - if any of the entries of the lists in *rows* do not belong to - the underlying semiring. + if any of the entries of the lists in *rows* do not belong to + the underlying semiring. )pbdoc"); thing.def(py::init()); thing.def("one", [](Mat const& self, size_t n) { return Mat::one(n); }); @@ -419,15 +429,18 @@ Construct a matrix from rows. auto bind_matrix_trunc_semiring(py::module& m) { using semiring_type = typename Mat::semiring_type; using scalar_type = typename Mat::scalar_type; - auto thing = bind_matrix_common(m); + + auto thing = bind_matrix_common(m); thing.def(py::init([](size_t threshold, size_t r, size_t c) { return Mat(semiring(threshold), r, c); })); - thing.def( - py::init([](size_t threshold, - std::vector> const& entries) { - return make(semiring(threshold), entries); + thing.def(py::init( + [](size_t threshold, + std::vector>> const& + entries) { + return make(semiring(threshold), + to_ints(entries)); })); thing.def("one", [](Mat const& self, size_t n) { return Mat::one(semiring(matrix::threshold(self)), n); @@ -435,7 +448,7 @@ Construct a matrix from rows. thing.def("one", [](Mat const& self) { return self.one(); }); m.def( - "threshold", + "matrix_threshold", [](Mat const& x) { return matrix::threshold(x); }, py::arg("x"), R"pbdoc( @@ -462,14 +475,16 @@ that is a matrix whose kind is any of: auto bind_ntp_matrix(py::module& m) { using semiring_type = typename Mat::semiring_type; using scalar_type = typename Mat::scalar_type; - auto thing = bind_matrix_common(m); - thing.def( - py::init([](size_t threshold, - size_t period, - std::vector> const& entries) { + auto thing = bind_matrix_common(m); + + thing.def(py::init( + [](size_t threshold, + size_t period, + std::vector>> const& + entries) { return make(semiring(threshold, period), - entries); + to_ints(entries)); })); thing.def( py::init([](size_t threshold, size_t period, size_t r, size_t c) { @@ -483,7 +498,7 @@ that is a matrix whose kind is any of: thing.def("one", [](Mat const& self) { return self.one(); }); m.def( - "period", + "matrix_period", [](Mat const& x) { return matrix::period(x); }, py::arg("x"), R"pbdoc( @@ -498,7 +513,7 @@ the ntp matrix *x* using its underlying semiring. :rtype: int )pbdoc"); m.def( - "threshold", + "matrix_threshold", [](Mat const& x) { return matrix::threshold(x); }, py::arg("x"), R"pbdoc( @@ -538,6 +553,7 @@ that is a matrix whose kind is any of: py::arg("x"), R"pbdoc( :sig=(x:Matrix)->int: + Returns the size of the row space of a boolean matrix. This function returns the size of the row space of the boolean matrix *x*. @@ -559,7 +575,7 @@ the size of the row space of the boolean matrix *x*. 7 )pbdoc"); m.def( - "row_basis", + "matrix_row_basis", [](BMat<> const& x) { std::vector> result; for (auto rv : matrix::row_basis(x)) { @@ -569,7 +585,7 @@ the size of the row space of the boolean matrix *x*. }, py::arg("x"), R"pbdoc( -:sig=(x:Matrix)->list[list[int | POSITIVE_INFINITY | NEGATIVE_INFINITY]]: +:sig=(x: Matrix) -> list[list[int | PositiveInfinity | NegativeInfinity]]: Returns a row space basis of a matrix as a list of lists. The matrix *x* which must be one of: @@ -589,10 +605,12 @@ of rows. :returns: A basis for the row space of *x*. :rtype: list[list[int | POSITIVE_INFINITY | NEGATIVE_INFINITY]] )pbdoc"); - m.def("row_basis", [](MaxPlusTruncMat<0, 0, 0, int64_t> const& x) { - std::vector> result; + + m.def("matrix_row_basis", [](MaxPlusTruncMat<0, 0, 0, int64_t> const& x) { + std::vector>> result; for (auto rv : matrix::row_basis(x)) { result.emplace_back(rv.begin(), rv.end()); + from_ints(result.back()); } return result; }); diff --git a/src/paths.cpp b/src/paths.cpp index 6981c498a..69e2ba244 100644 --- a/src/paths.cpp +++ b/src/paths.cpp @@ -148,13 +148,9 @@ are no more paths in the range, and ``False`` otherwise. thing1.def( "count", - [](Paths_& p) -> std::variant { + [](Paths_& p) { p.throw_if_source_undefined(); - auto result = p.count(); - if (result != POSITIVE_INFINITY) { - return {result}; - } - return {POSITIVE_INFINITY}; + return from_int(p.count()); }, R"pbdoc( :sig=(self: Paths) -> int | PositiveInfinity: @@ -204,13 +200,7 @@ Get the current path in the range. )pbdoc"); thing1.def( "max", - [](Paths_ const& self) -> std::variant { - auto result = self.max(); - if (result != POSITIVE_INFINITY) { - return {result}; - } - return {POSITIVE_INFINITY}; - }, + [](Paths_ const& self) { return from_int(self.max()); }, R"pbdoc( :sig=(self: Paths) -> int | PositiveInfinity: :only-document-once: diff --git a/src/present.cpp b/src/present.cpp index f8601ee97..772567c9b 100644 --- a/src/present.cpp +++ b/src/present.cpp @@ -820,12 +820,16 @@ If no such word can be found, then a word of length :math:`0` is returned. :rtype: :ref:`Word`. )pbdoc"); - m.def("make_semigroup", - &presentation::make_semigroup, - py::arg("p"), - R"pbdoc( -:sig=(p: Presentation) -> Word: + m.def( + "make_semigroup", + [](Presentation_& p) { + return from_int(presentation::make_semigroup(p)); + }, + py::arg("p"), + R"pbdoc( +:sig=(p: Presentation) -> Letter | Undefined: :only-document-once: + Convert a monoid presentation to a semigroup presentation. This function modifies its argument in-place by replacing the empty word in all @@ -838,7 +842,7 @@ identity, then this generator is returned. :type p: Presentation :returns: The new generator added, if any, and :any:`UNDEFINED` if not. -:rtype: :ref:`Word` +:rtype: :ref:`Letter` | Undefined :raises LibsemigroupsError: if :any:`replace_word` or :any:`add_identity_rules` does. diff --git a/src/stephen.cpp b/src/stephen.cpp index 14399060d..a26e72f75 100644 --- a/src/stephen.cpp +++ b/src/stephen.cpp @@ -394,12 +394,15 @@ This function triggers the algorithm implemented in this class (if it hasn't bee Termination of the Stephen algorithm is undecidable in general, and this function may never terminate. )pbdoc"); - m.def("stephen_number_of_left_factors", - &stephen::number_of_left_factors, - py::arg("s"), - py::arg("min") = 0, - py::arg("max") = static_cast(POSITIVE_INFINITY), - R"pbdoc( + m.def( + "stephen_number_of_left_factors", + [](Stephen_& s, size_t min, size_t max) { + return from_int(stephen::number_of_left_factors(s, min, max)); + }, + py::arg("s"), + py::arg("min") = 0, + py::arg("max") = static_cast(POSITIVE_INFINITY), + R"pbdoc( :sig=(s: Stephen, min: int = 0, max: int | PositiveInfinity = POSITIVE_INFINITY) -> int | PositiveInfinity: :only-document-once: Returns the number of left factors with length in a given range. @@ -433,12 +436,15 @@ in the range *min* to *max*. Termination of the Stephen algorithm is undecidable in general, and this function may never terminate. )pbdoc"); - m.def("stephen_number_of_words_accepted", - &stephen::number_of_words_accepted, - py::arg("s"), - py::arg("min") = 0, - py::arg("max") = static_cast(POSITIVE_INFINITY), - R"pbdoc( + m.def( + "stephen_number_of_words_accepted", + [](Stephen_& s, size_t min, size_t max) { + return from_int(stephen::number_of_words_accepted(s, min, max)); + }, + py::arg("s"), + py::arg("min") = 0, + py::arg("max") = static_cast(POSITIVE_INFINITY), + R"pbdoc( :sig=(s: Stephen, min: int = 0, max: int | PositiveInfinity = POSITIVE_INFINITY) -> int | PositiveInfinity: :only-document-once: diff --git a/src/todd-coxeter.cpp b/src/todd-coxeter.cpp index f50e3a0ec..2f8ba1dbb 100644 --- a/src/todd-coxeter.cpp +++ b/src/todd-coxeter.cpp @@ -241,13 +241,8 @@ semigroup. thing.def( "current_index_of", - [](ToddCoxeter_ const& self, - Word const& w) -> std::variant { - auto result = todd_coxeter::current_index_of(self, w); - if (result != UNDEFINED) { - return {result}; - } - return {UNDEFINED}; + [](ToddCoxeter_ const& self, Word const& w) { + return from_int(todd_coxeter::current_index_of(self, w)); }, py::arg("w"), R"pbdoc( diff --git a/src/transf.cpp b/src/transf.cpp index ce9df8bd1..e871e3f74 100644 --- a/src/transf.cpp +++ b/src/transf.cpp @@ -24,7 +24,6 @@ #include #include #include -#include // libsemigroups_pybind11.... #include "debug.hpp" @@ -104,7 +103,7 @@ the image of the point ``i`` under the {0} is ``imgs[i]``. thing.def( "__getitem__", [](PTransfSubclass const& a, - size_t b) -> std::variant { + size_t b) -> int_or_unsigned_constant { auto result = a.at(b); if (result != UNDEFINED) { return {result}; @@ -157,7 +156,7 @@ definition, which is equal to the size of :any:`{0}.images`. [](PTransfSubclass& self) { auto r = rx::iterator_range(self.begin(), self.end()) | rx::transform( - [](auto val) -> std::variant { + [](auto val) -> int_or_unsigned_constant { if (val != UNDEFINED) { return {val}; } @@ -520,8 +519,8 @@ among the points where :math:`f` is defined). thing.def( py::init( - [](std::vector> const& imgs) { - return make(to_ints(imgs)); + [](std::vector> const& imgs) { + return make(to_ints(imgs)); }), py::arg("imgs"), R"pbdoc( diff --git a/src/ukkonen.cpp b/src/ukkonen.cpp index ae90e88bd..9d102f064 100644 --- a/src/ukkonen.cpp +++ b/src/ukkonen.cpp @@ -41,11 +41,11 @@ namespace libsemigroups { uk.def( "index", [](Ukkonen const& self, Word const& w) { - return self.index(w.begin(), w.end()); + return from_int(self.index(w.begin(), w.end())); }, py::arg("w"), R"pbdoc( -:sig=(self: Ukkonen, w: str | list[int]) -> int: +:sig=(self: Ukkonen, w: str | list[int]) -> int | Undefined: :only-document-once: Find the index of a word in the suffix tree. @@ -59,7 +59,7 @@ suffix tree represents, then :any:`UNDEFINED` is returned. :type w: str | list[int] :returns: The index of *w*. -:rtype: int +:rtype: int | Undefined :raises LibsemigroupsError: if ``throw_if_contains_unique_letter(w)`` throws. @@ -378,12 +378,12 @@ contained in *u*. If no such suffix exists, then an empty word is returned. m.def( "number_of_pieces", [](Ukkonen const& u, Word const& w) { - return ukkonen::number_of_pieces(u, w); + return from_int(ukkonen::number_of_pieces(u, w)); }, py::arg("u"), py::arg("w"), R"pbdoc( -:sig=(u: Ukkonen, w: str | list[int]) -> int: +:sig=(u: Ukkonen, w: str | list[int]) -> int | PositiveInfinity: :only-document-once: Find the number of pieces in a decomposition of a word (if any). @@ -400,7 +400,7 @@ Recall that a *piece* is a word that occurs in two distinct positions :type w: str | list[int] :returns: The number of pieces. -:rtype: int +:rtype: int | PositiveInfinity :raises LibsemigroupsError: if ``u.throw_if_contains_unique_letter(w)`` throws. @@ -618,9 +618,11 @@ The children of the current node. R"pbdoc( The index of the first letter in the edge leading to the node. )pbdoc"); - node.def_readwrite("parent", - &Ukkonen::Node::parent, - R"pbdoc( + // TODO should the others here also be def_property_readonly? + node.def_property_readonly( + "parent", + [](Ukkonen::Node const& node) { return from_int(node.parent); }, + R"pbdoc( The index of the parent node. )pbdoc"); node.def_readwrite("r", diff --git a/src/word-graph.cpp b/src/word-graph.cpp index eb2d56910..2938fec72 100644 --- a/src/word-graph.cpp +++ b/src/word-graph.cpp @@ -52,8 +52,6 @@ namespace libsemigroups { using node_type = typename WordGraph_::node_type; using label_type = typename WordGraph_::label_type; - using int_or_undefined = std::variant; - py::class_ thing(m, "WordGraph", R"pbdoc( @@ -112,10 +110,10 @@ out-degree of any node is *n*. There are no edges in the defined word graph. out-degree of the word graph.)pbdoc"); thing.def( - py::init([](size_t num_nodes, + py::init([](size_t num_nodes, std::vector>> const& targets) { - return make(num_nodes, to_ints(targets)); + int_or_unsigned_constant>> const& targets) { + return make(num_nodes, to_ints(targets)); }), py::arg("num_nodes"), py::arg("targets"), @@ -201,13 +199,9 @@ the word graph. "targets", [](WordGraph_ const& self, node_type source) { auto result - = (self.targets(source) - | rx::transform([](node_type target) -> int_or_undefined { - if (target == UNDEFINED) { - return {UNDEFINED}; - } - return {target}; - })); + = (self.targets(source) | rx::transform([](node_type target) { + return from_int(target); + })); return py::make_iterator(rx::begin(result), rx::end(result)); }, py::arg("source"), @@ -308,15 +302,9 @@ had just been newly constructed with the same parameters *m* and *n*. "labels_and_targets", [](WordGraph_ const& self, node_type source) { auto r = (self.labels_and_targets(source) - | rx::transform( - [](auto const& label_target) - -> std::pair { - if (std::get<1>(label_target) != UNDEFINED) { - return {std::get<0>(label_target), - {std::get<1>(label_target)}}; - } - return {std::get<0>(label_target), {UNDEFINED}}; - })); + | rx::transform([](auto const& label_target) { + return from_ints(label_target); + })); return py::make_iterator(rx::begin(r), rx::end(r)); }, py::arg("source"), @@ -336,18 +324,8 @@ targets of edges with source *source*. :raises LibsemigroupsError: if *source* is out of bounds.)pbdoc"); thing.def( "next_label_and_target", - [](WordGraph_ const& self, - node_type s, - label_type a) -> std::pair { - std::pair result( - self.next_label_and_target(s, a)); - if (std::get<0>(result.first) == UNDEFINED) { - result.first = UNDEFINED; - } - if (std::get<0>(result.second) == UNDEFINED) { - result.second = UNDEFINED; - } - return result; + [](WordGraph_ const& self, node_type s, label_type a) { + return from_ints(self.next_label_and_target(s, a)); }, py::arg("s"), py::arg("a") = 0, @@ -573,14 +551,8 @@ out_degree())`` , then this function adds an edge from *a* to *b* labelled *a*. :complexity: Constant.)pbdoc"); thing.def( "target", - [](WordGraph_ const& self, - node_type source, - label_type a) -> int_or_undefined { - auto t = self.target(source, a); - if (t == UNDEFINED) { - return {UNDEFINED}; - } - return {t}; + [](WordGraph_ const& self, node_type source, label_type a) { + return from_int(self.target(source, a)); }, py::arg("source"), py::arg("a"), diff --git a/tests/test_action.py b/tests/test_action.py index cc8174ca0..40c119166 100644 --- a/tests/test_action.py +++ b/tests/test_action.py @@ -400,6 +400,7 @@ def test_action_current_size(right_actions, left_actions): ) act = right_actions[1] right_actions[1].run_until(lambda: x in act) + assert x in act assert right_actions[1].current_size() == 43749 diff --git a/tests/test_constants.py b/tests/test_constants.py index b8fa8c00f..815cc24cc 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -28,8 +28,8 @@ def test_UNDEFINED(): # pylint: disable=invalid-name assert not UNDEFINED == NEGATIVE_INFINITY assert not UNDEFINED == LIMIT_MAX assert not UNDEFINED == 0 - assert 18446744073709551615 == UNDEFINED - assert UNDEFINED == 18446744073709551615 + assert 18446744073709551615 != UNDEFINED + assert UNDEFINED != 18446744073709551615 assert not UNDEFINED != UNDEFINED assert UNDEFINED != POSITIVE_INFINITY @@ -50,8 +50,8 @@ def test_POSITIVE_INFINITY(): # pylint: disable=invalid-name Test the properties of the POSITIVE_INFINITY constant """ assert POSITIVE_INFINITY == POSITIVE_INFINITY - assert POSITIVE_INFINITY == 2147483646 - assert 2147483646 == POSITIVE_INFINITY + assert POSITIVE_INFINITY != 2147483646 + assert 2147483646 != POSITIVE_INFINITY assert not POSITIVE_INFINITY == UNDEFINED assert not POSITIVE_INFINITY == NEGATIVE_INFINITY assert not POSITIVE_INFINITY == LIMIT_MAX @@ -91,8 +91,8 @@ def test_NEGATIVE_INFINITY(): # pylint: disable=invalid-name Test the properties of the NEGATIVE_INFINITY constant """ assert NEGATIVE_INFINITY == NEGATIVE_INFINITY - assert NEGATIVE_INFINITY == -2147483648 - assert -2147483648 == NEGATIVE_INFINITY + assert NEGATIVE_INFINITY != -2147483648 + assert -2147483648 != NEGATIVE_INFINITY assert not NEGATIVE_INFINITY == UNDEFINED assert not NEGATIVE_INFINITY == POSITIVE_INFINITY assert not NEGATIVE_INFINITY == LIMIT_MAX @@ -152,14 +152,5 @@ def test_LIMIT_MAX(): # pylint: disable=invalid-name assert not LIMIT_MAX > LIMIT_MAX assert not LIMIT_MAX < LIMIT_MAX - assert LIMIT_MAX - 1 - assert 1 - LIMIT_MAX - assert LIMIT_MAX > 0 - assert not 0 > LIMIT_MAX - assert 0 < LIMIT_MAX - assert 100 < LIMIT_MAX - assert not 0 > LIMIT_MAX - assert not 100 > LIMIT_MAX - d = {LIMIT_MAX: 0} assert LIMIT_MAX in d diff --git a/tests/test_froidure_pin.py b/tests/test_froidure_pin.py index 670115da5..e807c70aa 100644 --- a/tests/test_froidure_pin.py +++ b/tests/test_froidure_pin.py @@ -87,7 +87,9 @@ 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]) + froidure_pin.current_position( + S, [0, 0, 0, 0, 0, 0, 0, S.number_of_generators(), 1] + ) with pytest.raises(RuntimeError): S.position_of_generator(S.number_of_generators()) @@ -99,14 +101,15 @@ def check_mem_compare(S): # self.assertEqual( # [S.position(froidure_pin.factorisation(S, x)) for x in S], list(range(S.size())) # ) - assert [froidure_pin.current_position(S, froidure_pin.factorisation(S, x)) for x in S] == list( - range(S.size()) - ) + assert [ + froidure_pin.current_position(S, froidure_pin.factorisation(S, x)) + for x in S + ] == list(range(S.size())) assert [S.current_position(x) for x in S] == list(range(S.size())) - assert [S.position_of_generator(i) for i in range(S.number_of_generators())] == list( - range(S.number_of_generators()) - ) + assert [ + S.position_of_generator(i) for i in range(S.number_of_generators()) + ] == list(range(S.number_of_generators())) for x in S: assert S.sorted_position(x) == S.to_sorted_position(S.position(x)) @@ -149,10 +152,14 @@ def check_idempotents(S): pass assert all( - S.fast_product(S.position(x), S.position(x)) == S.position(x) for x in S.idempotents() + S.fast_product(S.position(x), S.position(x)) == S.position(x) + for x in S.idempotents() ) - assert sum(1 for x in range(S.size()) if S.is_idempotent(x)) == S.number_of_idempotents() + assert ( + sum(1 for x in range(S.size()) if S.is_idempotent(x)) + == S.number_of_idempotents() + ) def check_cayley_graphs(S): @@ -184,20 +191,30 @@ def check_factor_prod_rels(S): # (minimal_)factorisation + to_element for i, x in enumerate(S): assert froidure_pin.to_element(S, froidure_pin.factorisation(S, x)) == x - assert froidure_pin.to_element(S, froidure_pin.minimal_factorisation(S, i)) == x + assert ( + froidure_pin.to_element(S, froidure_pin.minimal_factorisation(S, i)) + == x + ) # rules, number_of_rules assert len(list(froidure_pin.rules(S))) == S.number_of_rules() for lhs, rhs in froidure_pin.rules(S): - assert froidure_pin.current_position(S, lhs) == froidure_pin.current_position(S, rhs) - assert froidure_pin.factorisation(S, froidure_pin.current_position(S, rhs)) == rhs + assert froidure_pin.current_position( + S, lhs + ) == froidure_pin.current_position(S, rhs) + assert ( + froidure_pin.factorisation(S, froidure_pin.current_position(S, rhs)) + == rhs + ) # product_by_reduction + fast_product try: for i in range(S.size()): for j in range(S.size()): - assert froidure_pin.product_by_reduction(S, i, j) == S.position(S[i] * S[j]) + assert froidure_pin.product_by_reduction(S, i, j) == S.position( + S[i] * S[j] + ) assert S.fast_product(i, j) == S.position(S[i] * S[j]) except TypeError: # no product defined pass @@ -460,7 +477,9 @@ def test_froidure_pin_min_plus(checks_for_froidure_pin, checks_for_generators): check(FroidurePin(gens)) -def test_froidure_pin_proj_max_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()]])] @@ -473,7 +492,9 @@ def test_froidure_pin_proj_max_plus(checks_for_froidure_pin, checks_for_generato check(FroidurePin(gens)) -def test_froidure_pin_max_plus_trunc(checks_for_froidure_pin, checks_for_generators): +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 @@ -485,7 +506,9 @@ def test_froidure_pin_max_plus_trunc(checks_for_froidure_pin, checks_for_generat check(FroidurePin(gens)) -def test_froidure_pin_min_plus_trunc(checks_for_froidure_pin, checks_for_generators): +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 @@ -534,7 +557,9 @@ def test_froidure_pin_method_wrap(): S.init() with pytest.raises(LibsemigroupsError): - S.add_generators([Perm([0, 1, 2, 3, 4, 5]), Perm([0, 1, 2, 3, 4, 5, 6])]) + S.add_generators( + [Perm([0, 1, 2, 3, 4, 5]), Perm([0, 1, 2, 3, 4, 5, 6])] + ) S = FroidurePin(Perm([1, 0, 2, 3, 4, 5, 6]), Perm([1, 2, 3, 4, 5, 6, 0])) diff --git a/tests/test_schreier_sims.py b/tests/test_schreier_sims.py index f6b8cabda..57fcfde1c 100644 --- a/tests/test_schreier_sims.py +++ b/tests/test_schreier_sims.py @@ -381,27 +381,45 @@ def check_SchreierSims_001(n): S.init() assert S.size() == 1 S.add_generator( - Perm([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + list(range(17, n))) + Perm( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + + list(range(17, n)) + ) ) S.add_generator( - Perm([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 14] + list(range(17, n))) + Perm( + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 14] + + list(range(17, n)) + ) ) assert not S.currently_contains( - Perm([1, 0, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + list(range(17, n))) + Perm( + [1, 0, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + list(range(17, n)) + ) ) assert S.current_size() == 17 assert S.size() == 177843714048000 assert S.base(0) == 0 assert S.contains( - Perm([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + list(range(17, n))) + Perm( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + + list(range(17, n)) + ) ) assert not S.contains( - Perm([1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + list(range(17, n))) + Perm( + [1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + list(range(17, n)) + ) ) assert S.contains( - Perm([1, 0, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + list(range(17, n))) + Perm( + [1, 0, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + list(range(17, n)) + ) ) S.init() @@ -412,12 +430,18 @@ def check_SchreierSims_001(n): S.add_base_point(14) S.add_base_point(15) S.add_generator( - Perm([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + list(range(17, n))) + Perm( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + + list(range(17, n)) + ) ) S.add_base_point(1) S.add_base_point(3) S.add_generator( - Perm([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 14] + list(range(17, n))) + Perm( + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 14] + + list(range(17, n)) + ) ) assert S.base_size() == 4 assert S.size() == 177843714048000 @@ -433,24 +457,39 @@ def check_SchreierSims_001(n): S.base(15) assert S.contains( - Perm([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + list(range(17, n))) + Perm( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + + list(range(17, n)) + ) ) assert not S.contains( - Perm([1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + list(range(17, n))) + Perm( + [1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + list(range(17, n)) + ) ) assert S.contains( - Perm([1, 0, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + list(range(17, n))) + Perm( + [1, 0, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + list(range(17, n)) + ) ) with pytest.raises(LibsemigroupsError): S.add_base_point(1) S.init() S.add_generator( - Perm([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + list(range(17, n))) + Perm( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0] + + list(range(17, n)) + ) ) assert S.size() == 17 S.add_generator( - Perm([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 14] + list(range(17, n))) + Perm( + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 14] + + list(range(17, n)) + ) ) assert S.size() == 177843714048000 diff --git a/tests/test_sims.py b/tests/test_sims.py index e55e6a6df..59a2d24af 100644 --- a/tests/test_sims.py +++ b/tests/test_sims.py @@ -119,12 +119,16 @@ def test_sims1_000(): it = S.iterator(3) assert next(it) == WordGraph(3, [[0, 0]]) - S.number_of_threads(1).for_each(5, lambda wg: check_right_generating_pairs(S, wg)) + S.number_of_threads(1).for_each( + 5, lambda wg: check_right_generating_pairs(S, wg) + ) presentation.reverse(p) S = Sims1() assert S.presentation(p).number_of_congruences(5) == 9 for wg in S.iterator(5): - assert word_graph.follow_path(wg, 0, [1, 0, 1, 0]) == word_graph.follow_path(wg, 0, [0]) + assert word_graph.follow_path( + wg, 0, [1, 0, 1, 0] + ) == word_graph.follow_path(wg, 0, [0]) S.for_each(5, lambda wg: check_right_generating_pairs(S, wg)) mat = sims.poset(S, 5) assert mat == Matrix( @@ -332,7 +336,12 @@ def test_sims1_004(): assert T.number_of_congruences(16) == 13 orc = MinimalRepOrc() - d = orc.presentation(p).target_size(15).number_of_threads(os.cpu_count()).word_graph() + d = ( + orc.presentation(p) + .target_size(15) + .number_of_threads(os.cpu_count()) + .word_graph() + ) assert d.number_of_nodes() == 7 @@ -352,13 +361,21 @@ def test_sims_refiner_faithful_128(): S = Sims1() S.presentation(p) S.add_pruner(pruno) - assert S.number_of_threads(2).number_of_congruences(9) == 4 # Verified with GAP + assert ( + S.number_of_threads(2).number_of_congruences(9) == 4 + ) # Verified with GAP it = S.iterator(9) - assert next(it) == WordGraph(9, [[1, 2], [1, 3], [4, 5], [4, 4], [3, 1], [3, 0]]) - assert next(it) == WordGraph(9, [[1, 2], [3, 3], [4, 5], [1, 4], [4, 1], [3, 0]]) - assert next(it) == WordGraph(9, [[1, 2], [3, 4], [3, 5], [1, 1], [4, 3], [4, 0]]) + assert next(it) == WordGraph( + 9, [[1, 2], [1, 3], [4, 5], [4, 4], [3, 1], [3, 0]] + ) + assert next(it) == WordGraph( + 9, [[1, 2], [3, 3], [4, 5], [1, 4], [4, 1], [3, 0]] + ) + assert next(it) == WordGraph( + 9, [[1, 2], [3, 4], [3, 5], [1, 1], [4, 3], [4, 0]] + ) assert next(it) == WordGraph( 9, [ diff --git a/tests/test_stephen.py b/tests/test_stephen.py index 5fe6962e2..2e9f39e44 100644 --- a/tests/test_stephen.py +++ b/tests/test_stephen.py @@ -91,7 +91,12 @@ def verify_c4_normal_form(p, word, nf): S = Stephen(p) S.set_word(word).run() - assert sorted(list(stephen.words_accepted(S)), key=lexicographic_compare_key_func)[0] == nf + assert ( + sorted( + list(stephen.words_accepted(S)), key=lexicographic_compare_key_func + )[0] + == nf + ) assert all(stephen.accepts(S, w) for w in stephen.words_accepted(S)) assert stephen.number_of_words_accepted(S) == len(stephen.words_accepted(S)) @@ -186,18 +191,25 @@ def test_stephen_001(): [1, 1, 0, 0, 1], ] assert stephen.number_of_left_factors(s) == POSITIVE_INFINITY - assert all(stephen.is_left_factor(s, ww) for ww in islice(stephen.left_factors(s), 10)) + assert all( + stephen.is_left_factor(s, ww) + for ww in islice(stephen.left_factors(s), 10) + ) s.set_word([0, 0]).run() assert s.word_graph().number_of_nodes() == 5 - assert s.word_graph() == WordGraph(5, [[1, UNDEFINED], [2, 3], [1, 4], [4, 1], [3, 2]]) + assert s.word_graph() == WordGraph( + 5, [[1, UNDEFINED], [2, 3], [1, 4], [4, 1], [3, 2]] + ) p.rules = [] presentation.add_rule(p, [0, 0, 0], [0]) presentation.add_rule(p, [1, 1, 1], [1]) s.init(p).set_word([0, 0]).run() assert s.word() == [0, 0] - assert s.word_graph() == WordGraph(3, [[1, UNDEFINED], [2, UNDEFINED], [1, UNDEFINED]]) + assert s.word_graph() == WordGraph( + 3, [[1, UNDEFINED], [2, UNDEFINED], [1, UNDEFINED]] + ) @pytest.mark.quick @@ -546,9 +558,9 @@ def test_stephen_008(): to_word("dgabcdg"), ] - assert sorted(list(stephen.words_accepted(S)), key=lexicographic_compare_key_func)[ - 0 - ] == to_word("dfabcdf") + assert sorted( + list(stephen.words_accepted(S)), key=lexicographic_compare_key_func + )[0] == to_word("dfabcdf") assert all(stephen.accepts(S, w) for w in stephen.words_accepted(S)) assert stephen.number_of_words_accepted(S) == len(stephen.words_accepted(S)) @@ -556,7 +568,9 @@ def test_stephen_008(): S.set_word(to_word("abcdfceg")).run() assert stephen.number_of_words_accepted(S) == 16 - assert sorted(list(stephen.words_accepted(S)), key=lexicographic_compare_key_func) == [ + assert sorted( + list(stephen.words_accepted(S)), key=lexicographic_compare_key_func + ) == [ to_word("abcdfabcdf"), to_word("abcdfabcdg"), to_word("abcdfcef"), @@ -575,9 +589,9 @@ def test_stephen_008(): to_word("cegceg"), ] - assert sorted(list(stephen.words_accepted(S)), key=lexicographic_compare_key_func)[ - 0 - ] == to_word("abcdfabcdf") + assert sorted( + list(stephen.words_accepted(S)), key=lexicographic_compare_key_func + )[0] == to_word("abcdfabcdf") assert stephen.accepts(S, to_word("abcdfabcdf")) @@ -708,8 +722,12 @@ def test_stephen_014(): to_word = ToWord("abcd") p = Presentation(to_word("abcd")) presentation.add_rule(p, to_word("abbba"), to_word("cdc")) - verify_c4_normal_form(p, to_word("cdcdcabbbabbbabbcd"), to_word("abbbadcabbbabbbabbcd")) - verify_c4_equal_to(p, to_word("cdcdcabbbabbbabbcd"), to_word("abbbadcabbbabbbabbcd")) + verify_c4_normal_form( + p, to_word("cdcdcabbbabbbabbcd"), to_word("abbbadcabbbabbbabbcd") + ) + verify_c4_equal_to( + p, to_word("cdcdcabbbabbbabbcd"), to_word("abbbadcabbbabbbabbcd") + ) verify_c4_equal_to(p, to_word("abbbadcbbba"), to_word("cdabbbcdc")) verify_c4_equal_to(p, to_word("cdabbbcdc"), to_word("cdabbbcdc")) @@ -762,8 +780,12 @@ def test_stephen_017(): p = Presentation(to_word("abcd")) presentation.add_rule(p, to_word("abcd"), to_word("accca")) - verify_c4_normal_form(p, to_word("bbcabcdaccaccabcddd"), to_word("bbcabcdaccaccabcddd")) - verify_c4_equal_to(p, to_word("bbcabcdaccaccabcddd"), to_word("bbcabcdaccaccabcddd")) + verify_c4_normal_form( + p, to_word("bbcabcdaccaccabcddd"), to_word("bbcabcdaccaccabcddd") + ) + verify_c4_equal_to( + p, to_word("bbcabcdaccaccabcddd"), to_word("bbcabcdaccaccabcddd") + ) @pytest.mark.quick @@ -786,8 +808,12 @@ def test_stephen_019(): p = Presentation(to_word("abc")) presentation.add_rule(p, to_word("ccab"), to_word("cbac")) - verify_c4_normal_form(p, to_word("bacbaccabccabcbacbac"), to_word("bacbacbaccbaccbacbac")) - verify_c4_equal_to(p, to_word("bacbaccabccabcbacbac"), to_word("bacbacbaccbaccbacbac")) + verify_c4_normal_form( + p, to_word("bacbaccabccabcbacbac"), to_word("bacbacbaccbaccbacbac") + ) + verify_c4_equal_to( + p, to_word("bacbaccabccabcbacbac"), to_word("bacbacbaccbaccbacbac") + ) verify_c4_normal_form(p, to_word("ccabcbaccab"), to_word("cbaccbacbac")) verify_c4_equal_to(p, to_word("ccabcbaccab"), to_word("cbaccbacbac")) @@ -862,8 +888,12 @@ def test_stephen_025(): ReportGuard(False) to_word = ToWord("abcd") p = Presentation(to_word("abcd")) - presentation.add_rule(p, to_word("ababbabbbabbbb"), to_word("abbbbbabbbbbbabbbbbbbabbbbbbbb")) - presentation.add_rule(p, to_word("cdcddcdddcdddd"), to_word("cdddddcddddddcdddddddcdddddddd")) + presentation.add_rule( + p, to_word("ababbabbbabbbb"), to_word("abbbbbabbbbbbabbbbbbbabbbbbbbb") + ) + presentation.add_rule( + p, to_word("cdcddcdddcdddd"), to_word("cdddddcddddddcdddddddcdddddddd") + ) verify_c4_normal_form( p, @@ -930,7 +960,9 @@ def test_stephen_029(): p = Presentation(to_word("abcd")) presentation.add_rule(p, to_word("acba"), to_word("aabc")) presentation.add_rule(p, to_word("acba"), to_word("dbbd")) - verify_c4_normal_form(p, to_word("bbacbcaaabcbbd"), to_word("bbacbcaaabcbbd")) + verify_c4_normal_form( + p, to_word("bbacbcaaabcbbd"), to_word("bbacbcaaabcbbd") + ) verify_c4_normal_form(p, to_word("acbacba"), to_word("aabcabc")) verify_c4_normal_form(p, to_word("aabcabc"), to_word("aabcabc")) @@ -1510,17 +1542,25 @@ def test_stephen_049(): presentation.add_rule(p, [0, 0, 1], [1, 0]) S = Stephen(Presentation([])) - assert repr(S) == f"" + assert ( + repr(S) + == f"" + ) S.init(p) - assert repr(S) == f"" + assert ( + repr(S) + == f"" + ) S.set_word([0, 1, 1, 0]) assert ( - repr(S) == f"" ) S.run() assert ( - repr(S) == f"" ) S.set_word([0, 1, 1, 0, 0, 1, 1, 0, 0]) @@ -1538,17 +1578,22 @@ def test_stephen_049(): S.set_word([0, 1, 1, 0, 0, 1, 1, 0, 0, 1]) S.run() assert ( - repr(S) == f"" ) S.set_word([0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0]) S.run() assert ( - repr(S) == f"" ) S.init(p) - assert repr(S) == f"" + assert ( + repr(S) + == f"" + ) to_word = ToWord("abcABC") pi = InversePresentation(to_word("abcABC")) @@ -1558,9 +1603,15 @@ def test_stephen_049(): presentation.add_rule(pi, to_word("bc"), to_word("cb")) IS = Stephen(InversePresentation([])) - assert repr(IS) == f"" + assert ( + repr(IS) + == f"" + ) IS.init(pi) - assert repr(IS) == f"" + assert ( + repr(IS) + == f"" + ) IS.set_word(to_word("BaAbaBcAb")) assert ( repr(IS) diff --git a/tests/test_to.py b/tests/test_to.py index 46cdeb272..8d331ee12 100644 --- a/tests/test_to.py +++ b/tests/test_to.py @@ -69,7 +69,11 @@ def sample_to_str(i): def sample_to_int(x): - return "mnbvcxzlkjhgfdsapoiuytrewqMNBVCXZLKJHGFDSAPOIUYTREWQ5432167890".index(x) + return ( + "mnbvcxzlkjhgfdsapoiuytrewqMNBVCXZLKJHGFDSAPOIUYTREWQ5432167890".index( + x + ) + ) def sample_froidure_pin(): @@ -179,7 +183,9 @@ def check_froidure_pin_to_congruence(Word): def test_to_FroidurePin_000(): - fp = check_cong_to_froidure_pin(KnuthBendix, str, Rewriter="RewriteFromLeft") + fp = check_cong_to_froidure_pin( + KnuthBendix, str, Rewriter="RewriteFromLeft" + ) assert isinstance(to_cxx(fp), FroidurePinKBERewriteFromLeft) @@ -189,7 +195,9 @@ def test_to_FroidurePin_001(): def test_to_FroidurePin_002(): - fp = check_cong_to_froidure_pin(KnuthBendix, int, Rewriter="RewriteFromLeft") + fp = check_cong_to_froidure_pin( + KnuthBendix, int, Rewriter="RewriteFromLeft" + ) assert isinstance(to_cxx(fp), FroidurePinKBERewriteFromLeft) @@ -306,7 +314,9 @@ def test_to_FroidurePin_013(): def test_to_ToddCoxeter_014(): - tc = check_cong_to_todd_coxeter(KnuthBendix, str, Rewriter="RewriteFromLeft") + tc = check_cong_to_todd_coxeter( + KnuthBendix, str, Rewriter="RewriteFromLeft" + ) assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (str,) @@ -318,7 +328,9 @@ def test_to_ToddCoxeter_015(): def test_to_ToddCoxeter_016(): - tc = check_cong_to_todd_coxeter(KnuthBendix, int, Rewriter="RewriteFromLeft") + tc = check_cong_to_todd_coxeter( + KnuthBendix, int, Rewriter="RewriteFromLeft" + ) assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (list[int],) @@ -704,13 +716,15 @@ def test_to_InversePresentation_032(): assert iq.inverses() == [3, 4, 5, 0, 1, 2] assert iq.rules == q.rules - assert to(to(p, Return=(Presentation, list[int])), Return=(InversePresentation,)) == to( + assert to( + to(p, Return=(Presentation, list[int])), Return=(InversePresentation,) + ) == to( to(p, Return=(InversePresentation,)), Return=(Presentation, list[int]) ) - assert to(to(q, Return=(Presentation, str)), Return=(InversePresentation,)) == to( - to(q, Return=(InversePresentation,)), Return=(Presentation, str) - ) + assert to( + to(q, Return=(Presentation, str)), Return=(InversePresentation,) + ) == to(to(q, Return=(InversePresentation,)), Return=(Presentation, str)) ############################################################################### diff --git a/tests/test_ukkonen.py b/tests/test_ukkonen.py index 9fb294477..8e19294d9 100644 --- a/tests/test_ukkonen.py +++ b/tests/test_ukkonen.py @@ -13,7 +13,6 @@ # pylint: disable=fixme, missing-function-docstring # pylint: disable=missing-class-docstring, invalid-name - import pytest from libsemigroups_pybind11 import ( @@ -93,7 +92,7 @@ def test_000_b(): assert not ukkonen.is_subword(t, [3, 3]) assert not ukkonen.is_subword(t, "ab") - with pytest.raises(RuntimeError): + with pytest.raises(TypeError): ukkonen.is_subword(t, [UNDEFINED])