add example and code to generate dot file
This commit is contained in:
parent
55f0c2d093
commit
fea1b1eb2e
67
automaton.py → coxeter_automaton.py
Executable file → Normal file
67
automaton.py → coxeter_automaton.py
Executable file → Normal file
@ -1,10 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# 0 is infinity
|
||||
coxeter_matrix = [[1, 5, 5],
|
||||
[5, 1, 5],
|
||||
[5, 5, 1]]
|
||||
|
||||
import numpy as np
|
||||
import math
|
||||
from copy import copy
|
||||
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)
|
||||
|
||||
# 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):
|
||||
rank = len(form)
|
||||
root = root_.copy()
|
||||
@ -169,29 +163,24 @@ def generate_automaton(small_roots, lex_reduced = False):
|
||||
graph[fr][gen] = to
|
||||
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[0].inverse = group[0]
|
||||
group[0].node = group[0].lex_node = 0
|
||||
|
||||
group = [Groupelement(0, rank, tuple())]
|
||||
group[0].inverse = group[0]
|
||||
group[0].node = group[0].lex_node = 0
|
||||
|
||||
i = 0
|
||||
size = 1
|
||||
while True:
|
||||
i = 0
|
||||
size = 1
|
||||
while True:
|
||||
current = group[i]
|
||||
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
|
||||
|
||||
for gen, new_lex_node in enumerate(graph_lex[current.lex_node]):
|
||||
if new_lex_node:
|
||||
for gen, new_lex_node in filter(lambda x: x[1], enumerate(graph_lex[current.lex_node])):
|
||||
new_element = Groupelement(size, rank, current.word + (gen,))
|
||||
new_element.lex_node = new_lex_node
|
||||
new_element.node = graph[current.node][gen]
|
||||
@ -199,10 +188,8 @@ while True:
|
||||
size += 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):
|
||||
|
||||
# if right multiplication by k decreases length
|
||||
if not graph[new_element.node][k]:
|
||||
word = list(new_element.word)
|
||||
longer_suffix = group[0]
|
||||
@ -213,7 +200,6 @@ while True:
|
||||
|
||||
# w = w_1 t w_2, w_2 s_k = t w_2
|
||||
# in the case word = [] longer_suffix could be None
|
||||
# found it
|
||||
if len(word) == 0 or shorter_suffix.right[k] == longer_suffix:
|
||||
# finish word
|
||||
while len(word) > 0:
|
||||
@ -240,8 +226,25 @@ while True:
|
||||
other = new_element.right[k].inverse
|
||||
inverse.left[k] = other
|
||||
other.left[k] = inverse
|
||||
return group
|
||||
|
||||
length = 0
|
||||
for i in range(1,len(group)+1):
|
||||
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 word(w):
|
||||
return ''.join([chr(ord('a')+x) for x in w])
|
||||
|
||||
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
48
dot_graph.py
Executable 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
18
example.py
Executable 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])
|
Loading…
Reference in New Issue
Block a user