Skip to content

Commit 5d06b1b

Browse files
Merge stable-0.5
2 parents 767829c + 81796fb commit 5d06b1b

File tree

5 files changed

+297
-77
lines changed

5 files changed

+297
-77
lines changed

setup.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,11 @@ def __str__(self):
205205
ext_modules=ext_modules,
206206
packages=find_packages(),
207207
setup_requires=["pkgconfig>=1.5.0"],
208-
install_requires=["pybind11>=2.6", "packaging>=20.4", "pkgconfig>=1.5.0"],
208+
install_requires=[
209+
"pybind11>=2.10.1",
210+
"packaging>=20.4",
211+
"pkgconfig>=1.5.0",
212+
],
209213
tests_require=["pytest==6.2.4"],
210214
cmdclass={"build_ext": build_ext},
211215
zip_safe=False,

src/cong.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <libsemigroups/types.hpp> // for word_type
3636

3737
// pybind11....
38+
#include <pybind11/chrono.h> // for auto conversion of py types for run_for
3839
#include <pybind11/pybind11.h> // for class_, init, make_iterator, module
3940
#include <pybind11/stl.h>
4041

src/knuth-bendix.cpp

Lines changed: 130 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,33 @@
3737
#include <pybind11/chrono.h>
3838
#include <pybind11/functional.h>
3939
#include <pybind11/pybind11.h> // for class_, make_iterator, enum_, init
40+
#include <pybind11/pytypes.h> // for py::str
4041
#include <pybind11/stl.h>
4142

43+
#include <Python.h> // for PyUnicode_DecodeLatin1
44+
4245
// libsemigroups_pybind11....
4346
#include "doc-strings.hpp" // for dead, finished, kill, report
4447
#include "main.hpp" // for init_knuth_bendix
4548

49+
namespace py = pybind11;
50+
4651
namespace libsemigroups {
4752
class FroidurePinBase;
48-
}
4953

50-
namespace py = pybind11;
54+
namespace {
55+
std::string to_latin1(std::string const& u) {
56+
static py::object bytes = py::globals()["__builtins__"]["bytes"];
57+
return PyBytes_AS_STRING(bytes(py::str(u), "latin1").ptr());
58+
}
59+
60+
py::str from_latin1(std::string const& u) {
61+
// TODO don't pass NULL as the final param
62+
return py::reinterpret_steal<py::str>(
63+
PyUnicode_DecodeLatin1(u.data(), u.length(), NULL));
64+
}
65+
} // namespace
5166

52-
namespace libsemigroups {
5367
void init_knuth_bendix(py::module& m) {
5468
using rule_type = FpSemigroupInterface::rule_type;
5569

@@ -99,11 +113,13 @@ namespace libsemigroups {
99113
R"pbdoc(
100114
Default constructor.
101115
)pbdoc")
102-
.def("set_alphabet",
103-
py::overload_cast<std::string const&>(
104-
&fpsemigroup::KnuthBendix::set_alphabet),
105-
py::arg("a"),
106-
R"pbdoc(
116+
.def(
117+
"set_alphabet",
118+
[](fpsemigroup::KnuthBendix& kb, std::string const& a) {
119+
kb.set_alphabet(to_latin1(a));
120+
},
121+
py::arg("a"),
122+
R"pbdoc(
107123
Set the alphabet of the finitely presented semigroup.
108124
109125
:Parameters: **a** (str) - the alphabet.
@@ -119,33 +135,41 @@ namespace libsemigroups {
119135
:Parameters: **n** (int) - the number of letters.
120136
:Returns: None
121137
)pbdoc")
122-
.def("alphabet",
123-
py::overload_cast<>(&fpsemigroup::KnuthBendix::alphabet,
124-
py::const_),
125-
R"pbdoc(
138+
.def(
139+
"alphabet",
140+
[](fpsemigroup::KnuthBendix const& kb) -> py::str {
141+
return from_latin1(kb.alphabet());
142+
},
143+
R"pbdoc(
126144
Returns the alphabet.
127145
128146
:Parameters: None
129147
:Returns: A string.
130148
)pbdoc")
131-
.def("alphabet",
132-
py::overload_cast<size_t>(&fpsemigroup::KnuthBendix::alphabet,
133-
py::const_),
134-
py::arg("i"),
135-
R"pbdoc(
149+
.def(
150+
"alphabet",
151+
[](fpsemigroup::KnuthBendix const& kb, size_t i) -> py::str {
152+
return from_latin1(kb.alphabet(i));
153+
},
154+
py::arg("i"),
155+
R"pbdoc(
136156
Returns the i-th letter of the alphabet of the finitely presented
137157
semigroup represented by this.
138158
139159
:Parameters: **i** (int) - the index of the letter.
140160
141161
:Returns: A string.
142162
)pbdoc")
143-
.def("add_rule",
144-
py::overload_cast<std::string const&, std::string const&>(
145-
&fpsemigroup::KnuthBendix::add_rule),
146-
py::arg("u"),
147-
py::arg("v"),
148-
R"pbdoc(
163+
.def(
164+
"add_rule",
165+
[](fpsemigroup::KnuthBendix& kb,
166+
std::string const& u,
167+
std::string const& v) -> void {
168+
kb.add_rule(to_latin1(u), to_latin1(v));
169+
},
170+
py::arg("u"),
171+
py::arg("v"),
172+
R"pbdoc(
149173
Add a rule.
150174
151175
:Parameters: - **u** (str) - the left-hand side of the rule
@@ -154,7 +178,7 @@ namespace libsemigroups {
154178
being added.
155179
156180
:Returns: None
157-
)pbdoc")
181+
)pbdoc")
158182
.def("size",
159183
&fpsemigroup::KnuthBendix::size,
160184
R"pbdoc(
@@ -184,9 +208,17 @@ namespace libsemigroups {
184208
``True`` if the KnuthBendix instance is confluent and
185209
``False`` if it is not.
186210
)pbdoc")
187-
.def("active_rules",
188-
&fpsemigroup::KnuthBendix::active_rules,
189-
R"pbdoc(
211+
.def(
212+
"active_rules",
213+
[](fpsemigroup::KnuthBendix const& kb) {
214+
auto result = kb.active_rules();
215+
std::for_each(result.begin(), result.end(), [](rule_type& rule) {
216+
rule.first = from_latin1(rule.first);
217+
rule.second = from_latin1(rule.second);
218+
});
219+
return result;
220+
},
221+
R"pbdoc(
190222
Returns a copy of the active rules of the KnuthBendix instance.
191223
192224
:Parameters: None
@@ -216,41 +248,52 @@ namespace libsemigroups {
216248
217249
:Returns: None
218250
)pbdoc")
219-
.def("set_identity",
220-
py::overload_cast<std::string const&>(
221-
&fpsemigroup::KnuthBendix::set_identity),
222-
py::arg("id"),
223-
R"pbdoc(
251+
.def(
252+
"set_identity",
253+
[](fpsemigroup::KnuthBendix& kb, std::string const& id) {
254+
kb.set_identity(to_latin1(id));
255+
},
256+
py::arg("id"),
257+
R"pbdoc(
224258
Set a character in alphabet() to be the identity.
225259
226260
:Parameters: **id** (str) - a string containing the character to
227261
be the identity.
228262
229263
:Returns: None
230264
)pbdoc")
231-
.def("set_inverses",
232-
&fpsemigroup::KnuthBendix::set_inverses,
233-
py::arg("a"),
234-
R"pbdoc(
265+
.def(
266+
"identity",
267+
[](fpsemigroup::KnuthBendix const& kb) {
268+
return from_latin1(kb.identity());
269+
},
270+
R"pbdoc(
271+
Returns the identity of this, or raises an exception if there
272+
isn't one.
273+
274+
:Parameters: None
275+
:return: A string of length 1.
276+
)pbdoc")
277+
.def(
278+
"set_inverses",
279+
[](fpsemigroup::KnuthBendix& kb, std::string const& a) {
280+
return kb.set_inverses(to_latin1(a));
281+
},
282+
py::arg("a"),
283+
R"pbdoc(
235284
Set the inverses of letters in alphabet().
236285
237286
:param a: a string containing the inverses of the generators.
238287
:type a: str
239288
240289
:return: None
241290
)pbdoc")
242-
.def("identity",
243-
&fpsemigroup::KnuthBendix::identity,
244-
R"pbdoc(
245-
Returns the identity of this, or raises an exception if there
246-
isn't one.
247-
248-
:Parameters: None
249-
:return: A string of length 1.
250-
)pbdoc")
251-
.def("inverses",
252-
&fpsemigroup::KnuthBendix::inverses,
253-
R"pbdoc(
291+
.def(
292+
"inverses",
293+
[](fpsemigroup::KnuthBendix const& kb) {
294+
return from_latin1(kb.inverses());
295+
},
296+
R"pbdoc(
254297
Returns the inverses of this, or raises an exception if there aren't
255298
any.
256299
@@ -275,12 +318,16 @@ namespace libsemigroups {
275318
276319
:return: A bool.
277320
)pbdoc")
278-
.def("equal_to",
279-
py::overload_cast<std::string const&, std::string const&>(
280-
&fpsemigroup::KnuthBendix::equal_to),
281-
py::arg("u"),
282-
py::arg("v"),
283-
R"pbdoc(
321+
.def(
322+
"equal_to",
323+
[](fpsemigroup::KnuthBendix& kb,
324+
std::string const& u,
325+
std::string const& v) {
326+
return kb.equal_to(to_latin1(u), to_latin1(v));
327+
},
328+
py::arg("u"),
329+
py::arg("v"),
330+
R"pbdoc(
284331
Check if two words represent the same element.
285332
286333
:Parameters: - **u** (str) - first word for comparison.
@@ -307,11 +354,13 @@ namespace libsemigroups {
307354
element of the finitely presented semigroup, and ``False``
308355
otherwise.
309356
)pbdoc")
310-
.def("normal_form",
311-
py::overload_cast<std::string const&>(
312-
&fpsemigroup::KnuthBendix::normal_form),
313-
py::arg("w"),
314-
R"pbdoc(
357+
.def(
358+
"normal_form",
359+
[](fpsemigroup::KnuthBendix& kb, std::string const& w) {
360+
return from_latin1(kb.normal_form(to_latin1(w)));
361+
},
362+
py::arg("w"),
363+
R"pbdoc(
315364
Returns a normal form for a string.
316365
317366
:Parameters: **w** (str) - the word whose normal form we want to find.
@@ -389,11 +438,13 @@ namespace libsemigroups {
389438
390439
:Returns: None
391440
)pbdoc")
392-
.def("validate_word",
393-
py::overload_cast<std::string const&>(
394-
&fpsemigroup::KnuthBendix::validate_word, py::const_),
395-
py::arg("w"),
396-
R"pbdoc(
441+
.def(
442+
"validate_word",
443+
[](fpsemigroup::KnuthBendix const& kb, std::string const& w) {
444+
kb.validate_word(to_latin1(w));
445+
},
446+
py::arg("w"),
447+
R"pbdoc(
397448
Validates a word.
398449
399450
:Parameters: **w** (str) - the word to validate.
@@ -510,10 +561,13 @@ namespace libsemigroups {
510561
511562
:return: A ``str``.
512563
)pbdoc")
513-
.def("string_to_word",
514-
&fpsemigroup::KnuthBendix::string_to_word,
515-
py::arg("w"),
516-
R"pbdoc(
564+
.def(
565+
"string_to_word",
566+
[](fpsemigroup::KnuthBendix const& kb, std::string const& w) {
567+
return kb.string_to_word(to_latin1(w));
568+
},
569+
py::arg("w"),
570+
R"pbdoc(
517571
Convert a string to a list of ``int`` representing the same
518572
element of the finitely presented semigroup represented by this.
519573
@@ -522,10 +576,13 @@ namespace libsemigroups {
522576
523577
:return: a ``List[int]``.
524578
)pbdoc")
525-
.def("word_to_string",
526-
&fpsemigroup::KnuthBendix::word_to_string,
527-
py::arg("w"),
528-
R"pbdoc(
579+
.def(
580+
"word_to_string",
581+
[](fpsemigroup::KnuthBendix const& kb, word_type const& w) {
582+
return from_latin1(kb.word_to_string(w));
583+
},
584+
py::arg("w"),
585+
R"pbdoc(
529586
Convert a list of ``int`` to a string representing the same
530587
element of the finitely presented semigroup represented by this.
531588
@@ -706,5 +763,5 @@ namespace libsemigroups {
706763
707764
:returns: A copy of the argument ``w`` after it has been rewritten.
708765
)pbdoc");
709-
}
766+
} // namespace
710767
} // namespace libsemigroups

tests/test_cong.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
"""
1212

1313
# pylint: disable=no-name-in-module, missing-function-docstring, invalid-name
14-
14+
from datetime import timedelta
1515
from libsemigroups_pybind11 import (
16-
FpSemigroup,
1716
Congruence,
18-
congruence_kind,
17+
FpSemigroup,
1918
ReportGuard,
19+
congruence_kind,
2020
)
2121

2222

@@ -46,3 +46,6 @@ def test_018():
4646
assert cong.number_of_non_trivial_classes() == 1
4747
assert cong.finished()
4848
assert cong.non_trivial_classes(0) == [[0], [1], [0, 1], [1, 1], [0, 1, 1]]
49+
# The next line does nothing except check that it's possible to call
50+
# `run_for` with a timedelta
51+
cong.run_for(timedelta(seconds=1))

0 commit comments

Comments
 (0)