add documentation
This commit is contained in:
parent
fea1b1eb2e
commit
5a1b2883d7
39
README.md
Normal file
39
README.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# coxeter_automaton.py - Find geodesic automata for Coxeter groups #
|
||||||
|
|
||||||
|
This Python code computes two kinds of finite automata for any [Coxeter group]: one which consumes every reduced word, and one which consumes only the lexicographically minimal reduced word for each group element. These automata are then used to enumerate all group elements up to a given word length.
|
||||||
|
|
||||||
|
The construction of the first automaton is explained in detail in the book by [Björner-Brenti]. The key results leading to the second automaton are from [Brink-Howlett].
|
||||||
|
|
||||||
|
## Simple example ##
|
||||||
|
|
||||||
|
To explain what these automata are about, let's have a look at the tiling of the Euclidean plane by equilateral triangles, as drawn below.
|
||||||
|
|
||||||
|
![Euclidean tiling](https://florianstecker.net/git_files/coxeter_automaton/tiling.png)
|
||||||
|
|
||||||
|
Any triangle in the tiling can be obtained from the gray one by successively reflecting it along some of its sides. For example, to get to the orange triangle we could use the sequences of reflections
|
||||||
|
|
||||||
|
red-blue-red-green-red
|
||||||
|
blue-red-blue-green-red
|
||||||
|
blue-red-green-blue-green-blue-red
|
||||||
|
|
||||||
|
The first two sequences are _reduced_, which means they have the minimal number of reflections (5) necessary to reach their endpoint, the orange triangle. In other words, in a reduced sequence every step gets us further away from the starting triangle. The set of all reduced sequences is described by the following automaton. Every path starting from the gray vertex corresponds to a reduced sequence, and vice-versa.
|
||||||
|
|
||||||
|
![Automaton generating all reduced words](https://florianstecker.net/git_files/coxeter_automaton/geodesic_automaton.png)
|
||||||
|
|
||||||
|
In the above, multiple sequences might lead to the same triangle. To get unique labels, we can instead restrict ourselves to only the lexicographically minimal sequence for every triangle. For the orange triangle above, and with the order `red < green < blue`, that would be the sequence `red-blue-red-green-red`. The following automaton yields all lexicographically minimal reduced words.
|
||||||
|
|
||||||
|
![Automaton generating all lex reduced words](https://florianstecker.net/git_files/coxeter_automaton/lex_automaton.png)
|
||||||
|
|
||||||
|
What this program can do is produce these two automata, not only for the equilateral triangle tiling, but for any [Coxeter group]. Essentially, Coxeter groups correspond to all tilings generated by reflections along the sides of a convex polyhedron in projective space, in arbitrary dimensions. This includes regular triangulations of Euclidean and hyperbolic space.
|
||||||
|
|
||||||
|
## Usage ##
|
||||||
|
|
||||||
|
See `example.py`. The function `generate_automaton_coxeter_matrix` takes as argument the [Coxeter matrix] of the desired group and a boolean determining which of the two automata is generated. It returns the automaton as an adjacency list. In addition, the function `enumerate_group` can compute all group elements up to a given word length, including the edges of the Cayley graph. To do this, it uses both automata.
|
||||||
|
|
||||||
|
For a more human-readable output, `dot_graph.py` generates dot files, which can be used as input to [Graphviz] to render the graph as a PDF file. The resulting images are not quite as nice as the manually drawn ones above, but usually good enough to be useful.
|
||||||
|
|
||||||
|
[Brink-Howlett]: https://link.springer.com/article/10.1007/BF01445101
|
||||||
|
[Björner-Brenti]: https://link.springer.com/book/10.1007/3-540-27596-7
|
||||||
|
[Coxeter group]: https://en.wikipedia.org/wiki/Coxeter_group
|
||||||
|
[Coxeter matrix]: https://en.wikipedia.org/wiki/Coxeter_group#Coxeter_matrix_and_Schl%C3%A4fli_matrix
|
||||||
|
[Graphviz]: https://www.graphviz.org/
|
26
dot_graph.py
26
dot_graph.py
@ -8,14 +8,24 @@
|
|||||||
import coxeter_automaton
|
import coxeter_automaton
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
coxeter_matrix = [[1, 2, 0, 0, 0, 2],
|
coxeter_matrix = [[1, 3, 3],
|
||||||
[2, 1, 2, 0, 0, 0],
|
[3, 1, 3],
|
||||||
[0, 2, 1, 2, 0, 0],
|
[3, 3, 1]]
|
||||||
[0, 0, 2, 1, 2, 0],
|
|
||||||
[0, 0, 0, 2, 1, 2],
|
|
||||||
[2, 0, 0, 0, 2, 1]]
|
|
||||||
|
|
||||||
graph = coxeter_automaton.generate_automaton_coxeter_matrix(coxeter_matrix, lex_reduced = False)
|
# coxeter_matrix = [[1, 2, 0, 0, 0, 2],
|
||||||
|
# [2, 1, 2, 0, 0, 0],
|
||||||
|
# [0, 2, 1, 2, 0, 0],
|
||||||
|
# [0, 0, 2, 1, 2, 0],
|
||||||
|
# [0, 0, 0, 2, 1, 2],
|
||||||
|
# [2, 0, 0, 0, 2, 1]]
|
||||||
|
|
||||||
|
#coxeter_matrix = [[1, 0, 0],
|
||||||
|
# [0, 1, 0],
|
||||||
|
# [0, 0, 1]]
|
||||||
|
|
||||||
|
graph = coxeter_automaton.generate_automaton_coxeter_matrix(coxeter_matrix, lex_reduced = True)
|
||||||
|
|
||||||
|
#graph = coxeter_automaton.even_graph(graph)
|
||||||
|
|
||||||
colors = {0: "red", 1: "darkgreen", 2: "blue", 3: "orange", 4: "black", 5: "gray"}
|
colors = {0: "red", 1: "darkgreen", 2: "blue", 3: "orange", 4: "black", 5: "gray"}
|
||||||
|
|
||||||
@ -44,5 +54,7 @@ for dn in nodes_by_distance:
|
|||||||
for i,node in enumerate(graph):
|
for i,node in enumerate(graph):
|
||||||
for edge,j in enumerate(node):
|
for edge,j in enumerate(node):
|
||||||
if j:
|
if j:
|
||||||
|
# print('{i:d} -> {j:d} [color={color}];'.format(i = i, j = j, color = "black"))
|
||||||
print('{i:d} -> {j:d} [color={color}];'.format(i = i, j = j, color = colors[edge]))
|
print('{i:d} -> {j:d} [color={color}];'.format(i = i, j = j, color = colors[edge]))
|
||||||
|
|
||||||
print('}')
|
print('}')
|
||||||
|
26
example.py
26
example.py
@ -1,18 +1,32 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
import coxeter_automaton
|
import coxeter_automaton
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
# the (3, 3, 3) triangle group; or equivalently, the
|
||||||
|
# equilateral triangle tiling of the Euclidean plane
|
||||||
|
coxeter_matrix = [[1, 3, 3],
|
||||||
|
[3, 1, 3],
|
||||||
|
[3, 3, 1]]
|
||||||
|
|
||||||
# (2, 3, infinity) triangle group; 0 stands for infinity
|
# (2, 3, infinity) triangle group; 0 stands for infinity
|
||||||
coxeter_matrix = [[1, 0, 3],
|
# coxeter_matrix = [[1, 0, 3],
|
||||||
[0, 1, 2],
|
# [0, 1, 2],
|
||||||
[3, 2, 1]]
|
# [3, 2, 1]]
|
||||||
|
|
||||||
|
# coxeter_matrix = [[1, 2, 0, 0, 0, 2],
|
||||||
|
# [2, 1, 2, 0, 0, 0],
|
||||||
|
# [0, 2, 1, 2, 0, 0],
|
||||||
|
# [0, 0, 2, 1, 2, 0],
|
||||||
|
# [0, 0, 0, 2, 1, 2],
|
||||||
|
# [2, 0, 0, 0, 2, 1]]
|
||||||
|
|
||||||
graph = coxeter_automaton.generate_automaton_coxeter_matrix(coxeter_matrix, lex_reduced = False)
|
graph = coxeter_automaton.generate_automaton_coxeter_matrix(coxeter_matrix, lex_reduced = False)
|
||||||
graph_shortlex = coxeter_automaton.generate_automaton_coxeter_matrix(coxeter_matrix, lex_reduced = True)
|
graph_shortlex = coxeter_automaton.generate_automaton_coxeter_matrix(coxeter_matrix, lex_reduced = True)
|
||||||
|
|
||||||
print(graph)
|
pprint(graph)
|
||||||
|
|
||||||
group = coxeter_automaton.enumerate_group(graph, graph_shortlex, 10)
|
# group = coxeter_automaton.enumerate_group(graph, graph_shortlex, 10)
|
||||||
|
|
||||||
# for each group element g and generator a, print index of a*g
|
# for each group element g and generator a, print index of a*g
|
||||||
print([[l.id if l else None for l in g.left] for g in group])
|
# print([[l.id if l else None for l in g.left] for g in group])
|
||||||
|
Loading…
Reference in New Issue
Block a user