1
0
mirror of https://github.com/kalmarek/SmallHyperbolic synced 2024-11-27 16:35:26 +01:00

Merge pull request #4 from kalmarek/add_magma

Add magma
This commit is contained in:
Marek Kaluba 2021-09-20 14:19:49 +02:00 committed by GitHub
commit 89fbf76f32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 175 additions and 104 deletions

View File

@ -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
View 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)

View 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;

View File

@ -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