add example and code to generate dot file

This commit is contained in:
Florian Stecker 2022-10-15 14:05:14 +02:00
parent 55f0c2d093
commit fea1b1eb2e
3 changed files with 104 additions and 35 deletions

55
automaton.py → coxeter_automaton.py Executable file → Normal file
View File

@ -1,10 +1,4 @@
#!/usr/bin/python import numpy as np
# 0 is infinity
coxeter_matrix = [[1, 5, 5],
[5, 1, 5],
[5, 5, 1]]
import math import math
from copy import copy from copy import copy
from collections import deque from collections import deque
@ -48,7 +42,7 @@ def apply_gen_to_root(form, k, root):
root[k] -= 2*form_gen_root(form, k, root) root[k] -= 2*form_gen_root(form, k, root)
# find a sequence of generators to apply to obtain a negative root, from left to right # find a sequence of generators to apply to obtain a negative root, from left to right
# "startwidth" argument can be used to force the first entry # "startwith" argument can be used to force the first entry
def find_word_to_negative(form, root_, startwith = None): def find_word_to_negative(form, root_, startwith = None):
rank = len(form) rank = len(form)
root = root_.copy() root = root_.copy()
@ -169,14 +163,9 @@ def generate_automaton(small_roots, lex_reduced = False):
graph[fr][gen] = to graph[fr][gen] = to
return graph return graph
# main program
form = [[-math.cos(math.pi/m) if m > 0 else -1 for m in row] for row in coxeter_matrix]
rank = len(coxeter_matrix)
small_roots = find_small_roots(form)
graph = generate_automaton(small_roots, lex_reduced = False)
graph_lex = generate_automaton(small_roots, lex_reduced = True)
def enumerate_group(graph, graph_lex, max_len):
rank = len(graph[0])
group = [Groupelement(0, rank, tuple())] group = [Groupelement(0, rank, tuple())]
group[0].inverse = group[0] group[0].inverse = group[0]
group[0].node = group[0].lex_node = 0 group[0].node = group[0].lex_node = 0
@ -187,11 +176,11 @@ while True:
current = group[i] current = group[i]
i+=1 i+=1
if current.length >= 10: # break if current has the max length we have, as that's when we would start adding elements 1 longer
if current.length >= max_len:
break break
for gen, new_lex_node in enumerate(graph_lex[current.lex_node]): for gen, new_lex_node in filter(lambda x: x[1], enumerate(graph_lex[current.lex_node])):
if new_lex_node:
new_element = Groupelement(size, rank, current.word + (gen,)) new_element = Groupelement(size, rank, current.word + (gen,))
new_element.lex_node = new_lex_node new_element.lex_node = new_lex_node
new_element.node = graph[current.node][gen] new_element.node = graph[current.node][gen]
@ -199,10 +188,8 @@ while True:
size += 1 size += 1
# w = w_1 t, w s = w_1 # w = w_1 t, w s = w_1
# right multiplication (and left in case it does the same as a right mult) # right multiplication, if it decreases length
for k in range(rank): for k in range(rank):
# if right multiplication by k decreases length
if not graph[new_element.node][k]: if not graph[new_element.node][k]:
word = list(new_element.word) word = list(new_element.word)
longer_suffix = group[0] longer_suffix = group[0]
@ -213,7 +200,6 @@ while True:
# w = w_1 t w_2, w_2 s_k = t w_2 # w = w_1 t w_2, w_2 s_k = t w_2
# in the case word = [] longer_suffix could be None # in the case word = [] longer_suffix could be None
# found it
if len(word) == 0 or shorter_suffix.right[k] == longer_suffix: if len(word) == 0 or shorter_suffix.right[k] == longer_suffix:
# finish word # finish word
while len(word) > 0: while len(word) > 0:
@ -240,8 +226,25 @@ while True:
other = new_element.right[k].inverse other = new_element.right[k].inverse
inverse.left[k] = other inverse.left[k] = other
other.left[k] = inverse other.left[k] = inverse
return group
length = 0 def word(w):
for i in range(1,len(group)+1): return ''.join([chr(ord('a')+x) for x in w])
if i == len(group) or group[i].length > group[i-1].length:
print("{number:d} elements up to length {length:d}".format(number = i, length = group[i-1].length)) def generate_automaton_coxeter_matrix(coxeter_matrix, lex_reduced = False):
form = [[-math.cos(math.pi/m) if m > 0 else -1 for m in row] for row in coxeter_matrix]
rank = len(coxeter_matrix)
small_roots = find_small_roots(form)
return generate_automaton(small_roots, lex_reduced)
def even_graph(graph):
rank = len(graph[0])
result = []
for node in graph:
newnode = {}
for i in range(rank):
for j in range(rank):
if node[i] and graph[node[i]][j]:
newnode[(i,j)] = graph[node[i]][j]
result.append(newnode)
return result

48
dot_graph.py Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/python
# outputs the automaton as a graphviz dot file, arranging the vertices
# in levels according to their distance from the starting vertex
# to convert to a PDF, run:
# ./dot_graph.py | dot -Tpdf > output.pdf
import coxeter_automaton
from collections import deque
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)
colors = {0: "red", 1: "darkgreen", 2: "blue", 3: "orange", 4: "black", 5: "gray"}
todo = deque([0])
distances = [None]*len(graph)
distances[0] = 0
while todo:
node = todo.pop()
for newnode in graph[node]:
if newnode:
if not distances[newnode] or distances[newnode] > distances[node] + 1:
distances[newnode] = distances[node] + 1
todo.appendleft(newnode)
max_distance = max(filter(None, distances))
nodes_by_distance = [[] for _ in range(max_distance+1)]
for n,d in enumerate(distances):
if d != None:
nodes_by_distance[d].append(n)
print('digraph test123 {')
for dn in nodes_by_distance:
print('{rank = same; %s}' % "; ".join([str(x) for x in dn]))
for i,node in enumerate(graph):
for edge,j in enumerate(node):
if j:
print('{i:d} -> {j:d} [color={color}];'.format(i = i, j = j, color = colors[edge]))
print('}')

18
example.py Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/python
import coxeter_automaton
# (2, 3, infinity) triangle group; 0 stands for infinity
coxeter_matrix = [[1, 0, 3],
[0, 1, 2],
[3, 2, 1]]
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)
print(graph)
group = coxeter_automaton.enumerate_group(graph, graph_shortlex, 10)
# 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])