GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
#W classic.gi GAP group library Frank Celler
#W & Heiko Theißen
#W & Thomas Breuer
##
#Y Copyright (C) 1997, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
#Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
##
#############################################################################
##
#M SymplecticGroupCons( <IsMatrixGroup>, <d>, <q> )
##
InstallMethod( SymplecticGroupCons,
"matrix group for dimension and finite field size",
[ IsMatrixGroup and IsFinite,
IsPosInt,
IsPosInt ],
function( filter, d, q )
local g, f, z, o, mat1, mat2, i, size, qi, c;
# the dimension must be even
if d mod 2 = 1 then
Error( "the dimension <d> must be even" );
fi;
f := GF(q);
z := PrimitiveRoot( f );
o := One( f );
#T introduce variable d_2 = d/2 ?
# if the dimension is two it is a special linear group
if d = 2 then
g := SL( 2, q );
#T no form for SL(2,q) if constructed like this?
#T better add the form in the SL(2,q) call
# construct the generators
else
# SP(4,2)
if d = 4 and q = 2 then
mat1 := [ [1,0,1,1], [1,0,0,1], [0,1,0,1], [1,1,1,1] ] * o;
mat2 := [ [0,0,1,0], [1,0,0,0], [0,0,0,1], [0,1,0,0] ] * o;
# SP(d,q)
else
mat1 := IdentityMat( d, f );
mat2 := List( 0 * mat1, ShallowCopy );
for i in [ 2 .. d/2 ] do mat2[i][i-1]:= o; od;
for i in [ d/2+1 .. d-1 ] do mat2[i][i+1]:= o; od;
if q mod 2 = 1 then
mat1[ 1][ 1] := z;
mat1[ d][ d] := z^-1;
mat2[ 1][ 1] := o;
mat2[ 1][d/2+1] := o;
mat2[d-1][ d/2] := o;
mat2[ d][ d/2] := -o;
elif q <> 2 then
mat1[ 1][ 1] := z;
mat1[ d/2][ d/2] := z;
mat1[d/2+1][d/2+1] := z^-1;
mat1[ d][ d] := z^-1;
mat2[ 1][d/2-1] := o;
mat2[ 1][ d/2] := o;
mat2[ 1][d/2+1] := o;
mat2[d/2+1][ d/2] := o;
mat2[ d][ d/2] := o;
else
mat1[ 1][ d/2] := o;
mat1[ 1][ d] := o;
mat1[d/2+1][ d] := o;
mat2[ 1][d/2+1] := o;
mat2[ d][ d/2] := o;
fi;
fi;
mat1:=ImmutableMatrix(f,mat1,true);
mat2:=ImmutableMatrix(f,mat2,true);
# avoid to call 'Group' because this would check invertibility ...
g := GroupWithGenerators( [ mat1, mat2 ] );
SetName( g, Concatenation("Sp(",String(d),",",String(q),")") );
SetDimensionOfMatrixGroup( g, Length( mat1 ) );
SetFieldOfMatrixGroup( g, f );
# add the size
size := 1;
qi := 1;
for i in [ 1 .. d/2 ] do
qi := qi * q^2;
size := size * (qi-1);
od;
SetSize( g, q^((d/2)^2) * size );
fi;
# construct the form
c := List( 0 * One( g ), ShallowCopy );
for i in [ 1 .. d/2 ] do
c[i][d-i+1] := o;
c[d/2+i][d/2-i+1] := -o;
od;
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, c, true ) ) );
SetIsFullSubgroupGLorSLRespectingBilinearForm(g,true);
SetIsSubgroupSL(g,true);
# and return
return g;
end );
InstallMethod( SymplecticGroupCons,
"matrix group for dimension and finite field",
[ IsMatrixGroup and IsFinite,
IsPosInt,
IsField and IsFinite ],
function(filt,n,f)
return SymplecticGroupCons(filt,n,Size(f));
end);
#############################################################################
##
#M GeneralUnitaryGroupCons( <IsMatrixGroup>, <n>, <q> )
##
InstallMethod( GeneralUnitaryGroupCons,
"matrix group for dimension and finite field size",
[ IsMatrixGroup and IsFinite,
IsPosInt,
IsPosInt ],
function( filter, n, q )
local g, i, e, f, z, o, mat1, mat2, size, qi, eps, c;
f:= GF( q^2 );
# Handle the trivial case first.
if n = 1 then
g:= GroupWithGenerators( [ [ [ PrimitiveRoot( f ) ^ (q-1) ] ] ] );
SetName( g, Concatenation("GU(1,",String(q),")") );
#T no form?
return g;
fi;
# Construct the generators.
z:= PrimitiveRoot( f );
o:= One( f );
mat1:= IdentityMat( n, f );
mat2:= List( 0 * mat1, ShallowCopy );
if n = 2 then
# We use the isomorphism of 'SU(2,q)' and 'SL(2,q)':
# 'e' is mapped to '-e' under the Frobenius mapping.
e:= Z(q^2) - Z(q^2)^q;
if q = 2 then
mat1[1][1]:= z;
mat1[2][2]:= z;
mat1[1][2]:= z;
mat2[1][2]:= o;
mat2[2][1]:= o;
else
mat1[1][1]:= z;
mat1[2][2]:= z^-q;
mat2[1][1]:= -o;
mat2[1][2]:= e;
mat2[2][1]:= -e^-1;
fi;
elif n mod 2 = 0 then
if q mod 2 = 1 then e:= z^( (q+1)/2 ); else e:= o; fi;
mat1[1][1]:= z;
mat1[n][n]:= z^-q;
for i in [ 2 .. n/2 ] do mat2[ i ][ i-1 ]:= o; od;
for i in [ n/2+1 .. n-1 ] do mat2[ i ][ i+1 ]:= o; od;
mat2[ 1 ][ 1 ]:= o;
mat2[1][n/2+1]:= e;
mat2[n-1][n/2]:= e^-1;
mat2[n][ n/2 ]:= -e^-1;
else
mat1[(n-1)/2][(n-1)/2]:= z;
mat1[(n-1)/2+2][(n-1)/2+2]:= z^-q;
for i in [ 1 .. (n-1)/2-1 ] do mat2[ i ][ i+1 ]:= o; od;
for i in [ (n-1)/2+3 .. n ] do mat2[ i ][ i-1 ]:= o; od;
mat2[(n-1)/2][ 1 ]:= -(1+z^q/z)^-1;
mat2[(n-1)/2][(n-1)/2+1]:= -o;
mat2[(n-1)/2][ n ]:= o;
mat2[(n-1)/2+1][ 1 ]:= -o;
mat2[(n-1)/2+1][(n-1)/2+1]:= -o;
mat2[(n-1)/2+2][ 1 ]:= o;
fi;
mat1:=ImmutableMatrix(f,mat1,true);
mat2:=ImmutableMatrix(f,mat2,true);
# Avoid to call 'Group' because this would check invertibility ...
g:= GroupWithGenerators( [ mat1, mat2 ] );
SetName( g, Concatenation("GU(",String(n),",",String(q),")") );
SetDimensionOfMatrixGroup( g, Length( mat1 ) );
SetFieldOfMatrixGroup( g, f );
# Add the size.
size := q+1;
qi := q;
eps := 1;
for i in [ 2 .. n ] do
qi := qi * q;
eps := -eps;
size := size * (qi+eps);
od;
SetSize( g, q^(n*(n-1)/2) * size );
# construct the form
c := Reversed( One( g ) );
SetInvariantSesquilinearForm( g,
rec( matrix:= ImmutableMatrix( f, c, true ) ) );
SetIsFullSubgroupGLorSLRespectingSesquilinearForm(g,true);
# Return the group.
return g;
end );
#############################################################################
##
#M SpecialUnitaryGroupCons( <IsMatrixGroup>, <n>, <q> )
##
InstallMethod( SpecialUnitaryGroupCons,
"matrix group for dimension and finite field size",
[ IsMatrixGroup and IsFinite,
IsPosInt,
IsPosInt ],
function( filter, n, q )
local g, i, e, f, z, o, mat1, mat2, size, qi, eps, c;
f:= GF( q^2 );
# Handle the trivial case first.
if n = 1 then
g:= GroupWithGenerators( [ [ [ One( f ) ] ] ] );
SetName( g, Concatenation("SL(1,",String(q),")") );
#T no form?
return g;
fi;
# Construct the generators.
z:= PrimitiveRoot( f );
o:= One( f );
if n = 3 and q = 2 then
mat1:= [ [o,z,z], [0,o,z^2], [0,0,o] ] * o;
mat2:= [ [z,o,o], [o,o, 0 ], [o,0,0] ] * o;
else
mat1:= IdentityMat( n, f );
mat2:= List( 0 * mat1, ShallowCopy );
if n = 2 then
# We use the isomorphism of 'SU(2,q)' and 'SL(2,q)':
# 'e' is mapped to '-e' under the Frobenius mapping.
e:= Z(q^2) - Z(q^2)^q;
if q <= 3 then
mat1[1][2]:= e;
mat2[1][2]:= e;
mat2[2][1]:= -e^-1;
else
mat1[1][1]:= z^(q+1);
mat1[2][2]:= z^(-q-1);
mat2[1][1]:= -o;
mat2[1][2]:= e;
mat2[2][1]:= -e^-1;
fi;
elif n mod 2 = 0 then
mat1[1][1]:= z;
mat1[n][n]:= z^-q;
mat1[2][2]:= z^-1;
mat1[ n-1 ][ n-1 ]:= z^q;
if q mod 2 = 1 then e:= z^( (q+1)/2 ); else e:= o; fi;
for i in [ 2 .. n/2 ] do mat2[ i ][ i-1 ]:= o; od;
for i in [ n/2+1 .. n-1 ] do mat2[ i ][ i+1 ]:= o; od;
mat2[ 1 ][ 1 ]:= o;
mat2[1][n/2+1]:= e;
mat2[n-1][n/2]:= e^-1;
mat2[n][ n/2 ]:= -e^-1;
else
mat1[ (n-1)/2 ][ (n-1)/2 ]:= z;
mat1[ (n-1)/2+1 ][ (n-1)/2+1 ]:= z^q/z;
mat1[ (n-1)/2+2 ][ (n-1)/2+2 ]:= z^-q;
for i in [ 1 .. (n-1)/2-1 ] do mat2[ i ][ i+1 ]:= o; od;
for i in [ (n-1)/2+3 .. n ] do mat2[ i ][ i-1 ]:= o; od;
mat2[(n-1)/2][ 1 ]:= -(1+z^q/z)^-1;
mat2[(n-1)/2][(n-1)/2+1]:= -o;
mat2[(n-1)/2][ n ]:= o;
mat2[(n-1)/2+1][ 1 ]:= -o;
mat2[(n-1)/2+1][(n-1)/2+1]:= -o;
mat2[(n-1)/2+2][ 1 ]:= o;
fi;
fi;
mat1:=ImmutableMatrix(f,mat1,true);
mat2:=ImmutableMatrix(f,mat2,true);
# Avoid to call 'Group' because this would check invertibility ...
g:= GroupWithGenerators( [ mat1, mat2 ] );
SetName( g, Concatenation("SU(",String(n),",",String(q),")") );
SetDimensionOfMatrixGroup( g, Length( mat1 ) );
SetFieldOfMatrixGroup( g, f );
# Add the size.
size := 1;
qi := q;
eps := 1;
for i in [ 2 .. n ] do
qi := qi * q;
eps := -eps;
size := size * (qi+eps);
od;
SetSize( g, q^(n*(n-1)/2) * size );
# construct the form
c := Reversed( One( g ) );
SetInvariantSesquilinearForm( g,
rec( matrix:= ImmutableMatrix( f, c, true ) ) );
SetIsFullSubgroupGLorSLRespectingSesquilinearForm(g,true);
SetIsSubgroupSL(g,true);
# Return the group.
return g;
end );
#############################################################################
##
#F EichlerTransformation( <g>, <u>, <x> ) . . eichler trans of <u> and <x>
##
BindGlobal( "EichlerTransformation", function( g, u, x )
local e, b, i;
# construct matrix of eichler transformation in <e>
e := [];
# loop over the standard vectors
for b in One( g ) do
i := b
+ (b*InvariantBilinearForm(g).matrix*x)*u
- (b*InvariantBilinearForm(g).matrix*u)*x
- (b*InvariantBilinearForm(g).matrix*u)
*((x*InvariantQuadraticForm( g ) )*x)*u;
Add( e, i );
od;
# and return
return e;
end );
#############################################################################
##
#F Oplus45() . . . . . . . . . . . . . . . . . . . . . . . . . . . . O+_4(5)
##
BindGlobal( "Oplus45", function()
local f, id, tau2, tau, phi, delta, eichler, g;
# identity matrix over <f>
f := GF(5);
id := Immutable( IdentityMat( 4, f ) );
# construct TAU2: tau(x1-x2)
tau2 := List( 0*id, ShallowCopy );
tau2[1][1] := One( f );
tau2[2][2] := One( f );
tau2[3][4] := One( f );
tau2[4][3] := One( f );
# construct TAU: tau(x1+x2)
tau := List( 0*id, ShallowCopy );
tau[1][1] := One( f );
tau[2][2] := One( f );
tau[3][4] := -One( f );
tau[4][3] := -One( f );
# construct PHI: phi(2)
phi := List( id, ShallowCopy );
phi[1][1] := 2*One( f );
phi[2][2] := 3*One( f );
# construct DELTA: u <-> v
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct eichler transformation
eichler := [[1,0,0,0],[-1,1,-1,0],[2,0,1,0],[0,0,0,1]]*One( f );
# construct the group without calling 'Group'
g := [ phi*tau2, tau*eichler*delta ];
g:=List(g,i->ImmutableMatrix(f,i),true);
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, 4 );
SetFieldOfMatrixGroup( g, f );
# set the size
SetSize( g, 28800 );
# construct the form
SetInvariantBilinearForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[1,0,0,0],[0,0,2,0],[0,0,0,2]] * One( f ), true ) ) );
# and the quadratic form
SetInvariantQuadraticForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,1]] * One( f ), true ) ) );
# and return
return g;
end );
#############################################################################
##
#F Opm3( <s>, <d> ) . . . . . . . . . . . . . . . . . . . . . . O+-_<d>(3)
##
## <q> must be 3, <d> at least 6, beta is 2
##
BindGlobal( "Opm3", function( s, d )
local f, id, theta, i, theta2, phi, eichler, g, delta;
# identity matrix over <f>
f := GF(3);
id := Immutable( IdentityMat( d, f ) );
# construct DELTA: u <-> v, x -> x
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct THETA: x2 -> ... -> xk -> x2
theta := List( 0*id, ShallowCopy );
theta[1][1] := One( f );
theta[2][2] := One( f );
theta[3][3] := One( f );
for i in [ 4 .. d-1 ] do
theta[i][i+1] := One( f );
od;
theta[d][4] := One( f );
# construct THETA2: x2 -> x1 -> x3 -> x2
theta2 := List( id, ShallowCopy );
theta2{[3..5]}{[3..5]} := [[0,1,1],[-1,-1,1],[1,-1,1]]*One( f );
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := 2*One( f );
phi[2][2] := (2*One( f ))^-1;
# construct the eichler transformation
eichler := List( id, ShallowCopy );
eichler[2][1] := -One( f );
eichler[2][4] := -One( f );
eichler[4][1] := 2*One( f );
# construct the group without calling 'Group'
g := [ phi*theta2, theta*eichler*delta ];
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# construct the form
delta := List( 2*id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
delta[3][3] := 2*One( f )*2;
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# construct quadratic form
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f );
delta[3][3] := One( f )*2;
SetInvariantQuadraticForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# set the size
delta := 1;
theta := 1;
theta2 := 3^2;
for i in [ 1 .. d/2-1 ] do
theta := theta * theta2;
delta := delta * (theta-1);
od;
SetSize( g, 2*3^(d/2*(d/2-1))*(3^(d/2)-s)*delta );
return g;
end );
#############################################################################
##
#F OpmSmall( <s>, <d>, <q> ) . . . . . . . . . . . . . . . . . O+-_<d>(<q>)
##
## <q> must be 3 or 5, <d> at least 6, beta is 1
##
BindGlobal( "OpmSmall", function( s, d, q )
local f, id, theta, i, theta2, phi, eichler, g, delta;
# identity matrix over <f>
f := GF(q);
id := Immutable( IdentityMat( d, f ) );
# construct DELTA: u <-> v, x -> x
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct THETA: x2 -> ... -> xk -> x2
theta := List( 0*id, ShallowCopy );
theta[1][1] := One( f );
theta[2][2] := One( f );
theta[3][3] := One( f );
for i in [ 4 .. d-1 ] do
theta[i][i+1] := One( f );
od;
theta[d][4] := One( f );
# construct THETA2: x2 -> x1 -> x3 -> x2
theta2 := List( id, ShallowCopy );
theta2{[3..5]}{[3..5]} := [[0,0,1],[1,0,0],[0,1,0]]*One( f );
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := 2*One( f );
phi[2][2] := (2*One( f ))^-1;
# construct the eichler transformation
eichler := List( id, ShallowCopy );
eichler[2][1] := -One( f );
eichler[2][4] := -One( f );
eichler[4][1] := 2*One( f );
# construct the group without calling 'Group'
g := [ phi*theta2, theta*eichler*delta ];
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# construct the form
delta := List( 2*id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
delta[3][3] := 2*One( f );
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# construct quadratic form
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f );
delta[3][3] := One( f );
SetInvariantQuadraticForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# set the size
delta := 1;
theta := 1;
theta2 := q^2;
for i in [ 1 .. d/2-1 ] do
theta := theta * theta2;
delta := delta * (theta-1);
od;
SetSize( g, 2*q^(d/2*(d/2-1))*(q^(d/2)-s)*delta );
return g;
end );
#############################################################################
##
#F OpmOdd( <s>, <d>, <q> ) . . . . . . . . . . . . . . . . . . O<s>_<d>(<q>)
##
BindGlobal( "OpmOdd", function( s, d, q )
local f, w, beta, epsilon, id, eb1, tau, theta, i, phi,
delta, eichler, g;
# <d> must be at least 4
if d mod 2 = 1 then
Error( "<d> must be even" );
fi;
if d < 4 then
Error( "<d> must be at least 4" );
fi;
# beta is either 1 or a generator of the field
f := GF(q);
w := LogFFE( -1*2^(d-2)*One( f ), PrimitiveRoot( f ) ) mod 2 = 0;
beta := One( f );
if s = +1 and (d*(q-1)/4) mod 2 = 0 then
if not w then
beta := PrimitiveRoot( f );
fi;
elif s = +1 and (d*(q-1)/4) mod 2 = 1 then
if w then
beta := PrimitiveRoot( f );
fi;
elif s = -1 and (d*(q-1)/4) mod 2 = 1 then
if not w then
beta := PrimitiveRoot( f );
fi;
elif s = -1 and (d*(q-1)/4) mod 2 = 0 then
if w then
beta := PrimitiveRoot( f );
fi;
else
Error( "<s> must be -1 or +1" );
fi;
# special cases
if q = 3 and d = 4 and s = +1 then
g := GroupWithGenerators( [
[[1,0,0,0],[0,1,2,1],[2,0,2,0],[1,0,0,1]]*One( f ),
[[0,2,2,2],[0,1,1,2],[1,0,2,0],[1,2,2,0]]*One( f ) ] );
SetInvariantBilinearForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,2]]*One( f ), true ) ) );
SetInvariantQuadraticForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[0,0,0,0],[0,0,2,0],[0,0,0,1]]*One( f ), true ) ) );
SetSize( g, 1152 );
return g;
elif q = 3 and d = 4 and s = -1 then
g := GroupWithGenerators( [
[[0,2,0,0],[2,1,0,1],[0,2,0,1],[0,0,1,0]]*One( f ),
[[2,0,0,0],[1,2,0,2],[1,0,0,1],[0,0,1,0]]*One( f ) ] );
SetInvariantBilinearForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[1,0,0,0],[0,0,2,0],[0,0,0,2]]*One( f ), true ) ) );
SetInvariantQuadraticForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,1]]*One( f ), true ) ) );
SetSize( g, 1440 );
return g;
elif q = 5 and d = 4 and s = +1 then
return Oplus45();
elif ( q = 3 or q = 5 ) and 4 < d and beta = One( f ) then
return OpmSmall( s, d, q );
elif q = 3 and 4 < d and beta <> One( f ) then
return Opm3( s, d );
fi;
# find an epsilon such that (epsilon^2*beta)^2 <> 1
if beta = PrimitiveRoot( f ) then
epsilon := One( f );
else
epsilon := PrimitiveRoot( f );
fi;
# identity matrix over <f>
id := Immutable( IdentityMat( d, f ) );
# construct the reflection TAU_epsilon*x1+x2
eb1 := epsilon^2*beta+1;
tau := List( id, ShallowCopy );
tau[3][3] := 1-2*beta*epsilon^2/eb1;
tau[3][4] := -2*beta*epsilon/eb1;
tau[4][3] := -2*epsilon/eb1;
tau[4][4] := 1-2/eb1;
# construct THETA
theta := List( 0*id, ShallowCopy );
theta[1][1] := One( f );
theta[2][2] := One( f );
theta[3][3] := One( f );
for i in [ 4 .. d-1 ] do
theta[i][i+1] := One( f );
od;
theta[d][4] := -One( f );
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := PrimitiveRoot( f );
phi[2][2] := PrimitiveRoot( f )^-1;
# construct DELTA: u <-> v, x -> x
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct the eichler transformation
eichler := List( id, ShallowCopy );
eichler[2][1] := -One( f );
eichler[2][4] := -One( f );
eichler[4][1] := 2*One( f );
# construct the group without calling 'Group'
g := [ phi, theta*tau*eichler*delta ];
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# construct the form
delta := List( 2*id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
delta[3][3] := 2*beta;
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# construct quadratic form
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f );
delta[3][3] := beta;
SetInvariantQuadraticForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# set the size
delta := 1;
theta := 1;
tau := q^2;
for i in [ 1 .. d/2-1 ] do
theta := theta * tau;
delta := delta * (theta-1);
od;
SetSize( g, 2*q^(d/2*(d/2-1))*(q^(d/2)-s)*delta );
return g;
end );
#############################################################################
##
#F Oplus2( <q> ) . . . . . . . . . . . . . . . . . . . . . . . . . O+_2(<q>)
##
BindGlobal( "Oplus2", function( q )
local z, f, m1, m2, g;
# a field generator
z := Z(q);
f := GF(q);
# a matrix of order q-1
m1 := [ [ z, 0*z ], [ 0*z, z^-1 ] ];
# a matrix of order 2
m2 := [ [ 0, 1 ], [ 1, 0 ] ] * z^0;
m1:= ImmutableMatrix( f, m1, true );
m2:= ImmutableMatrix( f, m2, true );
# construct the group, set the order, and return
g := GroupWithGenerators( [ m1, m2 ] );
SetInvariantBilinearForm(g,
rec( matrix:= ImmutableMatrix( f, m2, true ) ) );
SetInvariantQuadraticForm( g, rec( matrix:= ImmutableMatrix( f,
[ [ 0, 1 ], [ 0, 0 ] ] * z^0, true ) ) );
SetSize( g, 2*(q-1) );
return g;
end );
#############################################################################
##
#F Oplus4Even( <q> ) . . . . . . . . . . . . . . . . . . . . . . . O+_4(<q>)
##
BindGlobal( "Oplus4Even", function( q )
local f, id, rho, delta, phi, eichler, g;
# <q> must be even
if q mod 2 = 1 then
Error( "<q> must be even" );
fi;
f := GF(q);
# identity matrix over <f>
id := Immutable( IdentityMat( 4, f ) );
# construct RHO: x1 <-> y1
rho := List( id, ShallowCopy );
rho{[3,4]}{[3,4]} := [[0,1],[1,0]] * One( f );
# construct DELTA: u <-> v
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := PrimitiveRoot( f );
phi[2][2] := PrimitiveRoot( f )^-1;
# construct eichler transformation
eichler := [[1,0,0,0],[0,1,-1,0],[0,0,1,0],[1,0,0,1]] * One( f );
# construct the group without calling 'Group'
g := [ phi*rho, rho*eichler*delta ];
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, 4 );
SetFieldOfMatrixGroup( g, f );
# set the size
SetSize( g, 2*q^2*(q^2-1)^2 );
# construct the form
SetInvariantBilinearForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]] * One( f ), true ) ) );
# and the quadratic form
SetInvariantQuadraticForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[0,0,0,0],[0,0,0,1],[0,0,0,0]] * One( f ), true ) ) );
# and return
return g;
end );
#############################################################################
##
#F OplusEven( <d>, <q> ) . . . . . . . . . . . . . . . . . . . . O+_<d>(<q>)
##
BindGlobal( "OplusEven", function( d, q )
local f, id, k, phi, delta, theta, i, delta2, eichler,
rho, g;
# <d> and <q> must be even
if d mod 2 = 1 then
Error( "<d> must be even" );
fi;
if d < 6 then
Error( "<d> must be at least 6" );
fi;
if q mod 2 = 1 then
Error( "<q> must be even" );
fi;
f := GF(q);
# identity matrix over <f>
id := Immutable( IdentityMat( d, f ) );
# V = H | H_1 | ... | H_k
k := (d-2) / 2;
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := PrimitiveRoot( f );
phi[2][2] := PrimitiveRoot( f )^-1;
# construct DELTA: u <-> v, x -> x
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct THETA: x_2 -> x_3 -> .. -> x_k -> y_2 -> .. -> y_k -> x_2
theta := List( 0*id, ShallowCopy );
for i in [ 1 .. 4 ] do
theta[i][i] := One( f );
od;
for i in [ 2 .. k-1 ] do
theta[1+2*i][3+2*i] := One( f );
theta[2+2*i][4+2*i] := One( f );
od;
theta[1+2*k][6] := One( f );
theta[2+2*k][5] := One( f );
# (k even) construct DELTA2: x_i <-> y_i, 1 <= i <= k-1
if k mod 2 = 0 then
delta2 := List( 0*id, ShallowCopy );
delta2{[1,2]}{[1,2]} := [[1,0],[0,1]] * One( f );
for i in [ 1 .. k ] do
delta2[1+2*i][2+2*i] := One( f );
delta2[2+2*i][1+2*i] := One( f );
od;
# (k odd) construct DELTA2: x_1 <-> y_1, x_i <-> x_i+1, y_i <-> y_i+1
else
delta2 := List( 0*id, ShallowCopy );
delta2{[1,2]}{[1,2]} := [[1,0],[0,1]] * One( f );
delta2{[3,4]}{[3,4]} := [[0,1],[1,0]] * One( f );
for i in [ 2, 4 .. k-1 ] do
delta2[1+2*i][3+2*i] := One( f );
delta2[3+2*i][1+2*i] := One( f );
delta2[2+2*i][4+2*i] := One( f );
delta2[4+2*i][2+2*i] := One( f );
od;
fi;
# construct eichler transformation
eichler := List( id, ShallowCopy );
eichler[4][6] := One( f );
eichler[5][3] := -One( f );
# construct RHO = THETA * EICHLER
rho := theta*eichler;
# construct second eichler transformation
eichler := List( id, ShallowCopy );
eichler[2][5] := -One( f );
eichler[6][1] := One( f );
# there seems to be something wrong in I/E for p=2
if k mod 2 = 0 then
if q = 2 then
g := [ phi*delta2, rho, eichler, delta ];
else
g := [ phi*delta2, rho*eichler*delta, delta ];
fi;
elif q = 2 then
g := [ phi*delta2, rho*eichler*delta, rho*delta ];
else
g := [ phi*delta2, rho*eichler*delta ];
fi;
# construct the group without calling 'Group'
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# construct the form
delta := List( 0*id, ShallowCopy );
for i in [ 1 .. d/2 ] do
delta[2*i-1][2*i] := One( f );
delta[2*i][2*i-1] := One( f );
od;
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# construct quadratic form
delta := List( 0*id, ShallowCopy );
for i in [ 1 .. d/2 ] do
delta[2*i-1][2*i] := One( f );
od;
SetInvariantQuadraticForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# set the size
delta := 1;
theta := 1;
rho := q^2;
for i in [ 1 .. d/2-1 ] do
theta := theta * rho;
delta := delta * (theta-1);
od;
SetSize( g, 2*q^(d/2*(d/2-1))*(q^(d/2)-1)*delta );
return g;
end );
#############################################################################
##
#F Ominus2( <q> ) . . . . . . . . . . . . . . . . . . . . . . . . O-_2(<q>)
##
BindGlobal( "Ominus2", function( q )
local z, f, R, x, t, n, e, bc, m2, m1, g;
# construct the root
z := Z(q);
# find $x^2+x+t$ that is irreducible over GF(`q')
f:= GF( q );
R:= PolynomialRing( f );
x:= Indeterminate( f );
t:= z^First( [ 0 .. q-2 ], u -> Length( Factors( R, x^2+x+z^u ) ) = 1 );
# get roots in GF(q^2)
n := List( Factors( PolynomialRing( GF( q^2 ) ), x^2+x+t ),
x -> - CoefficientsOfLaurentPolynomial( x )[1][1] );
e := 4*t-1;
# construct base change
bc := [ [ n[1]/e, 1/e ], [ n[2], z^0 ] ];
# matrix of order 2
m2 := [ [ -1, 0 ], [ -1, 1 ] ] * z^0;
# matrix of order q+1 (this will lie in $GF(q)^{d \times d}$)
z := Z(q^2)^(q-1);
m1 := bc^-1 * [[z,0*z],[0*z,z^-1]] * bc;
# and return the group
m1:=ImmutableMatrix(GF(q),m1,true);
m2:=ImmutableMatrix(GF(q),m2,true);
g := GroupWithGenerators( [ m1, m2 ] );
SetInvariantBilinearForm( g, rec( matrix:= ImmutableMatrix( f,
[ [ 2, 1 ], [ 1, 2*t ] ] * z^0, true ) ) );
SetInvariantQuadraticForm( g, rec( matrix:= ImmutableMatrix( f,
[ [ 1, 1 ], [ 0, t ] ] * z^0, true ) ) );
SetSize( g, 2*(q+1) );
return g;
end );
#############################################################################
##
#F Ominus4Even( <q> ) . . . . . . . . . . . . . . . . . . . . . . O-_4(<q>)
##
BindGlobal( "Ominus4Even", function( q )
local f, id, rho, delta, phi, R, x, t, eichler, g;
# <q> must be even
if q mod 2 = 1 then
Error( "<q> must be even" );
fi;
f := GF(q);
# identity matrix over <f>
id := Immutable( IdentityMat( 4, f ) );
# construct RHO: x1 <-> y1
rho := List( id, ShallowCopy );
rho{[3,4]}{[3,4]} := [[0,1],[1,0]] * One( f );
# construct DELTA: u <-> v
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := PrimitiveRoot( f );
phi[2][2] := PrimitiveRoot( f )^-1;
# find x^2+x+t that is irreducible over <f>
R:= PolynomialRing( f, 1 );
x:= Indeterminate( f );
t:= First( [ 0 .. q-2 ],
u -> Length( Factors( R, x^2+x+PrimitiveRoot( f )^u ) ) = 1 );
# compute square root of <t>
t := t/2 mod (q-1);
t := PrimitiveRoot( f )^t;
# construct eichler transformation
eichler := [[1,0,0,0],[-t,1,-1,0],[0,0,1,0],[1,0,0,1]] * One( f );
# construct the group without calling 'Group'
g := [ phi*rho, rho*eichler*delta ];
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, 4 );
SetFieldOfMatrixGroup( g, f );
# set the size
SetSize( g, 2*q^2*(q^2+1)*(q^2-1) );
# construct the form
SetInvariantBilinearForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]] * One( f ), true ) ) );
# and the quadratic form
SetInvariantQuadraticForm( g, rec( matrix:= ImmutableMatrix( f,
[[0,1,0,0],[0,0,0,0],[0,0,t,1],[0,0,0,t]] * One( f ), true ) ) );
# and return
return g;
end );
#############################################################################
##
#F OminusEven( <d>, <q> ) . . . . . . . . . . . . . . . . . . . O-_<d>(<q>)
##
BindGlobal( "OminusEven", function( d, q )
local f, id, k, phi, delta, theta, i, delta2, eichler, rho, g, t, R, x;
# <d> and <q> must be odd
if d mod 2 = 1 then
Error( "<d> must be even" );
elif d < 6 then
Error( "<d> must be at least 6" );
elif q mod 2 = 1 then
Error( "<q> must be even" );
fi;
f := GF(q);
# identity matrix over <f>
id := Immutable( IdentityMat( d, f ) );
# V = H | H_1 | ... | H_k
k := (d-2) / 2;
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := PrimitiveRoot( f );
phi[2][2] := PrimitiveRoot( f )^-1;
# construct DELTA: u <-> v, x -> x
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct THETA: x_2 -> x_3 -> .. -> x_k -> y_2 -> .. -> y_k -> x_2
theta := List( 0*id, ShallowCopy );
for i in [ 1 .. 4 ] do
theta[i][i] := One( f );
od;
for i in [ 2 .. k-1 ] do
theta[1+2*i][3+2*i] := One( f );
theta[2+2*i][4+2*i] := One( f );
od;
theta[1+2*k][6] := One( f );
theta[2+2*k][5] := One( f );
# (k even) construct DELTA2: x_i <-> y_i, 1 <= i <= k-1
if k mod 2 = 0 then
delta2 := List( 0*id, ShallowCopy );
delta2{[1,2]}{[1,2]} := [[1,0],[0,1]] * One( f );
for i in [ 1 .. k ] do
delta2[1+2*i][2+2*i] := One( f );
delta2[2+2*i][1+2*i] := One( f );
od;
# (k odd) construct DELTA2: x_1 <-> y_1, x_i <-> x_i+1, y_i <-> y_i+1
else
delta2 := List( 0*id, ShallowCopy );
delta2{[1,2]}{[1,2]} := [[1,0],[0,1]] * One( f );
delta2{[3,4]}{[3,4]} := [[0,1],[1,0]] * One( f );
for i in [ 2, 4 .. k-1 ] do
delta2[1+2*i][3+2*i] := One( f );
delta2[3+2*i][1+2*i] := One( f );
delta2[2+2*i][4+2*i] := One( f );
delta2[4+2*i][2+2*i] := One( f );
od;
fi;
# find x^2+x+t that is irreducible over GF(`q')
R:= PolynomialRing( f );
x:= Indeterminate( f );
t:= First( [ 0 .. q-2 ],
u -> Length( Factors( R, x^2+x+PrimitiveRoot( f )^u ) ) = 1 );
# compute square root of <t>
t := t/2 mod (q-1);
t := PrimitiveRoot( f )^t;
# construct Eichler transformation
eichler := List( id, ShallowCopy );
eichler[4][6] := One( f );
eichler[5][3] := -One( f );
eichler[5][6] := -t;
# construct RHO = THETA * EICHLER
rho := theta*eichler;
# construct second eichler transformation
eichler := List( id, ShallowCopy );
eichler[2][5] := -One( f );
eichler[6][1] := One( f );
# there seems to be something wrong in I/E for p=2
if k mod 2 = 0 then
if q = 2 then
g := [ phi*delta2, rho, eichler, delta ];
else
g := [ phi*delta2, rho*eichler*delta, delta ];
fi;
elif q = 2 then
g := [ phi*delta2, rho*eichler*delta, rho*delta ];
else
g := [ phi*delta2, rho*eichler*delta ];
fi;
# construct the group without calling 'Group'
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# construct the form
delta := List( 0*id, ShallowCopy );
for i in [ 1 .. d/2 ] do
delta[2*i-1][2*i] := One( f );
delta[2*i][2*i-1] := One( f );
od;
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# construct quadratic form
delta := List( 0*id, ShallowCopy );
for i in [ 1 .. d/2 ] do
delta[2*i-1][2*i] := One( f );
od;
delta[3][3] := t;
delta[4][4] := t;
SetInvariantQuadraticForm( g,
rec( matrix:= ImmutableMatrix( f, delta, true ) ) );
# set the size
delta := 1;
theta := 1;
rho := q^2;
for i in [ 1 .. d/2-1 ] do
theta := theta * rho;
delta := delta * (theta-1);
od;
SetSize( g, 2*q^(d/2*(d/2-1))*(q^(d/2)+1)*delta );
return g;
end );
#############################################################################
##
#F OzeroOdd( <d>, <q>, <b> ) . . . . . . . . . . . . . . . . . . O0_<d>(<q>)
##
## 'OzeroOdd' construct the orthogonal group in odd dimension and odd
## characteristic. The discriminant of the quadratic form is -(2<b>)^(<d>-2)
##
BindGlobal( "OzeroOdd", function( d, q, b )
local id, phi, delta, rho, i, eichler, g, s, f, q2, q2i;
# <d> and <q> must be odd
if d mod 2 = 0 then
Error( "<d> must be odd" );
elif d < 3 then
Error( "<d> must be at least 3" );
elif q mod 2 = 0 then
Error( "<q> must be odd" );
fi;
f := GF(q);
# identity matrix over <f>
id := Immutable( IdentityMat( d, f ) );
# construct PHI: u -> au, v -> a^-1v, x -> x
phi := List( id, ShallowCopy );
phi[1][1] := PrimitiveRoot( f );
phi[2][2] := PrimitiveRoot( f )^-1;
# construct DELTA: u <-> v, x -> x
delta := List( id, ShallowCopy );
delta{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
# construct RHO: u -> u, v -> v, x_i -> x_i+1
rho := List( 0*id, ShallowCopy );
rho[1][1] := One( f );
rho[2][2] := One( f );
for i in [ 3 .. d-1 ] do
rho[i][i+1] := One( f );
od;
rho[d][3] := One( f );
# construct eichler transformation
eichler := List( id, ShallowCopy );
eichler{[1..3]}{[1..3]} := [[1,0,0],[-b,1,-1],[2*b,0,1]] * One( f );
# construct the group without calling 'Group'
g := [ phi, rho*eichler*delta ];
g:=List(g,i->ImmutableMatrix(f,i,true));
g := GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# and set its size
s := 1;
q2 := q^2;
q2i := 1;
for i in [ 1 .. (d-1)/2 ] do
q2i := q2 * q2i;
s := s * (q2i-1);
od;
SetSize( g, 2 * q^((d-1)^2/4) * s );
# construct the form
s := List( 2*b*id, ShallowCopy );
s{[1,2]}{[1,2]} := [[0,1],[1,0]]*One( f );
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, s, true ) ) );
# and the quadratic form
s := List( b*id, ShallowCopy );
s{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f );
SetInvariantQuadraticForm( g,
rec( matrix:= ImmutableMatrix( f, s, true ) ) );
# and return
return g;
end );
#############################################################################
##
#F OzeroEven( <d>, <q> ) . . . . . . . . . . . . . . . . . . . . O0_<d>(<q>)
##
## 'OzeroEven' constructs the orthogonal group in odd dimension and even
## characteristic.
## The generators are constructed via the isomorphism with the symplectic
## group in dimension $<d>-1$ over the field with <q> elements.
##
## Removing the first row and the first column from the matrices defines the
## isomorphism to the symplectic group.
## This group is *not* equal to the symplectic group constructed with the
## function `Sp',
## since the bilinear form of the orthogonal group is the one used in the
## book of Carter and not the one used for `SP'.
## (Note that our matrices are transposed, relative to the ones given by
## Carter, because the group shall act on a *row* space.)
##
## The generators of the orthogonal groups can be computed as those matrices
## that project onto the generators of the symplectic group and satisfy the
## quadratic form
## $f(x) = x_0^2 + x_1 x_{-1} + x_2 x_{-2} + \cdots + x_l x_{-l}$.
## This condition results in a quadratic equation system that can be
## interpreted as a linear equation system because taking square roots is
## one-to-one in characteristic $2$.
##
BindGlobal( "OzeroEven", function( d, q )
local f, z, o, n, mat1, mat2, i, g, size, qi, c, s;
# <d> must be odd, <q> must be even
if d mod 2 = 0 then
Error( "<d> must be odd" );
elif d < 3 then
Error( "<d> must be at least 3" );
elif q mod 2 = 1 then
Error( "<q> must be even" );
fi;
f:= GF(q);
z:= PrimitiveRoot( f );
o:= One( f );
n:= Zero( f );
if d = 3 then
# The isomorphic symplectic group is $SL(2,<q>)$.
if q = 2 then
mat1:= ImmutableMatrix( f, [ [o,n,n], [o,o,o], [n,n,o] ],true );
mat2:= ImmutableMatrix( f, [ [o,n,n], [n,n,o], [n,o,n] ],true );
else
mat1:= ImmutableMatrix( f, [ [o,n,n], [n,z,n], [n,n,z^-1] ],true );
mat2:= ImmutableMatrix( f, [ [o,n,n], [o,o,o], [n,o,n] ],true );
fi;
elif d = 5 and q = 2 then
# The isomorphic symplectic group is $SP(4,2)$.
mat1:= ImmutableMatrix( f, [ [o,n,n,n,n], [o,n,o,n,o], [o,n,o,o,o],
[n,o,n,n,o], [n,o,o,o,o] ],true );
mat2:= ImmutableMatrix( f, [ [o,n,n,n,n], [n,n,o,n,n], [n,n,n,o,n],
[n,n,n,n,o], [n,o,n,n,n] ],true );
else
mat1:= IdentityMat( d, f );
mat2:= List( 0 * mat1, ShallowCopy );
mat2[1][1]:= o;
mat2[d][2]:= o;
for i in [ 2 .. d-1 ] do
mat2[i][i+1]:= o;
od;
if q = 2 then
mat1[(d+1)/2][ 1]:= o;
mat1[(d+1)/2][ 2]:= o;
mat1[(d+1)/2][ d]:= o;
mat1[(d+3)/2][ d]:= o;
else
mat1[ 2][ 2]:= z;
mat1[(d+1)/2][(d+1)/2]:= z;
mat1[(d+3)/2][(d+3)/2]:= z^-1;
mat1[ d][ d]:= z^-1;
mat2[(d+1)/2][ 1]:= o;
mat2[(d+1)/2][ 2]:= o;
mat2[(d+1)/2][ 3]:= o;
mat2[(d+3)/2][ 2]:= o;
fi;
fi;
mat1:= ImmutableMatrix( f, mat1,true );
mat2:= ImmutableMatrix( f, mat2,true );
# avoid to call 'Group' because this would check invertibility ...
g:= GroupWithGenerators( [ mat1, mat2 ] );
SetDimensionOfMatrixGroup( g, Length( mat1 ) );
SetFieldOfMatrixGroup( g, f );
# add the size
size := 1;
qi := 1;
for i in [ 1 .. (d-1)/2 ] do
qi := qi * q^2;
size := size * (qi-1);
od;
SetSize( g, q^(((d-1)/2)^2) * size );
# construct the form
c := List( 0 * One( g ), ShallowCopy );
for i in [ 2 .. (d+1)/2 ] do
c[(d-1)/2+i][i] := o;
c[i][(d-1)/2+i] := o;
od;
SetInvariantBilinearForm( g,
rec( matrix:= ImmutableMatrix( f, c, true ) ) );
SetIsSubgroupSL( g, true );
# and the quadratic form
s := List( 0 * One( g ), ShallowCopy );
s[1][1]:= o;
for i in [ 2 .. (d+1)/2 ] do
s[(d-1)/2+i][i]:= o;
od;
SetInvariantQuadraticForm( g,
rec( matrix:= ImmutableMatrix( f, s, true ) ) );
# and return
return g;
end );
#############################################################################
##
#M GeneralOrthogonalGroupCons( <e>, <d>, <q> ) . . . . . . . GO<e>_<d>(<q>)
##
InstallMethod( GeneralOrthogonalGroupCons,
"matrix group for <e>, dimension, and finite field size",
[ IsMatrixGroup and IsFinite,
IsInt,
IsPosInt,
IsPosInt ],
function( filter, e, d, q )
local g, i;
# <e> must be -1, 0, +1
if e <> -1 and e <> 0 and e <> +1 then
Error( "sign <e> must be -1, 0, +1\n" );
fi;
# if <e> = 0 then <d> must be odd
if e = 0 and d mod 2 = 0 then
Error( "sign <e> = 0 but dimension <d> is even\n" );
# if <e> <> 0 then <d> must be even
elif e <> 0 and d mod 2 = 1 then
Error( "sign <e> <> 0 but dimension <d> is odd\n" );
fi;
# construct the various orthogonal groups
if e = 0 and q mod 2 <> 0 then
g := OzeroOdd( d, q, 1 );
elif e = 0 then
g := OzeroEven( d, q );
# O+(2,q) = D_2(q-1)
elif e = +1 and d = 2 then
g := Oplus2(q);
# if <d> = 4 and <q> even use 'Oplus4Even'
elif e = +1 and d = 4 and q mod 2 = 0 then
g := Oplus4Even(q);
# if <q> is even use 'OplusEven'
elif e = +1 and q mod 2 = 0 then
g := OplusEven( d, q );
# if <q> is odd use 'OpmOdd'
elif e = +1 and q mod 2 = 1 then
g := OpmOdd( +1, d, q );
# O-(2,q) = D_2(q+1)
elif e = -1 and d = 2 then
g := Ominus2(q);
# if <d> = 4 and <q> even use 'Ominus4Even'
elif e = -1 and d = 4 and q mod 2 = 0 then
g := Ominus4Even(q);
# if <q> is even use 'OminusEven'
elif e = -1 and q mod 2 = 0 then
g := OminusEven( d, q );
# if <q> is odd use 'OpmOdd'
elif e = -1 and q mod 2 = 1 then
g := OpmOdd( -1, d, q );
fi;
# set name
if e = +1 then i := "+"; else i := ""; fi;
SetName( g, Concatenation( "GO(", i, String(e), ",", String(d), ",",
String(q), ")" ) );
SetIsFullSubgroupGLorSLRespectingQuadraticForm( g, true );
if q mod 2 = 1 then
SetIsFullSubgroupGLorSLRespectingBilinearForm( g, true );
#T in which cases does characteristic 2 imply `false'?
fi;
# and return
return g;
end );
InstallMethod( GeneralOrthogonalGroupCons,
"matrix group for dimension and finite field",
[ IsMatrixGroup and IsFinite,
IsInt,
IsPosInt,
IsField and IsFinite ],
function(filt,sign,n,f)
return GeneralOrthogonalGroupCons(filt,sign,n,Size(f));
end);
#############################################################################
##
#M SpecialOrthogonalGroupCons( <e>, <d>, <q> ) . . . . . . . GO<e>_<d>(<q>)
##
## SO has index $1$ in GO if the characteristic is even
## and index $2$ if the characteristic is odd.
##
## In the latter case, the generators of GO are $a$ and $b$.
## When GO is constructed with `OzeroOdd', `Oplus2', and `Ominus2' then by
## construction $a$ has determinant $1$, and $b$ has determinant $-1$.
## The group $\langle a, b^{-1} a b, b^2 \rangle$ is therefore equal to SO.
## (Note that it is clearly contained in SO, and each word in terms of $a$
## and $b$ can be written as a word in terms of the three generators above
## or $b$ times such a word.)
## So the case `OpmOdd' is left, which deals with three exceptions
## $(s,d,q) \in \{ (1,4,3), (-1,4,3), (1,4,5) \}$, two series for small $q$
## (via `OpmSmall' and `Opm3'), and the generic remainder;
## exactly in the two of the three exceptional cases where $s = 1$ holds,
## the determinant of the first generator is $-1$; in these cases, the
## determinant of the second generator is $1$, so we get the generating set
## $\{ a^2, a^{-1} b a, b \}$.
##
InstallMethod( SpecialOrthogonalGroupCons,
"matrix group for <e>, dimension, and finite field size",
[ IsMatrixGroup and IsFinite,
IsInt,
IsPosInt,
IsPosInt ],
function( filter, e, d, q )
local G, gens, U, i;
G:= GeneralOrthogonalGroupCons( filter, e, d, q );
if q mod 2 = 1 then
# Deal with the special cases.
gens:= GeneratorsOfGroup( G );
if e = 1 and d = 4 and q in [ 3, 5 ] then
gens:= Reversed( gens );
fi;
Assert( 1, Length( gens ) = 2 and IsOne( DeterminantMat( gens[1] ) ) );
# Construct the group.
U:= GroupWithGenerators( [ gens[1], gens[1]^gens[2], gens[2]^2 ] );
# Set the group order.
SetSize( U, Size( G ) / 2 );
# Set the name.
if e = +1 then i := "+"; else i := ""; fi;
SetName( U, Concatenation( "SO(", i, String(e), ",", String(d), ",",
String(q), ")" ) );
# Set the invariant quadratic form and the symmetric bilinear form.
SetInvariantBilinearForm( U, InvariantBilinearForm( G ) );
SetInvariantQuadraticForm( U, InvariantQuadraticForm( G ) );
SetIsFullSubgroupGLorSLRespectingQuadraticForm( U, true );
if q mod 2 = 1 then
SetIsFullSubgroupGLorSLRespectingBilinearForm( U, true );
fi;
G:= U;
fi;
return G;
end );
InstallMethod( SpecialOrthogonalGroupCons,
"matrix group for dimension and finite field",
[ IsMatrixGroup and IsFinite,
IsInt,
IsPosInt,
IsField and IsFinite ],
function(filt,sign,n,f)
return SpecialOrthogonalGroupCons(filt,sign,n,Size(f));
end);
#############################################################################
##
#F WallForm( <form>, <m> ) . . . . . . . . . . . . . compute the wall of <m>
##
BindGlobal( "WallForm", function( form, m )
local id, w, b, p, i, x, j;
# first argument should really be something useful
id := One( m );
# compute a base for Image(id-m), use the most stupid algorithm
w := id - m;
b := [];
p := [];
for i in [ 1 .. Length(w) ] do
if Length(b) = 0 then
if w[i] <> 0*w[i] then
Add( b, w[i] );
Add( p, i );
fi;
elif RankMat(b) <> RankMat(Concatenation(b,[w[i]])) then
Add( b, w[i] );
Add( p, i );
fi;
od;
# compute the form
x := List( b, x -> [] );
for i in [ 1 .. Length(b) ] do
for j in [ 1 .. Length(b) ] do
x[i][j] := id[p[i]] * form * b[j];
od;
od;
# and return
return rec( base := b, pos := p, form := x );
end );
#############################################################################
##
#F SpinorNorm( <form>, <m> ) . . . . . . . . compute the spinor norm of <m>
##
BindGlobal( "SpinorNorm", function( form, m )
if IsOne(m) then return One(m[1][1]); fi;
return DeterminantMat( WallForm(form,m).form );
end );
#############################################################################
##
#F OmegaZero( <d>, <q> ) . . . . . . . . . . . . . . . . \Omega^0_{<d>}(<q>)
##
BindGlobal( "OmegaZero", function( d, q )
local f, o, m, mo, n, i, x1, x2, x, g, xi, h, s, q2, q2i;
# <d> must be odd
if d mod 2 = 0 then
Error( "<d> must be odd" );
elif d < 3 then
Error( "<d> must be at least 3" );
fi;
f:= GF(q);
o:= One( f );
m:= ( d-1 ) / 2;
if d = 5 and q = 2 then
# The matrices given in [RylandsTalor98] generate only A6 not S6.
# So we take the isomorphic group SO( 5, 2 ) instead.
return SO( 5, 2 );
elif 3 < d then
# Omega(0,d,q) for d=2m+1, m >= 2, Section 4.5
if d mod 4 = 3 then
mo:= -o; # (-1)^m
else
mo:= o;
fi;
n:= NullMat( d, d, f );
n[ m+2 ][1]:= mo;
n[m][d]:= mo;
n[ m+1 ][ m+1 ]:= -o;
for i in [ 1 .. m-1 ] do
n[i][i+1]:= o;
n[ d+1-i ][ d-i ]:= o;
od;
if q mod 2 = 0 then
# $x = x_{\epsilon_1 - \epsilon_m}(1) x_{-\alpha_1}(1)$
x1:= IdentityMat( d, f );
x1[1][m]:= o;
x1[ m+2 ][d]:= o;
x2:= IdentityMat( d, f );
x2[ m+1 ][m]:= o;
x2[ m+2 ][m]:= o;
x:= x1 * x2;
else
# $x = x_{\alpha_1}(1)$
x:= IdentityMat( d, f );
x[m][ m+1 ]:= 2*o;
x[ m+1 ][ m+2 ]:= -o;
x[m][ m+2 ]:= -o;
fi;
if q <= 3 then
# the matrices $x$ and $n$
g:= [ x, n ];
else
# the matrices $h$ and $x n$
xi:= Z(q);
h:= IdentityMat( d, f );
h[1][1]:= xi;
h[m][m]:= xi;
h[ m+2 ][ m+2 ]:= xi^-1;
h[d][d]:= xi^-1;
g:= [ h, x*n ];
fi;
else
# Omega(0,3,q), Section 4.6
if q <= 3 then
# the matrices $x$ and $n$
g:= [ [[1,0,0],[1,1,0],[-1,-2,1]],
[[0,0,-1],[0,-1,0],[-1,0,0]] ] * o;
else
# the matrices $n x$ and $h$
xi:= Z(q);
g:= [ [[1,2,-1],[-1,-1,0],[-1,0,0]],
[[xi^-2,0,0],[0,1,0],[0,0,xi^2]] ] * o;
fi;
fi;
# construct the group without calling 'Group'
g:= List( g, i -> ImmutableMatrix( f, i, true ) );
g:= GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# and set its size
s := 1;
q2 := q^2;
q2i:= 1;
for i in [ 1 .. m ] do
q2i:= q2 * q2i;
s := s * (q2i-1);
od;
if q mod 2 = 1 then
s:= s/2;
fi;
SetSize( g, q^(m^2) * s );
# construct the bilinear form
#T add the form!
# and the quadratic form
#T add the form!
# and return
return g;
end );
#############################################################################
##
#F OmegaPlus( <d>, <q> ) . . . . . . . . . . . . . . . . \Omega^-_{<d>}(<q>)
##
BindGlobal( "OmegaPlus", function( d, q )
local f, o, m, xi, g, a, mo, n, i, x1, x2, x, h, s, q2, q2i;
# <d> must be even
if d mod 2 = 1 then
Error( "<d> must be even" );
fi;
f:= GF(q);
o:= One( f );
m:= d / 2;
xi:= Z(q);
if m = 1 then
# Omega(+1,2,q), Section 4.4
g:= [ [[xi^2,0],[0,xi^-2]] ] * o;
elif m = 2 then
# Omega(+1,4,q), Section 4.3
xi:= Z(q^2)^(q-1);
a:= xi + xi^-1;
g:= [ [[0,-1,0,-1],[1,a,-1,a],[0,0,0,1],[0,0,-1,a]],
[[0,0,1,-1],[0,0,0,-1],[-1,-1,a,-a],[0,1,0,a]] ] * o;
else
# Omega(+1,d,q) for d=2m, Sections 4.1 and 4.2
if d mod 4 = 2 then
mo:= -o; # (-1)^m
else
mo:= o;
fi;
n:= NullMat( d, d, f );
n[ m+2 ][1]:= mo;
n[ m-1 ][d]:= mo;
n[m][ m+1 ]:= o;
n[ m+1 ][m]:= o;
for i in [ 1 .. m-2 ] do
n[i][ i+1 ]:= o;
n[ d+1-i ][ d-i ]:= o;
od;
if m mod 2 = 0 then
x1:= IdentityMat( d, f );
if q = 2 then
x1[ m-1 ][ m+1 ]:= -o;
x1[m][ m+2 ]:= o;
else
x1[ m+2 ][m]:= o;
x1[ m+1 ][ m-1 ]:= -o;
fi;
x2:= IdentityMat( d, f );
x2[ m-2 ][ m-1 ]:= o;
x2[ m+2 ][ m+3 ]:= -o;
x:= x1 * x2;
else
x:= IdentityMat( d, f );
x[ m-1 ][ m+1 ]:= -o;
x[m][ m+2 ]:= o;
fi;
if ( m mod 2 = 0 and q = 2 ) or ( m mod 2 = 1 and q <= 3 ) then
# the matrices $x$ and $n$
g:= [ x, n ];
else
# the matrices $h$ and $x n$
h:= IdentityMat( d, f );
h[ m-1 ][ m-1 ]:= xi;
h[ m+2 ][ m+2 ]:= xi^-1;
if m mod 2 = 0 then
h[ m ][ m ]:= xi^-1;
h[ m+1 ][ m+1 ]:= xi;
else
h[ m ][ m ]:= xi;
h[ m+1 ][ m+1 ]:= xi^-1;
fi;
g:= [ h, x*n ];
fi;
fi;
# construct the group without calling 'Group'
g:= List( g, i -> ImmutableMatrix( f, i, true ) );
g:= GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# and set its size
s := 1;
q2 := q^2;
q2i:= 1;
for i in [ 1 .. m-1 ] do
q2i:= q2 * q2i;
s := s * (q2i-1);
od;
if q mod 2 = 1 then
s:= s/2;
fi;
SetSize( g, q^(m*(m-1)) * (q^m-1) * s );
# construct the bilinear form
#T add the form!
# and the quadratic form
#T add the form!
# and return
return g;
end );
#############################################################################
##
#F OmegaMinus( <d>, <q> ) . . . . . . . . . . . . . . . \Omega^-_{<d>}(<q>)
##
BindGlobal( "OmegaMinus", function( d, q )
local f, o, m, xi, mo, nu, nubar, h, x, n, i, g, s,q2, q2i;
# <d> must be even
if d mod 2 = 1 then
Error( "<d> must be even" );
elif d < 4 then
# The construction in the paper does not apply to the case d = 2
Error( "<d> = 2 is not supported" );
fi;
f:= GF(q);
o:= One( f );
m:= d / 2 - 1;
xi:= Z(q);
if d mod 4 = 2 then
mo:= -o; # (-1)^(m-1)
else
mo:= o;
fi;
nu:= Z(q^2);
nubar:= nu^q;
h:= IdentityMat( d, f );
h[m][m]:= nu * nubar;
h[ m+3 ][ m+3 ]:= (nu * nubar)^-1;
h{ [ m+1 .. m+2 ] }{ [ m+1 .. m+2 ] }:= [
[-1,nu^-1 + nubar^-1],
[-nu-nubar, 1 + nu*nubar^-1 + nu^-1*nubar]] * o;
x:= IdentityMat( d, f );
x{ [ m .. m+3 ] }{ [ m .. m+3 ] }:= [[1,1,0,1],[0,1,0,2],
[0,0,1,nu+nubar],
[0,0,0,1]] * o;
n:= NullMat( d, d, f );
n[ m+3 ][1]:= mo;
n[m][d]:= mo;
n[ m+1 ][ m+1 ]:= -o;
n[ m+2 ][ m+1 ]:= -nu - nubar;
n[ m+2 ][ m+2 ]:= o;
for i in [ 1 .. m-1 ] do
n[i][ i+1 ]:= o;
n[ d+1-i ][ d-i ]:= o;
od;
g:= [ h, x*n ];
# construct the group without calling 'Group'
g:= List( g, i -> ImmutableMatrix( f, i, true ) );
g:= GroupWithGenerators( g );
SetDimensionOfMatrixGroup( g, d );
SetFieldOfMatrixGroup( g, f );
# and set its size
m:= d/2;
s := 1;
q2 := q^2;
q2i:= 1;
for i in [ 1 .. m-1 ] do
q2i:= q2 * q2i;
s := s * (q2i-1);
od;
if q mod 2 = 1 then
s:= s/2;
fi;
SetSize( g, q^(m*(m-1)) * (q^m+1) * s );
# construct the bilinear form
#T add the form!
# and the quadratic form
#T add the form!
# and return
return g;
end );
#############################################################################
##
#M OmegaCons( <filter>, <e>, <d>, <q> ) . . . . . . . . . orthogonal group
##
InstallMethod( OmegaCons,
"matrix group for <e>, dimension, and finite field size",
[ IsMatrixGroup and IsFinite,
IsInt,
IsPosInt,
IsPosInt ],
function( filter, e, d, q )
local g, i;
# if <e> = 0 then <d> must be odd
if e = 0 and d mod 2 = 0 then
Error( "sign <e> = 0 but dimension <d> is even\n" );
# if <e> <> 0 then <d> must be even
elif e <> 0 and d mod 2 = 1 then
Error( "sign <e> <> 0 but dimension <d> is odd\n" );
fi;
# construct the various orthogonal groups
if e = 0 then
g:= OmegaZero( d, q );
elif e = 1 then
g:= OmegaPlus( d, q );
elif e = -1 then
g:= OmegaMinus( d, q );
else
Error( "sign <e> must be -1, 0, +1" );
fi;
# set name
if e = +1 then i := "+"; else i := ""; fi;
SetName( g, Concatenation( "Omega(", i, String(e), ",", String(d), ",",
String(q), ")" ) );
# and return
return g;
end );
#############################################################################
##
#M Omega( [<filt>, ][<e>, ]<d>, <q> )
##
InstallMethod( Omega,
[ IsPosInt, IsPosInt ],
function( d, q )
return OmegaCons( IsMatrixGroup, 0, d, q );
end );
InstallMethod( Omega,
[ IsInt, IsPosInt, IsPosInt ],
function( e, d, q )
return OmegaCons( IsMatrixGroup, e, d, q );
end );
InstallMethod( Omega,
[ IsFunction, IsPosInt, IsPosInt ],
function( filt, d, q )
return OmegaCons( filt, 0, d, q );
end );
InstallMethod( Omega,
[ IsFunction, IsInt, IsPosInt, IsPosInt ],
OmegaCons );
#############################################################################
##
#F WreathProductOfMatrixGroup( <M>, <P> ) . . . . . . . . . wreath product
##
BindGlobal( "WreathProductOfMatrixGroup", function( M, P )
local m, d, id, gens, b, ran, raN, mat, gen, G;
m := DimensionOfMatrixGroup( M );
d := LargestMovedPoint( P );
id := IdentityMat( m * d, DefaultFieldOfMatrixGroup( M ) );
gens := [ ];
for b in [ 1 .. d ] do
ran := ( b - 1 ) * m + [ 1 .. m ];
for mat in GeneratorsOfGroup( M ) do
gen := StructuralCopy( id );
gen{ ran }{ ran } := mat;
Add( gens, gen );
od;
od;
for gen in GeneratorsOfGroup( P ) do
mat := StructuralCopy( id );
for b in [ 1 .. d ] do
ran := ( b - 1 ) * m + [ 1 .. m ];
raN := ( b^gen - 1 ) * m + [ 1 .. m ];
mat{ ran } := id{ raN };
od;
Add( gens, mat );
od;
G := GroupWithGenerators( gens );
if HasName( M ) and HasName( P ) then
SetName( G, Concatenation( Name( M ), " wr ", Name( P ) ) );
fi;
return G;
end );
#############################################################################
##
#F TensorWreathProductOfMatrixGroup( <M>, <P> ) . . . tensor wreath product
##
BindGlobal( "TensorWreathProductOfMatrixGroup", function( M, P )
local m, n, one, id, a, gens, b, ran, mat, gen, list,
p, q, adic, i, G;
m := DimensionOfMatrixGroup( M );
one := One( FieldOfMatrixGroup( M ) );
a := LargestMovedPoint( P );
n := m ^ a;
id := Immutable( IdentityMat( n, one ) );
gens := [ ];
for b in [ 1 .. a ] do
for mat in GeneratorsOfGroup( M ) do
gen := KroneckerProduct
( IdentityMat( m ^ ( b - 1 ), one ), mat );
gen := KroneckerProduct
( gen, IdentityMat( m ^ ( a - b ), one ) );
Add( gens, gen );
od;
od;
for gen in GeneratorsOfGroup( SymmetricGroup( a ) ) do
list := [ ];
for p in [ 0 .. n - 1 ] do
adic := [ ];
for i in [ 0 .. a - 1 ] do
adic[ ( a - i ) ^ gen ] := p mod m;
p := QuoInt( p, m );
od;
q := 0;
for i in adic do
q := q * m + i;
od;
Add( list, q );
od;
Add( gens, id{ list + 1 } );
od;
G := GroupWithGenerators( gens );
if HasName( M ) and HasName( P ) then
SetName( G, Concatenation( Name( M ), " twr ", Name( P ) ) );
fi;
return G;
end );
#############################################################################
##
#F CentralProductOfMatrixGroups( <M>, <N> ) . . . . . . . . central product
##
BindGlobal( "CentralProductOfMatrixGroups", function( M, N )
local gens, id, mat, G;
gens := [ ];
id := One( N );
for mat in GeneratorsOfGroup( M ) do
Add( gens, KroneckerProduct( mat, id ) );
od;
id := One( M );
for mat in GeneratorsOfGroup( N ) do
Add( gens, KroneckerProduct( id, mat ) );
od;
G := GroupWithGenerators( gens );
if HasName( M ) and HasName( N ) then
SetName( G, Concatenation( Name( M ), " o ", Name( N ) ) );
fi;
return G;
end );
# Permutation constructors by using `IsomorphismPermGroup'
PermConstructor(GeneralLinearGroupCons,[IsPermGroup,IsInt,IsObject],
IsMatrixGroup and IsFinite);
PermConstructor(GeneralOrthogonalGroupCons,[IsPermGroup,IsInt,IsInt,IsObject],
IsMatrixGroup and IsFinite);
PermConstructor(GeneralUnitaryGroupCons,[IsPermGroup,IsInt,IsObject],
IsMatrixGroup and IsFinite);
PermConstructor(SpecialLinearGroupCons,[IsPermGroup,IsInt,IsObject],
IsMatrixGroup and IsFinite);
PermConstructor(SpecialOrthogonalGroupCons,[IsPermGroup,IsInt,IsInt,IsObject],
IsMatrixGroup and IsFinite);
PermConstructor(SpecialUnitaryGroupCons,[IsPermGroup,IsInt,IsObject],
IsMatrixGroup and IsFinite);
PermConstructor(SymplecticGroupCons,[IsPermGroup,IsInt,IsObject],
IsMatrixGroup and IsFinite);
PermConstructor(OmegaCons,[IsPermGroup,IsInt,IsObject],
IsMatrixGroup and IsFinite);
#############################################################################
##
#E