From 5b2d0fb0eda6f2a946337f29d4e3180e035c663b Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Fri, 29 May 2026 15:15:57 +0100 Subject: [PATCH 1/3] presentation: properly init InversePresentation from Presentation Previously we forgot to pass the Presentation to init_cxx_obj resulting in the object not being properly initialised. --- src/libsemigroups_pybind11/presentation/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libsemigroups_pybind11/presentation/__init__.py b/src/libsemigroups_pybind11/presentation/__init__.py index 6b8dc872..5ba42461 100644 --- a/src/libsemigroups_pybind11/presentation/__init__.py +++ b/src/libsemigroups_pybind11/presentation/__init__.py @@ -220,9 +220,7 @@ def __init__(self: _Self, *args, **kwargs) -> None: assert isinstance(args[0], Presentation) self.py_template_params = args[0].py_template_params - self.init_cxx_obj() - self.alphabet(args[0].alphabet()) - self.rules = args[0].rules + self.init_cxx_obj(args[0]) _copy_cxx_mem_fns(_InversePresentationWord, InversePresentation) From 3570b48cd7386d3f24f0e066630ec343b16c1fbb Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Fri, 29 May 2026 15:17:08 +0100 Subject: [PATCH 2/3] stephen: fix for upstream changes --- src/stephen.cpp | 24 ++++++++++++++++-------- tests/test_stephen.py | 8 ++++---- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/stephen.cpp b/src/stephen.cpp index 9691f99c..02f2cb9c 100644 --- a/src/stephen.cpp +++ b/src/stephen.cpp @@ -379,10 +379,14 @@ it labels a path in :any:`Stephen.word_graph` with source ``0``. this function may never terminate. )pbdoc"); - m.def("stephen_left_factors", - &stephen::left_factors, - py::arg("s"), - R"pbdoc( + m.def( + "stephen_left_factors", + [](Stephen_& s) { + auto range = stephen::left_factors(s); + return py::make_iterator(rx::begin(range), rx::end(range)); + }, + py::arg("s"), + R"pbdoc( :sig=(s: Stephen) -> Paths: :only-document-once: Returns a :any:`Paths` object containing all the words (in short-lex order) @@ -504,10 +508,14 @@ equivalent to :math:`u` in the semigroup defined by this function may never terminate. )pbdoc"); - m.def("stephen_words_accepted", - &stephen::words_accepted, - py::arg("s"), - R"pbdoc( + m.def( + "stephen_words_accepted", + [](Stephen_& s) { + auto range = stephen::words_accepted(s); + return py::make_iterator(rx::begin(range), rx::end(range)); + }, + py::arg("s"), + R"pbdoc( :sig=(s: Stephen) -> Paths: :only-document-once: diff --git a/tests/test_stephen.py b/tests/test_stephen.py index f9be2e32..1e4b7fe6 100644 --- a/tests/test_stephen.py +++ b/tests/test_stephen.py @@ -89,7 +89,7 @@ def verify_c4_normal_form(p, word, nf): assert sorted(list(stephen.words_accepted(S)), key=lexicographic_compare_key_func)[0] == nf assert all(stephen.accepts(S, w) for w in stephen.words_accepted(S)) - assert stephen.number_of_words_accepted(S) == len(stephen.words_accepted(S)) + assert stephen.number_of_words_accepted(S) == sum(1 for _ in stephen.words_accepted(S)) def verify_c4_equal_to(p, word1, word2): @@ -521,7 +521,7 @@ def test_stephen_008(): ] == to_word("dfabcdf") assert all(stephen.accepts(S, w) for w in stephen.words_accepted(S)) - assert stephen.number_of_words_accepted(S) == len(stephen.words_accepted(S)) + assert stephen.number_of_words_accepted(S) == sum(1 for _ in stephen.words_accepted(S)) S.set_word(to_word("abcdfceg")).run() assert stephen.number_of_words_accepted(S) == 16 @@ -572,7 +572,7 @@ def test_Stephen_009(): S.set_word(to_word("acba")).run() - assert list(stephen.words_accepted(S)) == [to_word("aabc"), to_word("acba")] + assert list(stephen.words_accepted(S)) == [to_word("acba"), to_word("aabc")] verify_c4_normal_form(p, to_word("acba"), to_word("aabc")) @@ -1434,7 +1434,7 @@ def test_stephen_045(): T.set_word(T.word() * 2) T.run() assert S == T - assert stephen.words_accepted(S).get() == [0, 2, 0, 2] + assert next(stephen.words_accepted(S)) == [0, 2, 0, 2] assert stephen.number_of_left_factors(S) == POSITIVE_INFINITY S.set_word(to_word("aBbcaABAabCc")) T.set_word(to_word("CcBAabaACBbA")) From d02f94322a2f44238b6b9985626bb9ae5345018a Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Fri, 29 May 2026 15:37:53 +0100 Subject: [PATCH 3/3] stephen: add support for Presentation[str] --- docs/pictures/to-table.svg | 2072 ++++++++++++------------- src/libsemigroups_pybind11/stephen.py | 8 +- src/stephen.cpp | 12 +- tests/test_stephen.py | 138 +- 4 files changed, 1133 insertions(+), 1097 deletions(-) diff --git a/docs/pictures/to-table.svg b/docs/pictures/to-table.svg index 332e7fbe..120bdfbe 100644 --- a/docs/pictures/to-table.svg +++ b/docs/pictures/to-table.svg @@ -4,7 +4,7 @@ height="231.103pt" viewBox="0 0 420.566 231.103" version="1.1" - id="svg2168" + id="svg726" sodipodi:docname="to-table.pdf" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" @@ -12,408 +12,408 @@ xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + id="defs106"> + id="g65"> + id="path1" /> + id="path2" /> + id="path3" /> + id="path4" /> + id="path5" /> + id="path6" /> + id="path7" /> + id="path8" /> + id="path9" /> + id="path10" /> + id="path11" /> + id="path12" /> + id="path13" /> + id="path14" /> + id="path15" /> + id="path16" /> + id="path17" /> + id="path18" /> + id="path19" /> + id="path20" /> + id="path21" /> + id="path22" /> + id="path23" /> + id="path24" /> + id="path25" /> + id="path26" /> + id="path27" /> + id="path28" /> + id="path29" /> + id="path30" /> + id="path31" /> + id="path32" /> + id="path33" /> + id="path34" /> + id="path35" /> + id="path36" /> + id="path37" /> + id="path38" /> + id="path39" /> + id="path40" /> + id="path41" /> + id="path42" /> + id="path43" /> + id="path44" /> + id="path45" /> + id="path46" /> + id="path47" /> + id="path48" /> + id="path49" /> + id="path50" /> + id="path51" /> + id="path52" /> + id="path53" /> + id="path54" /> + id="path55" /> + id="path56" /> + id="path57" /> + id="path58" /> + id="path59" /> + id="path60" /> + id="path61" /> + id="path62" /> + id="path63" /> + id="path64" /> + id="path65" /> + id="path66" /> + id="path67" /> + id="path68" /> + id="path69" /> + id="path70" /> + id="path71" /> + id="path72" /> + id="path73" /> + id="path74" /> + id="path75" /> + id="path76" /> + id="path77" /> + id="path78" /> + id="path79" /> + id="path80" /> + id="path81" /> + id="path82" /> + id="path83" /> + id="path84" /> + id="path85" /> + id="path86" /> + id="path87" /> + id="path88" /> + id="path89" /> + id="path90" /> + id="path91" /> + id="path92" /> + id="path93" /> + id="path94" /> + id="path95" /> + id="path96" /> + id="path97" /> + id="path98" /> + id="path99" /> + id="path100" /> + id="path101" /> + id="path102" /> + id="path103" /> + id="path104" /> + id="path105" /> + id="path106" /> + id="path107" /> + id="g116"> + id="use107" /> + id="use108" /> + id="use109" /> + id="use110" /> + id="use111" /> + id="use112" /> + id="use113" /> + id="use114" /> + id="use115" /> + id="use116" /> + id="path116" /> + id="g127"> + id="use117" /> + id="use118" /> + id="use119" /> + id="use120" /> + id="use121" /> + id="use122" /> + id="use123" /> + id="use124" /> + id="use125" /> + id="use126" /> + id="use127" /> + id="path127" /> + id="g146"> + id="use128" /> + id="use129" /> + id="use130" /> + id="use131" /> + id="use132" /> + id="use133" /> + id="use134" /> + id="use135" /> + id="use136" /> + id="use137" /> + id="use138" /> + id="use139" /> + id="use140" /> + id="use141" /> + id="use142" /> + id="use143" /> + id="use144" /> + id="use145" /> + id="use146" /> + id="path146" /> + id="g154"> + id="use147" /> + id="use148" /> + id="use149" /> + id="use150" /> + id="use151" /> + id="use152" /> + id="use153" /> + id="use154" /> + id="path154" /> + id="g165"> + id="use155" /> + id="use156" /> + id="use157" /> + id="use158" /> + id="use159" /> + id="use160" /> + id="use161" /> + id="use162" /> + id="use163" /> + id="use164" /> + id="use165" /> + id="path165" /> + id="g174"> + id="use166" /> + id="use167" /> + id="use168" /> + id="use169" /> + id="use170" /> + id="use171" /> + id="use172" /> + id="use173" /> + id="use174" /> + id="path174" /> + id="g186"> + id="use175" /> + id="use176" /> + id="use177" /> + id="use178" /> + id="use179" /> + id="use180" /> + id="use181" /> + id="use182" /> + id="use183" /> + id="use184" /> + id="use185" /> + id="use186" /> + id="path186" /> + id="g198"> + id="use187" /> + id="use188" /> + id="use189" /> + id="use190" /> + id="use191" /> + id="use192" /> + id="use193" /> + id="use194" /> + id="use195" /> + id="use196" /> + id="use197" /> + id="use198" /> + id="path198" /> + id="g205"> + id="use199" /> + id="use200" /> + id="use201" /> + id="use202" /> + id="use203" /> + id="use204" /> + id="use205" /> + id="path205" /> + id="g216"> + id="use206" /> + id="use207" /> + id="use208" /> + id="use209" /> + id="use210" /> + id="use211" /> + id="use212" /> + id="use213" /> + id="use214" /> + id="use215" /> + id="use216" /> + id="path216" /> + id="g225"> + id="use217" /> + id="use218" /> + id="use219" /> + id="use220" /> + id="use221" /> + id="use222" /> + id="use223" /> + id="use224" /> + id="use225" /> + id="g226"> + id="path225" /> + id="g234"> + id="use226" /> + id="use227" /> + id="use228" /> + id="use229" /> + id="use230" /> + id="use231" /> + id="use232" /> + id="use233" /> + id="use234" /> + id="g251"> + id="use235" /> + id="use236" /> + id="use237" /> + id="use238" /> + id="use239" /> + id="use240" /> + id="use241" /> + id="use242" /> + id="use243" /> + id="use244" /> + id="use245" /> + id="use246" /> + id="use247" /> + id="use248" /> + id="use249" /> + id="use250" /> + id="use251" /> + id="path251" /> + id="path252" /> + id="g252"> + id="use252" /> + id="path253" /> + id="path254" /> + id="g254"> + id="use254" /> + id="path255" /> + id="path256" /> + id="g256"> + id="use256" /> + id="path257" /> + id="path258" /> + id="g258"> + id="use258" /> + id="path259" /> + id="path260" /> + id="g260"> + id="use260" /> + id="path261" /> + id="path262" /> + id="g262"> + id="use262" /> + id="path263" /> + id="path264" /> + id="g264"> + id="use264" /> + id="path265" /> + id="path266" /> + id="g266"> + id="use266" /> + id="path267" /> + id="path268" /> + id="g268"> + id="use268" /> + id="path269" /> + id="path270" /> + id="g270"> + id="use270" /> + id="path271" /> + id="g272"> + id="path272" /> + id="g273"> + id="use272" /> + id="g274"> + id="path273" /> + id="g282"> + id="use274" /> + id="use275" /> + id="use276" /> + id="use277" /> + id="use278" /> + id="use279" /> + id="use280" /> + id="use281" /> + id="use282" /> + id="g300"> + id="use283" /> + id="use284" /> + id="use285" /> + id="use286" /> + id="use287" /> + id="use288" /> + id="use289" /> + id="use290" /> + id="use291" /> + id="use292" /> + id="use293" /> + id="use294" /> + id="use295" /> + id="use296" /> + id="use297" /> + id="use298" /> + id="use299" /> + id="use300" /> + id="path300" /> + id="path301" /> + id="g301"> + id="use301" /> + id="path302" /> + id="path303" /> + id="g303"> + id="use303" /> + id="path304" /> + id="path305" /> + id="g305"> + id="use305" /> + id="path306" /> + id="path307" /> + id="g307"> + id="use307" /> + id="path308" /> + id="path309" /> + id="g309"> + id="use309" /> + id="path310" /> + id="path311" /> + id="g311"> + id="use311" /> + id="path312" /> + id="path313" /> + id="g313"> + id="use313" /> + id="path314" /> + id="path315" /> + id="g315"> + id="use315" /> + id="path316" /> + id="path317" /> + id="g317"> + id="use317" /> + id="path318" /> + id="path319" /> + id="g319"> + id="use319" /> + id="path320" /> + id="g321"> + id="path321" /> + id="g322"> + id="use321" /> + id="g323"> + id="path322" /> + id="g331"> + id="use323" /> + id="use324" /> + id="use325" /> + id="use326" /> + id="use327" /> + id="use328" /> + id="use329" /> + id="use330" /> + id="use331" /> + id="g357"> + id="use332" /> + id="use333" /> + id="use334" /> + id="use335" /> + id="use336" /> + id="use337" /> + id="use338" /> + id="use339" /> + id="use340" /> + id="use341" /> + id="use342" /> + id="use343" /> + id="use344" /> + id="use345" /> + id="use346" /> + id="use347" /> + id="use348" /> + id="use349" /> + id="use350" /> + id="use351" /> + id="use352" /> + id="use353" /> + id="use354" /> + id="use355" /> + id="use356" /> + id="use357" /> + id="path357" /> + id="path358" /> + id="g358"> + id="use358" /> + id="path359" /> + id="path360" /> + id="g360"> + id="use360" /> + id="path361" /> + id="path362" /> + id="g362"> + id="use362" /> + id="path363" /> + id="path364" /> + id="g364"> + id="use364" /> + id="path365" /> + id="path366" /> + id="g366"> + id="use366" /> + id="path367" /> + id="path368" /> + id="g368"> + id="use368" /> + id="path369" /> + id="path370" /> + id="g370"> + id="use370" /> + id="path371" /> + id="path372" /> + id="g372"> + id="use372" /> + id="path373" /> + id="path374" /> + id="g374"> + id="use374" /> + id="path375" /> + id="path376" /> + id="g376"> + id="use376" /> + id="path377" /> + id="g378"> + id="path378" /> + id="g379"> + id="use378" /> + id="g380"> + id="path379" /> + id="g388"> + id="use380" /> + id="use381" /> + id="use382" /> + id="use383" /> + id="use384" /> + id="use385" /> + id="use386" /> + id="use387" /> + id="use388" /> + id="g403"> + id="use389" /> + id="use390" /> + id="use391" /> + id="use392" /> + id="use393" /> + id="use394" /> + id="use395" /> + id="use396" /> + id="use397" /> + id="use398" /> + id="use399" /> + id="use400" /> + id="use401" /> + id="use402" /> + id="use403" /> + id="path403" /> + id="path404" /> + id="g404"> + id="use404" /> + id="path405" /> + id="path406" /> + id="g406"> + id="use406" /> + id="path407" /> + id="path408" /> + id="g408"> + id="use408" /> + id="path409" /> + id="path410" /> + id="g410"> + id="use410" /> + id="path411" /> + id="path412" /> + id="g412"> + id="use412" /> + id="path413" /> + id="path414" /> + id="g414"> + id="use414" /> + id="path415" /> + id="path416" /> + id="g416"> + id="use416" /> + id="path417" /> + id="path418" /> + id="g418"> + id="use418" /> + id="path419" /> + id="path420" /> + id="g420"> + id="use420" /> + id="path421" /> + id="path422" /> + id="g422"> + id="use422" /> + id="path423" /> + id="g424"> + id="path424" /> + id="g425"> + id="use424" /> + id="g426"> + id="path425" /> + id="g434"> + id="use426" /> + id="use427" /> + id="use428" /> + id="use429" /> + id="use430" /> + id="use431" /> + id="use432" /> + id="use433" /> + id="use434" /> + id="g452"> + id="use435" /> + id="use436" /> + id="use437" /> + id="use438" /> + id="use439" /> + id="use440" /> + id="use441" /> + id="use442" /> + id="use443" /> + id="use444" /> + id="use445" /> + id="use446" /> + id="use447" /> + id="use448" /> + id="use449" /> + id="use450" /> + id="use451" /> + id="use452" /> + id="path452" /> + id="path453" /> + id="g453"> + id="use453" /> + id="path454" /> + id="path455" /> + id="g455"> + id="use455" /> + id="path456" /> + id="path457" /> + id="g457"> + id="use457" /> + id="path458" /> + id="path459" /> + id="g459"> + id="use459" /> + id="path460" /> + id="path461" /> + id="g461"> + id="use461" /> + id="path462" /> + id="path463" /> + id="g463"> + id="use463" /> + id="path464" /> + id="path465" /> + id="g465"> + id="use465" /> + id="path466" /> + id="path467" /> + id="g467"> + id="use467" /> + id="path468" /> + id="path469" /> + id="g469"> + id="use469" /> + id="path470" /> + id="path471" /> + id="g471"> + id="use471" /> + id="path472" /> + id="g473"> + id="path473" /> + id="g474"> + id="use473" /> + id="g475"> + id="path474" /> + id="g483"> + id="use475" /> + id="use476" /> + id="use477" /> + id="use478" /> + id="use479" /> + id="use480" /> + id="use481" /> + id="use482" /> + id="use483" /> + id="g499"> + id="use484" /> + id="use485" /> + id="use486" /> + id="use487" /> + id="use488" /> + id="use489" /> + id="use490" /> + id="use491" /> + id="use492" /> + id="use493" /> + id="use494" /> + id="use495" /> + id="use496" /> + id="use497" /> + id="use498" /> + id="use499" /> + id="path499" /> + id="path500" /> + id="g500"> + id="use500" /> + id="path501" /> + id="path502" /> + id="g502"> + id="use502" /> + id="path503" /> + id="path504" /> + id="g504"> + id="use504" /> + id="path505" /> + id="path506" /> + id="g506"> + id="use506" /> + id="path507" /> + id="path508" /> + id="g508"> + id="use508" /> + id="path509" /> + id="path510" /> + id="g510"> + id="use510" /> + id="path511" /> + id="path512" /> + id="g512"> + id="use512" /> + id="path513" /> + id="path514" /> + id="g514"> + id="use514" /> + id="path515" /> + id="path516" /> + id="g516"> + id="use516" /> + id="path517" /> + id="path518" /> + id="g518"> + id="use518" /> + id="path519" /> + id="g520"> + id="path520" /> + id="g521"> + id="use520" /> + id="g522"> + id="path521" /> + id="g530"> + id="use522" /> + id="use523" /> + id="use524" /> + id="use525" /> + id="use526" /> + id="use527" /> + id="use528" /> + id="use529" /> + id="use530" /> + id="g549"> + id="use531" /> + id="use532" /> + id="use533" /> + id="use534" /> + id="use535" /> + id="use536" /> + id="use537" /> + id="use538" /> + id="use539" /> + id="use540" /> + id="use541" /> + id="use542" /> + id="use543" /> + id="use544" /> + id="use545" /> + id="use546" /> + id="use547" /> + id="use548" /> + id="use549" /> + id="path549" /> + id="path550" /> + id="g550"> + id="use550" /> + id="path551" /> + id="path552" /> + id="g552"> + id="use552" /> + id="path553" /> + id="path554" /> + id="g554"> + id="use554" /> + id="path555" /> + id="path556" /> + id="g556"> + id="use556" /> + id="path557" /> + id="path558" /> + id="g558"> + id="use558" /> + id="path559" /> + id="path560" /> + id="g560"> + id="use560" /> + id="path561" /> + id="path562" /> + id="g562"> + id="use562" /> + id="path563" /> + id="path564" /> + id="g564"> + id="use564" /> + id="path565" /> + id="path566" /> + id="g566"> + id="use566" /> + id="path567" /> + id="path568" /> + id="g568"> + id="use568" /> + id="path569" /> + id="g570"> + id="path570" /> + id="g571"> + id="use570" /> + id="g572"> + id="path571" /> + id="g580"> + id="use572" /> + id="use573" /> + id="use574" /> + id="use575" /> + id="use576" /> + id="use577" /> + id="use578" /> + id="use579" /> + id="use580" /> + id="g599"> + id="use581" /> + id="use582" /> + id="use583" /> + id="use584" /> + id="use585" /> + id="use586" /> + id="use587" /> + id="use588" /> + id="use589" /> + id="use590" /> + id="use591" /> + id="use592" /> + id="use593" /> + id="use594" /> + id="use595" /> + id="use596" /> + id="use597" /> + id="use598" /> + id="use599" /> + id="path599" /> + id="path600" /> + id="g600"> + id="use600" /> + id="path601" /> + id="path602" /> + id="g602"> + id="use602" /> + id="path603" /> + id="path604" /> + id="g604"> + id="use604" /> + id="path605" /> + id="path606" /> + id="g606"> + id="use606" /> + id="path607" /> + id="path608" /> + id="g608"> + id="use608" /> + id="path609" /> + id="path610" /> + id="g610"> + id="use610" /> + id="path611" /> + id="path612" /> + id="g612"> + id="use612" /> + id="path613" /> + id="path614" /> + id="g614"> + id="use614" /> + id="path615" /> + id="path616" /> + id="g616"> + id="use616" /> + id="path617" /> + id="path618" /> + id="g618"> + id="use618" /> + id="path619" /> + id="g620"> + id="path620" /> + id="g621"> + id="use620" /> + id="g622"> + id="path621" /> + id="g630"> + id="use622" /> + id="use623" /> + id="use624" /> + id="use625" /> + id="use626" /> + id="use627" /> + id="use628" /> + id="use629" /> + id="use630" /> + id="g644"> + id="use631" /> + id="use632" /> + id="use633" /> + id="use634" /> + id="use635" /> + id="use636" /> + id="use637" /> + id="use638" /> + id="use639" /> + id="use640" /> + id="use641" /> + id="use642" /> + id="use643" /> + id="use644" /> + id="path644" /> + id="path645" /> + id="g645"> + id="use645" /> + id="path646" /> + id="path647" /> + id="g647"> + id="use647" /> + id="path648" /> + id="path649" /> + id="g649"> + id="use649" /> + id="path650" /> + id="path651" /> + id="g651"> + id="use651" /> + id="path652" /> + id="path653" /> + id="g653"> + id="use653" /> + id="path654" /> + id="path655" /> + id="g655"> + id="use655" /> + id="path656" /> + id="path657" /> + id="g657"> + id="use657" /> + id="path658" /> + id="path659" /> + id="g659"> + id="use659" /> + id="path660" /> + id="path661" /> + id="g661"> + id="use661" /> + id="path662" /> + id="path663" /> + id="g663"> + id="use663" /> + id="path664" /> + id="g665"> + id="path665" /> + id="g666"> + id="use665" /> + id="g667"> + id="path666" /> + id="g675"> + id="use667" /> + id="use668" /> + id="use669" /> + id="use670" /> + id="use671" /> + id="use672" /> + id="use673" /> + id="use674" /> + id="use675" /> + id="g693"> + id="use676" /> + id="use677" /> + id="use678" /> + id="use679" /> + id="use680" /> + id="use681" /> + id="use682" /> + id="use683" /> + id="use684" /> + id="use685" /> + id="use686" /> + id="use687" /> + id="use688" /> + id="use689" /> + id="use690" /> + id="use691" /> + id="use692" /> + id="use693" /> + id="g694"> + id="path693" /> + id="g695"> + id="path694" /> + id="g696"> + id="use695" /> + id="g697"> + id="path696" /> + id="g698"> + id="path697" /> + id="g699"> + id="use698" /> + id="g700"> + id="path699" /> + id="g701"> + id="path700" /> + id="g702"> + id="use701" /> + id="g703"> + id="path702" /> + id="g704"> + id="path703" /> + id="g705"> + id="use704" /> + id="g706"> + id="path705" /> + id="g707"> + id="path706" /> + id="g708"> + id="use707" /> + id="g709"> + id="path708" /> + id="g710"> + id="path709" /> + id="g711"> + id="use710" /> + id="g712"> + id="path711" /> + id="g713"> + id="path712" /> + id="g714"> + id="use713" /> + id="g715"> + id="path714" /> + id="g716"> + id="path715" /> + id="g717"> + id="use716" /> + id="g718"> + id="path717" /> + id="g719"> + id="path718" /> + id="g720"> + id="use719" /> + id="g721"> + id="path720" /> + id="g722"> + id="path721" /> + id="g723"> + id="use722" /> + id="g724"> + id="path723" /> + id="g725"> + id="path724" /> + id="g726"> + id="use725" /> diff --git a/src/libsemigroups_pybind11/stephen.py b/src/libsemigroups_pybind11/stephen.py index 5598cce4..c5f60f83 100644 --- a/src/libsemigroups_pybind11/stephen.py +++ b/src/libsemigroups_pybind11/stephen.py @@ -13,9 +13,13 @@ from typing_extensions import Self as _Self from _libsemigroups_pybind11 import ( + InversePresentationString as _InversePresentationString, InversePresentationWord as _InversePresentationWord, + PresentationString as _PresentationString, PresentationWord as _PresentationWord, + StephenInversePresentationString as _StephenInversePresentationString, StephenInversePresentationWord as _StephenInversePresentationWord, + StephenPresentationString as _StephenPresentationString, StephenPresentationWord as _StephenPresentationWord, stephen_accepts as _stephen_accepts, stephen_dot as _stephen_dot, @@ -46,8 +50,10 @@ class Stephen(_CxxWrapper): __doc__ = _StephenPresentationWord.__doc__ _py_template_params_to_cxx_type = { - (_PresentationWord,): _StephenPresentationWord, + (_InversePresentationString,): _StephenInversePresentationString, (_InversePresentationWord,): _StephenInversePresentationWord, + (_PresentationString,): _StephenPresentationString, + (_PresentationWord,): _StephenPresentationWord, } _cxx_type_to_py_template_params = dict( diff --git a/src/stephen.cpp b/src/stephen.cpp index 02f2cb9c..09d741c0 100644 --- a/src/stephen.cpp +++ b/src/stephen.cpp @@ -34,7 +34,8 @@ namespace libsemigroups { namespace { template void bind_stephen(py::module& m, std::string const& name) { - using Stephen_ = Stephen; + using Stephen_ = Stephen; + using native_word_type = typename Stephen_::native_word_type; py::class_ thing(m, name.c_str(), @@ -213,11 +214,9 @@ Get the input presentation. :returns: A presentation. :rtype: Presentation | InversePresentation )pbdoc"); - // TODO(2): Change to support std::string once we have that implemented - // in libsemigroups itself thing.def( "set_word", - [](Stephen_& self, word_type const& word) -> Stephen_& { + [](Stephen_& self, native_word_type const& word) -> Stephen_& { return stephen::set_word(self, word); }, py::arg("word"), @@ -545,11 +544,12 @@ been triggered already). } // namespace void init_stephen(py::module& m) { - // TODO(2): figure out how to handle std::string Stephens once that's - // supported bind_stephen>(m, "StephenPresentationWord"); bind_stephen>( m, "StephenInversePresentationWord"); + bind_stephen>(m, "StephenPresentationString"); + bind_stephen>( + m, "StephenInversePresentationString"); } } // namespace libsemigroups diff --git a/tests/test_stephen.py b/tests/test_stephen.py index 1e4b7fe6..5a76dd45 100644 --- a/tests/test_stephen.py +++ b/tests/test_stephen.py @@ -39,7 +39,6 @@ def check_000(s): s.set_word([0]).run() assert s.word_graph().number_of_nodes() == 2 - # TODO(1): use UNDEFINED once that works assert s.word_graph() == WordGraph(2, [[1, UNDEFINED], [UNDEFINED, 1]]) assert stephen.number_of_words_accepted(s) == POSITIVE_INFINITY assert list(islice(stephen.words_accepted(s), 10)) == [ @@ -323,8 +322,6 @@ def test_stephen_002(): ) -# TODO(2): add a version of all test cases for std::string once this is -# allowed by Stephen. @pytest.mark.quick def test_stephen_003(): """from step_hen 002""" @@ -354,6 +351,34 @@ def test_stephen_003(): assert stephen.accepts(S, to_word("bbaba")) +@pytest.mark.quick +def test_stephen_003_str(): + """from step_hen 002""" + ReportGuard(False) + p = Presentation("ab") + presentation.add_rule(p, "aaa", "a") + presentation.add_rule(p, "bbb", "b") + presentation.add_rule(p, "abab", "aa") + + S = Stephen(p) + S.set_word("bbab") + + assert stephen.accepts(S, "bbaaba") + assert not stephen.accepts(S, "") + assert not stephen.accepts(S, "aaaaaaaaaa") + assert not stephen.accepts(S, "bbb") + + S.set_word("bba") + assert stephen.accepts(S, "bbabb") + assert stephen.accepts(S, "bba") + assert not stephen.accepts(S, "bbb") + assert not stephen.accepts(S, "a") + assert not stephen.accepts(S, "ab") + + S.set_word("bbaab") + assert stephen.accepts(S, "bbaba") + + @pytest.mark.quick def test_stephen_004(): """from step_hen 003""" @@ -454,6 +479,40 @@ def test_stephen_005(): ] +@pytest.mark.quick +def test_stephen_005_str(): + """from step_hen 004""" + ReportGuard(False) + p = Presentation("abc") + presentation.add_rule(p, "ab", "ba") + presentation.add_rule(p, "ac", "cc") + presentation.add_rule(p, "ac", "a") + presentation.add_rule(p, "cc", "a") + presentation.add_rule(p, "bc", "cc") + presentation.add_rule(p, "bcc", "b") + presentation.add_rule(p, "bc", "b") + presentation.add_rule(p, "cc", "b") + presentation.add_rule(p, "a", "b") + + S = Stephen(p) + S.set_word("abcc").run() + assert stephen.accepts(S, "baac") + assert S.word_graph().number_of_nodes() == 3 + assert stephen.number_of_words_accepted(S) == POSITIVE_INFINITY + assert list(islice(stephen.words_accepted(S), 10)) == [ + "a", + "b", + "aa", + "ab", + "ac", + "ba", + "bb", + "bc", + "ca", + "cb", + ] + + @pytest.mark.quick def test_stephen_006(): """from step_hen 005""" @@ -918,34 +977,13 @@ def test_stephen_031(): """Test behaviour when uninitialised""" ReportGuard(False) p = Presentation([]) - S = Stephen(p) with pytest.raises(LibsemigroupsError): - S.accept_state() - with pytest.raises(LibsemigroupsError): - S.word() - with pytest.raises(LibsemigroupsError): - S.word_graph() - - with pytest.raises(LibsemigroupsError): - stephen.is_left_factor(S, [0, 0, 0]) - with pytest.raises(LibsemigroupsError): - stephen.accepts(S, [0, 0, 0]) - with pytest.raises(LibsemigroupsError): - stephen.number_of_left_factors(S) - with pytest.raises(LibsemigroupsError): - stephen.number_of_words_accepted(S) - with pytest.raises(LibsemigroupsError): - S.run() - - with pytest.raises(LibsemigroupsError): - stephen.words_accepted(S) - with pytest.raises(LibsemigroupsError): - stephen.left_factors(S) + S = Stephen(p) p = Presentation([0, 1]) presentation.add_rule(p, [0, 1], [1, 0]) - S.init(p) + S = Stephen(p) with pytest.raises(LibsemigroupsError): S.accept_state() @@ -1236,9 +1274,6 @@ def test_stephen_044(): assert stephen.accepts(T.set_word(ww), ww) -# TODO(2): add test_case_45 once we fix it - - @pytest.mark.quick def test_stephen_046(): """non-inverse presentation -- operator==""" @@ -1471,7 +1506,7 @@ def test_stephen_049(): presentation.add_rule(p, [0, 0, 0], [1, 1]) presentation.add_rule(p, [0, 0, 1], [1, 0]) - S = Stephen(Presentation([])) + S = Stephen(p) assert repr(S) == f"" S.init(p) assert repr(S) == f"" @@ -1512,27 +1547,24 @@ def test_stephen_049(): S.init(p) assert repr(S) == f"" - to_word = ToWord("abcABC") - pi = InversePresentation(to_word("abcABC")) - pi.inverses(to_word("ABCabc")) - presentation.add_rule(pi, to_word("ac"), to_word("ca")) - presentation.add_rule(pi, to_word("ab"), to_word("ba")) - presentation.add_rule(pi, to_word("bc"), to_word("cb")) + pi = InversePresentation("abcABC") + pi.inverses("ABCabc") + presentation.add_rule(pi, "ac", "ca") + presentation.add_rule(pi, "ab", "ba") + presentation.add_rule(pi, "bc", "cb") - IS = Stephen(InversePresentation([])) + IS = Stephen(pi) assert repr(IS) == f"" IS.init(pi) assert repr(IS) == f"" - IS.set_word(to_word("BaAbaBcAb")) + IS.set_word("BaAbaBcAb") assert ( - repr(IS) - == f"" ) IS.run() assert ( - repr(IS) - == f"" ) @@ -1541,28 +1573,27 @@ def test_stephen_049(): def test_stephen_051(): """Incomplete Munn tree products""" ReportGuard(False) - to_word = ToWord("abcABC") - p = InversePresentation(to_word("abcABC")) - p.inverses(to_word("ABCabc")) + p = InversePresentation("abcABC") + p.inverses("ABCabc") S = Stephen(p) Si = Stephen(p) T = Stephen(p) Ti = Stephen(p) - S.set_word(to_word("aBbcaABAabCc")).run() - T.set_word(to_word("aBbcaABAabCc")).run() + S.set_word("aBbcaABAabCc").run() + T.set_word("aBbcaABAabCc").run() S *= T S.run() - Si.set_word(to_word("aBbcaABAabCc")) + Si.set_word("aBbcaABAabCc") Si *= T Si.run() assert Si == S - Si.set_word(to_word("aBbcaABAabCc")) - Ti.set_word(to_word("aBbcaABAabCc")) + Si.set_word("aBbcaABAabCc") + Ti.set_word("aBbcaABAabCc") Si.run() Si *= Ti Si.run() @@ -1572,14 +1603,13 @@ def test_stephen_051(): @pytest.mark.quick def test_stephen_return_policy(): ReportGuard(False) - to_word = ToWord("abcABC") - p = InversePresentation(to_word("abcABC")) - p.inverses(to_word("ABCabc")) + p = InversePresentation("abcABC") + p.inverses("ABCabc") S = Stephen(p) assert S.copy() is not S assert S.init(p) is S - assert S.set_word([0, 1]) is S + assert S.set_word("ab") is S assert S.word_graph() is S.word_graph()