From baa1b6acb748339181b49205d1b2490d6bdb7d81 Mon Sep 17 00:00:00 2001 From: Joseph Edwards Date: Fri, 28 Aug 2026 13:12:34 +0100 Subject: [PATCH 1/2] Update rpo and rev_rpo --- docs/source/data-structures/order/index.rst | 21 +++ docs/source/libsemigroups.bib | 13 ++ .../knuth-bendix/to-knuth-bendix.rst | 14 ++ src/cong-common.cpp | 130 ++++++++++++++++++ src/du-narendran-rusinowitch.cpp | 18 +-- src/froidure-pin.cpp | 11 ++ src/kbe.cpp | 13 ++ src/knuth-bendix-impl.cpp | 5 + src/knuth-bendix.cpp | 18 ++- src/libsemigroups_pybind11/froidure_pin.py | 12 ++ src/libsemigroups_pybind11/knuth_bendix.py | 16 ++- src/libsemigroups_pybind11/to.py | 24 +++- src/order.cpp | 74 ++++------ src/to-froidure-pin.cpp | 7 + src/to-knuth-bendix.cpp | 11 ++ src/to-presentation.cpp | 16 +++ src/to-todd-coxeter.cpp | 7 + tests/test_du_narendran_rusinowitch.py | 4 +- tests/test_order.py | 4 +- tests/test_to.py | 68 +++++++++ 20 files changed, 417 insertions(+), 69 deletions(-) diff --git a/docs/source/data-structures/order/index.rst b/docs/source/data-structures/order/index.rst index 8a8449d0..f594c159 100644 --- a/docs/source/data-structures/order/index.rst +++ b/docs/source/data-structures/order/index.rst @@ -14,6 +14,27 @@ This page contains the documentation for classes and several functions for comparing words (i.e. lists of integers ``list[int]`` or strings ``str``) with respect to certain reduction orderings. +Some of the orders are generalisations of others. In particular, +when the weight of every generator is the same: + + - :any:`len_wt_lex_cmp` is a generalisation of :any:`lenlex_cmp`; + - :any:`rev_len_wt_lex_cmp` is a generalisation of :any:`rev_lenlex_cmp`; + - :any:`wt_lenlex_cmp` is a generalisation of :any:`lenlex_cmp`; and + - :any:`rev_wt_lenlex_cmp` is a generalisation of :any:`rev_lenlex_cmp`; + - :any:`wt_lex_cmp` is a generalisation of :any:`lex_cmp`; and + - :any:`rev_wt_lex_cmp` is a generalisation of :any:`rev_lex_cmp`. + +Additionally: + + - :any:`wr_cmp` is a generalisation of :any:`lenlex_cmp` when all + of the generators have the same level; + - :any:`rev_wr_cmp` is a generalisation of :any:`rev_lenlex_cmp` when all + of the generators have the same level; + - :any:`wr_cmp` is a generalisation of :any:`rev_rpo_cmp` when all + of the generators have a different level; and + - :any:`rev_wr_cmp` is a generalisation of :any:`rpo_cmp` when all + of the generators have a different level. + .. seealso:: - :any:`Order` diff --git a/docs/source/libsemigroups.bib b/docs/source/libsemigroups.bib index d2f6c4c0..98373b87 100644 --- a/docs/source/libsemigroups.bib +++ b/docs/source/libsemigroups.bib @@ -672,3 +672,16 @@ @article{Du2026aa volume = {150}, year = {2026} } + +@article{Dershowitz1982aa, + title = {Orderings for term-rewriting systems}, + journal = {Theoretical Computer Science}, + volume = {17}, + number = {3}, + pages = {279-301}, + year = {1982}, + issn = {0304-3975}, + doi = {https://doi.org/10.1016/0304-3975(82)90026-3}, + url = {https://www.sciencedirect.com/science/article/pii/0304397582900263}, + author = {Nachum Dershowitz}, +} 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 4e623bc1..d0072ff1 100644 --- a/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst +++ b/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst @@ -110,6 +110,8 @@ and the third item one of: with short-lex reduction ordering. - :any:`Order.rpo` for constructing a :any:`KnuthBendix` with recursive-path reduction ordering. + - :any:`Order.rev_rpo` for constructing a :any:`KnuthBendix` + with reverse recursive-path reduction ordering. This function converts a :any:`ToddCoxeter` object *tc* to a :any:`KnuthBendix` object with the rewriter as specified above, using @@ -186,6 +188,18 @@ Additionally, specify one of the following for *rtype*: - ``(KnuthBendix, list[int], 'Set', Order.rpo)`` for constructing a :any:`KnuthBendix` on words with type ``list[int]`` using a set based rewriting system and short-lex reduction ordering. + - ``(KnuthBendix, str, 'Trie', Order.rev_rpo)`` for constructing a + :any:`KnuthBendix` on words with type ``str`` using the + trie based rewriting system and reverse recursive-path reduction ordering. + - ``(KnuthBendix, list[int], 'Trie', Order.rev_rpo)`` for constructing a + :any:`KnuthBendix` on words with type ``list[int]`` using the + trie based rewriting system and reverse recursive-path reduction ordering. + - ``(KnuthBendix, str, 'Set', Order.rev_rpo)`` for constructing a + :any:`KnuthBendix` on words with type ``str`` using a set based rewriting + system and reverse recursive-path reduction ordering. + - ``(KnuthBendix, list[int], 'Set', Order.rev_rpo)`` for constructing a + :any:`KnuthBendix` on words with type ``list[int]`` using a set based + rewriting system and reverse recursive-path reduction. 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 diff --git a/src/cong-common.cpp b/src/cong-common.cpp index 94870ab5..d37dceb1 100644 --- a/src/cong-common.cpp +++ b/src/cong-common.cpp @@ -42,6 +42,8 @@ namespace libsemigroups { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -54,6 +56,11 @@ namespace libsemigroups { using KnuthBendixWordLenLexTrie = KnuthBendix; using KnuthBendixWordLenLexSet = KnuthBendix; + using KnuthBendixStringRPOTrie = KnuthBendix; + using KnuthBendixStringRPOSet = KnuthBendix; + using KnuthBendixWordRPOTrie = KnuthBendix; + using KnuthBendixWordRPOSet = KnuthBendix; + using KnuthBendixStringRevRPOTrie = KnuthBendix; using KnuthBendixStringRevRPOSet = KnuthBendix; using KnuthBendixWordRevRPOTrie = KnuthBendix; @@ -138,6 +145,11 @@ This function default constructs an uninitialised :any:`{name}` instance. DEF_CONSTRUCT_DEFAULT(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_CONSTRUCT_DEFAULT(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_CONSTRUCT_DEFAULT(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_CONSTRUCT_DEFAULT(detail::KnuthBendixImpl, detail::CongruenceCommon); DEF_CONSTRUCT_DEFAULT(detail::KnuthBendixImpl, @@ -152,6 +164,14 @@ This function default constructs an uninitialised :any:`{name}` instance. DEF_CONSTRUCT_DEFAULT(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_CONSTRUCT_DEFAULT(KnuthBendixStringRPOTrie, + detail::KnuthBendixImpl); + DEF_CONSTRUCT_DEFAULT(KnuthBendixStringRPOSet, + detail::KnuthBendixImpl); + DEF_CONSTRUCT_DEFAULT(KnuthBendixWordRPOTrie, + detail::KnuthBendixImpl); + DEF_CONSTRUCT_DEFAULT(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_CONSTRUCT_DEFAULT(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_CONSTRUCT_DEFAULT(KnuthBendixStringRevRPOSet, @@ -212,6 +232,9 @@ have been in if it had just been newly default constructed. DEF_INIT_DEFAULT(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_INIT_DEFAULT(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_INIT_DEFAULT(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_INIT_DEFAULT(detail::KnuthBendixImpl, detail::CongruenceCommon); DEF_INIT_DEFAULT(detail::KnuthBendixImpl, @@ -226,6 +249,11 @@ have been in if it had just been newly default constructed. DEF_INIT_DEFAULT(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_INIT_DEFAULT(KnuthBendixStringRPOTrie, detail::KnuthBendixImpl); + DEF_INIT_DEFAULT(KnuthBendixStringRPOSet, detail::KnuthBendixImpl); + DEF_INIT_DEFAULT(KnuthBendixWordRPOTrie, detail::KnuthBendixImpl); + DEF_INIT_DEFAULT(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_INIT_DEFAULT(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_INIT_DEFAULT(KnuthBendixStringRevRPOSet, @@ -309,11 +337,25 @@ of kind *knd* over the semigroup or monoid defined by the presentation *p*. DEF_CONSTRUCT_KIND_PRESENTATION(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_CONSTRUCT_KIND_PRESENTATION(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_CONSTRUCT_KIND_PRESENTATION(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_CONSTRUCT_KIND_PRESENTATION(detail::KnuthBendixImpl, detail::CongruenceCommon); DEF_CONSTRUCT_KIND_PRESENTATION(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_CONSTRUCT_KIND_PRESENTATION(KnuthBendixStringRPOTrie, + detail::KnuthBendixImpl); + DEF_CONSTRUCT_KIND_PRESENTATION(KnuthBendixStringRPOSet, + detail::KnuthBendixImpl); + DEF_CONSTRUCT_KIND_PRESENTATION(KnuthBendixWordRPOTrie, + detail::KnuthBendixImpl); + DEF_CONSTRUCT_KIND_PRESENTATION(KnuthBendixWordRPOSet, + detail::KnuthBendixImpl); + DEF_CONSTRUCT_KIND_PRESENTATION(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_CONSTRUCT_KIND_PRESENTATION(KnuthBendixStringRevRPOSet, @@ -400,11 +442,25 @@ had been newly constructed from *knd* and *p*. DEF_INIT_KIND_PRESENTATION(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_INIT_KIND_PRESENTATION(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_INIT_KIND_PRESENTATION(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_INIT_KIND_PRESENTATION(detail::KnuthBendixImpl, detail::CongruenceCommon); DEF_INIT_KIND_PRESENTATION(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_INIT_KIND_PRESENTATION(KnuthBendixStringRPOTrie, + detail::KnuthBendixImpl); + DEF_INIT_KIND_PRESENTATION(KnuthBendixStringRPOSet, + detail::KnuthBendixImpl); + DEF_INIT_KIND_PRESENTATION(KnuthBendixWordRPOTrie, + detail::KnuthBendixImpl); + DEF_INIT_KIND_PRESENTATION(KnuthBendixWordRPOSet, + detail::KnuthBendixImpl); + DEF_INIT_KIND_PRESENTATION(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_INIT_KIND_PRESENTATION(KnuthBendixStringRevRPOSet, @@ -465,9 +521,17 @@ Copy a :any:`{name}` object. DEF_COPY(KnuthBendixWordLenLexTrie, detail::KnuthBendixImpl); DEF_COPY(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_COPY(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_COPY(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_COPY(detail::KnuthBendixImpl, detail::CongruenceCommon); DEF_COPY(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_COPY(KnuthBendixStringRPOTrie, detail::KnuthBendixImpl); + DEF_COPY(KnuthBendixStringRPOSet, detail::KnuthBendixImpl); + DEF_COPY(KnuthBendixWordRPOTrie, detail::KnuthBendixImpl); + DEF_COPY(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_COPY(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_COPY(KnuthBendixStringRevRPOSet, detail::KnuthBendixImpl); DEF_COPY(KnuthBendixWordRevRPOTrie, detail::KnuthBendixImpl); @@ -529,6 +593,11 @@ number of classes in the congruence represented by a :any:`{name}` instance. DEF_NUMBER_OF_CLASSES(detail::KnuthBendixImpl, detail::CongruenceCommon); + DEF_NUMBER_OF_CLASSES(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_NUMBER_OF_CLASSES(detail::KnuthBendixImpl, + detail::CongruenceCommon); + DEF_NUMBER_OF_CLASSES(detail::KnuthBendixImpl, detail::CongruenceCommon); DEF_NUMBER_OF_CLASSES(detail::KnuthBendixImpl, @@ -610,6 +679,15 @@ This function adds a generating pair to the congruence represented by a DEF_ADD_GENERATING_PAIR(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_ADD_GENERATING_PAIR(KnuthBendixStringRPOTrie, + detail::KnuthBendixImpl); + DEF_ADD_GENERATING_PAIR(KnuthBendixStringRPOSet, + detail::KnuthBendixImpl); + DEF_ADD_GENERATING_PAIR(KnuthBendixWordRPOTrie, + detail::KnuthBendixImpl); + DEF_ADD_GENERATING_PAIR(KnuthBendixWordRPOSet, + detail::KnuthBendixImpl); + DEF_ADD_GENERATING_PAIR(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_ADD_GENERATING_PAIR(KnuthBendixStringRevRPOSet, @@ -695,6 +773,15 @@ contained in the congruence, but that this is not currently known. DEF_CURRENTLY_CONTAINS(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_CURRENTLY_CONTAINS(KnuthBendixStringRPOTrie, + detail::KnuthBendixImpl); + DEF_CURRENTLY_CONTAINS(KnuthBendixStringRPOSet, + detail::KnuthBendixImpl); + DEF_CURRENTLY_CONTAINS(KnuthBendixWordRPOTrie, + detail::KnuthBendixImpl); + DEF_CURRENTLY_CONTAINS(KnuthBendixWordRPOSet, + detail::KnuthBendixImpl); + DEF_CURRENTLY_CONTAINS(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_CURRENTLY_CONTAINS(KnuthBendixStringRevRPOSet, @@ -770,6 +857,11 @@ congruence represented by a :py:class:`{name}` instance. DEF_CONTAINS(KnuthBendixWordLenLexTrie, detail::KnuthBendixImpl); DEF_CONTAINS(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_CONTAINS(KnuthBendixStringRPOTrie, detail::KnuthBendixImpl); + DEF_CONTAINS(KnuthBendixStringRPOSet, detail::KnuthBendixImpl); + DEF_CONTAINS(KnuthBendixWordRPOTrie, detail::KnuthBendixImpl); + DEF_CONTAINS(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_CONTAINS(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_CONTAINS(KnuthBendixStringRevRPOSet, detail::KnuthBendixImpl); @@ -842,6 +934,11 @@ normal form for the input word *w*. DEF_REDUCE_NO_RUN(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_REDUCE_NO_RUN(KnuthBendixStringRPOTrie, detail::KnuthBendixImpl); + DEF_REDUCE_NO_RUN(KnuthBendixStringRPOSet, detail::KnuthBendixImpl); + DEF_REDUCE_NO_RUN(KnuthBendixWordRPOTrie, detail::KnuthBendixImpl); + DEF_REDUCE_NO_RUN(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_REDUCE_NO_RUN(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_REDUCE_NO_RUN(KnuthBendixStringRevRPOSet, @@ -914,6 +1011,11 @@ input word. DEF_REDUCE(KnuthBendixWordLenLexTrie, detail::KnuthBendixImpl); DEF_REDUCE(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_REDUCE(KnuthBendixStringRPOTrie, detail::KnuthBendixImpl); + DEF_REDUCE(KnuthBendixStringRPOSet, detail::KnuthBendixImpl); + DEF_REDUCE(KnuthBendixWordRPOTrie, detail::KnuthBendixImpl); + DEF_REDUCE(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_REDUCE(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_REDUCE(KnuthBendixStringRevRPOSet, detail::KnuthBendixImpl); DEF_REDUCE(KnuthBendixWordRevRPOTrie, detail::KnuthBendixImpl); @@ -977,6 +1079,14 @@ This function returns the generating pairs of the congruence as added via DEF_GENERATING_PAIRS(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_GENERATING_PAIRS(KnuthBendixStringRPOTrie, + detail::KnuthBendixImpl); + DEF_GENERATING_PAIRS(KnuthBendixStringRPOSet, + detail::KnuthBendixImpl); + DEF_GENERATING_PAIRS(KnuthBendixWordRPOTrie, + detail::KnuthBendixImpl); + DEF_GENERATING_PAIRS(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_GENERATING_PAIRS(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_GENERATING_PAIRS(KnuthBendixStringRevRPOSet, @@ -1045,6 +1155,11 @@ presentation, then this presentation is returned by this function. DEF_PRESENTATION(KnuthBendixWordLenLexSet, detail::KnuthBendixImpl); + DEF_PRESENTATION(KnuthBendixStringRPOTrie, detail::KnuthBendixImpl); + DEF_PRESENTATION(KnuthBendixStringRPOSet, detail::KnuthBendixImpl); + DEF_PRESENTATION(KnuthBendixWordRPOTrie, detail::KnuthBendixImpl); + DEF_PRESENTATION(KnuthBendixWordRPOSet, detail::KnuthBendixImpl); + DEF_PRESENTATION(KnuthBendixStringRevRPOTrie, detail::KnuthBendixImpl); DEF_PRESENTATION(KnuthBendixStringRevRPOSet, @@ -1122,6 +1237,11 @@ triggers a full enumeration of *{var}*. DEF_PARTITION(KnuthBendixWordLenLexTrie); DEF_PARTITION(KnuthBendixWordLenLexSet); + DEF_PARTITION(KnuthBendixStringRPOTrie); + DEF_PARTITION(KnuthBendixStringRPOSet); + DEF_PARTITION(KnuthBendixWordRPOTrie); + DEF_PARTITION(KnuthBendixWordRPOSet); + DEF_PARTITION(KnuthBendixStringRevRPOTrie); DEF_PARTITION(KnuthBendixStringRevRPOSet); DEF_PARTITION(KnuthBendixWordRevRPOTrie); @@ -1194,6 +1314,11 @@ instance *{var}*. DEF_NON_TRIVIAL_CLASSES(KnuthBendixWordLenLexTrie); DEF_NON_TRIVIAL_CLASSES(KnuthBendixWordLenLexSet); + DEF_NON_TRIVIAL_CLASSES(KnuthBendixStringRPOTrie); + DEF_NON_TRIVIAL_CLASSES(KnuthBendixStringRPOSet); + DEF_NON_TRIVIAL_CLASSES(KnuthBendixWordRPOTrie); + DEF_NON_TRIVIAL_CLASSES(KnuthBendixWordRPOSet); + DEF_NON_TRIVIAL_CLASSES(KnuthBendixStringRevRPOTrie); DEF_NON_TRIVIAL_CLASSES(KnuthBendixStringRevRPOSet); DEF_NON_TRIVIAL_CLASSES(KnuthBendixWordRevRPOTrie); @@ -1262,6 +1387,11 @@ the congruence represented by an instance of :any:`{name}`. DEF_NORMAL_FORMS(KnuthBendixWordLenLexTrie); DEF_NORMAL_FORMS(KnuthBendixWordLenLexSet); + DEF_NORMAL_FORMS(KnuthBendixStringRPOTrie); + DEF_NORMAL_FORMS(KnuthBendixStringRPOSet); + DEF_NORMAL_FORMS(KnuthBendixWordRPOTrie); + DEF_NORMAL_FORMS(KnuthBendixWordRPOSet); + DEF_NORMAL_FORMS(KnuthBendixStringRevRPOTrie); DEF_NORMAL_FORMS(KnuthBendixStringRevRPOSet); DEF_NORMAL_FORMS(KnuthBendixWordRevRPOTrie); diff --git a/src/du-narendran-rusinowitch.cpp b/src/du-narendran-rusinowitch.cpp index 008b5250..7b60578f 100644 --- a/src/du-narendran-rusinowitch.cpp +++ b/src/du-narendran-rusinowitch.cpp @@ -46,24 +46,26 @@ namespace libsemigroups { R"pbdoc( :sig=(p: Presentation) -> str | list[int]: :only-document-once: -Find an alphabet order that orients every rule using reverse recursive-path ordering. +Return an ordered alphabet such that the rules are oriented with +respect to recursive-path order; see :any:`rpo_cmp`. -This function returns the alphabet of *p*, ordered so that every rule -:math:`u \to v` satisfies :math:`u > v` with respect to reverse recursive-path -ordering. It returns an empty word if no such order exists, or if the alphabet -of *p* is empty. +This function returns the alphabet of *p* ordered so that the rules of +*p* satisfy :math:`x_i \to y_i` and :math`x_i > y_i` with respect to +recursive-path order and the returned alphabet order. The returned +alphabet is empty if this fails, or if the alphabet was empty to begin +with. :param p: the presentation whose rules are to be oriented. :type p: Presentation -:returns: An alphabet order orienting every rule, or an empty word if none - exists. +:returns: The ordered alphabet, if such an alphabet exists. Otherwise, the + empty alphabet. :rtype: str | list[int] :raises LibsemigroupsError: if the alphabet or rules of *p* are invalid. .. seealso:: - :any:`rev_rpo_cmp` + :any:`rpo_cmp` .. doctest:: diff --git a/src/froidure-pin.cpp b/src/froidure-pin.cpp index eaf8cccf..122d06d7 100644 --- a/src/froidure-pin.cpp +++ b/src/froidure-pin.cpp @@ -1274,6 +1274,8 @@ This function returns the element of *fp* obtained by evaluating *w*. void init_froidure_pin(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -1316,6 +1318,15 @@ This function returns the element of *fp* obtained by evaluating *w*. bind_froidure_pin_stateful>>( m, "KBEWordLenLexTrie"); + bind_froidure_pin_stateful>>( + m, "KBEStringRPOSet"); + bind_froidure_pin_stateful>>( + m, "KBEStringRPOTrie"); + bind_froidure_pin_stateful>>( + m, "KBEWordRPOSet"); + bind_froidure_pin_stateful>>( + m, "KBEWordRPOTrie"); + bind_froidure_pin_stateful< detail::KBE>>(m, "KBEStringRevRPOSet"); diff --git a/src/kbe.cpp b/src/kbe.cpp index 19065bbb..a92bcec2 100644 --- a/src/kbe.cpp +++ b/src/kbe.cpp @@ -75,6 +75,8 @@ namespace libsemigroups { void init_kbe(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -91,6 +93,17 @@ namespace libsemigroups { bind_kbe(m, "KBEWordLenLexSet"); // RPO + using KBEStringRPOTrie = detail::KBE>; + using KBEWordRPOTrie = detail::KBE>; + using KBEStringRPOSet = detail::KBE>; + using KBEWordRPOSet = detail::KBE>; + + bind_kbe(m, "KBEStringRPOTrie"); + bind_kbe(m, "KBEWordRPOTrie"); + bind_kbe(m, "KBEStringRPOSet"); + bind_kbe(m, "KBEWordRPOSet"); + + // RevRPO using KBEStringRevRPOTrie = detail::KBE>; using KBEWordRevRPOTrie = detail::KBE>; diff --git a/src/knuth-bendix-impl.cpp b/src/knuth-bendix-impl.cpp index 16bb2d11..ebb8c00f 100644 --- a/src/knuth-bendix-impl.cpp +++ b/src/knuth-bendix-impl.cpp @@ -503,6 +503,8 @@ infinite; ``False`` is returned if it is not. void init_detail_knuth_bendix_impl(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -511,6 +513,9 @@ infinite; ``False`` is returned if it is not. detail::bind_detail_knuth_bendix_impl( m, "KnuthBendixImplLenLexTrie"); + detail::bind_detail_knuth_bendix_impl(m, "KnuthBendixImplRPOSet"); + detail::bind_detail_knuth_bendix_impl(m, "KnuthBendixImplRPOTrie"); + detail::bind_detail_knuth_bendix_impl( m, "KnuthBendixImplRevRPOSet"); detail::bind_detail_knuth_bendix_impl( diff --git a/src/knuth-bendix.cpp b/src/knuth-bendix.cpp index 294a6b6b..778d26d9 100644 --- a/src/knuth-bendix.cpp +++ b/src/knuth-bendix.cpp @@ -90,7 +90,7 @@ nested class :any:`KnuthBendix.options`. doc{.extra_kwargs = ", rewriting_system: str, order: Order", .extra_kwargs_doc = R"pbdoc( * **rewriting_system** (*str*) -- the type of rewriting system to use, must be either ``"Trie"`` or ``"Set"``. - * **order** (*Order*) -- the reduction ordering to use, must be either :any:`Order.lenlex` or :any:`Order.rpo`.)pbdoc"sv}); + * **order** (*Order*) -- the reduction ordering to use, must be either :any:`Order.lenlex`, :any:`Order.rpo` or :any:`Order.rev_rpo`.)pbdoc"sv}); def_init_default(thing, "KnuthBendix"); def_construct_kind_presentation(thing, "KnuthBendix"); @@ -451,6 +451,8 @@ redundant in this way, then ``None`` is returned. void init_knuth_bendix(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -460,6 +462,11 @@ redundant in this way, then ``None`` is returned. "KnuthBendixStringLenLexTrie"); bind_knuth_bendix(m, "KnuthBendixStringLenLexSet"); + bind_knuth_bendix(m, "KnuthBendixWordRPOTrie"); + bind_knuth_bendix(m, "KnuthBendixWordRPOSet"); + bind_knuth_bendix(m, "KnuthBendixStringRPOTrie"); + bind_knuth_bendix(m, "KnuthBendixStringRPOSet"); + bind_knuth_bendix(m, "KnuthBendixWordRevRPOTrie"); bind_knuth_bendix(m, "KnuthBendixWordRevRPOSet"); bind_knuth_bendix(m, @@ -475,6 +482,15 @@ redundant in this way, then ``None`` is returned. bind_normal_form_range( m, "KnuthBendixNormalFormRangeStringLenLexSet"); + bind_normal_form_range( + m, "KnuthBendixNormalFormRangeWordRPOTrie"); + bind_normal_form_range( + m, "KnuthBendixNormalFormRangeWordRPOSet"); + bind_normal_form_range( + m, "KnuthBendixNormalFormRangeStringRPOTrie"); + bind_normal_form_range( + m, "KnuthBendixNormalFormRangeStringRPOSet"); + bind_normal_form_range( m, "KnuthBendixNormalFormRangeWordRevRPOTrie"); bind_normal_form_range( diff --git a/src/libsemigroups_pybind11/froidure_pin.py b/src/libsemigroups_pybind11/froidure_pin.py index baa206e5..66a710ee 100644 --- a/src/libsemigroups_pybind11/froidure_pin.py +++ b/src/libsemigroups_pybind11/froidure_pin.py @@ -30,10 +30,14 @@ FroidurePinKBEStringLenLexTrie as _FroidurePinKBEStringLenLexTrie, FroidurePinKBEStringRevRPOSet as _FroidurePinKBEStringRevRPOSet, FroidurePinKBEStringRevRPOTrie as _FroidurePinKBEStringRevRPOTrie, + FroidurePinKBEStringRPOSet as _FroidurePinKBEStringRPOSet, + FroidurePinKBEStringRPOTrie as _FroidurePinKBEStringRPOTrie, FroidurePinKBEWordLenLexSet as _FroidurePinKBEWordLenLexSet, FroidurePinKBEWordLenLexTrie as _FroidurePinKBEWordLenLexTrie, FroidurePinKBEWordRevRPOSet as _FroidurePinKBEWordRevRPOSet, FroidurePinKBEWordRevRPOTrie as _FroidurePinKBEWordRevRPOTrie, + FroidurePinKBEWordRPOSet as _FroidurePinKBEWordRPOSet, + FroidurePinKBEWordRPOTrie as _FroidurePinKBEWordRPOTrie, FroidurePinKEMultiViewString as _FroidurePinKEMultiViewString, FroidurePinKEString as _FroidurePinKEString, FroidurePinKEWord as _FroidurePinKEWord, @@ -59,10 +63,14 @@ KBEStringLenLexTrie as _KBEStringLenLexTrie, KBEStringRevRPOSet as _KBEStringRevRPOSet, KBEStringRevRPOTrie as _KBEStringRevRPOTrie, + KBEStringRPOSet as _KBEStringRPOSet, + KBEStringRPOTrie as _KBEStringRPOTrie, KBEWordLenLexSet as _KBEWordLenLexSet, KBEWordLenLexTrie as _KBEWordLenLexTrie, KBEWordRevRPOSet as _KBEWordRevRPOSet, KBEWordRevRPOTrie as _KBEWordRevRPOTrie, + KBEWordRPOSet as _KBEWordRPOSet, + KBEWordRPOTrie as _KBEWordRPOTrie, MaxPlusMat as _MaxPlusMat, MaxPlusTruncMat as _MaxPlusTruncMat, MinPlusMat as _MinPlusMat, @@ -157,6 +165,10 @@ class FroidurePin(_CxxWrapper): (_KBEStringLenLexSet,): _FroidurePinKBEStringLenLexSet, (_KBEWordLenLexTrie,): _FroidurePinKBEWordLenLexTrie, (_KBEWordLenLexSet,): _FroidurePinKBEWordLenLexSet, + (_KBEStringRPOTrie,): _FroidurePinKBEStringRPOTrie, + (_KBEStringRPOSet,): _FroidurePinKBEStringRPOSet, + (_KBEWordRPOTrie,): _FroidurePinKBEWordRPOTrie, + (_KBEWordRPOSet,): _FroidurePinKBEWordRPOSet, (_KBEStringRevRPOTrie,): _FroidurePinKBEStringRevRPOTrie, (_KBEStringRevRPOSet,): _FroidurePinKBEStringRevRPOSet, (_KBEWordRevRPOTrie,): _FroidurePinKBEWordRevRPOTrie, diff --git a/src/libsemigroups_pybind11/knuth_bendix.py b/src/libsemigroups_pybind11/knuth_bendix.py index 3fdb14e6..50802b85 100644 --- a/src/libsemigroups_pybind11/knuth_bendix.py +++ b/src/libsemigroups_pybind11/knuth_bendix.py @@ -16,10 +16,14 @@ KnuthBendixStringLenLexTrie as _KnuthBendixStringLenLexTrie, KnuthBendixStringRevRPOSet as _KnuthBendixStringRevRPOSet, KnuthBendixStringRevRPOTrie as _KnuthBendixStringRevRPOTrie, + KnuthBendixStringRPOSet as _KnuthBendixStringRPOSet, + KnuthBendixStringRPOTrie as _KnuthBendixStringRPOTrie, KnuthBendixWordLenLexSet as _KnuthBendixWordLenLexSet, KnuthBendixWordLenLexTrie as _KnuthBendixWordLenLexTrie, KnuthBendixWordRevRPOSet as _KnuthBendixWordRevRPOSet, KnuthBendixWordRevRPOTrie as _KnuthBendixWordRevRPOTrie, + KnuthBendixWordRPOSet as _KnuthBendixWordRPOSet, + KnuthBendixWordRPOTrie as _KnuthBendixWordRPOTrie, Order as _Order, knuth_bendix_by_overlap_length as _knuth_bendix_by_overlap_length, knuth_bendix_is_reduced as _knuth_bendix_is_reduced, @@ -54,10 +58,14 @@ class KnuthBendix(_CongruenceCommon): (str, "Trie", _Order.lenlex): _KnuthBendixStringLenLexTrie, (list[int], "Set", _Order.lenlex): _KnuthBendixWordLenLexSet, (str, "Set", _Order.lenlex): _KnuthBendixStringLenLexSet, - (list[int], "Trie", _Order.rpo): _KnuthBendixWordRevRPOTrie, - (str, "Trie", _Order.rpo): _KnuthBendixStringRevRPOTrie, - (list[int], "Set", _Order.rpo): _KnuthBendixWordRevRPOSet, - (str, "Set", _Order.rpo): _KnuthBendixStringRevRPOSet, + (list[int], "Trie", _Order.rpo): _KnuthBendixWordRPOTrie, + (str, "Trie", _Order.rpo): _KnuthBendixStringRPOTrie, + (list[int], "Set", _Order.rpo): _KnuthBendixWordRPOSet, + (str, "Set", _Order.rpo): _KnuthBendixStringRPOSet, + (list[int], "Trie", _Order.rev_rpo): _KnuthBendixWordRevRPOTrie, + (str, "Trie", _Order.rev_rpo): _KnuthBendixStringRevRPOTrie, + (list[int], "Set", _Order.rev_rpo): _KnuthBendixWordRevRPOSet, + (str, "Set", _Order.rev_rpo): _KnuthBendixStringRevRPOSet, } _cxx_type_to_py_template_params = dict( diff --git a/src/libsemigroups_pybind11/to.py b/src/libsemigroups_pybind11/to.py index aa21ccd1..c4953c79 100644 --- a/src/libsemigroups_pybind11/to.py +++ b/src/libsemigroups_pybind11/to.py @@ -25,14 +25,20 @@ to_knuth_bendix_LenLexTrie as _to_knuth_bendix_LenLexTrie, to_knuth_bendix_RevRPOSet as _to_knuth_bendix_RevRPOSet, to_knuth_bendix_RevRPOTrie as _to_knuth_bendix_RevRPOTrie, + to_knuth_bendix_RPOSet as _to_knuth_bendix_RPOSet, + to_knuth_bendix_RPOTrie as _to_knuth_bendix_RPOTrie, to_knuth_bendix_string_LenLexSet as _to_knuth_bendix_string_LenLexSet, to_knuth_bendix_string_LenLexTrie as _to_knuth_bendix_string_LenLexTrie, to_knuth_bendix_string_RevRPOSet as _to_knuth_bendix_string_RevRPOSet, to_knuth_bendix_string_RevRPOTrie as _to_knuth_bendix_string_RevRPOTrie, + to_knuth_bendix_string_RPOSet as _to_knuth_bendix_string_RPOSet, + to_knuth_bendix_string_RPOTrie as _to_knuth_bendix_string_RPOTrie, to_knuth_bendix_word_LenLexSet as _to_knuth_bendix_word_LenLexSet, to_knuth_bendix_word_LenLexTrie as _to_knuth_bendix_word_LenLexTrie, to_knuth_bendix_word_RevRPOSet as _to_knuth_bendix_word_RevRPOSet, to_knuth_bendix_word_RevRPOTrie as _to_knuth_bendix_word_RevRPOTrie, + to_knuth_bendix_word_RPOSet as _to_knuth_bendix_word_RPOSet, + to_knuth_bendix_word_RPOTrie as _to_knuth_bendix_word_RPOTrie, to_presentation as _to_presentation, to_presentation_string as _to_presentation_string, to_presentation_word as _to_presentation_word, @@ -88,12 +94,18 @@ def _nice_name(type_list): (_KnuthBendix, list[int], "Trie", _Order.lenlex): _to_knuth_bendix_word_LenLexTrie, (_KnuthBendix, str, "Set", _Order.lenlex): _to_knuth_bendix_string_LenLexSet, (_KnuthBendix, str, "Trie", _Order.lenlex): _to_knuth_bendix_string_LenLexTrie, - (_KnuthBendix, "Set", _Order.rpo): _to_knuth_bendix_RevRPOSet, - (_KnuthBendix, "Trie", _Order.rpo): _to_knuth_bendix_RevRPOTrie, - (_KnuthBendix, list[int], "Set", _Order.rpo): _to_knuth_bendix_word_RevRPOSet, - (_KnuthBendix, list[int], "Trie", _Order.rpo): _to_knuth_bendix_word_RevRPOTrie, - (_KnuthBendix, str, "Set", _Order.rpo): _to_knuth_bendix_string_RevRPOSet, - (_KnuthBendix, str, "Trie", _Order.rpo): _to_knuth_bendix_string_RevRPOTrie, + (_KnuthBendix, "Set", _Order.rpo): _to_knuth_bendix_RPOSet, + (_KnuthBendix, "Trie", _Order.rpo): _to_knuth_bendix_RPOTrie, + (_KnuthBendix, list[int], "Set", _Order.rpo): _to_knuth_bendix_word_RPOSet, + (_KnuthBendix, list[int], "Trie", _Order.rpo): _to_knuth_bendix_word_RPOTrie, + (_KnuthBendix, str, "Set", _Order.rpo): _to_knuth_bendix_string_RPOSet, + (_KnuthBendix, str, "Trie", _Order.rpo): _to_knuth_bendix_string_RPOTrie, + (_KnuthBendix, "Set", _Order.rev_rpo): _to_knuth_bendix_RevRPOSet, + (_KnuthBendix, "Trie", _Order.rev_rpo): _to_knuth_bendix_RevRPOTrie, + (_KnuthBendix, list[int], "Set", _Order.rev_rpo): _to_knuth_bendix_word_RevRPOSet, + (_KnuthBendix, list[int], "Trie", _Order.rev_rpo): _to_knuth_bendix_word_RevRPOTrie, + (_KnuthBendix, str, "Set", _Order.rev_rpo): _to_knuth_bendix_string_RevRPOSet, + (_KnuthBendix, str, "Trie", _Order.rev_rpo): _to_knuth_bendix_string_RevRPOTrie, (_Presentation,): _to_presentation, (_Presentation, str): _to_presentation_string, (_Presentation, list[int]): _to_presentation_word, diff --git a/src/order.cpp b/src/order.cpp index e928e1a4..cf90691c 100644 --- a/src/order.cpp +++ b/src/order.cpp @@ -855,6 +855,21 @@ read from right to left. :only-document-once: Compare two words using recursive-path ordering. +This function compares two objects using the recursive-path comparison, based on +the description in :cite:`Jantzen2012aa` (Definition 1.2.14, page 24) and +:cite:`Dershowitz1982aa` (Definition 5, page 289). The following definition is +used in ``libsemigroups_pybind11``. + +If :math:`u, v\ in X ^ {*}`, then :math:`u < v` if and only if one of the +following conditions holds: + +1. :math:`u` is empty and :math:`v` is not empty; or +2. :math:`u = au'` and :math:`v = bv'` for some :math:`a,b \in X`, :math:`u',v'\in X ^ {*}` and: + + 1. :math:`a = b` and :math:`u' < v'`; or + 2. :math:`a < b` and :math:`u' < v`; or + 3. :math:`a > b` and :math:`u \leq v'`. + :param x: the first word. :type x: str | list[int] :param y: the second word. @@ -862,10 +877,6 @@ Compare two words using recursive-path ordering. :returns: Whether *x* is less than *y*. :rtype: bool -.. warning:: - This function has significantly worse performance than :any:`lenlex_cmp` - and :any:`lex_cmp`. - .. seealso:: :any:`RPOCmp` for a reusable recursive-path comparison object. .. doctest:: python @@ -903,10 +914,6 @@ Letters are compared by their positions in *alphabet*. :raises LibsemigroupsError: if either word contains a letter that does not belong to *alphabet*. -.. warning:: - This function has significantly worse performance than :any:`lenlex_cmp` - and :any:`lex_cmp`. - .. doctest:: python >>> from libsemigroups_pybind11 import Alphabet, rpo_cmp @@ -925,8 +932,7 @@ Letters are compared by their positions in *alphabet*. :only-document-once: Compare two words using reversed recursive-path ordering. -This is recursive-path ordering applied after reading both words from right to -left. +This function applies :any:`rpo_cmp` to the *x* and *y* read from right to left. :param x: the first word. :type x: str | list[int] @@ -935,10 +941,6 @@ left. :returns: Whether *x* is less than *y*. :rtype: bool -.. warning:: - This function has significantly worse performance than :any:`lenlex_cmp` - and :any:`lex_cmp`. - .. seealso:: :any:`RevRPOCmp` for a reusable reversed recursive-path comparison object. @@ -964,8 +966,8 @@ left. :only-document-once: Compare two words using reversed recursive-path ordering and an alphabet. -This is recursive-path ordering applied after reading both words from right to -left, with letters compared by their positions in *alphabet*. +This function applies :any:`rpo_cmp` to the *x* and *y* read from right to left, +with letters compared by their positions in *alphabet*. :param alphabet: the alphabet that determines the ordering of letters. :type alphabet: Alphabet @@ -978,10 +980,6 @@ left, with letters compared by their positions in *alphabet*. :raises LibsemigroupsError: if either word contains a letter that does not belong to *alphabet*. -.. warning:: - This function has significantly worse performance than :any:`lenlex_cmp` - and :any:`lex_cmp`. - .. seealso:: :any:`RevRPOCmp` for a reusable reversed recursive-path comparison object. @@ -2049,10 +2047,6 @@ the positions of their letters in *alphabet*. The latter form copies ``RPOCmp(alphabet).init(new_alphabet)`` requires *new_alphabet* to have the same word type as *alphabet*. -.. warning:: - This comparison has significantly worse performance than :any:`LenLexCmp` - and :any:`LexCmp`. - .. seealso:: :any:`Alphabet` @@ -2190,10 +2184,6 @@ their positions in the alphabet. if *self* is alphabet-aware and either word contains a letter that does not belong to its alphabet. -.. warning:: - This comparison has significantly worse performance than :any:`LenLexCmp` - and :any:`LexCmp`. - .. doctest:: python >>> from libsemigroups_pybind11 import RPOCmp @@ -2239,7 +2229,7 @@ Return the alphabet used to compare letters. py::class_ thing(m, name, R"pbdoc( Compare words using reversed recursive-path ordering. -This is recursive-path ordering applied after reading both words from right to +This is recursive-path ordering applied to words that are read from right to left. Use ``RevRPOCmp()`` to compare either ``str`` or ``list[int]`` words using the natural order of their letters. Use ``RevRPOCmp(alphabet)`` to compare words by the positions of their letters in *alphabet*. The latter form @@ -2253,10 +2243,6 @@ copies *alphabet* and only accepts words with the same type as *alphabet*. ``RevRPOCmp(alphabet).init(new_alphabet)`` requires *new_alphabet* to have the same word type as *alphabet*. -.. warning:: - This comparison has significantly worse performance than :any:`LenLexCmp` - and :any:`LexCmp`. - .. seealso:: :any:`Alphabet` @@ -2264,9 +2250,9 @@ copies *alphabet* and only accepts words with the same type as *alphabet*. .. doctest:: python >>> from libsemigroups_pybind11 import Alphabet, RevRPOCmp - >>> RevRPOCmp()("ab", "ba") + >>> RevRPOCmp()("ba", "ab") True - >>> RevRPOCmp()([0, 1], [1, 0]) + >>> RevRPOCmp()([1, 0], [0, 1]) True >>> RevRPOCmp(Alphabet("ba"))("b", "a") True @@ -2376,8 +2362,8 @@ had it been newly constructed from *alphabet*. :sig=(self: RevRPOCmp, x: str | list[int], y: str | list[int]) -> bool: Compare two words using reversed recursive-path ordering. -This is recursive-path ordering applied after reading both words from right to -left. If *self* was constructed as ``RevRPOCmp()``, then *x* and *y* must +This is recursive-path ordering applied to *x* and *y* read from right to left. +If *self* was constructed as ``RevRPOCmp()``, then *x* and *y* must either both be strings or both be lists of integers, and letters are compared using their natural order. If *self* was constructed using an :any:`Alphabet`, then *x* and *y* must have the same type of words as *alphabet*, and letters are @@ -2397,16 +2383,12 @@ compared by their positions in the alphabet. if *self* is alphabet-aware and either word contains a letter that does not belong to its alphabet. -.. warning:: - This comparison has significantly worse performance than :any:`LenLexCmp` - and :any:`LexCmp`. - .. doctest:: python >>> from libsemigroups_pybind11 import RevRPOCmp - >>> RevRPOCmp()("ab", "ba") + >>> RevRPOCmp()("ba", "ab") True - >>> RevRPOCmp()([0, 1], [1, 0]) + >>> RevRPOCmp()([1, 0], [0, 1]) True )pbdoc"); @@ -2895,10 +2877,10 @@ respectively, in new code. .. py:attribute:: Order.recursive :value: - The recursive-path ordering, as described in :cite:`Jantzen2012aa` - (Definition 1.2.14, page 24). + The reversed recursive-path ordering, based on the description in + :cite:`Jantzen2012aa` (Definition 1.2.14, page 24). - This is deprecated; use :any:`Order.rpo` instead. + This is deprecated; use :any:`Order.rev_rpo` instead. .. doctest:: python diff --git a/src/to-froidure-pin.cpp b/src/to-froidure-pin.cpp index fc5886fb..efd4ad90 100644 --- a/src/to-froidure-pin.cpp +++ b/src/to-froidure-pin.cpp @@ -54,6 +54,8 @@ namespace libsemigroups { void init_to_froidure_pin(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -72,6 +74,11 @@ namespace libsemigroups { bind_to_froidure_pin>(m); bind_to_froidure_pin>(m); + bind_to_froidure_pin>(m); + bind_to_froidure_pin>(m); + bind_to_froidure_pin>(m); + bind_to_froidure_pin>(m); + bind_to_froidure_pin>(m); bind_to_froidure_pin>(m); bind_to_froidure_pin>(m); diff --git a/src/to-knuth-bendix.cpp b/src/to-knuth-bendix.cpp index c3ffa79d..e77d79da 100644 --- a/src/to-knuth-bendix.cpp +++ b/src/to-knuth-bendix.cpp @@ -67,6 +67,8 @@ namespace libsemigroups { void init_to_knuth_bendix(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -79,6 +81,11 @@ namespace libsemigroups { "word_LenLexSet"); bind_froidure_pin_to_knuth_bendix(m, "word_LenLexTrie"); + bind_froidure_pin_to_knuth_bendix(m, "string_RPOSet"); + bind_froidure_pin_to_knuth_bendix(m, + "string_RPOTrie"); + bind_froidure_pin_to_knuth_bendix(m, "word_RPOSet"); + bind_froidure_pin_to_knuth_bendix(m, "word_RPOTrie"); bind_froidure_pin_to_knuth_bendix( m, "string_RevRPOSet"); bind_froidure_pin_to_knuth_bendix( @@ -93,6 +100,10 @@ namespace libsemigroups { bind_todd_coxeter_to_knuth_bendix(m, "LenLexSet"); bind_todd_coxeter_to_knuth_bendix(m, "LenLexTrie"); bind_todd_coxeter_to_knuth_bendix(m, "LenLexTrie"); + bind_todd_coxeter_to_knuth_bendix(m, "RPOSet"); + bind_todd_coxeter_to_knuth_bendix(m, "RPOSet"); + bind_todd_coxeter_to_knuth_bendix(m, "RPOTrie"); + bind_todd_coxeter_to_knuth_bendix(m, "RPOTrie"); bind_todd_coxeter_to_knuth_bendix(m, "RevRPOSet"); bind_todd_coxeter_to_knuth_bendix(m, "RevRPOSet"); bind_todd_coxeter_to_knuth_bendix(m, "RevRPOTrie"); diff --git a/src/to-presentation.cpp b/src/to-presentation.cpp index f7e12189..597ddb96 100644 --- a/src/to-presentation.cpp +++ b/src/to-presentation.cpp @@ -192,6 +192,8 @@ namespace libsemigroups { void init_to_present(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -227,11 +229,25 @@ namespace libsemigroups { bind_kb_to_pres_with_word(m, "word"); bind_kb_to_pres_with_word(m, "word"); + bind_kb_to_pres(m); + bind_kb_to_pres(m); + bind_kb_to_pres(m); + bind_kb_to_pres(m); + bind_kb_to_pres(m); bind_kb_to_pres(m); bind_kb_to_pres(m); bind_kb_to_pres(m); + bind_kb_to_pres_with_word(m, "string"); + bind_kb_to_pres_with_word(m, "string"); + bind_kb_to_pres_with_word(m, "string"); + bind_kb_to_pres_with_word(m, "string"); + bind_kb_to_pres_with_word(m, "word"); + bind_kb_to_pres_with_word(m, "word"); + bind_kb_to_pres_with_word(m, "word"); + bind_kb_to_pres_with_word(m, "word"); + bind_kb_to_pres_with_word(m, "string"); bind_kb_to_pres_with_word(m, "string"); diff --git a/src/to-todd-coxeter.cpp b/src/to-todd-coxeter.cpp index 450f3e1e..9a93814f 100644 --- a/src/to-todd-coxeter.cpp +++ b/src/to-todd-coxeter.cpp @@ -53,6 +53,8 @@ namespace libsemigroups { void init_to_todd_coxeter(py::module& m) { using LenLexTrie = detail::RewritingSystemTrie; using LenLexSet = detail::RewritingSystemSet; + using RPOTrie = detail::RewritingSystemTrie; + using RPOSet = detail::RewritingSystemSet; using RevRPOTrie = detail::RewritingSystemTrie; using RevRPOSet = detail::RewritingSystemSet; @@ -62,6 +64,11 @@ namespace libsemigroups { bind_to_todd_coxeter_kb(m); bind_to_todd_coxeter_kb(m); + bind_to_todd_coxeter_kb(m); + bind_to_todd_coxeter_kb(m); + bind_to_todd_coxeter_kb(m); + bind_to_todd_coxeter_kb(m); + bind_to_todd_coxeter_kb(m); bind_to_todd_coxeter_kb(m); bind_to_todd_coxeter_kb(m); diff --git a/tests/test_du_narendran_rusinowitch.py b/tests/test_du_narendran_rusinowitch.py index 7f5b5e57..eb4fdc16 100644 --- a/tests/test_du_narendran_rusinowitch.py +++ b/tests/test_du_narendran_rusinowitch.py @@ -15,7 +15,7 @@ LibsemigroupsError, Presentation, du_narendran_rusinowitch, - rev_rpo_cmp, + rpo_cmp, ) @@ -36,7 +36,7 @@ def test_du_narendran_rusinowitch(alphabet, rules, expected): assert du_narendran_rusinowitch(p) == expected for lhs, rhs in list(zip(rules[::2], rules[1::2], strict=True)): - assert rev_rpo_cmp(Alphabet(expected), rhs, lhs) + assert rpo_cmp(Alphabet(expected), rhs, lhs) def test_du_narendran_rusinowitch_no_order_exists(): diff --git a/tests/test_order.py b/tests/test_order.py index 80756759..8d315171 100644 --- a/tests/test_order.py +++ b/tests/test_order.py @@ -377,7 +377,7 @@ def test_rpo_without_alphabet(): cmp = RPOCmp() assert cmp("a", "b") assert cmp([0], [1]) - assert not cmp("ab", "ba") + assert not cmp("ba", "ab") def test_rpo_with_alphabet(): @@ -436,7 +436,7 @@ def test_rev_rpo_without_alphabet(): cmp = RevRPOCmp() assert cmp("a", "b") assert cmp([0], [1]) - assert not cmp("ba", "ab") + assert not cmp("ab", "ba") def test_rev_rpo_with_alphabet(): diff --git a/tests/test_to.py b/tests/test_to.py index 0e14dd48..1e50cc34 100644 --- a/tests/test_to.py +++ b/tests/test_to.py @@ -17,10 +17,14 @@ FroidurePinKBEStringLenLexTrie, FroidurePinKBEStringRevRPOSet, FroidurePinKBEStringRevRPOTrie, + FroidurePinKBEStringRPOSet, + FroidurePinKBEStringRPOTrie, FroidurePinKBEWordLenLexSet, FroidurePinKBEWordLenLexTrie, FroidurePinKBEWordRevRPOSet, FroidurePinKBEWordRevRPOTrie, + FroidurePinKBEWordRPOSet, + FroidurePinKBEWordRPOTrie, FroidurePinKEMultiViewString, FroidurePinKEString, FroidurePinKEWord, @@ -236,6 +240,9 @@ def test_to_FroidurePin_000(): assert isinstance(to_cxx(fp), FroidurePinKBEStringLenLexSet) fp = check_cong_to_froidure_pin(KnuthBendix, str, rewriting_system="Set", order=Order.rpo) + assert isinstance(to_cxx(fp), FroidurePinKBEStringRPOSet) + + fp = check_cong_to_froidure_pin(KnuthBendix, str, rewriting_system="Set", order=Order.rev_rpo) assert isinstance(to_cxx(fp), FroidurePinKBEStringRevRPOSet) @@ -244,6 +251,9 @@ def test_to_FroidurePin_001(): assert isinstance(to_cxx(fp), FroidurePinKBEStringLenLexTrie) fp = check_cong_to_froidure_pin(KnuthBendix, str, rewriting_system="Trie", order=Order.rpo) + assert isinstance(to_cxx(fp), FroidurePinKBEStringRPOTrie) + + fp = check_cong_to_froidure_pin(KnuthBendix, str, rewriting_system="Trie", order=Order.rev_rpo) assert isinstance(to_cxx(fp), FroidurePinKBEStringRevRPOTrie) @@ -252,6 +262,9 @@ def test_to_FroidurePin_002(): assert isinstance(to_cxx(fp), FroidurePinKBEWordLenLexSet) fp = check_cong_to_froidure_pin(KnuthBendix, int, rewriting_system="Set", order=Order.rpo) + assert isinstance(to_cxx(fp), FroidurePinKBEWordRPOSet) + + fp = check_cong_to_froidure_pin(KnuthBendix, int, rewriting_system="Set", order=Order.rev_rpo) assert isinstance(to_cxx(fp), FroidurePinKBEWordRevRPOSet) @@ -260,6 +273,9 @@ def test_to_FroidurePin_003(): assert isinstance(to_cxx(fp), FroidurePinKBEWordLenLexTrie) fp = check_cong_to_froidure_pin(KnuthBendix, int, rewriting_system="Trie", order=Order.rpo) + assert isinstance(to_cxx(fp), FroidurePinKBEWordRPOTrie) + + fp = check_cong_to_froidure_pin(KnuthBendix, int, rewriting_system="Trie", order=Order.rev_rpo) assert isinstance(to_cxx(fp), FroidurePinKBEWordRevRPOTrie) @@ -379,6 +395,10 @@ def test_to_ToddCoxeter_014(): assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (str,) + tc = check_cong_to_todd_coxeter(KnuthBendix, str, rewriting_system="Set", order=Order.rev_rpo) + assert isinstance(tc, ToddCoxeter) + assert tc.py_template_params == (str,) + def test_to_ToddCoxeter_015(): tc = check_cong_to_todd_coxeter(KnuthBendix, str, rewriting_system="Trie", order=Order.lenlex) @@ -389,6 +409,10 @@ def test_to_ToddCoxeter_015(): assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (str,) + tc = check_cong_to_todd_coxeter(KnuthBendix, str, rewriting_system="Trie", order=Order.rev_rpo) + assert isinstance(tc, ToddCoxeter) + assert tc.py_template_params == (str,) + def test_to_ToddCoxeter_016(): tc = check_cong_to_todd_coxeter(KnuthBendix, int, rewriting_system="Set", order=Order.lenlex) @@ -399,6 +423,10 @@ def test_to_ToddCoxeter_016(): assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (list[int],) + tc = check_cong_to_todd_coxeter(KnuthBendix, int, rewriting_system="Set", order=Order.rev_rpo) + assert isinstance(tc, ToddCoxeter) + assert tc.py_template_params == (list[int],) + def test_to_ToddCoxeter_017(): tc = check_cong_to_todd_coxeter(KnuthBendix, int, rewriting_system="Trie", order=Order.lenlex) @@ -409,6 +437,10 @@ def test_to_ToddCoxeter_017(): assert isinstance(tc, ToddCoxeter) assert tc.py_template_params == (list[int],) + tc = check_cong_to_todd_coxeter(KnuthBendix, int, rewriting_system="Trie", order=Order.rev_rpo) + assert isinstance(tc, ToddCoxeter) + assert tc.py_template_params == (list[int],) + # From FroidurePin @@ -675,6 +707,8 @@ def test_to_Presentation_024(): check_knuth_bendix_to_pres(str, list[int], "Set", Order.lenlex) check_knuth_bendix_to_pres(str, str, "Set", Order.rpo) check_knuth_bendix_to_pres(str, list[int], "Set", Order.rpo) + check_knuth_bendix_to_pres(str, str, "Set", Order.rev_rpo) + check_knuth_bendix_to_pres(str, list[int], "Set", Order.rev_rpo) def test_to_Presentation_025(): @@ -682,6 +716,8 @@ def test_to_Presentation_025(): check_knuth_bendix_to_pres(str, list[int], "Trie", Order.lenlex) check_knuth_bendix_to_pres(str, str, "Trie", Order.rpo) check_knuth_bendix_to_pres(str, list[int], "Trie", Order.rpo) + check_knuth_bendix_to_pres(str, str, "Trie", Order.rev_rpo) + check_knuth_bendix_to_pres(str, list[int], "Trie", Order.rev_rpo) def test_to_Presentation_026(): @@ -689,6 +725,8 @@ def test_to_Presentation_026(): check_knuth_bendix_to_pres(list[int], list[int], "Set", Order.lenlex) check_knuth_bendix_to_pres(list[int], str, "Set", Order.rpo) check_knuth_bendix_to_pres(list[int], list[int], "Set", Order.rpo) + check_knuth_bendix_to_pres(list[int], str, "Set", Order.rev_rpo) + check_knuth_bendix_to_pres(list[int], list[int], "Set", Order.rev_rpo) def test_to_Presentation_027(): @@ -696,6 +734,8 @@ def test_to_Presentation_027(): check_knuth_bendix_to_pres(list[int], list[int], "Trie", Order.lenlex) check_knuth_bendix_to_pres(list[int], str, "Trie", Order.rpo) check_knuth_bendix_to_pres(list[int], list[int], "Trie", Order.rpo) + check_knuth_bendix_to_pres(list[int], str, "Trie", Order.rev_rpo) + check_knuth_bendix_to_pres(list[int], list[int], "Trie", Order.rev_rpo) # From FroidurePin @@ -884,6 +924,10 @@ def test_to_KnuthBendix_049(): assert isinstance(kb, KnuthBendix) assert kb.py_template_params == (str, "Set", Order.rpo) + kb = check_froidure_pin_to_knuth_bendix(str, "Set", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + assert kb.py_template_params == (str, "Set", Order.rev_rpo) + def test_to_KnuthBendix_050(): kb = check_froidure_pin_to_knuth_bendix(str, "Trie", Order.lenlex) @@ -893,6 +937,10 @@ def test_to_KnuthBendix_050(): assert isinstance(kb, KnuthBendix) assert kb.py_template_params == (str, "Trie", Order.rpo) + kb = check_froidure_pin_to_knuth_bendix(str, "Trie", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + assert kb.py_template_params == (str, "Trie", Order.rev_rpo) + def test_to_KnuthBendix_051(): kb = check_froidure_pin_to_knuth_bendix(list[int], "Set", Order.lenlex) @@ -902,6 +950,10 @@ def test_to_KnuthBendix_051(): assert isinstance(kb, KnuthBendix) assert kb.py_template_params == (list[int], "Set", Order.rpo) + kb = check_froidure_pin_to_knuth_bendix(list[int], "Set", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + assert kb.py_template_params == (list[int], "Set", Order.rev_rpo) + def test_to_KnuthBendix_052(): kb = check_froidure_pin_to_knuth_bendix(list[int], "Trie", Order.lenlex) @@ -911,6 +963,10 @@ def test_to_KnuthBendix_052(): assert isinstance(kb, KnuthBendix) assert kb.py_template_params == (list[int], "Trie", Order.rpo) + kb = check_froidure_pin_to_knuth_bendix(list[int], "Trie", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + assert kb.py_template_params == (list[int], "Trie", Order.rev_rpo) + # From ToddCoxeter + Rewriter @@ -922,6 +978,9 @@ def test_to_KnuthBendix_053(): kb = check_todd_coxeter_to_knuth_bendix(str, "Set", Order.rpo) assert isinstance(kb, KnuthBendix) + kb = check_todd_coxeter_to_knuth_bendix(str, "Set", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + def test_to_KnuthBendix_054(): kb = check_todd_coxeter_to_knuth_bendix(str, "Trie", Order.lenlex) @@ -930,6 +989,9 @@ def test_to_KnuthBendix_054(): kb = check_todd_coxeter_to_knuth_bendix(str, "Trie", Order.rpo) assert isinstance(kb, KnuthBendix) + kb = check_todd_coxeter_to_knuth_bendix(str, "Trie", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + def test_to_KnuthBendix_055(): kb = check_todd_coxeter_to_knuth_bendix(list[int], "Set", Order.lenlex) @@ -938,6 +1000,9 @@ def test_to_KnuthBendix_055(): kb = check_todd_coxeter_to_knuth_bendix(list[int], "Set", Order.rpo) assert isinstance(kb, KnuthBendix) + kb = check_todd_coxeter_to_knuth_bendix(list[int], "Set", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + def test_to_KnuthBendix_056(): kb = check_todd_coxeter_to_knuth_bendix(list[int], "Trie", Order.lenlex) @@ -946,6 +1011,9 @@ def test_to_KnuthBendix_056(): kb = check_todd_coxeter_to_knuth_bendix(list[int], "Trie", Order.rpo) assert isinstance(kb, KnuthBendix) + kb = check_todd_coxeter_to_knuth_bendix(list[int], "Trie", Order.rev_rpo) + assert isinstance(kb, KnuthBendix) + # From ToddCoxeter From fe322618a07603bedac6747c44db693a29f633c7 Mon Sep 17 00:00:00 2001 From: Joseph Edwards Date: Fri, 28 Aug 2026 15:42:19 +0100 Subject: [PATCH 2/2] KnuthBendix: register missing types --- src/libsemigroups_pybind11/knuth_bendix.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libsemigroups_pybind11/knuth_bendix.py b/src/libsemigroups_pybind11/knuth_bendix.py index 50802b85..6dedb49f 100644 --- a/src/libsemigroups_pybind11/knuth_bendix.py +++ b/src/libsemigroups_pybind11/knuth_bendix.py @@ -136,6 +136,16 @@ def __init__(self, *args, rewriting_system="Trie", order=_Order.lenlex, **kwargs _register_cxx_wrapped_type(_KnuthBendixStringLenLexSet, KnuthBendix) _register_cxx_wrapped_type(_KnuthBendixWordLenLexSet, KnuthBendix) +_register_cxx_wrapped_type(_KnuthBendixStringRPOTrie, KnuthBendix) +_register_cxx_wrapped_type(_KnuthBendixWordRPOTrie, KnuthBendix) +_register_cxx_wrapped_type(_KnuthBendixStringRPOSet, KnuthBendix) +_register_cxx_wrapped_type(_KnuthBendixWordRPOSet, KnuthBendix) + +_register_cxx_wrapped_type(_KnuthBendixStringRevRPOTrie, KnuthBendix) +_register_cxx_wrapped_type(_KnuthBendixWordRevRPOTrie, KnuthBendix) +_register_cxx_wrapped_type(_KnuthBendixStringRevRPOSet, KnuthBendix) +_register_cxx_wrapped_type(_KnuthBendixWordRevRPOSet, KnuthBendix) + ######################################################################## # Helpers ########################################################################