Skip to content

Commit 7dcf394

Browse files
Add ToddCoxeter alphabet order example (#448)
1 parent 2d18241 commit 7dcf394

6 files changed

Lines changed: 157 additions & 0 deletions

File tree

28.4 KB
Loading

examples/alphabet-order/M12.png

20.6 KB
Loading
21.1 KB
Loading
34.9 KB
Loading
31.6 KB
Loading
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# pylint: disable=redefined-outer-name, redefined-loop-name, import-error
2+
"""In this file, we demonstrate the impact of changing the order of a ToddCoxeter alphabet"""
3+
4+
from collections.abc import Callable
5+
from datetime import timedelta
6+
from itertools import permutations
7+
from math import factorial
8+
from time import perf_counter
9+
10+
import matplotlib.pyplot as plt
11+
import numpy as np
12+
import seaborn as sns
13+
from numpy.typing import NDArray
14+
15+
from libsemigroups_pybind11 import (
16+
Presentation,
17+
ReportGuard,
18+
ToddCoxeter,
19+
congruence_kind,
20+
presentation,
21+
)
22+
from libsemigroups_pybind11.words import parse
23+
24+
25+
def generate_alphabet_order_data(
26+
p: Presentation, f: Callable[[ToddCoxeter], float], t: int | None = None, repeats: int = 5
27+
) -> tuple[NDArray, NDArray]:
28+
"""For each permutation of the alphabet of <p>, construct a ToddCoxeter. On
29+
this instance, call the function <f> both before and after running, and
30+
record the difference between these two values. If <t> is not specified, the
31+
runner will be run using `run()`. Otherwise, the runner will be run for <t>
32+
seconds.
33+
34+
Return the list of alphabets and the corresponding list of data.
35+
"""
36+
37+
alphabet = p.alphabet()
38+
n = factorial(len(alphabet))
39+
alphabets = np.empty((n,), dtype=type(alphabet))
40+
data = np.empty((n, repeats), dtype=float)
41+
42+
for i, new_alphabet in enumerate(permutations(alphabet)):
43+
if isinstance(alphabet, list):
44+
new_alphabet = list(new_alphabet)
45+
else:
46+
new_alphabet = "".join(new_alphabet)
47+
48+
alphabets[i] = new_alphabet
49+
p.alphabet(new_alphabet)
50+
51+
print(f"alphabet: {new_alphabet}")
52+
53+
for j in range(repeats):
54+
tc = ToddCoxeter(congruence_kind.twosided, p)
55+
# We record an initial value so the that the time taken can be measured,
56+
# if desired.
57+
initial = f(tc)
58+
if t is None:
59+
tc.run()
60+
else:
61+
tc.run_for(timedelta(seconds=t))
62+
63+
final = f(tc)
64+
print(f"run {j + 1}: {final - initial}")
65+
data[i, j] = final - initial
66+
67+
return alphabets, data
68+
69+
70+
ReportGuard(False)
71+
72+
#########################################################################
73+
# Mathieu Group 12
74+
#########################################################################
75+
76+
p = Presentation("abAB")
77+
p.contains_empty_word(True)
78+
presentation.add_inverse_rules(p, "ABab")
79+
presentation.add_rule(p, parse("a^2"), "")
80+
presentation.add_rule(p, parse("b^3"), "")
81+
presentation.add_rule(p, parse("(ab)^11"), "")
82+
presentation.add_rule(p, parse("(a,b)^6"), "")
83+
presentation.add_rule(p, parse("(ababaB)^6"), "")
84+
85+
alphabets, times = generate_alphabet_order_data(p, lambda tc: perf_counter())
86+
times = times.mean(axis=1)
87+
88+
# Plot the alphabet vs time
89+
ax = sns.barplot(x=alphabets, y=times)
90+
ax.set(xlabel="alphabet", ylabel="time", title="Mathieu 12")
91+
plt.show()
92+
93+
# Plot the time distribution
94+
ax = sns.displot(x=times, kde=True)
95+
ax.set(xlabel="time", title="Mathieu Group 12")
96+
plt.show()
97+
98+
#########################################################################
99+
# Mathieu Group 22
100+
#########################################################################
101+
102+
p = Presentation("abAB")
103+
p.contains_empty_word(True)
104+
presentation.add_inverse_rules(p, "ABab")
105+
presentation.add_rule(p, parse("a^2"), "")
106+
presentation.add_rule(p, parse("b^4"), "")
107+
presentation.add_rule(p, parse("(ab)^11"), "")
108+
presentation.add_rule(p, parse("(ab^2)^5"), "")
109+
presentation.add_rule(p, parse("(a,bab)^3"), "")
110+
presentation.add_rule(p, parse("(ababaB)^5"), "")
111+
112+
alphabets, times = generate_alphabet_order_data(p, lambda tc: perf_counter())
113+
times = times.mean(axis=1)
114+
115+
# Plot the time distribution
116+
ax = sns.displot(x=times, kde=True)
117+
ax.set(xlabel="time", title="Mathieu Group 22")
118+
plt.show()
119+
120+
#########################################################################
121+
# Shutov's partial transformation monoid of degree 5
122+
#########################################################################
123+
124+
p = presentation.examples.partial_transformation_monoid_Shu60(5)
125+
alphabets, times = generate_alphabet_order_data(p, lambda tc: perf_counter())
126+
times = times.mean(axis=1)
127+
128+
# Plot the time distribution
129+
ax = sns.displot(x=times, kde=True)
130+
ax.set(xlabel="time", title="Partial transformation monoid degree 5")
131+
plt.show()
132+
133+
#########################################################################
134+
# Example 6.6 in Sims
135+
#########################################################################
136+
137+
p = Presentation("abcd")
138+
presentation.add_rule(p, "aa", "a")
139+
presentation.add_rule(p, "ba", "b")
140+
presentation.add_rule(p, "ab", "b")
141+
presentation.add_rule(p, "ca", "c")
142+
presentation.add_rule(p, "ac", "c")
143+
presentation.add_rule(p, "da", "d")
144+
presentation.add_rule(p, "ad", "d")
145+
presentation.add_rule(p, "bb", "a")
146+
presentation.add_rule(p, "cd", "a")
147+
presentation.add_rule(p, "ccc", "a")
148+
presentation.add_rule(p, "bcbcbcbcbcbcbc", "a")
149+
presentation.add_rule(p, "bcbdbcbdbcbdbcbdbcbdbcbdbcbdbcbd", "a")
150+
151+
alphabets, times = generate_alphabet_order_data(p, lambda tc: perf_counter())
152+
times = times.mean(axis=1)
153+
154+
# Plot the time distribution
155+
ax = sns.displot(x=times, kde=True)
156+
ax.set(xlabel="time", title="Example 6.6 in Sims")
157+
plt.show()

0 commit comments

Comments
 (0)