From 5c765f1d861625ef3c883cbb6c38867bcb26777a Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Thu, 19 Jun 2025 08:34:49 +0100 Subject: [PATCH 1/4] Lowercase kwargs everywhere --- docs/pictures/to-table.tex | 56 +++++---- .../presentations/to-inverse-present.rst | 8 +- .../presentations/to-present.rst | 12 +- docs/source/data-structures/to-function.rst | 6 +- .../main-algorithms/congruence/to-cong.rst | 2 +- .../froidure-pin/to-froidure-pin.rst | 10 +- .../knuth-bendix/to-knuth-bendix.rst | 8 +- .../todd-coxeter/to-todd-coxeter.rst | 4 +- .../detail/congruence_common.py | 12 +- src/libsemigroups_pybind11/knuth_bendix.py | 16 +-- .../presentation/__init__.py | 8 +- src/libsemigroups_pybind11/to.py | 18 +-- src/todd-coxeter.cpp | 2 +- tests/test_froidure_pin.py | 8 +- tests/test_knuth_bendix.py | 6 +- tests/test_obvinf.py | 2 +- tests/test_sims.py | 12 +- tests/test_stephen.py | 2 +- tests/test_to.py | 112 +++++++++--------- 19 files changed, 158 insertions(+), 146 deletions(-) diff --git a/docs/pictures/to-table.tex b/docs/pictures/to-table.tex index 6252a950a..554ad42be 100644 --- a/docs/pictures/to-table.tex +++ b/docs/pictures/to-table.tex @@ -10,29 +10,39 @@ \begin{document} \begin{tabular}{l|c|c|c|c|c|c|c|c|c|c|c} - & - \rotatebox{90}{\texttt{Congruence}} & - \rotatebox{90}{\texttt{FroidurePin}} & - \rotatebox{90}{\texttt{InversePresentation}} & - \rotatebox{90}{\texttt{Kambites}} & - \rotatebox{90}{\texttt{KnuthBendix}} & - \rotatebox{90}{\texttt{Konieczny}} & - \rotatebox{90}{\texttt{Presentation}} & - \rotatebox{90}{\texttt{SchreierSims}} & - \rotatebox{90}{\texttt{Stephen}} & - \rotatebox{90}{\texttt{ToddCoxeter}} - \\ - \midrule - \texttt{to(*args, Return=Congruence)} & \xmark & \cmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline - \texttt{to(*args, Return=FroidurePin)} & \cmark & \xmark & \xmark & \cmark & \cmark & \xmark & \xmark & \xmark & \xmark & \cmark \\\hline - \texttt{to(*args, Return=InversePresentation)} & \xmark & \xmark & \cmark & \xmark & \xmark & \xmark & \cmark & \xmark & \xmark & \xmark \\\hline - \texttt{to(*args, Return=Kambites)} & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline - \texttt{to(*args, Return=KnuthBendix)} & \xmark & \cmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \cmark \\\hline - \texttt{to(*args, Return=Konieczny)} & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline - \texttt{to(*args, Return=Presentation)} & \xmark & \cmark & \xmark & \xmark & \cmark & \xmark & \cmark & \xmark & \xmark & \xmark \\\hline - \texttt{to(*args, Return=SchreierSims)} & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline - \texttt{to(*args, Return=Stephen)} & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline - \texttt{to(*args, Return=ToddCoxeter)} & \xmark & \cmark & \xmark & \xmark & \cmark & \xmark & \xmark & \xmark & \xmark & \xmark \\ + & + \rotatebox{90}{\texttt{Congruence}} & + \rotatebox{90}{\texttt{FroidurePin}} & + \rotatebox{90}{\texttt{InversePresentation}} & + \rotatebox{90}{\texttt{Kambites}} & + \rotatebox{90}{\texttt{KnuthBendix}} & + \rotatebox{90}{\texttt{Konieczny}} & + \rotatebox{90}{\texttt{Presentation}} & + \rotatebox{90}{\texttt{SchreierSims}} & + \rotatebox{90}{\texttt{Stephen}} & + \rotatebox{90}{\texttt{ToddCoxeter}} + \\ + \midrule + \texttt{to(*args, rtype=Congruence)} & \xmark & \cmark & + \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline + \texttt{to(*args, rtype=FroidurePin)} & \cmark & \xmark & + \xmark & \cmark & \cmark & \xmark & \xmark & \xmark & \xmark & \cmark \\\hline + \texttt{to(*args, rtype=InversePresentation)} & \xmark & \xmark & + \cmark & \xmark & \xmark & \xmark & \cmark & \xmark & \xmark & \xmark \\\hline + \texttt{to(*args, rtype=Kambites)} & \xmark & \xmark & + \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline + \texttt{to(*args, rtype=KnuthBendix)} & \xmark & \cmark & + \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \cmark \\\hline + \texttt{to(*args, rtype=Konieczny)} & \xmark & \xmark & + \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline + \texttt{to(*args, rtype=Presentation)} & \xmark & \cmark & + \xmark & \xmark & \cmark & \xmark & \cmark & \xmark & \xmark & \xmark \\\hline + \texttt{to(*args, rtype=SchreierSims)} & \xmark & \xmark & + \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline + \texttt{to(*args, rtype=Stephen)} & \xmark & \xmark & + \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark & \xmark \\\hline + \texttt{to(*args, rtype=ToddCoxeter)} & \xmark & \cmark & + \xmark & \xmark & \cmark & \xmark & \xmark & \xmark & \xmark & \xmark \\ \end{tabular} % \cmark = implemented, \xmark = not yet implemented, - % = not applicable diff --git a/docs/source/data-structures/presentations/to-inverse-present.rst b/docs/source/data-structures/presentations/to-inverse-present.rst index 997bfa858..454ee2c1a 100644 --- a/docs/source/data-structures/presentations/to-inverse-present.rst +++ b/docs/source/data-structures/presentations/to-inverse-present.rst @@ -73,7 +73,7 @@ This function throws a :any:`LibsemigroupsError` if >>> presentation.add_rule(p, 'aaa', 'b') >>> presentation.add_rule(p, 'bac', 'cab') - >>> ip = to(p, Return=(InversePresentation,)) + >>> ip = to(p, rtype=(InversePresentation,)) >>> ip.alphabet() 'abcdef' >>> ip.inverses() @@ -139,10 +139,10 @@ not the same as that specified in *Return* and >>> presentation.add_rule(ip, 'aaa', 'b') >>> presentation.add_rule(ip, 'bac', 'cab') - >>> ip == to(ip, Return=(InversePresentation, str)) + >>> ip == to(ip, rtype=(InversePresentation, str)) True - >>> iq = to(ip, Return=(InversePresentation, list[int])) + >>> iq = to(ip, rtype=(InversePresentation, list[int])) >>> iq.alphabet() [0, 1, 2] >>> iq.inverses() @@ -204,7 +204,7 @@ type of word specified in *Return*. >>> iq = to( ... ip, # ip ... lambda x: chr(ord(x) + 11), # f - ... Return=(InversePresentation, str) + ... rtype=(InversePresentation, str) ... ) >>> iq.alphabet() 'lmn' diff --git a/docs/source/data-structures/presentations/to-present.rst b/docs/source/data-structures/presentations/to-present.rst index a3a4aca8c..0154ece27 100644 --- a/docs/source/data-structures/presentations/to-present.rst +++ b/docs/source/data-structures/presentations/to-present.rst @@ -87,16 +87,16 @@ not the same as that specified in *Return*, and >>> p.rules ['ae', 'e', 'ea', 'e', 'be', 'e', 'eb', 'e', 'ce', 'e', 'ec', 'e', 'de', 'e', 'ed', 'e', 'ee', 'e', 'fe', 'e', 'ef', 'e'] - >>> p == to(p, Return=(Presentation, str)) + >>> p == to(p, rtype=(Presentation, str)) True - >>> q = to(p, Return=(Presentation, list[int])) + >>> q = to(p, rtype=(Presentation, list[int])) >>> q.alphabet() [0, 1, 2, 3, 4, 5] >>> q.rules [[0, 4], [4], [4, 0], [4], [1, 4], [4], [4, 1], [4], [2, 4], [4], [4, 2], [4], [3, 4], [4], [4, 3], [4], [4, 4], [4], [5, 4], [4], [4, 5], [4]] - >>> p == to(q, Return=(Presentation, str)) + >>> p == to(q, rtype=(Presentation, str)) True .. _presentation-and-function-to-presentation: @@ -147,7 +147,7 @@ specified in *Return*. >>> q = to( ... p, # p ... double, # f - ... Return=(Presentation, list[int]) + ... rtype=(Presentation, list[int]) ... ) >>> q.alphabet() [0, 4, 8, 12] @@ -205,7 +205,7 @@ enumerates *kb*) prior to calling this function. >>> kb = KnuthBendix(congruence_kind.twosided, p1) >>> kb.run() - >>> p2 = to(kb, Return=(Presentation,)) + >>> p2 = to(kb, rtype=(Presentation,)) >>> for p in [p1, p2]: ... presentation.sort_each_rule(p) ... presentation.sort_rules(p) @@ -261,6 +261,6 @@ to calling this function. >>> b4 = Bipartition([[1, 2], [3, -3], [4, -4], [-1, -2]]) >>> S = FroidurePin(b1, b2, b3, b4) - >>> p = to(S, Return=(Presentation, str)) + >>> p = to(S, rtype=(Presentation, str)) >>> len(p.alphabet()) == 4 True diff --git a/docs/source/data-structures/to-function.rst b/docs/source/data-structures/to-function.rst index e9136cd96..d315c7405 100644 --- a/docs/source/data-structures/to-function.rst +++ b/docs/source/data-structures/to-function.rst @@ -15,11 +15,11 @@ This page contains links to the documentation of the uses of the function to another type. These mostly only apply to the types implementing the main algorithms in ``libsemigroups_pybind11``. -For example, to convert a :any:`ToddCoxeter` ``tc`` object to a -:any:`FroidurePin` object, you can simply do ``to(tc, Return=(FroidurePin,))``. +For example, to convert a :any:`ToddCoxeter` object ``tc`` to a +:any:`FroidurePin` object, you can simply do ``to(tc, rtype=(FroidurePin,))``. A summary of the possible conversions available in ``libsemigroups_pybind11`` of -``to(FromType, Return=(ToType,))`` are given below, where the rows correspond to +``to(FromType, rtype=(ToType,))`` are given below, where the rows correspond to ``ToType`` and the columns to ``FromType``: .. image:: ../../pictures/to-table.svg diff --git a/docs/source/main-algorithms/congruence/to-cong.rst b/docs/source/main-algorithms/congruence/to-cong.rst index 27784d21f..9e9518c7d 100644 --- a/docs/source/main-algorithms/congruence/to-cong.rst +++ b/docs/source/main-algorithms/congruence/to-cong.rst @@ -81,7 +81,7 @@ This will throw a :any:`LibsemigroupsError` if *wg* is not the ... congruence_kind.twosided, # knd ... S, # fpb ... S.right_cayley_graph(), # wg - ... Return=(Congruence, str), + ... rtype=(Congruence, str), ... ) >>> cong.run() diff --git a/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst b/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst index 1f9dd3d23..8222cc317 100644 --- a/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst +++ b/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst @@ -72,7 +72,7 @@ This function throws a :any:`LibsemigroupsError` if ``cong.kind`` is not >>> presentation.add_rule(p, [1, 1], [1]) >>> cong = Congruence(congruence_kind.twosided, p) - >>> fp = to(cong, Return=(FroidurePin,)) + >>> fp = to(cong, rtype=(FroidurePin,)) >>> fp.run() >>> fp.size() == cong.number_of_classes() @@ -121,7 +121,7 @@ This function throws a :any:`LibsemigroupsError` if the >>> presentation.add_rule(p, 'ef', 'dg') >>> k = Kambites(congruence_kind.twosided, p) - >>> fp = to(k, Return=(FroidurePin,)) + >>> fp = to(k, rtype=(FroidurePin,)) >>> fp.enumerate(100) >>> fp.current_size() == 8205 @@ -165,7 +165,7 @@ This function throws a :any:`LibsemigroupsError` if ``kb.kind()`` is not >>> presentation.add_rule(p, [1, 1], [1]) >>> kb = KnuthBendix(congruence_kind.twosided, p) - >>> fp = to(kb, Return=(FroidurePin,)) + >>> fp = to(kb, rtype=(FroidurePin,)) >>> fp.run() >>> fp.size() == kb.number_of_classes() @@ -209,7 +209,7 @@ This function throws a :any:`LibsemigroupsError` if ``tc.kind()`` is not >>> presentation.add_rule(p, [1, 1], [1]) >>> tc = ToddCoxeter(congruence_kind.twosided, p) - >>> fp = to(tc, Return=(FroidurePin,)) + >>> fp = to(tc, rtype=(FroidurePin,)) >>> fp.run() >>> fp.size() == tc.number_of_classes() @@ -286,7 +286,7 @@ corresponding :math:`f`. ... w, # wg ... 1, # first ... 2, # last - ... Return=(FroidurePin,) + ... rtype=(FroidurePin,) ... ) >>> fp.run() diff --git a/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst b/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst index 8ff008b21..f957dd613 100644 --- a/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst +++ b/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst @@ -77,7 +77,7 @@ the semigroup defined by *tc*. >>> kb = to( ... congruence_kind.twosided, # knd ... tc, # tc - ... Return=(KnuthBendix,) + ... rtype=(KnuthBendix,) ... ) >>> kb.run() @@ -132,7 +132,7 @@ the semigroup defined by *tc*. >>> kb = to( ... congruence_kind.twosided, # knd ... tc, # tc - ... Return=(KnuthBendix, 'RewriteFromLeft') + ... rtype=(KnuthBendix, 'RewriteFromLeft') ... ) >>> kb.run() @@ -169,7 +169,7 @@ Additionally, specify one of the following for *Return*: This function converts a :any:`FroidurePin` object *fpb* to a :any:`KnuthBendix` object with the word type and rewriter as specified above. This is done using -the presentation obtained from ``to(fpb, Return=(Presentation, Word)`` where +the presentation obtained from ``to(fpb, rtype=(Presentation, Word)`` where ``Word`` is either ``str`` or ``list[int]``. This returned :any:`KnuthBendix` object represents the trivial congruence over @@ -196,7 +196,7 @@ the semigroup defined by *fpb*. >>> kb = to( ... congruence_kind.twosided, # knd ... S, # tc - ... Return=(KnuthBendix, list[int], 'RewriteFromLeft') + ... rtype=(KnuthBendix, list[int], 'RewriteFromLeft') ... ) >>> kb.run() diff --git a/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst b/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst index 0b1da22bc..786155f59 100644 --- a/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst +++ b/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst @@ -83,7 +83,7 @@ This will throw a :any:`LibsemigroupsError` if *wg* is not the ... congruence_kind.twosided, # knd ... S, # fpb ... S.right_cayley_graph(), # wg - ... Return=(ToddCoxeter, str), + ... rtype=(ToddCoxeter, str), ... ) >>> tc.run() @@ -141,7 +141,7 @@ This will throw a :any:`LibsemigroupsError` if either: >>> tc = to( ... congruence_kind.twosided, # knd ... kb, # kb - ... Return=(ToddCoxeter,) + ... rtype=(ToddCoxeter,) ... ) >>> tc.run() diff --git a/src/libsemigroups_pybind11/detail/congruence_common.py b/src/libsemigroups_pybind11/detail/congruence_common.py index ed902c48d..3927e75f0 100644 --- a/src/libsemigroups_pybind11/detail/congruence_common.py +++ b/src/libsemigroups_pybind11/detail/congruence_common.py @@ -32,7 +32,7 @@ def __init__(self: Self, *args, wrong_num_args_msg="", **kwargs) -> None: # super().__init__ checks if there are unexpected kwargs, sets up # _cxx_type_to_py_template_params, and sets _cxx_obj if # the unique argument is a cxx_obj of type in _all_wrapped_cxx_types - super().__init__(*args, optional_kwargs="Word") + super().__init__(*args, optional_kwargs=("word",), **kwargs) if _to_cxx(self) is not None: # constructed from args[0] of type belonging to _all_wrapped_cxx_types return @@ -44,17 +44,17 @@ def __init__(self: Self, *args, wrong_num_args_msg="", **kwargs) -> None: if len(args) != 0 and len(kwargs) != 0: if len(wrong_num_args_msg) == 0: wrong_num_args_msg = ( - 'expected 2 positional arguments or 1 keyword arguments ("Word") ' + 'expected 2 positional arguments or 1 keyword arguments ("word",) ' f"but found {len(args)} and {len(kwargs)}" ) raise TypeError(wrong_num_args_msg) if len(args) == 0: - if kwargs["Word"] not in (str, list[int]): + if kwargs["word"] not in (str, list[int]): raise ValueError( - 'expected the keyword argument "Word" to be "str" or "list[int]" ' - f"but found {kwargs['Word']}" + 'expected the keyword argument "word" to be "str" or "list[int]" ' + f"but found {kwargs['word']}" ) - self.py_template_params = (kwargs["Word"],) + self.py_template_params = (kwargs["word"],) elif not isinstance(args[0], _congruence_kind): raise TypeError( f"expected the 1st argument to be congruence_kind but found {type(args[0])}" diff --git a/src/libsemigroups_pybind11/knuth_bendix.py b/src/libsemigroups_pybind11/knuth_bendix.py index 113589aaf..be8ccacf2 100644 --- a/src/libsemigroups_pybind11/knuth_bendix.py +++ b/src/libsemigroups_pybind11/knuth_bendix.py @@ -52,6 +52,8 @@ class KnuthBendix(_CongruenceCommon): # pylint: disable=missing-class-docstring __doc__ = _KnuthBendixStringRewriteTrie.__doc__ _py_template_params_to_cxx_type = { + (list[int],): _KnuthBendixWordRewriteTrie, + (str,): _KnuthBendixStringRewriteTrie, (list[int], "RewriteTrie"): _KnuthBendixWordRewriteTrie, (str, "RewriteTrie"): _KnuthBendixStringRewriteTrie, (list[int], "RewriteFromLeft"): _KnuthBendixWordRewriteFromLeft, @@ -70,17 +72,17 @@ class KnuthBendix(_CongruenceCommon): # pylint: disable=missing-class-docstring options = _KnuthBendixStringRewriteTrie.options @_copydoc(_KnuthBendixStringRewriteTrie.__init__) - def __init__(self, *args, Rewriter="RewriteTrie", **kwargs) -> None: - if Rewriter not in ("RewriteFromLeft", "RewriteTrie"): + def __init__(self, *args, rewriter="RewriteTrie", **kwargs) -> None: + if rewriter not in ("RewriteFromLeft", "RewriteTrie"): raise TypeError( - f'expected the keyword argument "Rewriter" to be ' - f'"RewriteFromLeft" or "RewriteTrie", but found "{Rewriter}"' + f'expected the keyword argument "rewriter" to be ' + f'"RewriteFromLeft" or "RewriteTrie", but found "{rewriter}"' ) msg = f"""expected either: 1) 2 positional arguments of types congruence_kind and Presentation; or -2) 0 positional arguments and the keyword argument "Word" - (and possibly the keyword argument "Rewriter"). +2) 0 positional arguments and the keyword argument "word" + (and possibly the keyword argument "rewriter"). Found {len(args)} positional arguments and keyword arguments {list(kwargs.keys())}!""" @@ -90,7 +92,7 @@ def __init__(self, *args, Rewriter="RewriteTrie", **kwargs) -> None: if len(args) == 2: if isinstance(args[1], _Presentation): self.py_template_params = args[1].py_template_params + ( - Rewriter, + rewriter, ) else: raise TypeError( diff --git a/src/libsemigroups_pybind11/presentation/__init__.py b/src/libsemigroups_pybind11/presentation/__init__.py index 6c72433b9..7fd8369c4 100644 --- a/src/libsemigroups_pybind11/presentation/__init__.py +++ b/src/libsemigroups_pybind11/presentation/__init__.py @@ -94,22 +94,22 @@ def __init__(self: Self, *args, **kwargs) -> None: """ # super().__init__ checks if there are unexpected kwargs, # and sets _cxx_obj if the unique argument is a cxx_obj of type in _all_wrapped_cxx_types - super().__init__(*args, optional_kwargs="Word") + super().__init__(*args, optional_kwargs="word") if _to_cxx(self) is not None: return if ( - (len(args) == 0 and "Word" not in kwargs) + (len(args) == 0 and "word" not in kwargs) or (len(args) == 1 and len(kwargs) > 0) or len(args) > 1 ): raise TypeError( - 'expected 1 positional argument or the keyword argument "Word"' + 'expected 1 positional argument or the keyword argument "word"' f" but found {len(args)} positional arguments, and keywords arguments " f"{tuple(kwargs.keys())}" ) if len(args) == 0: - self.py_template_params = (kwargs["Word"],) + self.py_template_params = (kwargs["word"],) if len(args) == 1: if not ( isinstance(args[0], (str, list)) diff --git a/src/libsemigroups_pybind11/to.py b/src/libsemigroups_pybind11/to.py index 2fecc0ce7..8b5933606 100644 --- a/src/libsemigroups_pybind11/to.py +++ b/src/libsemigroups_pybind11/to.py @@ -105,16 +105,16 @@ def _nice_name(type_list): _VALID_TYPES_STRING = "\n * " + "\n * ".join(_VALID_TYPES) + "\n" -def to(*args, Return): +def to(*args, rtype): """Convert from one type of `libsemigroups` object to another This function converts the the arguments specified in *args* to object of - type *Return*. + type *rtype*. :param args: the objects to convert. - :param Return: the type of object to convert to. + :param rtype: the type of object to convert to. - :returns: an object of type *Return*. + :returns: an object of type *rtype*. .. doctest:: @@ -132,7 +132,7 @@ def to(*args, Return): >>> presentation.add_rule(p, [0, 0], [0]) >>> presentation.add_rule(p, [1, 1], [1]) >>> kb = KnuthBendix(congruence_kind.twosided, p) - >>> fp = to(kb, Return=(FroidurePin,)) + >>> fp = to(kb, rtype=(FroidurePin,)) >>> fp # doctest: +NORMALIZE_WHITESPACE @@ -155,11 +155,11 @@ def to(*args, Return): """ cxx_args = [_to_cxx(arg) for arg in args] - if Return not in _RETURN_TYPE_TO_CONVERTER_FUNCTION: + if rtype not in _RETURN_TYPE_TO_CONVERTER_FUNCTION: raise TypeError( "expected the first keyword argument to be one of:" f"{_VALID_TYPES_STRING}" - f"but found: {_nice_name(Return)}" + f"but found: {_nice_name(rtype)}" ) - constructor = Return[0] - return constructor(_RETURN_TYPE_TO_CONVERTER_FUNCTION[Return](*cxx_args)) + constructor = rtype[0] + return constructor(_RETURN_TYPE_TO_CONVERTER_FUNCTION[rtype](*cxx_args)) diff --git a/src/todd-coxeter.cpp b/src/todd-coxeter.cpp index af4ddfee6..ab29e0e16 100644 --- a/src/todd-coxeter.cpp +++ b/src/todd-coxeter.cpp @@ -54,7 +54,7 @@ execution of (any version of) the Todd-Coxeter algorithm. >>> from libsemigroups_pybind11 import (presentation, Presentation, ToddCoxeter, ... congruence_kind, word_graph, Order, todd_coxeter) - >>> tc = ToddCoxeter(Word=str) + >>> tc = ToddCoxeter(word=str) >>> options = tc.options >>> p = Presentation("ab") >>> p.contains_empty_word(True) diff --git a/tests/test_froidure_pin.py b/tests/test_froidure_pin.py index 1feed66aa..3d33d4f3b 100644 --- a/tests/test_froidure_pin.py +++ b/tests/test_froidure_pin.py @@ -632,7 +632,7 @@ def test_froidure_pin_kbe_string(): # pylint: disable=too-many-statements presentation.add_rule(p, "bbbbbbbb", "bb") presentation.add_rule(p, "ab", "ba") kb = KnuthBendix(congruence_kind.twosided, p) - S = to(kb, Return=(FroidurePin,)) + S = to(kb, rtype=(FroidurePin,)) assert list(S.current_elements()) == ["a", "b"] assert S.size() == kb.number_of_classes() @@ -745,7 +745,7 @@ def test_froidure_pin_kbe_string(): # pylint: disable=too-many-statements assert T.number_of_generators() == 2 assert T.size() == 47 - S = to(kb, Return=(FroidurePin,)) + S = to(kb, rtype=(FroidurePin,)) assert S.sorted_position(S.generator(0)) == 0 assert S.sorted_position(S.generator(1)) == 1 assert S.sorted_position("a") == 0 @@ -775,7 +775,7 @@ def test_froidure_pin_kbe_word(): # pylint: disable=too-many-statements presentation.add_rule(p, [1] * 8, [1] * 2) presentation.add_rule(p, [0, 1], [1, 0]) kb = KnuthBendix(congruence_kind.twosided, p) - S = to(kb, Return=(FroidurePin,)) + S = to(kb, rtype=(FroidurePin,)) assert list(S.current_elements()) == [[0], [1]] @@ -862,7 +862,7 @@ def test_froidure_pin_kbe_word(): # pylint: disable=too-many-statements assert T.number_of_generators() == 2 assert T.size() == 47 - S = to(kb, Return=(FroidurePin,)) + S = to(kb, rtype=(FroidurePin,)) assert S.sorted_position(S.generator(0)) == 0 assert S.sorted_position(S.generator(1)) == 1 diff --git a/tests/test_knuth_bendix.py b/tests/test_knuth_bendix.py index 7f6a1aa38..f347a8dde 100644 --- a/tests/test_knuth_bendix.py +++ b/tests/test_knuth_bendix.py @@ -38,7 +38,7 @@ def check_initialisation(*args): for rewriter in ["RewriteFromLeft", "RewriteTrie"]: - kb = KnuthBendix(*args, Rewriter=rewriter) + kb = KnuthBendix(*args, rewriter=rewriter) kb.run() @@ -66,9 +66,9 @@ def test_initialisation(): kb2.run() with pytest.raises(TypeError): - KnuthBendix(kb, Rewriter="RewriteFromLeft") + KnuthBendix(kb, rewriter="RewriteFromLeft") - kb = KnuthBendix(kind, p, Rewriter="RewriteFromLeft") + kb = KnuthBendix(kind, p, rewriter="RewriteFromLeft") def test_attributes(): diff --git a/tests/test_obvinf.py b/tests/test_obvinf.py index 82aa0b370..d79bded87 100644 --- a/tests/test_obvinf.py +++ b/tests/test_obvinf.py @@ -38,7 +38,7 @@ def test_is_obviously_infinite_presentation(): assert is_obviously_infinite(p) - p = to(p, lambda x: "abcde"[x], Return=(Presentation, str)) + p = to(p, lambda x: "abcde"[x], rtype=(Presentation, str)) assert is_obviously_infinite(p) diff --git a/tests/test_sims.py b/tests/test_sims.py index 141b7bed4..79abb924b 100644 --- a/tests/test_sims.py +++ b/tests/test_sims.py @@ -291,7 +291,7 @@ def test_sims1_003(): presentation.add_rule(p, "acbbACb", "e") presentation.add_rule(p, "ABabccc", "e") S = Sims1() - S.presentation(to(p, Return=(Presentation, list[int]))) + S.presentation(to(p, rtype=(Presentation, list[int]))) assert S.number_of_congruences(3) == 14 @@ -422,7 +422,7 @@ def test_sims1_902(): presentation.add_rule(p, "db", "bb") presentation.add_rule(p, "cc", "c") presentation.add_rule(p, "bd", "bb") - s = Sims1(to(p, Return=(Presentation, list[int]))) + s = Sims1(to(p, rtype=(Presentation, list[int]))) assert s.number_of_congruences(2) == 67 assert s.number_of_threads(2).number_of_congruences(2) == 67 assert s.number_of_threads(4).number_of_congruences(2) == 67 @@ -458,7 +458,7 @@ def test_sims2_902(): p = Presentation("ab") presentation.add_rule(p, "ab", "ba") - s = Sims2(to(p, Return=(Presentation, list[int]))) + s = Sims2(to(p, rtype=(Presentation, list[int]))) assert s.number_of_congruences(1) == 1 assert s.number_of_congruences(2) == 9 assert s.number_of_congruences(3) == 37 @@ -525,7 +525,7 @@ def test_sims_refiner_ideals_902(): def test_sims1_return_policy(): p = Presentation("ab") p.rules = ["a" * 5, "a", "b" * 4, "b", "ab", "ba"] - q = to(p, Return=(Presentation, list[int])) + q = to(p, rtype=(Presentation, list[int])) s = Sims1(q) assert s.presentation() is s.presentation() @@ -552,7 +552,7 @@ def test_sims1_return_policy(): def test_sims2_return_policy(): p = Presentation("ab") p.rules = ["a" * 5, "a", "b" * 4, "b", "ab", "ba"] - q = to(p, Return=(Presentation, list[int])) + q = to(p, rtype=(Presentation, list[int])) s = Sims2(q) assert s.presentation() is s.presentation() @@ -609,5 +609,5 @@ def test_sims_refiner_ideals_return_policy(): assert sri.init() is sri p = Presentation("ab") p.rules = ["a" * 5, "a", "b" * 4, "b", "ab", "ba"] - q = to(p, Return=(Presentation, list[int])) + q = to(p, rtype=(Presentation, list[int])) assert sri.init(q) is sri diff --git a/tests/test_stephen.py b/tests/test_stephen.py index 561d66e66..2e3e4eca1 100644 --- a/tests/test_stephen.py +++ b/tests/test_stephen.py @@ -1278,7 +1278,7 @@ def test_stephen_043(): def test_stephen_044(): """inverse presentation -- operator==""" ReportGuard(False) - tc = ToddCoxeter(Word=list[int]) + tc = ToddCoxeter(word=list[int]) p = examples.symmetric_inverse_monoid(4) assert p.contains_empty_word() diff --git a/tests/test_to.py b/tests/test_to.py index f1e05a504..636c3f565 100644 --- a/tests/test_to.py +++ b/tests/test_to.py @@ -97,7 +97,7 @@ def cong_from_sample_pres(ReturnType, Word, **kwargs): def check_cong_to_froidure_pin(Type, Word, **kwargs): thing = cong_from_sample_pres(Type, Word, **kwargs) - fp = to(thing, Return=(FroidurePin,)) + fp = to(thing, rtype=(FroidurePin,)) fp.run() assert fp.is_finite() assert fp.number_of_idempotents() == 3 @@ -107,7 +107,7 @@ def check_cong_to_froidure_pin(Type, Word, **kwargs): def check_cong_to_todd_coxeter(Type, Word, **kwargs): thing = cong_from_sample_pres(Type, Word, **kwargs) - tc = to(congruence_kind.twosided, thing, Return=(ToddCoxeter,)) + tc = to(congruence_kind.twosided, thing, rtype=(ToddCoxeter,)) tc.run() assert tc.number_of_classes() == 3 return tc @@ -115,13 +115,13 @@ def check_cong_to_todd_coxeter(Type, Word, **kwargs): def check_knuth_bendix_to_pres(WordIn, WordOut, Rewriter): p = sample_pres(WordIn) - kb = KnuthBendix(congruence_kind.twosided, p, Rewriter=Rewriter) - q = to(kb, Return=(Presentation, WordOut)) + kb = KnuthBendix(congruence_kind.twosided, p, rewriter=Rewriter) + q = to(kb, rtype=(Presentation, WordOut)) assert len(q.rules) == kb.number_of_active_rules() * 2 if WordIn is WordOut: - assert q == to(kb, Return=(Presentation,)) + assert q == to(kb, rtype=(Presentation,)) presentation.sort_each_rule(p) presentation.sort_each_rule(q) presentation.sort_rules(p) @@ -140,7 +140,7 @@ def check_froidure_pin_to_pres(Word): S = sample_froidure_pin() assert S.size() == 105 - p = to(S, Return=(Presentation, Word)) + p = to(S, rtype=(Presentation, Word)) assert len(p.alphabet()) == 4 assert len(p.rules) == 86 assert isinstance(p, Presentation) @@ -148,21 +148,21 @@ def check_froidure_pin_to_pres(Word): def check_froidure_pin_to_knuth_bendix(Word, Rewriter): S = sample_froidure_pin() - kb = to(congruence_kind.twosided, S, Return=(KnuthBendix, Word, Rewriter)) + kb = to(congruence_kind.twosided, S, rtype=(KnuthBendix, Word, Rewriter)) assert S.size() == kb.number_of_classes() return kb def check_todd_coxeter_to_knuth_bendix(Word, Rewriter): tc = cong_from_sample_pres(ToddCoxeter, Word) - kb = to(congruence_kind.twosided, tc, Return=(KnuthBendix, Rewriter)) + kb = to(congruence_kind.twosided, tc, rtype=(KnuthBendix, Rewriter)) assert kb.number_of_classes() == tc.number_of_classes() return kb def check_todd_coxeter_to_knuth_bendix_default(Word): tc = cong_from_sample_pres(ToddCoxeter, Word) - kb = to(congruence_kind.twosided, tc, Return=(KnuthBendix,)) + kb = to(congruence_kind.twosided, tc, rtype=(KnuthBendix,)) assert kb.number_of_classes() == tc.number_of_classes() return kb @@ -173,7 +173,7 @@ def check_froidure_pin_to_congruence(Word): congruence_kind.twosided, S, S.right_cayley_graph(), - Return=(Congruence, Word), + rtype=(Congruence, Word), ) cong.run() assert S.size() == cong.number_of_classes() @@ -189,25 +189,25 @@ def check_froidure_pin_to_congruence(Word): def test_to_FroidurePin_000(): fp = check_cong_to_froidure_pin( - KnuthBendix, str, Rewriter="RewriteFromLeft" + KnuthBendix, str, rewriter="RewriteFromLeft" ) assert isinstance(to_cxx(fp), FroidurePinKBEStringRewriteFromLeft) def test_to_FroidurePin_001(): - fp = check_cong_to_froidure_pin(KnuthBendix, str, Rewriter="RewriteTrie") + fp = check_cong_to_froidure_pin(KnuthBendix, str, rewriter="RewriteTrie") assert isinstance(to_cxx(fp), FroidurePinKBEStringRewriteTrie) def test_to_FroidurePin_002(): fp = check_cong_to_froidure_pin( - KnuthBendix, int, Rewriter="RewriteFromLeft" + KnuthBendix, int, rewriter="RewriteFromLeft" ) assert isinstance(to_cxx(fp), FroidurePinKBEWordRewriteFromLeft) def test_to_FroidurePin_003(): - fp = check_cong_to_froidure_pin(KnuthBendix, int, Rewriter="RewriteTrie") + fp = check_cong_to_froidure_pin(KnuthBendix, int, rewriter="RewriteTrie") assert isinstance(to_cxx(fp), FroidurePinKBEWordRewriteTrie) @@ -239,8 +239,8 @@ def test_to_FroidurePin_007(): def test_to_FroidurePin_008(): - k = Kambites(Word=str) - fp = to(k, Return=(FroidurePin,)) + k = Kambites(word=str) + fp = to(k, rtype=(FroidurePin,)) assert isinstance(fp, FroidurePin) @@ -250,7 +250,7 @@ def test_to_FroidurePin_009(): presentation.add_rule(p, "ef", "dg") k = Kambites(congruence_kind.twosided, p) - fp = to(k, Return=(FroidurePin,)) + fp = to(k, rtype=(FroidurePin,)) fp.enumerate(100) assert fp.current_size() == 8205 assert isinstance(to_cxx(fp), FroidurePinKEMultiStringView) @@ -263,7 +263,7 @@ def test_to_FroidurePin_010(): presentation.add_rule(p, [4, 5], [3, 6]) k = Kambites(congruence_kind.twosided, p) - fp = to(k, Return=(FroidurePin,)) + fp = to(k, rtype=(FroidurePin,)) fp.enumerate(100) assert fp.current_size() == 8205 assert isinstance(to_cxx(fp), FroidurePinKEWord) @@ -277,7 +277,7 @@ def test_to_FroidurePin_011(): # Kambites wins here, so this checks FroidurePinKEString c = Congruence(congruence_kind.twosided, p) - fp = to(c, Return=(FroidurePin,)) + fp = to(c, rtype=(FroidurePin,)) fp.enumerate(100) assert fp.current_size() == 8205 assert isinstance(to_cxx(fp), FroidurePinKEString) @@ -293,7 +293,7 @@ def test_to_FroidurePin_012(): w.target(1, 0, 1) w.target(2, 0, 1) - fp = to(w, Return=(FroidurePin,)) + fp = to(w, rtype=(FroidurePin,)) fp.run() assert fp.number_of_rules() == 1 assert isinstance(fp, FroidurePin) @@ -305,7 +305,7 @@ def test_to_FroidurePin_013(): w.target(1, 0, 1) w.target(2, 0, 1) - fp = to(w, 1, 2, Return=(FroidurePin,)) + fp = to(w, 1, 2, rtype=(FroidurePin,)) fp.run() assert fp.number_of_rules() == 1 assert isinstance(fp, FroidurePin) @@ -320,28 +320,28 @@ def test_to_FroidurePin_013(): def test_to_ToddCoxeter_014(): tc = check_cong_to_todd_coxeter( - KnuthBendix, str, Rewriter="RewriteFromLeft" + KnuthBendix, str, rewriter="RewriteFromLeft" ) assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (str,) def test_to_ToddCoxeter_015(): - tc = check_cong_to_todd_coxeter(KnuthBendix, str, Rewriter="RewriteTrie") + tc = check_cong_to_todd_coxeter(KnuthBendix, str, rewriter="RewriteTrie") assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (str,) def test_to_ToddCoxeter_016(): tc = check_cong_to_todd_coxeter( - KnuthBendix, int, Rewriter="RewriteFromLeft" + KnuthBendix, int, rewriter="RewriteFromLeft" ) assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (list[int],) def test_to_ToddCoxeter_017(): - tc = check_cong_to_todd_coxeter(KnuthBendix, int, Rewriter="RewriteTrie") + tc = check_cong_to_todd_coxeter(KnuthBendix, int, rewriter="RewriteTrie") assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (list[int],) @@ -355,7 +355,7 @@ def test_to_ToddCoxeter_018(): congruence_kind.twosided, S, S.right_cayley_graph(), - Return=(ToddCoxeter, str), + rtype=(ToddCoxeter, str), ) assert tc.current_word_graph().number_of_nodes() == S.size() + 1 assert isinstance(tc, ToddCoxeter) @@ -367,7 +367,7 @@ def test_to_ToddCoxeter_019(): congruence_kind.twosided, S, S.right_cayley_graph(), - Return=(ToddCoxeter, list[int]), + rtype=(ToddCoxeter, list[int]), ) assert tc.current_word_graph().number_of_nodes() == S.size() + 1 assert isinstance(tc, ToddCoxeter) @@ -407,8 +407,8 @@ def test_to_Presentation_020(): "ef", "e", ] - assert p == to(p, Return=(Presentation, str)) - q = to(p, Return=(Presentation, list[int])) + assert p == to(p, rtype=(Presentation, str)) + q = to(p, rtype=(Presentation, list[int])) assert isinstance(q, Presentation) assert q.alphabet() == [0, 1, 2, 3, 4, 5] assert q.rules == [ @@ -435,7 +435,7 @@ def test_to_Presentation_020(): [4, 5], [4], ] - assert p == to(q, Return=(Presentation, str)) + assert p == to(q, rtype=(Presentation, str)) # From func + Presentation @@ -465,9 +465,9 @@ def test_to_Presentation_021(): "e", ] with pytest.raises(TypeError): - q = to(p, sample_to_str, Return=(Presentation, str)) + q = to(p, sample_to_str, rtype=(Presentation, str)) - q = to(p, sample_to_int, Return=(Presentation, list[int])) + q = to(p, sample_to_int, rtype=(Presentation, list[int])) assert isinstance(q, Presentation) assert q.alphabet() == [15, 2, 4, 13, 23] assert q.rules == [ @@ -492,9 +492,9 @@ def test_to_Presentation_021(): ] with pytest.raises(TypeError): - r = to(q, sample_to_int, Return=(Presentation, list[int])) + r = to(q, sample_to_int, rtype=(Presentation, list[int])) - r = to(q, sample_to_str, Return=(Presentation, str)) + r = to(q, sample_to_str, rtype=(Presentation, str)) assert isinstance(r, Presentation) assert r.alphabet() == "hetfb" assert r.rules == [ @@ -542,7 +542,7 @@ def test_to_Presentation_022(): "ee", "e", ] - q = to(p, lambda x: chr(ord(x) + 10), Return=(Presentation, str)) + q = to(p, lambda x: chr(ord(x) + 10), rtype=(Presentation, str)) assert q.alphabet() == "klmno" assert q.rules == [ "ko", @@ -589,7 +589,7 @@ def test_to_Presentation_023(): [4, 4], [4], ] - q = to(p, lambda x: x + 10, Return=(Presentation, list[int])) + q = to(p, lambda x: x + 10, rtype=(Presentation, list[int])) assert q.alphabet() == [10, 11, 12, 13, 14] assert q.rules == [ [10, 14], @@ -659,18 +659,18 @@ def test_to_InversePresentation_030(): ip.inverses("cba") presentation.add_rule(ip, "aaa", "b") presentation.add_rule(ip, "bac", "cab") - assert ip == to(ip, Return=(InversePresentation, str)) + assert ip == to(ip, rtype=(InversePresentation, str)) - iq = to(ip, Return=(InversePresentation, list[int])) + iq = to(ip, rtype=(InversePresentation, list[int])) assert iq.alphabet() == [0, 1, 2] assert iq.inverses() == [2, 1, 0] assert iq.rules == [[0, 0, 0], [1], [1, 0, 2], [2, 0, 1]] - ir = to(iq, Return=(InversePresentation, str)) + ir = to(iq, rtype=(InversePresentation, str)) assert ir == ip - assert iq == to(ir, Return=(InversePresentation, list[int])) - assert ip == to(iq, Return=(Presentation, str)) - assert iq == to(ir, Return=(Presentation, list[int])) + assert iq == to(ir, rtype=(InversePresentation, list[int])) + assert ip == to(iq, rtype=(Presentation, str)) + assert iq == to(ir, rtype=(Presentation, list[int])) # From function + InversePresentation @@ -682,22 +682,22 @@ def test_to_InversePresentation_031(): presentation.add_rule(ip, "aaa", "b") presentation.add_rule(ip, "bac", "cab") - iq = to(ip, sample_to_int, Return=(InversePresentation, list[int])) + iq = to(ip, sample_to_int, rtype=(InversePresentation, list[int])) assert iq.alphabet() == [15, 2, 4] assert iq.inverses() == [4, 2, 15] assert iq.rules == [[15, 15, 15], [2], [2, 15, 4], [4, 15, 2]] - ir = to(iq, sample_to_str, Return=(InversePresentation, str)) + ir = to(iq, sample_to_str, rtype=(InversePresentation, str)) assert ir.alphabet() == "het" assert ir.inverses() == "teh" # codespell:ignore teh assert ir.rules == ["hhh", "e", "eht", "the"] - iu = to(ip, lambda x: chr(ord(x) + 11), Return=(InversePresentation, str)) + iu = to(ip, lambda x: chr(ord(x) + 11), rtype=(InversePresentation, str)) assert iu.alphabet() == "lmn" assert iu.inverses() == "nml" assert iu.rules == ["lll", "m", "mln", "nlm"] - iv = to(iq, lambda x: x + 11, Return=(InversePresentation, list[int])) + iv = to(iq, lambda x: x + 11, rtype=(InversePresentation, list[int])) assert iv.alphabet() == [26, 13, 15] assert iv.inverses() == [15, 13, 26] assert iv.rules == [[26, 26, 26], [13], [13, 26, 15], [15, 26, 13]] @@ -710,26 +710,26 @@ def test_to_InversePresentation_032(): p = Presentation("abc") presentation.add_rule(p, "aaa", "b") presentation.add_rule(p, "bac", "cab") - ip = to(p, Return=(InversePresentation,)) + ip = to(p, rtype=(InversePresentation,)) assert ip.alphabet() == "abcdef" assert ip.inverses() == "defabc" assert ip.rules == p.rules - q = to(p, Return=(Presentation, list[int])) - iq = to(q, Return=(InversePresentation,)) + q = to(p, rtype=(Presentation, list[int])) + iq = to(q, rtype=(InversePresentation,)) assert iq.alphabet() == [0, 1, 2, 3, 4, 5] 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(p, rtype=(Presentation, list[int])), rtype=(InversePresentation,) ) == to( - to(p, Return=(InversePresentation,)), Return=(Presentation, list[int]) + to(p, rtype=(InversePresentation,)), rtype=(Presentation, list[int]) ) assert to( - to(q, Return=(Presentation, str)), Return=(InversePresentation,) - ) == to(to(q, Return=(InversePresentation,)), Return=(Presentation, str)) + to(q, rtype=(Presentation, str)), rtype=(InversePresentation,) + ) == to(to(q, rtype=(InversePresentation,)), rtype=(Presentation, str)) ############################################################################### @@ -825,8 +825,8 @@ def test_to_Congruence_044(): def test_to_999(): x = 10 with pytest.raises(TypeError): - to(x, Return=(FroidurePin,)) + to(x, rtype=(FroidurePin,)) with pytest.raises(TypeError): - to(x, Return=(ToddCoxeter,)) + to(x, rtype=(ToddCoxeter,)) with pytest.raises(TypeError): - to(x, Return=(str,)) + to(x, rtype=(str,)) From cb034acbea9ff01beb8df7a0920e906d987c081c Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Thu, 19 Jun 2025 09:21:21 +0100 Subject: [PATCH 2/4] cong-common: correct the doc for default ctors --- src/cong-common.cpp | 18 ++++++++++++------ src/cong-common.hpp | 4 +++- src/knuth-bendix.cpp | 15 ++++++++++----- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/cong-common.cpp b/src/cong-common.cpp index 5d0517b02..7ff11b44c 100644 --- a/src/cong-common.cpp +++ b/src/cong-common.cpp @@ -72,9 +72,11 @@ namespace libsemigroups { fmt::format_to(std::back_inserter(result), fmt_string, - "detail"_a = extra_doc.detail, - "example"_a = extra_doc.example, - "name"_a = name, + "detail"_a = extra_doc.detail, + "example"_a = extra_doc.example, + "extra_kwargs"_a = extra_doc.extra_kwargs, + "extra_kwargs_doc"_a = extra_doc.extra_kwargs_doc, + "name"_a = name, "only_document_once"_a = extra_doc.only_document_once ? only_doc_once : "", "raises"_a = extra_doc.raises, @@ -92,11 +94,15 @@ namespace libsemigroups { doc extra_doc) { thing.def(py::init<>(), make_doc(R"pbdoc( -:sig=() -> None: +:sig=(word: type{extra_kwargs}) -> None: {only_document_once} -Default constructor. This function default constructs an -uninitialised :any:`{name}` instance. +Default constructor. + +This function default constructs an uninitialised :any:`{name}` instance. + +:Keyword Arguments: + * **word** (*type*) -- the type of words to use, must be either ``str`` or ``list[int]``{extra_kwargs_doc} {detail} )pbdoc", diff --git a/src/cong-common.hpp b/src/cong-common.hpp index 233f474bc..2d80cbcf8 100644 --- a/src/cong-common.hpp +++ b/src/cong-common.hpp @@ -33,10 +33,12 @@ namespace libsemigroups { // declared below. struct doc { std::string_view detail = ""; + std::string_view example = ""; + std::string_view extra_kwargs = ""; + std::string_view extra_kwargs_doc = ""; bool only_document_once = false; std::string_view raises = ""; std::string_view var = ""; - std::string_view example = ""; }; //////////////////////////////////////////////////////////////////////// diff --git a/src/knuth-bendix.cpp b/src/knuth-bendix.cpp index c94d1f35d..847bc486f 100644 --- a/src/knuth-bendix.cpp +++ b/src/knuth-bendix.cpp @@ -78,7 +78,12 @@ nested class :any:`KnuthBendix.options`. //////////////////////////////////////////////////////////////////////// - def_construct_default(thing, "KnuthBendix"); + def_construct_default( + thing, + "KnuthBendix", + doc{.extra_kwargs = ", rewriter: str", .extra_kwargs_doc = R"pbdoc( + * **rewriter** (*str*) -- the type of rewriter to use, must be either ``"RewriteTrie"`` or ``"RewriteFromLeft"``.)pbdoc"sv}); + def_init_default(thing, "KnuthBendix"); def_construct_kind_presentation(thing, "KnuthBendix"); def_init_kind_presentation(thing, "KnuthBendix"); @@ -117,9 +122,9 @@ the current rules in the :py:class:`KnuthBendix` instance. // Helper functions - specific to KnuthBendix //////////////////////////////////////////////////////////////////////// - // This does not use def_normal_forms in cong-common.hpp because it does - // not return an Iterator object, and hence has its own implementation - // and doc. + // This does not use def_normal_forms in cong-common.hpp because it + // does not return an Iterator object, and hence has its own + // implementation and doc. m.def( "knuth_bendix_normal_forms", [](KnuthBendix_& ci) { return congruence_common::normal_forms(ci); }, @@ -336,7 +341,7 @@ Copy a :any:`NormalFormRange` object. }); thing.def("next", [](NormalFormRange& nfr) { nfr.next(); }); } // bind_normal_form_range - } // namespace + } // namespace template void bind_redundant_rule(py::module& m) { From 7becc735967e9eb5f9c944d4a4b5b3a4ffc83a6a Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Thu, 19 Jun 2025 09:50:02 +0100 Subject: [PATCH 3/4] sims: use keyword arg "word" instead of default ctor --- src/libsemigroups_pybind11/sims.py | 49 ++++++++++++++++++++++++------ src/sims.cpp | 49 ++++++++++++++++++++++-------- tests/test_sims.py | 26 ++++++++-------- 3 files changed, 89 insertions(+), 35 deletions(-) diff --git a/src/libsemigroups_pybind11/sims.py b/src/libsemigroups_pybind11/sims.py index 0d8c4fbc5..458a40461 100644 --- a/src/libsemigroups_pybind11/sims.py +++ b/src/libsemigroups_pybind11/sims.py @@ -44,21 +44,36 @@ class _SimsBase(_CxxWrapper): def __init__(self: _Self, *args, **kwargs) -> None: - super().__init__(*args, **kwargs) + super().__init__(*args, optional_kwargs=("word",), **kwargs) 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)}" ) - if len(kwargs) != 0: + if len(args) != 0 and len(kwargs) != 0: raise TypeError( - f"expected 0 keyword arguments, but found {len(kwargs)}" + "expected either 1 positional argument or 1" + f"keyword argument (but not both), but found {len(args)} and {len(kwargs)}" ) + if len(args) == 0: + if "word" not in kwargs: + raise TypeError( + f'expected the keyword argument "word", but found {tuple(kwargs.keys())}' + ) + # for when Sims has a facade + # if kwargs["word"] not in (str, list[int]): + # raise ValueError( + # 'the keyword argument "word" must be str or list[int], ' + # f"but found {kwargs['word']}" + # ) + if kwargs["word"] != list[int]: + raise ValueError( + f'the keyword argument "word" must be list[int], but found {kwargs["word"]}' + ) if len(args) == 0: - # self.Word = kwargs["Word"] - self.py_template_params = (list[int],) + self.py_template_params = (kwargs["word"],) else: if isinstance(args[0], _Presentation): self.py_template_params = args[0].py_template_params @@ -240,15 +255,31 @@ class SimsRefinerFaithful( @_copydoc(_SimsRefinerFaithful.__init__) def __init__(self: _Self, *args, **kwargs) -> None: - super().__init__(*args, **kwargs) + super().__init__(*args, optional_kwargs=("word",), **kwargs) 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)}" + ) + if len(args) != 0 and len(kwargs) != 0: + raise TypeError( + "expected either 1 positional argument or 1" + f"keyword argument (but not both), but found {len(args)} and {len(kwargs)}" + ) + if len(args) == 0: + if "word" not in kwargs: + raise TypeError( + f'expected the keyword argument "word", but found {tuple(kwargs.keys())}' + ) + if kwargs["word"] != list[int]: + raise ValueError( + f'the keyword argument "word" must be list[int], but found {kwargs["word"]}' + ) if len(args) == 0: - # self.Word = kwargs["Word"] - self.py_template_params = (list[int],) + self.py_template_params = (kwargs["word"],) else: - assert len(args) == 1 if ( isinstance(args[0], list) and all(isinstance(x, list) for x in args[0]) diff --git a/src/sims.cpp b/src/sims.cpp index e16131dca..494d6dac2 100644 --- a/src/sims.cpp +++ b/src/sims.cpp @@ -675,10 +675,13 @@ a congruence. [](Sims1 const& s1) { return to_human_readable_repr(s1); }); s1.def(py::init<>(), R"pbdoc( -:sig=(self: Sims1) -> None: -Default constructor. +:sig=(self: Sims1, word: type) -> None: + +This function returns an uninitialized :any:`Sims1` object that uses +words of type specified by *word*. -This function returns an uninitialized :any:`Sims1` object. +:Keyword Arguments: + * **word** (*type*) -- the type of words to use, must be ``list[int]``. )pbdoc"); s1.def(py::init const&>(), @@ -899,9 +902,13 @@ on the classes of a congruence. [](Sims2 const& s2) { return to_human_readable_repr(s2); }); s2.def(py::init<>(), R"pbdoc( -Default constructor. +:sig=(self: Sims2, word: type) -> None: -This function returns an uninitialized :any:`Sims2` object. +This function returns an uninitialized :any:`Sims2` object that uses +words of type specified by *word*. + +:Keyword Arguments: + * **word** (*type*) -- the type of words to use, must be ``list[int]``. )pbdoc"); s2.def("__copy__", [](Sims2 const& self) { return Sims2(self); }); @@ -1121,9 +1128,13 @@ returned (with ``0`` nodes and ``0`` edges). [](RepOrc const& ro) { return to_human_readable_repr(ro); }); ro.def(py::init<>(), R"pbdoc( -Default constructor. +:sig=(self: RepOrc, word: type) -> None: + +This function returns an uninitialized :any:`RepOrc` object that uses +words of type specified by *word*. -This function returns an uninitialized :any:`RepOrc` object. +:Keyword Arguments: + * **word** (*type*) -- the type of words to use, must be ``list[int]``. )pbdoc"); ro.def( @@ -1279,9 +1290,13 @@ edges). }); mro.def(py::init<>(), R"pbdoc( -Default constructor. +:sig=(self: MinimalRepOrc, word: type) -> None: + +This function returns an uninitialized :any:`MinimalRepOrc` object that uses +words of type specified by *word*. -This function returns an uninitialized :any:`MinimalRepOrc` object. +:Keyword Arguments: + * **word** (*type*) -- the type of words to use, must be ``list[int]``. )pbdoc"); mro.def( @@ -1386,9 +1401,13 @@ v)` such that every vertex of the word graph is compatible with :math:`(u, v)`. }); srf.def(py::init<>(), R"pbdoc( -Default constructor. +:sig=(self: SimsRefinerFaithful, word: type) -> None: -This function returns an uninitialized :any:`SimsRefinerFaithful` object. +This function returns an uninitialized :any:`SimsRefinerFaithful` object that uses +words of type specified by *word*. + +:Keyword Arguments: + * **word** (*type*) -- the type of words to use, must be ``list[int]``. )pbdoc"); srf.def(py::init const&>(), @@ -1510,9 +1529,13 @@ or two-sided congruences arising from ideals (Rees congruences). }); sri.def(py::init<>(), R"pbdoc( -Default constructor. +:sig=(self: SimsRefinerIdeals, word: type) -> None: + +This function returns an uninitialized :any:`SimsRefinerIdeals` object that uses +words of type specified by *word*. -This function returns an uninitialized :any:`SimsRefinerIdeals` object. +:Keyword Arguments: + * **word** (*type*) -- the type of words to use, must be ``list[int]``. )pbdoc"); sri.def(py::init const&>(), R"pbdoc( :sig=(self: SimsRefinerIdeals, p: Presentation) -> None: diff --git a/tests/test_sims.py b/tests/test_sims.py index 79abb924b..7283e626c 100644 --- a/tests/test_sims.py +++ b/tests/test_sims.py @@ -89,7 +89,7 @@ def test_sims1_000(): presentation.add_rule(p, [1, 1], [1]) presentation.add_rule(p, [0, 1, 0, 1], [0]) - S = Sims1() + S = Sims1(word=list[int]) assert S.presentation(p).number_of_threads(2).number_of_congruences(5) == 6 with pytest.raises(LibsemigroupsError): S.number_of_congruences(0) @@ -124,7 +124,7 @@ def test_sims1_000(): 5, lambda wg: check_right_generating_pairs(S, wg) ) presentation.reverse(p) - S = Sims1() + S = Sims1(word=list[int]) assert S.presentation(p).number_of_congruences(5) == 9 for wg in S.iterator(5): assert word_graph.follow_path( @@ -164,7 +164,7 @@ def test_sims1_001(): presentation.add_rule(p, [1, 1], [1]) presentation.add_rule(p, [0, 2], [0, 0]) - S = Sims1() + S = Sims1(word=list[int]) S.presentation(p) assert S.number_of_congruences(1) == 1 assert S.number_of_congruences(2) == 3 @@ -203,7 +203,7 @@ def test_sims1_002(): presentation.add_rule(p, [0, 0, 5, 0, 4], [6]) presentation.add_rule(p, [0, 4, 2, 2, 1, 5, 2], [6]) presentation.add_rule(p, [1, 3, 0, 2, 4, 4, 4], [6]) - S = Sims1() + S = Sims1(word=list[int]) S.presentation(p) S.for_each(3, lambda wg: check_right_generating_pairs(S, wg)) @@ -290,7 +290,7 @@ def test_sims1_003(): presentation.add_rule(p, "aaCac", "e") presentation.add_rule(p, "acbbACb", "e") presentation.add_rule(p, "ABabccc", "e") - S = Sims1() + S = Sims1(word=list[int]) S.presentation(to(p, rtype=(Presentation, list[int]))) assert S.number_of_congruences(3) == 14 @@ -331,12 +331,12 @@ def test_sims1_004(): assert S.number_of_congruences(16) == 105 assert S.number_of_congruences(17) == 105 - T = Sims2() + T = Sims2(word=list[int]) T.presentation(p) T.number_of_threads(2) assert T.number_of_congruences(16) == 13 - orc = MinimalRepOrc() + orc = MinimalRepOrc(word=list[int]) d = ( orc.presentation(p) .target_size(15) @@ -359,7 +359,7 @@ def test_sims_refiner_faithful_128(): forbid = [[0], [0, 1], [0, 0], []] pruno = SimsRefinerFaithful(forbid) - S = Sims1() + S = Sims1(word=list[int]) S.presentation(p) S.add_pruner(pruno) assert ( @@ -577,7 +577,7 @@ def test_sims2_return_policy(): def test_rep_orc_return_policy(): - ro = RepOrc() + ro = RepOrc(word=list[int]) assert ro.init() is ro assert ro.max_nodes(10) is ro assert ro.min_nodes(9) is ro @@ -585,26 +585,26 @@ def test_rep_orc_return_policy(): def test_min_rep_orc_return_policy(): - ro = MinimalRepOrc() + ro = MinimalRepOrc(word=list[int]) assert ro.init() is ro assert ro.target_size(27) is ro def test_sims_refiner_faithful_return_policy(): - srf = SimsRefinerFaithful() + srf = SimsRefinerFaithful(word=list[int]) assert srf.init() is srf assert srf.init([[0, 1], [0]]) is srf def test_sims_refiner_faithful_call(): - srf = SimsRefinerFaithful() + srf = SimsRefinerFaithful(word=list[int]) wg = WordGraph(2, [[0, 1]]) assert srf(wg) def test_sims_refiner_ideals_return_policy(): - sri = SimsRefinerIdeals() + sri = SimsRefinerIdeals(word=list[int]) assert sri.presentation() is sri.presentation() assert sri.init() is sri p = Presentation("ab") From 1cf456c5b176252c7eaa877685b06193def0c69e Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Thu, 19 Jun 2025 10:06:48 +0100 Subject: [PATCH 4/4] Add TODO --- src/libsemigroups_pybind11/presentation/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsemigroups_pybind11/presentation/__init__.py b/src/libsemigroups_pybind11/presentation/__init__.py index 7fd8369c4..54aaca7a9 100644 --- a/src/libsemigroups_pybind11/presentation/__init__.py +++ b/src/libsemigroups_pybind11/presentation/__init__.py @@ -88,10 +88,10 @@ class Presentation(_CxxWrapper): # pylint: disable=missing-class-docstring def __eq__(self: Self, other: Self): return _to_cxx(self) == _to_cxx(other) + # TODO this isn't correct, need to also doc passing the alphabet + # TODO ditto for InversePresentation + @_copydoc(_PresentationWord.__init__) def __init__(self: Self, *args, **kwargs) -> None: - """ - Construct a Presentation instance of the type specified by its argument. - """ # super().__init__ checks if there are unexpected kwargs, # and sets _cxx_obj if the unique argument is a cxx_obj of type in _all_wrapped_cxx_types super().__init__(*args, optional_kwargs="word")