GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
#
# units.g The Congruence package Ann Dooms
# Eric Jespers
# Alexander Konovalov
#
#############################################################################
#############################################################################
#
# NormalSubgroupsForM2Q(G,H)
#
# Returns a list of normal subgroups N of G such that quotient G/N is H.
#
NormalSubgroupsForM2Q := function( G, H )
local ord,m, N;
ord:= Size(G)/Size(H);
# Can we speedup this computing only normal subgroups of given size?
m:=Filtered( NormalSubgroups(G) , N -> Size(N)=ord);
m:=Filtered( m, N -> IdGroup( G/N ) = IdGroup( H ) );
return m;
end;
#############################################################################
#
# GeneratorsInM2Q(G,H)
#
# Returns a list of lists of generators of a subgroup of f.i. in M_2(Q),
# one for each homomorphic image.
# H has to be S3 or D8!
#
GeneratorsInM2Q:=function(G,H)
local k,m;
if IdGroup(H)=[6,1] then
k:=3; # H = S_3
else
k:=4; # H = D_8
fi;
m:=NormalSubgroupsForM2Q(G,H);
if Length(m) > 0 then
return GeneratorsOfGroup( PrincipalCongruenceSubgroup(k*Size(G)/Size(H) ) );
else
return [ ];
fi;
end;
#############################################################################
#
# MatrixEntries( matrix, k )
#
# Returns a list with integer entries. Will be applied with k=4n or 3n.
# PROBLEM: some matrices gave non-integers! SOLUTION: multiplied with -I_2!
#
MatrixEntries := function( matrix, k )
local g11,g12,g21,g22;
g11:=(matrix[1][1]-1)/k;
if not IsInt(g11) then
matrix:=-matrix;
g11:=(matrix[1][1]-1)/k;
fi;
g12:=matrix[1][2]/k;
g21:=matrix[2][1]/k;
g22:=(matrix[2][2]-1)/k;
return [ g11, g12, g21, g22 ];
end;
#############################################################################
#
# D8Alpha(matrix,n)
#
# Returns a list with integer entries.
# Will be applied with n = order of the normal subgroup N determining M_2(Q).
#
D8Alpha := function(matrix,n)
local m,a0,a1,a2,a3;
m := MatrixEntries(matrix,4*n);
a0 := m[1] + m[4];
a1 := m[1] - m[2] + 2*m[3] - m[4];
a2 := m[1] + 2*m[3] - m[4];
a3 :=-m[1] + m[2] + m[4];
return [ a0, a1, a2, a3 ];
end;
#############################################################################
#
# S3Alpha(matrix,n)
#
# Returns a list with integer entries.
# Will be applied with n = order of the normal subgroup N determining M_2(Q).
#
S3Alpha:= function(matrix,n)
local m,a0,a1,a2,a3;
m := MatrixEntries(matrix,3*n);
a0 := m[1] + m[4];
a1 := 2*m[1] + 3*m[2] - m[3] - m[4];
a2 := -2*m[1] - 3*m[2] + m[3] + 2*m[4];
a3 := -m[1] - 3*m[2] + m[4];
return [ a0, a1, a2, a3 ];
end;
#############################################################################
#
# Alphas( G, H )
#
# Returns a list of lists with integer entries which will serve for the units in U(ZG).
#
Alphas := function( G, H )
local gen,f,alpha,i;
gen := GeneratorsInM2Q( G, H );
if IdGroup(H)=[6,1] then
f:=S3Alpha;
else
f:=D8Alpha;
fi;
alpha:=[];
if Length(gen) > 0 then
for i in [1..Length(gen)] do
alpha[i] := f( gen[i], Size(G)/Size(H) );
od;
fi;
return alpha;
end;
#############################################################################
#
# LiftGenerator(G,N)
#
# Lifts a minimal list of generators form G/N to G.
#
LiftGenerator := function( G, N )
local l,q,s,hom,i;
l:=[];
hom:=NaturalHomomorphismByNormalSubgroup(G,N);
q := Image( hom );
s := MinimalGeneratingSet( q );
for i in [ 1 .. Length(s) ] do
Add( l, PreImagesRepresentative( hom,s[i]) );
od;
return l;
end;
#############################################################################
#
# CreateUnits(G,H)
#
# Creates units of ZG. H must be D8 or S3.
#
CreateUnits:=function(G,H)
local m,alpha,a,b,x,y,ZG,emb,hat,u,i,j;
m:=NormalSubgroupsForM2Q(G,H);
alpha:=Alphas(G,H);
a:=[];
b:=[];
ZG:=GroupRing(Integers,G);
emb := Embedding(G,ZG);
hat:=[];
u:=[];
if Length(m)<>0 then
for i in [1..Length(m)] do
hat[i]:=Sum( List(m[i], x->x^emb));
u[i]:=[];
x := LiftGenerator(G,m[i])[1];
y := LiftGenerator(G,m[i])[2];
if x^2=Identity(G) then
a[i]:=y^emb;
b[i]:=x^emb;
else
a[i]:=x^emb;
b[i]:=y^emb;
fi;
if IdGroup(H)=[6,1] then
for j in [1..Length(alpha)] do
u[i][j]:=Identity(ZG) +
(alpha[j][1]*Identity(ZG) +
alpha[j][2]*a[i] +
alpha[j][3]*b[i] +
alpha[j][4]*a[i]^2*b[i])*(Identity(ZG)-a[i])*hat[i];
od;
else
for j in [1..Length(alpha)] do
u[i][j]:=Identity(ZG) +
(alpha[j][1]*Identity(ZG) +
alpha[j][2]*a[i] +
alpha[j][3]*b[i] +
alpha[j][4]*a[i]*b[i])*(Identity(ZG)-a[i]^2)*hat[i];
od;
fi;
od;
else
fi;
return u;
end;
#############################################################################
#
# UnitsOfZGOfFiniteIndexInM2Q(G)
#
UnitsOfZGOfFiniteIndexInM2Q:=
function(G)
local u,v;
u:=[];
v:=[];
if IsNilpotent(G)=true then
u:=CreateUnits(G,DihedralGroup(8));
else
u:=CreateUnits(G,DihedralGroup(8));
v:=CreateUnits(G,DihedralGroup(6));
fi;
return [u,v];
end;