mirror of
https://github.com/kalmarek/SmallHyperbolic
synced 2024-11-27 16:35:26 +01:00
commit
89fbf76f32
15
README.md
15
README.md
@ -1,11 +1,11 @@
|
|||||||
The repository contains code for running experiments for
|
The repository contains code for running experiments for
|
||||||
_Hyperbolic generalized triangle groups_ by
|
[_Hyperbolic generalized triangle groups, property (T) and finite simple quotients_](https://arxiv.org/abs/2011.09276) by
|
||||||
[Pierre-Emmanuel Caprace](https://perso.uclouvain.be/pierre-emmanuel.caprace/),
|
[Pierre-Emmanuel Caprace](https://perso.uclouvain.be/pierre-emmanuel.caprace/),
|
||||||
[Marston Conder](https://www.math.auckland.ac.nz/~conder/),
|
[Marston Conder](https://www.math.auckland.ac.nz/~conder/),
|
||||||
[Marek Kaluba](https://kalmar.faculty.wmi.amu.edu.pl/) and
|
[Marek Kaluba](https://kalmar.faculty.wmi.amu.edu.pl/) and
|
||||||
[Stefan Witzel](https://www.math.uni-bielefeld.de/~switzel/).
|
[Stefan Witzel](https://www.math.uni-bielefeld.de/~switzel/).
|
||||||
|
|
||||||
There are two disjoint computations covered in this repository.
|
There are three disjoint computations covered in this repository.
|
||||||
|
|
||||||
## Eigenvalues computations for _PSL₂(p)_
|
## Eigenvalues computations for _PSL₂(p)_
|
||||||
|
|
||||||
@ -138,3 +138,14 @@ One can perform those computations in bulk by e.g. calling
|
|||||||
make 2_4_4
|
make 2_4_4
|
||||||
```
|
```
|
||||||
to run all examples in `presentations_2_4_4.txt` in parallel.
|
to run all examples in `presentations_2_4_4.txt` in parallel.
|
||||||
|
|
||||||
|
## Creating the tables of [arXiv:2011.09276](https://arxiv.org/abs/2011.09276)
|
||||||
|
|
||||||
|
The scripts are located in `magma` directory and thoroughly commented.
|
||||||
|
There are two files, one contains the core Magma code used to create the tables,
|
||||||
|
the other one is a python script that augments the magma file by a list of
|
||||||
|
hyperbolic words. To use it put both files in a common folder, run
|
||||||
|
```bash
|
||||||
|
python3 hyperbolic_words.py
|
||||||
|
```
|
||||||
|
and then load the resulting file `small_hyperbolic.magma` in Magma.
|
||||||
|
27
magma/hyperbolic_words.py
Normal file
27
magma/hyperbolic_words.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# This script augments creates the magma file small_hyperbolic.magma out of
|
||||||
|
# the file small_hyperbolic.magma_template by filling in the lines
|
||||||
|
# "hyp_words_a := ..." and "hyp_words_c := ..." with lists of all short words
|
||||||
|
# representing short hyperbolic elements.
|
||||||
|
|
||||||
|
from itertools import permutations,product
|
||||||
|
import sys
|
||||||
|
basic_words_a = ['abcb','abcabc','abcbabcb','abcabcabcb','abcbabcbabcb','abcabcabcabc']#,'abcabcabcbabcb']
|
||||||
|
basic_words_c = ['acbc','cbca','acabcb','cabcba','acbcacbc','cbcacbca','acabcabcbc','cabcabcbca','acabcbacabcb','cabcbacabcba','acbcacbcacbc','cbcacbcacbca']
|
||||||
|
|
||||||
|
def words(basic_word):
|
||||||
|
for p in permutations('ab'):
|
||||||
|
d = dict(zip('abc',p + ('c',)))
|
||||||
|
subs_word = ''.join(d[i] for i in basic_word)
|
||||||
|
for exps in product(('','^-1'), repeat=len(subs_word)):
|
||||||
|
word = ' * '.join((c + e) for (c,e) in zip(subs_word,exps))
|
||||||
|
yield word
|
||||||
|
|
||||||
|
with open("small_hyperbolic.magma_template","r") as magma_template:
|
||||||
|
with open("small_hyperbolic.magma","w") as magma:
|
||||||
|
for line in magma_template:
|
||||||
|
if 'hyp_words_a := ' in line:
|
||||||
|
magma.write('hyp_words_a := [ %s ];\n' % ' , '.join('{ %s }' % ', '.join(words(basic_word)) for basic_word in basic_words_a))
|
||||||
|
elif 'hyp_words_c := ' in line:
|
||||||
|
magma.write('hyp_words_c := [ %s ];\n' % ' , '.join('{ %s }' % ', '.join(words(basic_word)) for basic_word in basic_words_c))
|
||||||
|
else:
|
||||||
|
magma.write(line)
|
135
magma/small_hyperbolic.magma_template
Normal file
135
magma/small_hyperbolic.magma_template
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// Magma Functions related to the article
|
||||||
|
//
|
||||||
|
// Hyperbolic generalized triangle groups, property (T) and finite simple quotients
|
||||||
|
// by Pierre-Emmanuel Caprace, Marston Conder, Marek Kaluba, Stefan Witzel
|
||||||
|
//
|
||||||
|
// The functions and procedures in this file were written by Pierre-Emmanuel Caprace and Stefan Witzel
|
||||||
|
//
|
||||||
|
// The file is working magma code except for the two lines definint hyp_words_a and hyp_words_c that need to be replaced using hyperbolic_words.py
|
||||||
|
// It does not contain (all) the code that was used to create the tables but it is suited to reconstruct the tables.
|
||||||
|
|
||||||
|
SetColumns(0);
|
||||||
|
SetAutoColumns(false);
|
||||||
|
SetVerbose("KBMAG",1);
|
||||||
|
|
||||||
|
max_quotient_order:=5*10^7;
|
||||||
|
|
||||||
|
// Procedure testing whether a trivalent generalized triangle group of half girth type (3,3,3) ("type A") or half girth type (2,4,4) ("type C") contains a copy of Z^2 generated by short elements.
|
||||||
|
//
|
||||||
|
// The arguments are an automatic group representing a generalized triangle group and the list hyp_words_a or hyp_words_c depening on type (these lists are the only part specific to trivalent triangle groups).
|
||||||
|
//
|
||||||
|
// The prints generators of a copy of Z^2 f one is found (so the group is not hyperbolic). If none is found the group may or may not be hyperbolic.
|
||||||
|
|
||||||
|
find_flat := procedure(GA, ~hyp_words)
|
||||||
|
printf "Commuting pair: ";
|
||||||
|
for s in [1..#hyp_words] do
|
||||||
|
for i in [1..s] do
|
||||||
|
for x in hyp_words[i] do
|
||||||
|
for y in hyp_words[i] do
|
||||||
|
// Do x and y commute?
|
||||||
|
if (x, y) ne GA!1 then
|
||||||
|
continue;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
// If so, do they span a cyclic group?
|
||||||
|
num := GreatestCommonDivisor(#x,#y);
|
||||||
|
ex := Round(#y/num);
|
||||||
|
ey := Round(#x/num);
|
||||||
|
if x^ex eq y^ey or x^ex eq y^(-ey) then
|
||||||
|
continue;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
// If not they span a copy of Z^2
|
||||||
|
printf "%o, %o;\t", x, y;
|
||||||
|
return;
|
||||||
|
end for;
|
||||||
|
end for;
|
||||||
|
end for;
|
||||||
|
end for;
|
||||||
|
printf "\n";
|
||||||
|
end procedure;
|
||||||
|
|
||||||
|
// Auxiliary function determining the name of a simple quotient
|
||||||
|
identify := function(Qs)
|
||||||
|
succ, res := SimpleGroupName(Image(Qs[1]));
|
||||||
|
if succ then
|
||||||
|
return [*res,Order(Image(Qs[1])), #Qs*];
|
||||||
|
else
|
||||||
|
return [* [*<0,0,0>*], Order(Image(Qs[1])),#Qs*];
|
||||||
|
end if;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
// Procedure collecting information around the hyperbolicity of a generalized triangle group of half girth type (3,3,3) (type A) or (2,4,4) (type C).
|
||||||
|
//
|
||||||
|
// Arguments are a generalized triangle group (as a finitely presented group) and "A" or "C" describing the type.
|
||||||
|
//
|
||||||
|
// It will first try to find an automatic structure and prints whether it has found one (this should never fail).
|
||||||
|
// Based on the automatic struture, it tries to prove the group hyperbolic and prints whether it manged.
|
||||||
|
// If the group could not be verified to be hyperbolic, the procedure tries to find a copy of Z^2 and print, whether it has found one.
|
||||||
|
//
|
||||||
|
// Of course, if a group is expected to contain Z^2, it is reasonable to call find_flat before calling IsHyperbolic.
|
||||||
|
|
||||||
|
hyperbolic := procedure(G, type)
|
||||||
|
isa, GA := IsAutomaticGroup(G);
|
||||||
|
printf "automatic: %o\n", isa;
|
||||||
|
if not isa then
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
|
ish, GH := IsHyperbolic(GA: MaxTries := 20);
|
||||||
|
printf "hyperbolic: %o\n", ish;
|
||||||
|
if ish then
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
|
a := Generators(GA)[1];
|
||||||
|
b := Generators(GA)[2];
|
||||||
|
c := Generators(GA)[3];
|
||||||
|
if type eq "A" then
|
||||||
|
hyp_words_a := [ False ];
|
||||||
|
find_flat(GA, ~hyp_words_a);
|
||||||
|
elif type eq "C" then
|
||||||
|
hyp_words_c := [ False ];
|
||||||
|
find_flat(GA, ~hyp_words_c);
|
||||||
|
end if;
|
||||||
|
end procedure;
|
||||||
|
|
||||||
|
// Procedure collecting information abound finite simple quotients of a finitely presented group
|
||||||
|
//
|
||||||
|
// Arguments are a finitely presented group and a bound on the order of quotients (such as max_quotient_order)
|
||||||
|
//
|
||||||
|
// Prints the abelianization, the L2 quotients, and the finite simple quotients that are not L2 quotients up to the given order.
|
||||||
|
|
||||||
|
quotients := procedure(G,n)
|
||||||
|
Q, mor := AbelianQuotient(G);;
|
||||||
|
printf "rk(H_1): %o\n", #Generators(AbelianQuotient(G));
|
||||||
|
printf "l2-quotients: %o\n", L2Quotients(G);
|
||||||
|
printf "quotients: %o, %o\n", [identify(Qs) : Qs in SimpleQuotients(G,n:Family:="notPSL2",Limit:=0)], n;
|
||||||
|
end procedure;
|
||||||
|
|
||||||
|
|
||||||
|
// Function testing whether a generalized triangle group given in triangular presentation is virtually torsion free (VTF)
|
||||||
|
//
|
||||||
|
// Returns "true" if group is certified to be virtually torsion-free. The outpue "false" is inconclusive.
|
||||||
|
//
|
||||||
|
// The input is a quadruple consisting of the group presentation, followed by the triple of the orders of the vertex links, respectively corresponding to <a, b>, <b, c>, <c, a>
|
||||||
|
|
||||||
|
VTF:=function(g, n1, n2, n3)
|
||||||
|
o1:=n1*3/2; // Order group vx group generated by a, b
|
||||||
|
o2:=n2*3/2; // Order group vx group generated by b, c
|
||||||
|
o3:=n3*3/2; // Order group vx group generated by c, a
|
||||||
|
|
||||||
|
// Test whether vertex groups inject in simple quotients
|
||||||
|
t:=false;
|
||||||
|
quot:=SimpleQuotientProcess(g, 6, 10^3, 1, 5*10^7:Limit:=1);
|
||||||
|
|
||||||
|
while not t and not IsEmptySimpleQuotientProcess(quot) do
|
||||||
|
f:=SimpleEpimorphisms(quot)[1];
|
||||||
|
Im:=Parent(f(g.1));
|
||||||
|
o_im_1:=#sub<Im|f(g.1), f(g.2)>;
|
||||||
|
o_im_2:=#sub<Im|f(g.2), f(g.3)>;
|
||||||
|
o_im_3:=#sub<Im|f(g.3), f(g.1)>;
|
||||||
|
t:=o1 eq o_im_1 and o2 eq o_im_2 and o3 eq o_im_3;
|
||||||
|
NextSimpleQuotient(~quot);
|
||||||
|
end while;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
end function;
|
@ -1,102 +0,0 @@
|
|||||||
using Nemo
|
|
||||||
using DelimitedFiles
|
|
||||||
using LinearAlgebra
|
|
||||||
|
|
||||||
include("src/nemo_utils.jl")
|
|
||||||
|
|
||||||
const PRECISION = 256
|
|
||||||
|
|
||||||
function parse_eval(expr_str, value, var_name)
|
|
||||||
ex = Meta.parse(expr_str)
|
|
||||||
svar = :($var_name)
|
|
||||||
return @eval begin
|
|
||||||
let $svar = $value
|
|
||||||
$ex
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function read_eval(fname, var_name, value)
|
|
||||||
a = readdlm(fname, ',', String)
|
|
||||||
a .= replace.(a, '/' => "//")
|
|
||||||
return parse_eval.(a, value, var_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
function load_discrete_repr(i, q = 109; CC = AcbField(PRECISION))
|
|
||||||
ζ = root_of_unity(CC, (q + 1) ÷ 2)
|
|
||||||
degree = q - 1
|
|
||||||
|
|
||||||
ra = read_eval(
|
|
||||||
"data/Discrete reps PSL(2, $q)/discrete_rep_$(i)_a.txt",
|
|
||||||
:Z,
|
|
||||||
ζ,
|
|
||||||
)
|
|
||||||
a = matrix(CC, [CC(s) for s in ra[1:degree, 1:degree]])
|
|
||||||
|
|
||||||
rb = read_eval(
|
|
||||||
"data/Discrete reps PSL(2, $q)/discrete_rep_$(i)_b.txt",
|
|
||||||
:Z,
|
|
||||||
ζ,
|
|
||||||
)
|
|
||||||
b = matrix(CC, [CC(s) for s in rb[1:degree, 1:degree]])
|
|
||||||
@assert contains(det(a), 1)
|
|
||||||
@assert contains(det(b), 1)
|
|
||||||
|
|
||||||
return a, b
|
|
||||||
end
|
|
||||||
|
|
||||||
function load_principal_repr(i, q = 109; CC = AcbField(PRECISION))
|
|
||||||
ζ = root_of_unity(CC, (q - 1) ÷ 2)
|
|
||||||
degree = q + 1
|
|
||||||
|
|
||||||
ra = read_eval(
|
|
||||||
"data/Principal reps PSL(2, $q)/principal_rep_$(i)_a.txt",
|
|
||||||
:zz,
|
|
||||||
ζ,
|
|
||||||
)
|
|
||||||
a = matrix(CC, [CC(z) for z in ra[1:degree, 1:degree]])
|
|
||||||
|
|
||||||
rb = read_eval(
|
|
||||||
"data/Principal reps PSL(2, $q)/principal_rep_$(i)_b.txt",
|
|
||||||
:zz,
|
|
||||||
ζ,
|
|
||||||
)
|
|
||||||
b = matrix(CC, [CC(z) for z in rb[1:degree, 1:degree]])
|
|
||||||
@assert contains(det(a), 1)
|
|
||||||
@assert contains(det(b), 1)
|
|
||||||
|
|
||||||
return a, b
|
|
||||||
end
|
|
||||||
|
|
||||||
if !isinteractive()
|
|
||||||
|
|
||||||
for i = 0:27
|
|
||||||
try
|
|
||||||
a, b = load_principal_repr(i)
|
|
||||||
adjacency = sum(a^i for i = 1:4) + sum(b^i for i = 1:4)
|
|
||||||
@time ev = let evs = safe_eigvals(adjacency)
|
|
||||||
_count_multiplicites(evs)
|
|
||||||
end
|
|
||||||
|
|
||||||
@info "Principal Series Representation $i" ev[1:2] ev[end]
|
|
||||||
catch ex
|
|
||||||
@error "Principal Series Representation $i failed" ex
|
|
||||||
ex isa InterruptException && throw(ex)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1:27
|
|
||||||
try
|
|
||||||
a, b = load_discrete_repr(i)
|
|
||||||
adjacency = sum(a^i for i = 1:4) + sum(b^i for i = 1:4)
|
|
||||||
@time ev = let evs = safe_eigvals(adjacency)
|
|
||||||
_count_multiplicites(evs)
|
|
||||||
end
|
|
||||||
|
|
||||||
@info "Discrete Series Representation $i" ev[1:2] ev[end]
|
|
||||||
catch ex
|
|
||||||
@error "Discrete Series Representation $i : failed" ex
|
|
||||||
ex isa InterruptException && rethrow(ex)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user