Skip to content

Commit 1a16538

Browse files
present: add make for converting string presentations to words
1 parent 208a6f9 commit 1a16538

File tree

5 files changed

+108
-32
lines changed

5 files changed

+108
-32
lines changed

docs/source/presentations/present-helpers.rst

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,40 +61,45 @@ Contents
6161
- Reverse every rule.
6262

6363
* - :py:func:`normalize_alphabet`
64-
- Modify the presentation so that the alphabet is :math:`\{0, \ldots, n - 1\}` (or equivalent), and rewrites the rules to use this alphabet.
64+
- Modify the presentation so that the alphabet is :math:`\{0, \ldots, n -
65+
1\}` (or equivalent), and rewrites the rules to use this alphabet.
66+
67+
* - :py:func:`make`
68+
- Make a presentation from another type of presentation or a
69+
``FroidurePin`` instance.
6570

6671
Full API
6772
--------
6873

6974
.. py:function:: redundant_rule(p: Presentation, t: datetime.timedelta) -> int
7075
7176
Return the index of the the left hand side of a redundant rule.
72-
77+
7378
Starting with the last rule in the presentation, this function attempts to
7479
run the Knuth-Bendix algorithm on the rules of the presentation except for
7580
the given omitted rule. For every such omitted rule, Knuth-Bendix is run for
7681
the length of time indicated by the second parameter ``t`` and then it is
7782
checked if the omitted rule can be shown to be redundant (rewriting both
7883
sides of the omitted rule using the other rules using the output of the, not
7984
necessarily finished, Knuth-Bendix algorithm).
80-
85+
8186
If the omitted rule can be shown to be redundant in this way, then the index
8287
of its left hand side is returned.
83-
88+
8489
If no rule can be shown to be redundant in this way, then ``len(p.rules)``
8590
is returned.
86-
91+
8792
:warning:
8893
The progress of the Knuth-Bendix algorithm may differ between different
8994
calls to this function even if the parameters are identical. As such this
9095
is non-deterministic, and may produce different results with the same
9196
input.
92-
97+
9398
:param p: the presentation.
9499
:type p: Presentation
95100
:param t: time to run KnuthBendix for every omitted rule
96101
:type t: datetime.timedelta
97-
102+
98103
:return: The index of a redundant rule (if any).
99104

100105
**Example**::
@@ -111,19 +116,19 @@ Full API
111116
.. py:function:: add_rule(p: Presentation, lhop: Union[str, List[int]], rhop: Union[str, List[int]]) -> None
112117
113118
Add a rule to the presentation.
114-
119+
115120
Adds the rule with left hand side ``lhop`` and right hand side ``rhop``
116121
to the rules.
117-
122+
118123
:param p: the presentation
119124
:type p: Presentation
120125
:param lhop: the left hand side of the rule
121126
:type lhop: str or List[int]
122127
:param rhop: the right hand side of the rule
123128
:type rhop: str or List[int]
124-
129+
125130
:returns: None
126-
131+
127132
:warning:
128133
No checks that the arguments describe words over the alphabet of the
129134
presentation are performed.
@@ -205,7 +210,7 @@ Full API
205210
p.rules # ['ac', 'a', 'ca', 'a', 'bc', 'b', 'cb', 'b', 'cc', 'c']
206211

207212
.. py:function:: add_inverse_rules(p: Presentation, vals: Union[str, List[int], e: Union[str, int]) -> None
208-
213+
209214
Add rules for inverses.
210215
211216
The letter ``a`` with index ``i`` in ``vals`` is the inverse of the letter in the alphabet
@@ -362,4 +367,25 @@ Full API
362367
:param p: the presentation
363368
:type p: Presentation
364369
365-
:returns: None
370+
:returns: None
371+
372+
.. py:function:: make(p: Presentation) -> Presentation
373+
374+
Converts a presentation over strings to one over lists of integers or vice
375+
versa.
376+
377+
:param p: the presentation
378+
:type p: Presentation
379+
380+
:returns: A ``Presentation``.
381+
382+
.. py:function:: make(S: FroidurePin) -> Presentation
383+
:noindex:
384+
385+
Returns a presentation defining a semigroup isomorphic to that represented
386+
by a ``FroidurePin`` instance.
387+
388+
:param S: the ``FroidurePin`` instance.
389+
:type S: FroidurePin
390+
391+
:returns: A ``Presentation``.

libsemigroups_pybind11/presentation.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
redundant_rule_strings,
3434
redundant_rule_words,
3535
FroidurePinBase,
36-
make_from_froidure_pin,
36+
make,
3737
)
3838

3939

@@ -51,11 +51,10 @@ def Presentation(arg):
5151
elif isinstance(arg, list) and all(isinstance(x, int) for x in arg):
5252
result = PresentationWords()
5353
result.alphabet(arg)
54-
elif isinstance(arg, FroidurePinBase):
55-
result = make_from_froidure_pin(arg)
5654
else:
57-
# TODO update this string
58-
raise TypeError("expected string or list of ints argument")
55+
raise TypeError(
56+
"expected the argument to be a Presentation, string, or list of ints"
57+
)
5958
return result
6059

6160

src/present.cpp

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ namespace libsemigroups {
4646
namespace {
4747

4848
template <typename T>
49-
std::string presentation_repr(Presentation<T> &p) {
49+
std::string presentation_repr(Presentation<T>& p) {
5050
// FIXME presentation::length does not take const refs but refs and so we
5151
// must do the same.
5252
std::ostringstream out;
@@ -59,18 +59,18 @@ namespace libsemigroups {
5959
}
6060

6161
template <typename T>
62-
void bind_present(py::module &m, std::string const &name) {
62+
void bind_present(py::module& m, std::string const& name) {
6363
using size_type = typename Presentation<T>::size_type;
6464

6565
py::class_<Presentation<T>>(m, name.c_str())
6666
.def(py::init<>())
67-
.def(py::init<Presentation<T> const &>())
67+
.def(py::init<Presentation<T> const&>())
6868
.def("alphabet",
6969
py::overload_cast<>(&Presentation<T>::alphabet, py::const_))
7070
.def("alphabet",
7171
py::overload_cast<size_type>(&Presentation<T>::alphabet))
7272
.def("alphabet",
73-
py::overload_cast<T const &>(&Presentation<T>::alphabet))
73+
py::overload_cast<T const&>(&Presentation<T>::alphabet))
7474
.def("alphabet_from_rules", &Presentation<T>::alphabet_from_rules)
7575
.def("letter", &Presentation<T>::letter)
7676
.def("index", &Presentation<T>::index)
@@ -89,10 +89,10 @@ namespace libsemigroups {
8989
.def("__repr__", &presentation_repr<T>);
9090

9191
m.def("add_rule",
92-
py::overload_cast<Presentation<T> &, T const &, T const &>(
92+
py::overload_cast<Presentation<T>&, T const&, T const&>(
9393
&presentation::add_rule<T>));
9494
m.def("add_rule_and_check",
95-
py::overload_cast<Presentation<T> &, T const &, T const &>(
95+
py::overload_cast<Presentation<T>&, T const&, T const&>(
9696
&presentation::add_rule_and_check<T>));
9797
m.def("add_rules", &presentation::add_rules<T>);
9898
m.def("add_identity_rules", &presentation::add_identity_rules<T>);
@@ -103,21 +103,35 @@ namespace libsemigroups {
103103
m.def("sort_rules", &presentation::sort_rules<T>);
104104
m.def("longest_common_subword", &presentation::longest_common_subword<T>);
105105
m.def("replace_subword",
106-
py::overload_cast<Presentation<T> &, T const &>(
106+
py::overload_cast<Presentation<T>&, T const&>(
107107
&presentation::replace_subword<T>));
108108
m.def("length", &presentation::length<T>);
109109
m.def("reverse", &presentation::reverse<T>);
110110
m.def("normalize_alphabet", &presentation::normalize_alphabet<T>);
111111

112112
m.def(
113-
"make_from_froidure_pin",
114-
py::overload_cast<FroidurePinBase &>(&make<Presentation<word_type>>));
115-
116-
// TODO add make
113+
"make",
114+
py::overload_cast<FroidurePinBase&>(&make<Presentation<word_type>>));
115+
116+
m.def("make",
117+
[](Presentation<std::string> const& p) -> Presentation<word_type> {
118+
return make<Presentation<word_type>>(p);
119+
});
120+
121+
m.def("make",
122+
[](Presentation<word_type> const& p) -> Presentation<std::string> {
123+
return make<Presentation<std::string>>(p);
124+
});
125+
126+
m.def("make",
127+
[](Presentation<word_type> const& p,
128+
std::string const& s) -> Presentation<std::string> {
129+
return make<Presentation<word_type>>(p, s);
130+
});
117131
}
118132
} // namespace
119133

120-
void init_present(py::module &m) {
134+
void init_present(py::module& m) {
121135
bind_present<word_type>(m, "PresentationWords");
122136
bind_present<std::string>(m, "PresentationStrings");
123137
}

tests/test_present.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,40 @@ def test_helpers_longest_common_subword_019():
647647
def test_redundant_rule_020():
648648
check_redundant_rule(to_word)
649649
check_redundant_rule(to_string)
650+
651+
652+
def test_make_021():
653+
p = Presentation([])
654+
presentation.add_rule(p, [0, 1, 2, 1], [1, 2, 1])
655+
presentation.add_rule(p, [1, 2, 1], [1, 1, 2, 1])
656+
presentation.add_rule(p, [1, 1, 2, 1], [1, 1])
657+
presentation.add_rule(p, [1, 1], [1, 2, 1])
658+
presentation.add_rule(p, [1, 2, 1], [0])
659+
p.alphabet_from_rules()
660+
p = presentation.make(p, "abc")
661+
assert p.rules == [
662+
"abcb",
663+
"bcb",
664+
"bcb",
665+
"bbcb",
666+
"bbcb",
667+
"bb",
668+
"bb",
669+
"bcb",
670+
"bcb",
671+
"a",
672+
]
673+
674+
p = presentation.make(p)
675+
assert p.rules == [
676+
[0, 1, 2, 1],
677+
[1, 2, 1],
678+
[1, 2, 1],
679+
[1, 1, 2, 1],
680+
[1, 1, 2, 1],
681+
[1, 1],
682+
[1, 1],
683+
[1, 2, 1],
684+
[1, 2, 1],
685+
[0],
686+
]

tests/test_sims1.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def test_case_sims1_006():
185185
assert S.number_of_generators() == 3
186186
assert S.number_of_rules() == 16
187187
C = Sims1(congruence_kind.right)
188-
C.short_rules(Presentation(S))
188+
C.short_rules(presentation.make(S))
189189
assert C.number_of_congruences(27) == 287
190190

191191

@@ -196,7 +196,7 @@ def test_case_sims1_007():
196196
assert S.number_of_generators() == 3
197197
assert S.number_of_rules() == 16
198198
C = Sims1(congruence_kind.left)
199-
C.short_rules(Presentation(S))
199+
C.short_rules(presentation.make(S))
200200
assert C.number_of_congruences(27) == 120
201201

202202

0 commit comments

Comments
 (0)