Skip to content

Commit 2ee78d9

Browse files
stephen: add support for Presentation[str]
1 parent 3570b48 commit 2ee78d9

3 files changed

Lines changed: 85 additions & 23 deletions

File tree

src/libsemigroups_pybind11/stephen.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
from typing_extensions import Self as _Self
1414

1515
from _libsemigroups_pybind11 import (
16+
InversePresentationString as _InversePresentationString,
1617
InversePresentationWord as _InversePresentationWord,
18+
PresentationString as _PresentationString,
1719
PresentationWord as _PresentationWord,
20+
StephenInversePresentationString as _StephenInversePresentationString,
1821
StephenInversePresentationWord as _StephenInversePresentationWord,
22+
StephenPresentationString as _StephenPresentationString,
1923
StephenPresentationWord as _StephenPresentationWord,
2024
stephen_accepts as _stephen_accepts,
2125
stephen_dot as _stephen_dot,
@@ -46,8 +50,10 @@ class Stephen(_CxxWrapper):
4650
__doc__ = _StephenPresentationWord.__doc__
4751

4852
_py_template_params_to_cxx_type = {
49-
(_PresentationWord,): _StephenPresentationWord,
53+
(_InversePresentationString,): _StephenInversePresentationString,
5054
(_InversePresentationWord,): _StephenInversePresentationWord,
55+
(_PresentationString,): _StephenPresentationString,
56+
(_PresentationWord,): _StephenPresentationWord,
5157
}
5258

5359
_cxx_type_to_py_template_params = dict(

src/stephen.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ namespace libsemigroups {
3434
namespace {
3535
template <typename PresentationType>
3636
void bind_stephen(py::module& m, std::string const& name) {
37-
using Stephen_ = Stephen<PresentationType>;
37+
using Stephen_ = Stephen<PresentationType>;
38+
using native_word_type = typename Stephen_::native_word_type;
3839

3940
py::class_<Stephen_, Runner> thing(m,
4041
name.c_str(),
@@ -217,7 +218,7 @@ Get the input presentation.
217218
// in libsemigroups itself
218219
thing.def(
219220
"set_word",
220-
[](Stephen_& self, word_type const& word) -> Stephen_& {
221+
[](Stephen_& self, native_word_type const& word) -> Stephen_& {
221222
return stephen::set_word(self, word);
222223
},
223224
py::arg("word"),
@@ -545,11 +546,12 @@ been triggered already).
545546

546547
} // namespace
547548
void init_stephen(py::module& m) {
548-
// TODO(2): figure out how to handle std::string Stephens once that's
549-
// supported
550549
bind_stephen<Presentation<word_type>>(m, "StephenPresentationWord");
551550
bind_stephen<InversePresentation<word_type>>(
552551
m, "StephenInversePresentationWord");
552+
bind_stephen<Presentation<std::string>>(m, "StephenPresentationString");
553+
bind_stephen<InversePresentation<std::string>>(
554+
m, "StephenInversePresentationString");
553555
}
554556

555557
} // namespace libsemigroups

tests/test_stephen.py

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
def check_000(s):
4040
s.set_word([0]).run()
4141
assert s.word_graph().number_of_nodes() == 2
42-
# TODO(1): use UNDEFINED once that works
4342
assert s.word_graph() == WordGraph(2, [[1, UNDEFINED], [UNDEFINED, 1]])
4443
assert stephen.number_of_words_accepted(s) == POSITIVE_INFINITY
4544
assert list(islice(stephen.words_accepted(s), 10)) == [
@@ -323,8 +322,6 @@ def test_stephen_002():
323322
)
324323

325324

326-
# TODO(2): add a version of all test cases for std::string once this is
327-
# allowed by Stephen.
328325
@pytest.mark.quick
329326
def test_stephen_003():
330327
"""from step_hen 002"""
@@ -354,6 +351,34 @@ def test_stephen_003():
354351
assert stephen.accepts(S, to_word("bbaba"))
355352

356353

354+
@pytest.mark.quick
355+
def test_stephen_003_str():
356+
"""from step_hen 002"""
357+
ReportGuard(False)
358+
p = Presentation("ab")
359+
presentation.add_rule(p, "aaa", "a")
360+
presentation.add_rule(p, "bbb", "b")
361+
presentation.add_rule(p, "abab", "aa")
362+
363+
S = Stephen(p)
364+
S.set_word("bbab")
365+
366+
assert stephen.accepts(S, "bbaaba")
367+
assert not stephen.accepts(S, "")
368+
assert not stephen.accepts(S, "aaaaaaaaaa")
369+
assert not stephen.accepts(S, "bbb")
370+
371+
S.set_word("bba")
372+
assert stephen.accepts(S, "bbabb")
373+
assert stephen.accepts(S, "bba")
374+
assert not stephen.accepts(S, "bbb")
375+
assert not stephen.accepts(S, "a")
376+
assert not stephen.accepts(S, "ab")
377+
378+
S.set_word("bbaab")
379+
assert stephen.accepts(S, "bbaba")
380+
381+
357382
@pytest.mark.quick
358383
def test_stephen_004():
359384
"""from step_hen 003"""
@@ -454,6 +479,40 @@ def test_stephen_005():
454479
]
455480

456481

482+
@pytest.mark.quick
483+
def test_stephen_005_str():
484+
"""from step_hen 004"""
485+
ReportGuard(False)
486+
p = Presentation("abc")
487+
presentation.add_rule(p, "ab", "ba")
488+
presentation.add_rule(p, "ac", "cc")
489+
presentation.add_rule(p, "ac", "a")
490+
presentation.add_rule(p, "cc", "a")
491+
presentation.add_rule(p, "bc", "cc")
492+
presentation.add_rule(p, "bcc", "b")
493+
presentation.add_rule(p, "bc", "b")
494+
presentation.add_rule(p, "cc", "b")
495+
presentation.add_rule(p, "a", "b")
496+
497+
S = Stephen(p)
498+
S.set_word("abcc").run()
499+
assert stephen.accepts(S, "baac")
500+
assert S.word_graph().number_of_nodes() == 3
501+
assert stephen.number_of_words_accepted(S) == POSITIVE_INFINITY
502+
assert list(islice(stephen.words_accepted(S), 10)) == [
503+
"a",
504+
"b",
505+
"aa",
506+
"ab",
507+
"ac",
508+
"ba",
509+
"bb",
510+
"bc",
511+
"ca",
512+
"cb",
513+
]
514+
515+
457516
@pytest.mark.quick
458517
def test_stephen_006():
459518
"""from step_hen 005"""
@@ -1236,9 +1295,6 @@ def test_stephen_044():
12361295
assert stephen.accepts(T.set_word(ww), ww)
12371296

12381297

1239-
# TODO(2): add test_case_45 once we fix it
1240-
1241-
12421298
@pytest.mark.quick
12431299
def test_stephen_046():
12441300
"""non-inverse presentation -- operator=="""
@@ -1541,28 +1597,27 @@ def test_stephen_049():
15411597
def test_stephen_051():
15421598
"""Incomplete Munn tree products"""
15431599
ReportGuard(False)
1544-
to_word = ToWord("abcABC")
15451600

1546-
p = InversePresentation(to_word("abcABC"))
1547-
p.inverses(to_word("ABCabc"))
1601+
p = InversePresentation("abcABC")
1602+
p.inverses("ABCabc")
15481603

15491604
S = Stephen(p)
15501605
Si = Stephen(p)
15511606
T = Stephen(p)
15521607
Ti = Stephen(p)
15531608

1554-
S.set_word(to_word("aBbcaABAabCc")).run()
1555-
T.set_word(to_word("aBbcaABAabCc")).run()
1609+
S.set_word("aBbcaABAabCc").run()
1610+
T.set_word("aBbcaABAabCc").run()
15561611
S *= T
15571612
S.run()
15581613

1559-
Si.set_word(to_word("aBbcaABAabCc"))
1614+
Si.set_word("aBbcaABAabCc")
15601615
Si *= T
15611616
Si.run()
15621617
assert Si == S
15631618

1564-
Si.set_word(to_word("aBbcaABAabCc"))
1565-
Ti.set_word(to_word("aBbcaABAabCc"))
1619+
Si.set_word("aBbcaABAabCc")
1620+
Ti.set_word("aBbcaABAabCc")
15661621
Si.run()
15671622
Si *= Ti
15681623
Si.run()
@@ -1572,14 +1627,13 @@ def test_stephen_051():
15721627
@pytest.mark.quick
15731628
def test_stephen_return_policy():
15741629
ReportGuard(False)
1575-
to_word = ToWord("abcABC")
15761630

1577-
p = InversePresentation(to_word("abcABC"))
1578-
p.inverses(to_word("ABCabc"))
1631+
p = InversePresentation("abcABC")
1632+
p.inverses("ABCabc")
15791633

15801634
S = Stephen(p)
15811635

15821636
assert S.copy() is not S
15831637
assert S.init(p) is S
1584-
assert S.set_word([0, 1]) is S
1638+
assert S.set_word("ab") is S
15851639
assert S.word_graph() is S.word_graph()

0 commit comments

Comments
 (0)