############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Lukas Maas, Jack Schmidt. ## ## Copyright of GAP belongs to its developers, whose names are too numerous ## to list here. Please refer to the COPYRIGHT file for details. ## ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file contains the implementation for Schur covers of symmetric and ## alternating groups on Coxeter or standard generators. ##
############################################################################# ## ## Faithful, irreducible representations of minimal degree of the double ## covers of symmetric groups can be constructed inductively using the ## methods of https://arxiv.org/abs/0911.3794 ## ## The inductive formulation uses a number of helper routines which are ## wrapped inside a function call to keep from declaring a large number ## of (private) global variables. ##
## let 2S+(n) = < t_1, ..., t_(n-1) > subject to the relations ## (t_i)^2 = z for 1 <= i <= n-1, ## z^2 = 1, ## ( t_i*t_(i+1) )^3 = z for 1 <= i <= n-2, ## t_i*t_j = z*t_j*t_i for 1 <= i, j <= n-1 with | i - j | > 1. ## ## The following functions allow the construction of basic spin ## representations of 2S+(n) over fields of any characteristic.
## SpinDimSym ## IN integers n >= 4, p >= 0 ## OUT the degree of a basic spin repr. of 2S(n) over a field of ## characteristic p
SpinDimSym:= function( n, p )
local r;
r:= n mod 2; if r = 0then
return 2^((n-2)/2); elif p = 0then
return 2^((n-1)/2); elif r = 1 and n mod p = 0then
return 2^((n-3)/2); else
return 2^((n-1)/2); fi; end;
## SanityCheckPos ## IN A record containing the matrices in T, the degree of the symmetric ## group n, and the characteristic f the field p ## OUT true if the matrices in T are the right size, over the right field, and ## satisfy the presentation for 2S(n) given above. Also checks the ## components Sym and Alt if present.
SanityCheckPos := function( input )
local i, j;
if input.n <> Length( input.T ) + 1then
Print("#I SanityCheckPos: Wrong degree: ",input.n," vs. ",Length(input.T)+1,"\n");
return false; fi;
if input.p <> Characteristic( input.T[1] ) then
Print("#I SanityCheckPos: Wrong characteristic: ",input.p," vs. ",Characteristic(input.T[1]),"\n");
return false; fi;
if SpinDimSym( input.n, input.p ) <> Length( input.T[1] ) then
Print( "#I SanityCheckPos: Wrong degree: ",SpinDimSym( input.n, input.p )," vs. ",Length( input.T[1] ),"\n" );
return false; fi;
if not ForAll( input.T, mat -> Size(mat) = Size(mat[1]) and Size(mat)=Size(input.T[1])) then
Print("#I SanityCheckPos: Matrices not all same size\n");
return false; fi;
for i in [ 1 .. input.n-1 ] do if not IsOne(-input.T[i]^2) then
Print( "#I SanityCheckPos: Wrong order for T[",i,"]\n");
return false; fi;
od; for i in [ 1 .. input.n-2 ] do if not IsOne( -( input.T[i]*input.T[i+1] )^3 ) then
Print( "#I SanityCheckPos: Braid relation failed at position ", i, "\n" );
return false; fi; for j in [ i+2 .. input.n-1 ] do if not IsOne( - ( input.T[i]*input.T[j] )^2 ) then
Print( "#I SanityCheckPos: Commutator relation failed for ( ", i, ", ", j ," )\n" );
return false; fi;
od;
od;
if IsBound( input.Sym ) then if not input.Sym[1] = Product( Reversed( input.T ) ) then
Print( "SanityCheckPos: Wrong Sym[1]\n" );
return false; fi;
if not input.Sym[2] = input.T[1] then
Print( "SanityCheckPos: Wrong Sym[2]\n" );
return false; fi; fi;
if IsBound( input.Alt ) then if not input.Alt[1] = Product( Reversed( input.T{[1..2*Int((input.n-1)/2)]} ) ) then
Print( "SanityCheckPos: Wrong Alt[1]\n" );
return false; fi;
if not input.Alt[2] = input.T[input.n-1]*input.T[input.n-2] then
Print( "SanityCheckPos: Wrong Alt[2]\n" );
return false; fi; fi;
return true; end;
## SanityCheckNeg ## IN A record containing the matrices in T, the degree of the symmetric ## group n, and the characteristic f the field p ## OUT true if the matrices in T are the right size, over the right field, and ## satisfy the presentation for 2S-(n) given above. Also checks the ## components Sym and Alt if present.
SanityCheckNeg := function( S, p )
local d, deg, i, j;
d:= Length( S );
deg:= Length( S[1] ); if SpinDimSym( d+1, p ) <> deg then
Print( "#I SanityCheckNeg: wrong degree!\n" );
return false; fi; #Print( "#I SanityCheckNeg: degree: ", deg , "\n" ); for i in [ 1 .. d ] do if not IsOne( S[i]^2 ) then
Print( "#I SanityCheckNeg: order failed at position ", i, "\n" );
return false; fi;
od; for i in [ 1 .. d-1 ] do if not IsOne( ( S[i]*S[i+1] )^3 ) then
Print( "#I SanityCheckNeg: braid relation failed at position ", i, "\n" );
return false; fi; for j in [ i+2 .. d ] do if S[i]*S[j] <> -S[j]*S[i] then
Print( "#I SanityCheckNeg: commuting relation failed for ( ", i, ", ", j ," )\n" );
return false; fi;
od;
od; #Print( "#I SanityCheckNeg: all relations satisfied\n" );
return true; end;
## bmat -- blck matrix maker ## IN the blocks a,b,c,d of the matrix [[a,b],[c,d]] ## OUT a normal matrix with the same entries as the corresponding block ## matrix.
bmat := function(a,b,c,d)
local mat;
mat := DirectSumMat( a, d ); if b <> 0then mat{[1..Length(a)]}{[1+Length(a[1])..Length(mat[1])]} := b; fi; if c <> 0then mat{[1+Length(a)..Length(mat)]}{[1..Length(a[1])]} := c; fi;
return mat; end;
## construction S of Definition 4 / Lemma 5 ## IN an input record with n,p,T and optionally Sym and/or Alt, ## where n,p satisfy the hypothesis of Def 4 / Lemma 5 ## OUT the same, but for 2S(n+1)
S:= function( old )
local new, I, z, i;
#Print("S from ",old.n," to ",new.n,"\n");
new := rec( n := old.n+1, p:=old.p, T:=[] );
for i in [ 1 .. new.n-3 ] do
new.T[i] := DirectSumMat( old.T[i], -old.T[i] );
od;
I := old.T[1]^0;
z := 0*old.T[1];
new.T[new.n-2] := bmat( old.T[new.n-2], -I, 0, -old.T[new.n-2] );
new.T[new.n-1] := bmat( z, I, -I, z );
if IsBound( old.Sym ) then
new.Sym := []; if new.n < 5 then new.Sym[1] := Product(Reversed(new.T)); else new.Sym[1] := bmat( 0*old.Sym[1], (-1)^new.n*old.Sym[1], -old.Sym[1], (-1)^new.n*old.T[new.n-2]*old.Sym[1] ); fi;
new.Sym[2] := new.T[1]; fi;
if IsBound( old.Alt ) then
new.Alt := []; if IsOddInt(new.n) then new.Alt[1] := new.Sym[1]; else new.Alt[1] := -new.T[new.n-1]*new.Sym[1]; fi;
new.Alt[2] := new.T[new.n-1]*new.T[new.n-2]; fi;
Assert( 1, SanityCheckPos( new ) );
return new; end;
## construction S1 of Lemma 7 ## IN an input record with n,p,T and optionally Sym and/or Alt, ## where n,p satisfy the hypothesis of Lemma 7 ## OUT the same, but for 2S(n+1)
S1:= function( old )
local new, J;
#Print("S1 from ",old.n," to ",new.n,"\n");
new := rec( n := old.n + 1, p := old.p, T := ShallowCopy( old.T ) );
J := Sum( [1..new.n-2], k -> k*old.T[k] ); if new.p = 2 and 2 = new.n mod 4then
new.T[new.n-1] := J + J^0; else
new.T[new.n-1] := J; fi;
if IsBound( old.Sym ) then
new.Sym := [];
new.Sym[1] := new.T[new.n-1]*old.Sym[1];
new.Sym[2] := old.Sym[2]; fi;
if IsBound( old.Alt ) then
new.Alt := []; if IsOddInt(new.n) then new.Alt[1] := new.Sym[1]; else new.Alt[1] := old.Alt[1]; fi;
new.Alt[2] := new.T[new.n-1]*new.T[new.n-2]; fi;
Assert( 1, SanityCheckPos( new ) );
return new; end;
## return alpha ( = alpha^+ ) and beta as in Lemma 10 ## here n(n-1)(n-2) must not be divisible by p
coeffS2:= function( n, p )
local one, a, b, c, alpha; if p = 0then
c:= n-2;
alpha:= (n-1)^-1*( 1 + Sqrt( -n*c^-1 ) ); else
one:= Z( p )^0;
c:= (n-2) mod p;
a:= -n*c^-1 mod p;
a:= LogFFE( a*one, Z(p^2) ) / 2;
b:= (n-1)^-1 mod p;
alpha:= b*(one+Z(p^2)^a); fi;
return rec( alpha:= alpha, beta:= alpha*c ); end;
## construction S2 of Lemma 10 ## IN an input record with n,p,T and optionally Sym and/or Alt, ## where n,p satisfy the hypothesis of Lemma 10 ## OUT the same, but for 2S(n+2)
S2:= function( old )
local mid, new, coeffs, a, b, J, I;
#Print("S2 from ",old.n," to ",old.n+2," via S\n");
mid := S( old );
new := rec( n := mid.n + 1, p := mid.p, T := ShallowCopy( mid.T ) );
if IsBound( old.Sym ) then
new.Sym := [];
new.Sym[1] := new.T[new.n-1]*mid.Sym[1];
new.Sym[2] := mid.Sym[2]; fi;
if IsBound( old.Alt ) then
new.Alt := []; if IsOddInt( new.n ) then new.Alt[1] := new.Sym[1]; else new.Alt[1] := mid.Sym[1]; fi;
new.Alt[2] := new.T[new.n-1]*new.T[new.n-2]; fi;
Assert( 1, SanityCheckPos( new ) );
return new; end;
## coeffS3 - a needed coefficient ## IN A prime p, or p = 0 ## OUT Sqrt(-1) in GF(p^2) or CF(4)
coeffS3:= function( p ) if0 = p then return E(4); elif2 = p then return Z(2); elif1 = p mod 4then return Z(p)^((p-1)/4); else return Z(p^2)^((p^2-1)/4); fi; end;
## construction S3 of Lemma 11 ## IN an input record with n,p,T and optionally Sym and/or Alt, ## where n,p satisfy the hypothesis of Lemma 11 ## OUT the same, but for 2S(n+4)
S3:= function( old )
local mid, new, a, J0, I, J; #Print("S3 from ",old.n," to ",old.n+4," via S,S1,S\n");
mid := S( S1( S( old ) ) ); # now at n-1
new := rec( n := mid.n + 1, p := mid.p, T := ShallowCopy( mid.T ) );
if IsBound( old.Sym ) then
new.Sym := [];
new.Sym[1] := new.T[new.n-1]*mid.Sym[1];
new.Sym[2] := mid.Sym[2]; fi;
if IsBound( old.Alt ) then
new.Alt := []; if IsOddInt( new.n ) then new.Alt[1] := new.Sym[1]; else new.Alt[1] := mid.Alt[1]; fi;
new.Alt[2] := new.T[new.n-1]*new.T[new.n-2]; fi;
Assert( 1, SanityCheckPos( new ) );
return new; end;
## spinsteps ## IN the degree n and characteristic p > 2 ## OUT a list which describes the steps of construction
spinsteps:= function( n, p )
local d, k, kmodp, parity;
d:= [];
k:= n; while k > 4do
kmodp:= k mod p;
parity:= k mod 2; if kmodp > 2then if parity = 1then
Add( d, 0 );
k:= k-1; else
Add( d, 2 );
k:= k-2; fi; elif kmodp = 0then
Add( d, 1 );
k:= k-1; elif kmodp = 1then
Add( d, 0 );
k:= k-1; else if parity = 1then
Add( d, 0 );
k:= k-1; else
Add( d, 3 );
k:= k-4; fi; fi;
od;
return Reversed( d ); end;
## construction of a basic spin rep. of 2S+(n) in characteristic p
BasicSpinRepSymPos := function( n, p )
local z, M, k, i, steps; if not IsPosInt(n) or not IsInt(p) or n < 4 or not ( p = 0 or IsPrime( p ) ) then
return fail; fi; ## get the spin reps for 2S(4)
z := coeffS3(p); if p = 0then
M:= rec(
n := 2,
p := 0,
T := [ [ [ z ] ] ],
Sym := [~.T[1]],
Alt :=[]
);
M:= S2( M ); elif p = 2then
M:= rec(
n := 2,
p := 2,
T := [ [ [ z ] ] ],
Sym := [~.T[1]],
Alt :=[]
);
M:= S1( S( M ) ); elif p = 3then
M:= rec(
n := 3,
p := 3,
T := [ [ [ z ] ], [ [ z ] ] ],
Sym := [ [ [ z^2 ] ], ~.T[1] ],
Alt:=[ ~.Sym[1] ]
);
M:= S( M ); else# p>3
M:= rec(
n := 2,
p := p,
T := [ [ [ z ] ] ],
Sym := [ ~.T[1]],
Alt:=[]
);
M:= S2( M ); fi; if n = 4then return M; fi; if ValueOption("Sym") <> true and ValueOption("Alt")<>true then Unbind(M.Sym); fi; if ValueOption("Alt") <> true then Unbind(M.Alt); fi; if p = 0then if n mod 2 = 0then
k:= (n-4)/2; for i in [ 1 .. k ] do
M:= S2( M );
od; else
k:= (n-5)/2; for i in [ 1 .. k ] do
M:= S2( M );
od; # now M is a b.s.r. of 2S( n-1 )
M:= S( M ); fi; elif p = 2then
k:= 5; while k <= n do if k mod 2 = 1then
M:= S( M ); else
M:= S1( M ); fi;
k:= k+1;
od; else# p >= 3
steps:= spinsteps( n, p ); for k in steps do if k = 0then
M := S( M ); elif k = 1then
M := S1( M ); elif k = 2then
M := S2( M ); else
M := S3( M ); fi;
od; fi;
Assert( 1, SanityCheckPos( M ) );
return M; end;
BasicSpinRepSymNeg := function( n, p )
local T, S;
T := BasicSpinRepSymPos( n, p );
S := rec( n := T.n, p := T.p, T := coeffS3( p ) * T.T ); if IsBound( T.Sym ) then S.Sym := [ coeffS3( p )^(n-1) * T.Sym[1], S.T[1] ]; fi; if IsBound( T.Alt ) then S.Alt := [ (-1)^Int((n-1)/2)*T.Alt[1], -T.Alt[2] ]; fi;
Assert( 1, SanityCheckNeg( S.T, p ) );
return S; end;
return function( n, p, sign ) if sign in [ 1, '+', "+", 4 ] then return BasicSpinRepSymPos(n,p); elif sign in [ -1, '-', "-", 2 ] then return BasicSpinRepSymNeg(n,p); else Error("<sign> should be +1 or -1"); fi; end;
InstallGlobalFunction( BasicSpinRepresentationOfSymmetricGroup, function(arg)
local n, p, s, mats; if Length(arg) < 1then Error("Usage: BasicSpinRepresentationOfSymmetricGroup( <n>, <p>, <sign> );"); fi;
n := arg[1]; if Length(arg) < 2then p := 3; else p := arg[2]; fi; if Length(arg) < 3then s := 1; else s := arg[3]; fi;
mats := BasicSpinRepSym(n,p,s).T; if p = 2then return List( mats, mat -> ImmutableMatrix( GF(p), mat ) ); elif p > 0then return List( mats, mat -> ImmutableMatrix( GF(p^2), mat ) ); fi;
return mats; end );
InstallMethod( SchurCoverOfSymmetricGroup, "Use Lukas Maas's inductive construction of a basic spin rep",
[ IsPosInt, IsInt, IsInt ], function( n, p, s )
local mats, grp;
if p = 2then return fail; fi; # need a faithful rep
InstallMethod( DoubleCoverOfAlternatingGroup, "Use Lukas Maas's inductive construction of a basic spin rep",
[ IsPosInt, IsInt ], function( n, p )
local mats, grp;
if p = 2then return fail; fi; # need a faithful rep
if n >= 5then
Assert( 3, IsPerfectGroup( grp ) );
SetIsPerfectGroup( grp, true ); fi;
return grp; end );
############################################################################# ## ## Other method installations that do not require direct access to the ## inductive procedure. ##
############################################################################# ## ## Convenience routines that supply default values. ##
InstallOtherMethod( SchurCoverOfSymmetricGroup, "Sign=+1 by default",
[ IsPosInt, IsInt ], function( n, p )
return SchurCoverOfSymmetricGroup( n, p, 1 ); end );
InstallOtherMethod( SchurCoverOfSymmetricGroup, "P=3, Sign=+1 by default",
[ IsPosInt ], function( n )
return SchurCoverOfSymmetricGroup( n, 3, 1 ); end );
InstallOtherMethod( DoubleCoverOfAlternatingGroup, "P=3 by default",
[ IsPosInt ], function( n )
return DoubleCoverOfAlternatingGroup( n, 3 ); end );
############################################################################# ## ## Quickly setup the standard epimorphisms ##
InstallMethod( EpimorphismSchurCover, "Use library copy of double cover",
[ IsNaturalSymmetricGroup ], function( sym )
local dom, deg, cox, chr, grp, hom, img;
dom := MovedPoints( sym );
deg := Size( dom ); if deg < 4then return IdentityMapping( sym ); fi;
cox := List( [1..deg-1], i -> (dom[i],dom[i+1]) );
Assert( 1, ForAll( cox, gen -> gen in sym ) ); #chr := First( [3,5,7], p -> 0 = deg mod p ); #if chr = fail then chr := 3; fi;
chr := 3; # appears to be the best choice regardless of deg
grp := SchurCoverOfSymmetricGroup( deg, chr, 1 );
img := [ Product( Reversed( cox ) ), cox[1] ]; if AssertionLevel() > 2then
hom := GroupHomomorphismByImages( grp, sym, GeneratorsOfGroup( grp ), img );
Assert( 3, KernelOfMultiplicativeGeneralMapping( hom ) = Center( grp ) ); else
dom := RUN_IN_GGMBI; RUN_IN_GGMBI := true;
hom := GroupHomomorphismByImagesNC( grp, sym, GeneratorsOfGroup( grp ), img );
RUN_IN_GGMBI := dom;
SetKernelOfMultiplicativeGeneralMapping( hom, Center( grp ) ); fi;
return hom; end );
InstallMethod( EpimorphismSchurCover, "Use library copy of double cover",
[ IsNaturalAlternatingGroup ], function( alt )
local dom, deg, cox, chr, grp, hom, img;
dom := MovedPoints( alt );
deg := Size( dom ); if deg < 4then return IdentityMapping( alt ); fi; if deg in [6,7] then TryNextMethod(); fi;
cox := List( [1..deg-1], i -> (dom[i],dom[i+1]) );
Assert( 1, ForAll( [1..deg-2], i -> cox[i]*cox[i+1] in alt ) );
chr := 3;
grp := DoubleCoverOfAlternatingGroup( deg, chr );
img := [ Product( Reversed( cox{[1..2*Int((deg-1)/2)]} ) ), cox[deg-1]*cox[deg-2] ]; if AssertionLevel() > 2then
hom := GroupHomomorphismByImages( grp, alt, GeneratorsOfGroup( grp ), img );
Assert( 3, KernelOfMultiplicativeGeneralMapping( hom ) = Center( grp ) ); else
dom := RUN_IN_GGMBI; RUN_IN_GGMBI := true;
hom := GroupHomomorphismByImagesNC( grp, alt, GeneratorsOfGroup( grp ), img );
RUN_IN_GGMBI := dom;
SetKernelOfMultiplicativeGeneralMapping( hom, Center( grp ) ); fi;
return hom; end );
########################################################################### ## ## Special cases just handled explicitly ##
InstallMethod( SchurCoverOfSymmetricGroup, "Use explicit matrix reps for degrees 1,2,3",
[ IsPosInt, IsInt, IsInt ], 1, function( n, p, ignored )
local R; if p = 0then R := Integers; else R:=GF(p); fi; if n = 1then return TrivialSubgroup( GL(1,R) ); elif n = 2 and p<>2then return Group( -One(GL(1,R)) ); elif n = 3 and p<>3then return Group( [ [[0,1],[-1,-1]], [[0,1],[1,0]] ]*One(R) ); elif n = 2 and p = 2then return Group( [[1,1],[0,1]]*One(R) ); # indecomposable, not irreducible elif n = 3 and p = 3then return Group( [ [[0,1],[-1,-1]], [[0,1],[1,0]] ]*One(R) ); # indecomposable, not irreducible else TryNextMethod(); fi; end );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.