diff --git a/docs/source/data-structures/order/index.rst b/docs/source/data-structures/order/index.rst index 6f371ce9..6ba9a31a 100644 --- a/docs/source/data-structures/order/index.rst +++ b/docs/source/data-structures/order/index.rst @@ -23,17 +23,26 @@ Contents .. autosummary:: :signatures: short + len_wt_lex_cmp lenlex_cmp lex_cmp lexicographical_compare recursive_path_compare + rev_len_wt_lex_cmp + rev_lenlex_cmp + rev_lex_cmp rev_rpo_cmp + rev_wr_cmp + rev_wt_lenlex_cmp + rev_wt_lex_cmp rpo_cmp shortlex_compare Full API -------- +.. autofunction:: len_wt_lex_cmp + .. autofunction:: lenlex_cmp .. autofunction:: lex_cmp @@ -42,8 +51,20 @@ Full API .. autofunction:: recursive_path_compare +.. autofunction:: rev_len_wt_lex_cmp + +.. autofunction:: rev_lenlex_cmp + +.. autofunction:: rev_lex_cmp + .. autofunction:: rev_rpo_cmp +.. autofunction:: rev_wr_cmp + +.. autofunction:: rev_wt_lenlex_cmp + +.. autofunction:: rev_wt_lex_cmp + .. autofunction:: rpo_cmp .. autofunction:: shortlex_compare diff --git a/src/libsemigroups_pybind11/__init__.py b/src/libsemigroups_pybind11/__init__.py index 4d15bbd4..55452ab4 100644 --- a/src/libsemigroups_pybind11/__init__.py +++ b/src/libsemigroups_pybind11/__init__.py @@ -104,6 +104,7 @@ delta, error_message_with_prefix, freeband_equal_to, + len_wt_lex_cmp as _len_wt_lex_cmp, lenlex_cmp as _lenlex_cmp, lex_cmp as _lex_cmp, lexicographical_compare, @@ -112,7 +113,13 @@ random_strings, random_word, recursive_path_compare, + rev_len_wt_lex_cmp as _rev_len_wt_lex_cmp, + rev_lenlex_cmp as _rev_lenlex_cmp, + rev_lex_cmp as _rev_lex_cmp, rev_rpo_cmp as _rev_rpo_cmp, + rev_wr_cmp as _rev_wr_cmp, + rev_wt_lenlex_cmp as _rev_wt_lenlex_cmp, + rev_wt_lex_cmp as _rev_wt_lex_cmp, rpo_cmp as _rpo_cmp, shortlex_compare, side, @@ -125,9 +132,16 @@ ) from e +len_wt_lex_cmp = _wrap_cxx_free_fn(_len_wt_lex_cmp) lenlex_cmp = _wrap_cxx_free_fn(_lenlex_cmp) lex_cmp = _wrap_cxx_free_fn(_lex_cmp) +rev_len_wt_lex_cmp = _wrap_cxx_free_fn(_rev_len_wt_lex_cmp) +rev_lenlex_cmp = _wrap_cxx_free_fn(_rev_lenlex_cmp) +rev_lex_cmp = _wrap_cxx_free_fn(_rev_lex_cmp) rev_rpo_cmp = _wrap_cxx_free_fn(_rev_rpo_cmp) +rev_wr_cmp = _wrap_cxx_free_fn(_rev_wr_cmp) +rev_wt_lenlex_cmp = _wrap_cxx_free_fn(_rev_wt_lenlex_cmp) +rev_wt_lex_cmp = _wrap_cxx_free_fn(_rev_wt_lex_cmp) rpo_cmp = _wrap_cxx_free_fn(_rpo_cmp) @@ -169,6 +183,7 @@ "delta", "error_message_with_prefix", "freeband_equal_to", + "len_wt_lex_cmp", "lenlex_cmp", "lex_cmp", "lexicographical_compare", @@ -177,7 +192,13 @@ "random_strings", "random_word", "recursive_path_compare", + "rev_len_wt_lex_cmp", + "rev_lenlex_cmp", + "rev_lex_cmp", "rev_rpo_cmp", + "rev_wr_cmp", + "rev_wt_lenlex_cmp", + "rev_wt_lex_cmp", "rpo_cmp", "shortlex_compare", "side", diff --git a/src/order.cpp b/src/order.cpp index 8e05b195..514c76d4 100644 --- a/src/order.cpp +++ b/src/order.cpp @@ -137,6 +137,662 @@ word contains a letter that does not belong to *alphabet*. :rtype: bool )pbdoc"); + m.def( + "rev_lex_cmp", + [](Word const& x, Word const& y) { return rev_lex_cmp(x, y); }, + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using reversed lexicographic ordering. + +The words are read from right to left before being compared. + +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +.. doctest:: python + + >>> from libsemigroups_pybind11 import rev_lex_cmp + >>> rev_lex_cmp("ba", "ab") + True +)pbdoc"); + + m.def( + "rev_lex_cmp", + [](Alphabet const& alphabet, Word const& x, Word const& y) { + return rev_lex_cmp(alphabet, x, y); + }, + py::arg("alphabet"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using alphabet-aware reversed lexicographic ordering. + +Letters are compared by their positions in *alphabet*, and the words are read +from right to left before being compared. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if either word contains a letter that does not + belong to *alphabet*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, rev_lex_cmp + >>> rev_lex_cmp(Alphabet("ab"), "ba", "ab") + True +)pbdoc"); + + m.def( + "rev_lenlex_cmp", + [](Word const& x, Word const& y) { return rev_lenlex_cmp(x, y); }, + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using reversed len-lex ordering. + +Words are first ordered by length and then lexicographically after being read +from right to left. + +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +.. doctest:: python + + >>> from libsemigroups_pybind11 import rev_lenlex_cmp + >>> rev_lenlex_cmp([1, 0], [0, 1]) + True +)pbdoc"); + + m.def( + "rev_lenlex_cmp", + [](Alphabet const& alphabet, Word const& x, Word const& y) { + return rev_lenlex_cmp(alphabet, x, y); + }, + py::arg("alphabet"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using alphabet-aware reversed len-lex ordering. + +Words are first ordered by length and then lexicographically after being read +from right to left. Letters are compared by their positions in *alphabet*. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if either word contains a letter that does not + belong to *alphabet*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, rev_lenlex_cmp + >>> rev_lenlex_cmp(Alphabet("ab"), "ba", "ab") + True +)pbdoc"); + + m.def( + "wt_lenlex_cmp", + [](std::vector const& weights, Word const& x, Word const& y) { + return wt_lenlex_cmp(weights, x, y); + }, + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using weighted len-lex ordering. + +The *i*-th entry of *weights* is the weight assigned to generator *i*. +Words are first ordered by their total weight, then by length, and finally +lexicographically. + +:param weights: the weight assigned to each generator. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import wt_lenlex_cmp + >>> wt_lenlex_cmp([1, 2], [1], [0, 0]) + True +)pbdoc"); + + m.def( + "wt_lenlex_cmp", + [](Alphabet const& alphabet, + std::vector const& weights, + Word const& x, + Word const& y) { return wt_lenlex_cmp(alphabet, weights, x, y); }, + py::arg("alphabet"), + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using alphabet-aware weighted len-lex ordering. + +Letters are mapped to their positions in *alphabet*, and the *i*-th entry of +*weights* is the weight assigned to the *i*-th letter of *alphabet*. Words are +first ordered by their total weight, then by length, and finally +lexicographically according to *alphabet*. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param weights: the weight assigned to each letter of *alphabet*. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter does not belong to *alphabet*, or its + position in *alphabet* is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, wt_lenlex_cmp + >>> wt_lenlex_cmp(Alphabet("ba"), [1, 1], "b", "a") + True +)pbdoc"); + + m.def( + "wt_lex_cmp", + [](std::vector const& weights, Word const& x, Word const& y) { + return wt_lex_cmp(weights, x, y); + }, + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using weighted lexicographic ordering. + +The *i*-th entry of *weights* is the weight assigned to generator *i*. +Words are first ordered by their total weight and then lexicographically. + +:param weights: the weight assigned to each generator. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import wt_lex_cmp + >>> wt_lex_cmp([1, 2], [1], [0, 0]) + False +)pbdoc"); + + m.def( + "wt_lex_cmp", + [](Alphabet const& alphabet, + std::vector const& weights, + Word const& x, + Word const& y) { return wt_lex_cmp(alphabet, weights, x, y); }, + py::arg("alphabet"), + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using alphabet-aware weighted lexicographic ordering. + +Letters are mapped to their positions in *alphabet*, and the *i*-th entry of +*weights* is the weight assigned to the *i*-th letter of *alphabet*. Words are +first ordered by their total weight and then lexicographically according to +*alphabet*. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param weights: the weight assigned to each letter of *alphabet*. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter does not belong to *alphabet*, or its + position in *alphabet* is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, wt_lex_cmp + >>> wt_lex_cmp(Alphabet("ba"), [1, 1], "b", "a") + True +)pbdoc"); + + m.def( + "len_wt_lex_cmp", + [](std::vector const& weights, Word const& x, Word const& y) { + return len_wt_lex_cmp(weights, x, y); + }, + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words by length, weight, and lexicographic order. + +Words are first ordered by length, then by total weight, and finally +lexicographically. The *i*-th entry of *weights* is the weight assigned to +generator *i*. + +:param weights: the weight assigned to each generator. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import len_wt_lex_cmp + >>> len_wt_lex_cmp([1, 1], [0, 1], [1, 0]) + True +)pbdoc"); + + m.def( + "len_wt_lex_cmp", + [](Alphabet const& alphabet, + std::vector const& weights, + Word const& x, + Word const& y) { return len_wt_lex_cmp(alphabet, weights, x, y); }, + py::arg("alphabet"), + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words by length, weight, and alphabet-aware lexicographic order. + +Letters are mapped to their positions in *alphabet*, and the *i*-th entry of +*weights* is the weight assigned to the *i*-th letter of *alphabet*. Words are +first ordered by length, then by total weight, and finally lexicographically +according to *alphabet*. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param weights: the weight assigned to each letter of *alphabet*. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter does not belong to *alphabet*, or its + position in *alphabet* is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, len_wt_lex_cmp + >>> len_wt_lex_cmp(Alphabet("ab"), [1, 1], "ab", "ba") + True +)pbdoc"); + + m.def( + "rev_wr_cmp", + [](std::vector const& levels, Word const& x, Word const& y) { + return rev_wr_cmp(levels, x, y); + }, + py::arg("levels"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(levels: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using reversed wreath-product ordering. + +The words are read from right to left before being compared. The *i*-th entry +of *levels* is the wreath-product level assigned to generator *i*. + +:param levels: the level assigned to each generator. +:type levels: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter is not a valid index into *levels*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import rev_wr_cmp + >>> rev_wr_cmp([0, 0], [1, 0], [0, 1]) + True +)pbdoc"); + + m.def( + "rev_wr_cmp", + [](Alphabet const& alphabet, + std::vector const& levels, + Word const& x, + Word const& y) { return rev_wr_cmp(alphabet, levels, x, y); }, + py::arg("alphabet"), + py::arg("levels"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, levels: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using alphabet-aware reversed wreath-product ordering. + +Letters are mapped to their positions in *alphabet*, and the *i*-th entry of +*levels* is the wreath-product level assigned to the *i*-th letter of +*alphabet*. The words are read from right to left before being compared. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param levels: the level assigned to each letter of *alphabet*. +:type levels: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter does not belong to *alphabet*, or its + position in *alphabet* is not a valid index into *levels*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, rev_wr_cmp + >>> rev_wr_cmp(Alphabet("ab"), [0, 0], "ba", "ab") + True +)pbdoc"); + + m.def( + "rev_wt_lenlex_cmp", + [](std::vector const& weights, Word const& x, Word const& y) { + return rev_wt_lenlex_cmp(weights, x, y); + }, + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using reversed weighted len-lex ordering. + +Words are first ordered by total weight, then by length, and finally +lexicographically after being read from right to left. The *i*-th entry of +*weights* is the weight assigned to generator *i*. + +:param weights: the weight assigned to each generator. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import rev_wt_lenlex_cmp + >>> rev_wt_lenlex_cmp([1, 1], [1, 0], [0, 1]) + True +)pbdoc"); + + m.def( + "rev_wt_lenlex_cmp", + [](Alphabet const& alphabet, + std::vector const& weights, + Word const& x, + Word const& y) { + return rev_wt_lenlex_cmp(alphabet, weights, x, y); + }, + py::arg("alphabet"), + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using alphabet-aware reversed weighted len-lex ordering. + +Letters are mapped to their positions in *alphabet*, and the *i*-th entry of +*weights* is the weight assigned to the *i*-th letter of *alphabet*. Words are +first ordered by total weight, then by length, and finally lexicographically +after being read from right to left. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param weights: the weight assigned to each letter of *alphabet*. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter does not belong to *alphabet*, or its + position in *alphabet* is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, rev_wt_lenlex_cmp + >>> rev_wt_lenlex_cmp(Alphabet("ab"), [1, 1], "ba", "ab") + True +)pbdoc"); + + m.def( + "rev_wt_lex_cmp", + [](std::vector const& weights, Word const& x, Word const& y) { + return rev_wt_lex_cmp(weights, x, y); + }, + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using reversed weighted lexicographic ordering. + +Words are first ordered by total weight and then lexicographically after being +read from right to left. The *i*-th entry of *weights* is the weight assigned +to generator *i*. + +:param weights: the weight assigned to each generator. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import rev_wt_lex_cmp + >>> rev_wt_lex_cmp([1, 1], [1, 0], [0, 1]) + True +)pbdoc"); + + m.def( + "rev_wt_lex_cmp", + [](Alphabet const& alphabet, + std::vector const& weights, + Word const& x, + Word const& y) { return rev_wt_lex_cmp(alphabet, weights, x, y); }, + py::arg("alphabet"), + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words using alphabet-aware reversed weighted lexicographic ordering. + +Letters are mapped to their positions in *alphabet*, and the *i*-th entry of +*weights* is the weight assigned to the *i*-th letter of *alphabet*. Words are +first ordered by total weight and then lexicographically after being read from +right to left. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param weights: the weight assigned to each letter of *alphabet*. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter does not belong to *alphabet*, or its + position in *alphabet* is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, rev_wt_lex_cmp + >>> rev_wt_lex_cmp(Alphabet("ab"), [1, 1], "ba", "ab") + True +)pbdoc"); + + m.def( + "rev_len_wt_lex_cmp", + [](std::vector const& weights, Word const& x, Word const& y) { + return rev_len_wt_lex_cmp(weights, x, y); + }, + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words by length, weight, and reversed lexicographic order. + +Words are first ordered by length, then by total weight, and finally +lexicographically after being read from right to left. The *i*-th entry of +*weights* is the weight assigned to generator *i*. + +:param weights: the weight assigned to each generator. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import rev_len_wt_lex_cmp + >>> rev_len_wt_lex_cmp([1, 1], [1, 0], [0, 1]) + True +)pbdoc"); + + m.def( + "rev_len_wt_lex_cmp", + [](Alphabet const& alphabet, + std::vector const& weights, + Word const& x, + Word const& y) { + return rev_len_wt_lex_cmp(alphabet, weights, x, y); + }, + py::arg("alphabet"), + py::arg("weights"), + py::arg("x"), + py::arg("y"), + R"pbdoc( +:sig=(alphabet: Alphabet, weights: list[int], x: str | list[int], y: str | list[int]) -> bool: +:only-document-once: +Compare two words by length, weight, and alphabet-aware reversed lexicographic order. + +Letters are mapped to their positions in *alphabet*, and the *i*-th entry of +*weights* is the weight assigned to the *i*-th letter of *alphabet*. Words are +first ordered by length, then by total weight, and finally lexicographically +after being read from right to left. + +:param alphabet: the ordered alphabet containing the letters of both words. +:type alphabet: Alphabet +:param weights: the weight assigned to each letter of *alphabet*. +:type weights: list[int] +:param x: the first word. +:type x: str | list[int] +:param y: the second word. +:type y: str | list[int] +:returns: Whether *x* is less than *y*. +:rtype: bool + +:raises LibsemigroupsError: if a letter does not belong to *alphabet*, or its + position in *alphabet* is not a valid index into *weights*. + +.. doctest:: python + + >>> from libsemigroups_pybind11 import Alphabet, rev_len_wt_lex_cmp + >>> rev_len_wt_lex_cmp(Alphabet("ab"), [1, 1], "ba", "ab") + True +)pbdoc"); + bind_compare( m, "rpo_cmp", @@ -322,7 +978,7 @@ respectively, in new code. The recursive-path ordering, as described in :cite:`Jantzen2012aa` (Definition 1.2.14, page 24). - + This is deprecated; use :any:`Order.rpo` instead. )pbdoc") .value("none", Order::none) diff --git a/tests/test_order.py b/tests/test_order.py index 5805036f..8654ba46 100644 --- a/tests/test_order.py +++ b/tests/test_order.py @@ -12,11 +12,18 @@ Alphabet, LibsemigroupsError, Order, + len_wt_lex_cmp, lenlex_cmp, lex_cmp, lexicographical_compare, recursive_path_compare, + rev_len_wt_lex_cmp, + rev_lenlex_cmp, + rev_lex_cmp, rev_rpo_cmp, + rev_wr_cmp, + rev_wt_lenlex_cmp, + rev_wt_lex_cmp, rpo_cmp, shortlex_compare, ) @@ -29,6 +36,10 @@ (lex_cmp, [0, 1], [1, 0]), (lenlex_cmp, "ba", "aaa"), (lenlex_cmp, [1, 0], [0, 0, 0]), + (rev_lex_cmp, "ab", "ba"), + (rev_lex_cmp, [0, 1], [1, 0]), + (rev_lenlex_cmp, "ba", "aaa"), + (rev_lenlex_cmp, [1, 0], [0, 0, 0]), (rpo_cmp, "ab", "ba"), (rpo_cmp, [0, 1], [1, 0]), (rev_rpo_cmp, "ab", "ba"), @@ -40,7 +51,9 @@ def test_compare_without_alphabet(compare, x, y): assert isinstance(compare(x, y), bool) -@pytest.mark.parametrize("compare", [lex_cmp, lenlex_cmp, rpo_cmp, rev_rpo_cmp]) +@pytest.mark.parametrize( + "compare", [lex_cmp, lenlex_cmp, rev_lex_cmp, rev_lenlex_cmp, rpo_cmp, rev_rpo_cmp] +) @pytest.mark.parametrize( ("alphabet", "x", "y", "missing"), [(Alphabet("ba"), "ba", "ab", "c"), (Alphabet([1, 0]), [1, 0], [0, 1], [2])], @@ -73,3 +86,53 @@ def test_deprecated_comparisons(old_compare, new_compare): with pytest.deprecated_call(): result = old_compare("ab", "ba") assert result == new_compare("ab", "ba") + + +@pytest.mark.parametrize( + ("compare", "parameters"), + [ + (rev_wr_cmp, [0, 0]), + (rev_wt_lenlex_cmp, [1, 1]), + (rev_wt_lex_cmp, [1, 1]), + (rev_len_wt_lex_cmp, [1, 1]), + ], +) +def test_parameterized_reverse_comparisons(compare, parameters): + """Check parameterized reverse orders for both supported word types.""" + assert compare(parameters, [1, 0], [0, 1]) + assert compare(Alphabet("ab"), parameters, "ba", "ab") + + with pytest.raises(LibsemigroupsError): + compare(parameters, [2], [0, 1]) + + with pytest.raises(LibsemigroupsError): + compare(Alphabet("ab"), parameters, "c", "ab") + + +def test_reverse_weighted_comparisons_use_the_expected_priorities(): + """Check the weight and length priorities of the reverse weighted orders.""" + weights = [1, 2] + + assert rev_wt_lenlex_cmp(weights, [1], [0, 0]) + assert not rev_wt_lex_cmp(weights, [1], [0, 0]) + + weights = [100, 1] + assert rev_len_wt_lex_cmp(weights, [0], [1, 1]) + assert not rev_wt_lex_cmp(weights, [0], [1, 1]) + + +def test_len_wt_lex_cmp(): + """Check length-before-weighted-lex ordering and validation.""" + weights = [1, 1] + + assert len_wt_lex_cmp(weights, [0, 1], [1, 0]) + assert len_wt_lex_cmp(Alphabet("ab"), weights, "ab", "ba") + + with pytest.raises(LibsemigroupsError): + len_wt_lex_cmp(weights, [2], [0, 1]) + + with pytest.raises(LibsemigroupsError): + len_wt_lex_cmp(Alphabet("ab"), weights, "c", "ab") + + weights = [100, 1] + assert len_wt_lex_cmp(weights, [0], [1, 1])