Skip to content

Commit 8b3472e

Browse files
presentation: add try_detect_inverses
1 parent 4f41e1f commit 8b3472e

File tree

4 files changed

+48
-0
lines changed

4 files changed

+48
-0
lines changed

docs/source/data-structures/presentations/present-helpers.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Contents
7373
strongly_compress
7474
throw_if_bad_inverses
7575
to_gap_string
76+
try_detect_inverses
7677

7778
Full API
7879
--------

src/libsemigroups_pybind11/presentation/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
presentation_index_rule as _index_rule,
5757
presentation_is_normalized as _is_normalized,
5858
presentation_is_rule as _is_rule,
59+
presentation_try_detect_inverses as _try_detect_inverses,
5960
)
6061

6162
from libsemigroups_pybind11.detail.cxx_wrapper import (
@@ -274,3 +275,4 @@ def __init__(self: _Self, *args, **kwargs) -> None:
274275
index_rule = _wrap_cxx_free_fn(_index_rule)
275276
is_normalized = _wrap_cxx_free_fn(_is_normalized)
276277
is_rule = _wrap_cxx_free_fn(_is_rule)
278+
try_detect_inverses = _wrap_cxx_free_fn(_try_detect_inverses)

src/present.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,40 @@ and *rhs* is the next item in ``p.rules``.
14831483
if :any:`Presentation.throw_if_bad_alphabet_or_rules` throws.
14841484
)pbdoc");
14851485

1486+
m.def(
1487+
"presentation_try_detect_inverses",
1488+
[](Presentation<Word>& p) {
1489+
return presentation::try_detect_inverses(p);
1490+
},
1491+
py::arg("p"),
1492+
R"pbdoc(
1493+
:sig=(p: Presentation) -> tuple[str | list[int], str | list[int]]:
1494+
:only-document-once:
1495+
1496+
Try to detect group inverses.
1497+
1498+
This function tries to deduce group theoretic inverses defined by the rules of
1499+
the presentation *p* as following: the rules of the presentation where one
1500+
side has length 2 and the other has length 0 are detected. For any such rule we
1501+
remember that the first letter is a possible inverse of the second. If rules of
1502+
the form ``ab=1`` and ``ba=1`` are detected, then ``a`` has inverse ``b`` and
1503+
vice versa. If there are multiple different such rules and we deduce
1504+
conflicting values for the inverse of a letter, then an exception is
1505+
raised.
1506+
1507+
:param p: the presentation.
1508+
:type p: Presentation
1509+
1510+
:returns:
1511+
A tuple where the first item consists of letters such that an inverse was
1512+
detected; and the second item consists of the inverses such that the item in
1513+
position ``i`` is the inverse of the letter in position ``i``.
1514+
:rtype: tuple[str | list[int], str | list[int]]
1515+
1516+
:raises LibsemigroupsError:
1517+
if :any:`throw_if_bad_alphabet_or_rules` throws.
1518+
:raises LibsemigroupsError:
1519+
if conflicting inverses for any letter are detected.)pbdoc");
14861520
} // bind_present
14871521

14881522
template <typename Word>

tests/test_present.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,3 +2224,14 @@ def test_presentation_is_rule():
22242224
assert presentation.is_rule(p, "a" * 4, "")
22252225
assert not presentation.is_rule(p, "", "a" * 4)
22262226
assert not presentation.is_rule(p, "ad" * 4, "")
2227+
2228+
2229+
def test_presentation_try_detect_inverses():
2230+
p = Presentation("abc")
2231+
p.contains_empty_word(True)
2232+
p.rules = ["aa", ""]
2233+
2234+
assert presentation.try_detect_inverses(p) == ("a", "a")
2235+
p.alphabet("abcdef")
2236+
p.rules = ["ab", "", "ba", "", "cd", "", "dc", "", "e", "ef"]
2237+
assert presentation.try_detect_inverses(p) == ("dcba", "cdab")

0 commit comments

Comments
 (0)