Skip to content

Commit 8f643cf

Browse files
presentation: add balance
1 parent 5a4b6ee commit 8f643cf

4 files changed

Lines changed: 1155 additions & 1 deletion

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Contents
4040
add_rules
4141
add_zero_rules
4242
are_rules_sorted
43+
balance
4344
change_alphabet
4445
contains_rule
4546
first_unused_letter

src/libsemigroups_pybind11/presentation/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
presentation_strongly_compress as _strongly_compress,
5353
presentation_throw_if_bad_inverses as _throw_if_bad_inverses,
5454
presentation_to_gap_string as _to_gap_string,
55+
presentation_balance as _balance,
5556
)
5657

5758
from libsemigroups_pybind11.detail.cxx_wrapper import (
@@ -263,3 +264,4 @@ def __init__(self: _Self, *args, **kwargs) -> None:
263264
strongly_compress = _wrap_cxx_free_fn(_strongly_compress)
264265
throw_if_bad_inverses = _wrap_cxx_free_fn(_throw_if_bad_inverses)
265266
to_gap_string = _wrap_cxx_free_fn(_to_gap_string)
267+
balance = _wrap_cxx_free_fn(_balance)

src/present.cpp

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1272,6 +1272,103 @@ checks that :math:`v_i = x_j`, and therefore that :math:`(x_i^{-1})^{-1} = x`.
12721272
:raises LibsemigroupsError:
12731273
if the values in *vals* do not serve as semigroup inverses.
12741274
)pbdoc");
1275+
1276+
m.def(
1277+
"presentation_balance",
1278+
[](Presentation<Word>& p) { return presentation::balance(p); },
1279+
py::arg("p"),
1280+
R"pbdoc(
1281+
:sig=(p: Presentation) -> None:
1282+
:only-document-once:
1283+
1284+
Detect inverses and balance the length of the left-hand and right-hand sides.
1285+
1286+
This function calls the 3-argument version of ``balance`` where the 2nd and 3rd
1287+
arguments are deduced from the rules in the presentation if possible as
1288+
follows: the rules of the presentation where one side has length
1289+
``2`` and the other has length ``0`` are detected. For any such rule we remember
1290+
that the first letter is the inverse of the second and vice versa. If there
1291+
are no such rules, then no changes are made. If there are multiple different
1292+
such rules and we deduce conflicting values for the inverse of a letter, then
1293+
an exception is thrown.
1294+
1295+
:param p: the presentation.
1296+
:type p: Presentation
1297+
1298+
:raises LibsemigroupsError: if :any:`throw_if_bad_alphabet_or_rules` throws.
1299+
:raises LibsemigroupsError: if conflicting inverses for any letter are detected.)pbdoc");
1300+
1301+
m.def(
1302+
"presentation_balance",
1303+
[](Presentation<Word>& p, Word const& inverses) {
1304+
return presentation::balance(p, inverses);
1305+
},
1306+
py::arg("p"),
1307+
py::arg("inverses"),
1308+
R"pbdoc(
1309+
:sig=(p: Presentation, inverses : Word) -> None:
1310+
:only-document-once:
1311+
1312+
Balance the length of the left-hand and right-hand sides.
1313+
1314+
This function calls the 3-argument version of :any:`balance` where the 2nd
1315+
parameter is defined to be ``p.alphabet()``.
1316+
1317+
:param p: the presentation.
1318+
:type p: Presentation
1319+
1320+
:param inverses: the inverses of the letters.
1321+
:type inverses: :ref:`Word<pseudo_word_type_helper>`
1322+
1323+
:raises LibsemigroupsError: if :any:`throw_if_bad_alphabet_or_rules` throws.
1324+
1325+
:raises LibsemigroupsError:
1326+
if :any:`throw_if_bad_inverses` throws when called with ``p.alphabet()`` and
1327+
``inverses``. This function does not check that the values in ``inverses``
1328+
are actually inverses for the values in ``p.alphabet()``, and balances the
1329+
relations as described in :any:`balance` assuming that this is the
1330+
case.)pbdoc");
1331+
1332+
m.def(
1333+
"presentation_balance",
1334+
[](Presentation<Word>& p, Word const& letters, Word const& inverses) {
1335+
return presentation::balance(p, letters, inverses);
1336+
},
1337+
py::arg("p"),
1338+
py::arg("letters"),
1339+
py::arg("inverses"),
1340+
R"pbdoc(
1341+
:sig=(p: Presentation, letters: Word, inverses : Word) -> None:
1342+
:only-document-once:
1343+
1344+
Balance the length of the left-hand and right-hand sides.
1345+
1346+
This function first sorts the sides of each rules so that the larger
1347+
side of the rule is on the left. Then for each rule, while the last
1348+
letter of the left-hand side is in *letters*, the last letter of the
1349+
left-hand side is removed and the corresponding value in *inverses* is
1350+
appended to the end of the right-hand side. Next, while the first
1351+
letter of the left-hand side is in *letters*, the first letter of the
1352+
left-hand side is removed and the corresponding value in *inverses* is
1353+
appended to the front of the right-hand side.
1354+
1355+
:param p: the presentation.
1356+
:type p: Presentation
1357+
1358+
:param letters: the letters that can be replaced in the left-hand side.
1359+
:type letters: :ref:`Word<pseudo_word_type_helper>`
1360+
1361+
:param inverses: the inverses of the letters.
1362+
:type inverses: :ref:`Word<pseudo_word_type_helper>`
1363+
1364+
:raises LibsemigroupsError: if throw_if_bad_alphabet_or_rules throws.
1365+
1366+
:raises LibsemigroupsError:
1367+
if :any:`throw_if_bad_inverses` throws when called with *letters* and
1368+
*inverses*. This does not check that the values in *inverses* are
1369+
actually inverses for the values in *letters*, and balances the relations
1370+
as described above.
1371+
)pbdoc");
12751372
} // bind_present
12761373

12771374
template <typename Word>
@@ -1410,7 +1507,7 @@ defined in the alphabet, and that the inverses act as semigroup inverses.
14101507
* :any:`presentation.throw_if_bad_inverses`
14111508
)pbdoc");
14121509
} // bind_inverse_present
1413-
} // namespace
1510+
} // namespace
14141511

14151512
void init_present(py::module& m) {
14161513
bind_present<word_type>(m, "PresentationWord");

0 commit comments

Comments
 (0)