Skip to content

Convert from KnuthBendix and a word type to a Presentation. #243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: v1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ the following values for *args*:

Additionally, specify the following for *Return*:

- ``InversePresentation`` for constructing an :any:`InversePresentation`
- ``(InversePresentation,)`` for constructing an :any:`InversePresentation`
over words of the same type as those in *p*.

This function returns an :any:`InversePresentation` with rules equivalent to
Expand Down Expand Up @@ -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, Return=(InversePresentation,))
>>> ip.alphabet()
'abcdef'
>>> ip.inverses()
Expand Down
12 changes: 8 additions & 4 deletions docs/source/data-structures/presentations/to-present.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,14 @@ following values for *args*:
- **kb** (:any:`KnuthBendix`) -- the :any:`KnuthBendix` from which to obtain
the rules.

Additionally, specify the following for *Return*:
Additionally, specify one of the following for *Return*:

- ``Presentation`` for constructing a :any:`Presentation` over words of the
same type as that in *kb*.
- ``(Presentation,)`` for constructing a :any:`Presentation` over words of
the same type as that in *kb*.
- ``(Presentation, str)`` for constructing a :any:`Presentation` over words
of type ``str``.
- ``(Presentation, List[int]`` for constructing a :any:`Presentation` over
words of type ``List[int]``.

This function constructs and returns a :any:`Presentation` object using the
currently active rules of *kb*.
Expand Down Expand Up @@ -203,7 +207,7 @@ enumerates *kb*) prior to calling this function.

>>> kb = KnuthBendix(congruence_kind.twosided, p1)
>>> kb.run()
>>> p2 = to(kb, Return=Presentation)
>>> p2 = to(kb, Return=(Presentation,))
>>> for p in [p1, p2]:
... presentation.sort_each_rule(p)
... presentation.sort_rules(p)
Expand Down
4 changes: 2 additions & 2 deletions docs/source/data-structures/to-function.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ 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)``.
:any:`FroidurePin` object, you can simply do ``to(tc, Return=(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, Return=(ToType,))`` are given below, where the rows correspond to
``ToType`` and the columns to ``FromType``:

.. image:: ../../pictures/to-table.svg
Expand Down
20 changes: 10 additions & 10 deletions docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ following values for *args*:

Additionally, specify the following for *Return*:

- ``FroidurePin`` for constructing a :any:`FroidurePin`.
- ``(FroidurePin,)`` for constructing a :any:`FroidurePin`.

The :any:`FroidurePin` object returned is isomorphic to the quotient of the
underlying semigroup or monoid of *cong* by the congruence represented by
Expand All @@ -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, Return=(FroidurePin,))
>>> fp.run()

>>> fp.size() == cong.number_of_classes()
Expand All @@ -90,7 +90,7 @@ values for *args*:

Additionally, specify the following for *Return*:

- ``FroidurePin`` for constructing a :any:`FroidurePin`.
- ``(FroidurePin,)`` for constructing a :any:`FroidurePin`.

The :any:`FroidurePin` object returned is isomorphic to the quotient semigroup
or monoid represented by *k*.
Expand Down Expand Up @@ -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, Return=(FroidurePin,))
>>> fp.enumerate(100)

>>> fp.current_size() == 8205
Expand All @@ -140,7 +140,7 @@ following values for *args*:

Additionally, specify the following for *Return*:

- ``FroidurePin`` for constructing a :any:`FroidurePin`.
- ``(FroidurePin,)`` for constructing a :any:`FroidurePin`.

The :any:`FroidurePin` object returned is isomorphic to the quotient semigroup
or monoid represented by *kb*.
Expand All @@ -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, Return=(FroidurePin,))
>>> fp.run()

>>> fp.size() == kb.number_of_classes()
Expand All @@ -184,7 +184,7 @@ following values for *args*:

Additionally, specify the following for *Return*:

- ``FroidurePin`` for constructing a :any:`FroidurePin`.
- ``(FroidurePin,)`` for constructing a :any:`FroidurePin`.

The :any:`FroidurePin` object returned is isomorphic to the quotient semigroup
or monoid represented by *tc*.
Expand All @@ -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, Return=(FroidurePin,))
>>> fp.run()

>>> fp.size() == tc.number_of_classes()
Expand Down Expand Up @@ -237,7 +237,7 @@ or

Additionally, specify the following for *Return*:

- ``FroidurePin`` for constructing a :any:`FroidurePin`.
- ``(FroidurePin,)`` for constructing a :any:`FroidurePin`.

Each label ``n`` in the :any:`WordGraph` will correspond to a generator ``f`` in
the output :any:`FroidurePin` such that ``f[s] = t`` whenever there is an edge
Expand Down Expand Up @@ -286,7 +286,7 @@ corresponding :math:`f`.
... w, # wg
... 1, # first
... 2, # last
... Return=FroidurePin
... Return=(FroidurePin,)
... )
>>> fp.run()

Expand Down
4 changes: 2 additions & 2 deletions docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ rewriter, specify all of the following values for *args*:

Additionally, specify the following for *Return*:

- ``KnuthBendix`` for constructing a :any:`KnuthBendix` with the default
- ``(KnuthBendix,)`` for constructing a :any:`KnuthBendix` with the default
rewriter.

This function converts a :any:`ToddCoxeter` object *tc* to a :any:`KnuthBendix`
Expand Down Expand Up @@ -77,7 +77,7 @@ the semigroup defined by *tc*.
>>> kb = to(
... congruence_kind.twosided, # knd
... tc, # tc
... Return=KnuthBendix
... Return=(KnuthBendix,)
... )
>>> kb.run()

Expand Down
4 changes: 2 additions & 2 deletions docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ following values for *args*:

Additionally, specify the following for *Return*:

- ``ToddCoxeter`` for constructing a :any:`ToddCoxeter`.
- ``(ToddCoxeter,)`` for constructing a :any:`ToddCoxeter`.

This function converts the :any:`KnuthBendix` object *kb* into a
:any:`ToddCoxeter` object using the right Cayley graph of the semigroup
Expand Down Expand Up @@ -141,7 +141,7 @@ This will throw a :any:`LibsemigroupsError` if either:
>>> tc = to(
... congruence_kind.twosided, # knd
... kb, # kb
... Return=ToddCoxeter
... Return=(ToddCoxeter,)
... )
>>> tc.run()

Expand Down
112 changes: 43 additions & 69 deletions src/libsemigroups_pybind11/to.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,6 @@
from .detail.cxx_wrapper import to_cxx as _to_cxx


def __to_congruence_word(*args):
return _Congruence(_to_congruence_word(*args))


def __to_congruence_string(*args):
return _Congruence(_to_congruence_string(*args))


def _nice_name(type_list):
"""Convert an iterable of type-like things into a string"""
single_element = False
Expand All @@ -75,6 +67,44 @@ def _nice_name(type_list):
return f"({', '.join(out)})"


_RETURN_TYPE_TO_CONVERTER_FUNCTION = {
(_Congruence, str): _to_congruence_string,
(_Congruence, List[int]): _to_congruence_word,
(_FroidurePin,): _to_froidure_pin,
(_InversePresentation,): _to_inverse_presentation,
(_InversePresentation, List[int]): _to_inverse_presentation_word,
(_InversePresentation, str): _to_inverse_presentation_string,
(_KnuthBendix,): _to_knuth_bendix,
(_KnuthBendix, "RewriteTrie"): _to_knuth_bendix_RewriteTrie,
(_KnuthBendix, "RewriteFromLeft"): _to_knuth_bendix_RewriteFromLeft,
(
_KnuthBendix,
List[int],
"RewriteFromLeft",
): _to_knuth_bendix_word_RewriteFromLeft,
(
_KnuthBendix,
List[int],
"RewriteTrie",
): _to_knuth_bendix_word_RewriteTrie,
(
_KnuthBendix,
str,
"RewriteFromLeft",
): _to_knuth_bendix_string_RewriteFromLeft,
(_KnuthBendix, str, "RewriteTrie"): _to_knuth_bendix_string_RewriteTrie,
(_Presentation,): _to_presentation,
(_Presentation, str): _to_presentation_string,
(_Presentation, List[int]): _to_presentation_word,
(_ToddCoxeter,): _to_todd_coxeter,
(_ToddCoxeter, str): _to_todd_coxeter_string,
(_ToddCoxeter, List[int]): _to_todd_coxeter_word,
}

_VALID_TYPES = (_nice_name(x) for x in _RETURN_TYPE_TO_CONVERTER_FUNCTION)
_VALID_TYPES_STRING = "\n * " + "\n * ".join(_VALID_TYPES) + "\n"


def to(*args, Return):
"""Convert from one type of `libsemigroups` object to another

Expand Down Expand Up @@ -102,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, Return=(FroidurePin,))
>>> fp # doctest: +NORMALIZE_WHITESPACE
<partially enumerated FroidurePin with 2 generators, 2 elements,
Cayley graph ⌀ 1, & 0 rules>
Expand All @@ -125,67 +155,11 @@ def to(*args, Return):

"""
cxx_args = [_to_cxx(arg) for arg in args]
return_type_to_converter_function = {
(_Congruence, str): __to_congruence_string,
(_Congruence, List[int]): __to_congruence_word,
_FroidurePin: lambda *x: _FroidurePin(_to_froidure_pin(*x)),
_InversePresentation: lambda *x: _InversePresentation(
_to_inverse_presentation(*x)
),
(_InversePresentation, List[int]): lambda *x: _InversePresentation(
_to_inverse_presentation_word(*x)
),
(_InversePresentation, str): lambda *x: _InversePresentation(
_to_inverse_presentation_string(*x)
),
_KnuthBendix: lambda *x: _KnuthBendix(_to_knuth_bendix(*x)),
(_KnuthBendix, "RewriteTrie"): lambda *x: _KnuthBendix(
_to_knuth_bendix_RewriteTrie(*x)
),
(_KnuthBendix, "RewriteFromLeft"): lambda *x: _KnuthBendix(
_to_knuth_bendix_RewriteFromLeft(*x)
),
(
_KnuthBendix,
List[int],
"RewriteFromLeft",
): lambda *x: _KnuthBendix(_to_knuth_bendix_word_RewriteFromLeft(*x)),
(
_KnuthBendix,
List[int],
"RewriteTrie",
): lambda *x: _KnuthBendix(_to_knuth_bendix_word_RewriteTrie(*x)),
(
_KnuthBendix,
str,
"RewriteFromLeft",
): lambda *x: _KnuthBendix(_to_knuth_bendix_string_RewriteFromLeft(*x)),
(_KnuthBendix, str, "RewriteTrie"): lambda *x: _KnuthBendix(
_to_knuth_bendix_string_RewriteTrie(*x)
),
_Presentation: lambda *x: _Presentation(_to_presentation(*x)),
(_Presentation, str): lambda *x: _Presentation(
_to_presentation_string(*x)
),
(_Presentation, List[int]): lambda *x: _Presentation(
_to_presentation_word(*x)
),
_ToddCoxeter: lambda *x: _ToddCoxeter(_to_todd_coxeter(*x)),
(_ToddCoxeter, str): lambda *x: _ToddCoxeter(
_to_todd_coxeter_string(*x)
),
(_ToddCoxeter, List[int]): lambda *x: _ToddCoxeter(
_to_todd_coxeter_word(*x)
),
}

if Return not in return_type_to_converter_function:
valid_types = (_nice_name(x) for x in return_type_to_converter_function)
valid_types_string = "\n * " + "\n * ".join(valid_types) + "\n"
if Return not in _RETURN_TYPE_TO_CONVERTER_FUNCTION:
raise TypeError(
"expected the first keyword argument to be one of:"
f"{valid_types_string}"
f"{_VALID_TYPES_STRING}"
f"but found: {_nice_name(Return)}"
)

return return_type_to_converter_function[Return](*cxx_args)
constructor = Return[0]
return constructor(_RETURN_TYPE_TO_CONVERTER_FUNCTION[Return](*cxx_args))
26 changes: 26 additions & 0 deletions src/to-presentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ namespace libsemigroups {
});
}

template <typename WordIn, typename WordOut, typename Rewriter>
void bind_kb_to_pres_with_word(py::module& m, std::string const& name) {
std::string fn_name = std::string("to_presentation_") + name;
m.def(fn_name.c_str(), [](KnuthBendix<WordIn, Rewriter>& kb) {
return to<Presentation<WordOut>>(kb);
});
}

template <typename Word>
void bind_fp_to_pres(py::module& m, std::string const& name) {
std::string fn_name = std::string("to_presentation_") + name;
Expand Down Expand Up @@ -119,6 +127,24 @@ namespace libsemigroups {
bind_kb_to_pres<word_type, detail::RewriteFromLeft>(m);
bind_kb_to_pres<word_type, detail::RewriteTrie>(m);

bind_kb_to_pres_with_word<std::string,
std::string,
detail::RewriteFromLeft>(m, "string");
bind_kb_to_pres_with_word<std::string, std::string, detail::RewriteTrie>(
m, "string");
bind_kb_to_pres_with_word<word_type, std::string, detail::RewriteFromLeft>(
m, "string");
bind_kb_to_pres_with_word<word_type, std::string, detail::RewriteTrie>(
m, "string");
bind_kb_to_pres_with_word<std::string, word_type, detail::RewriteFromLeft>(
m, "word");
bind_kb_to_pres_with_word<std::string, word_type, detail::RewriteTrie>(
m, "word");
bind_kb_to_pres_with_word<word_type, word_type, detail::RewriteFromLeft>(
m, "word");
bind_kb_to_pres_with_word<word_type, word_type, detail::RewriteTrie>(
m, "word");

// From FroidurePin
bind_fp_to_pres<std::string>(m, "string");
bind_fp_to_pres<word_type>(m, "word");
Expand Down
Loading