################# cliffordmatrices ##### 10.5.2007 #**************************************************************************** # # Copyright (C) 2007 Herbert Pahlings # # # Distributed under the terms of the GNU General Public License (GPL) # # This code is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # See the GNU General Public License for more details; the full text # is available at: # # http://www.gnu.org/licenses/ #***************************************************************************** ################################################################## # # This is a collection of GAP4-programs used in the paper # # The Character Table of 2_+^{1+22}.Co_2 # # by Herbert Pahlings (RWTH-Aachen) # # to appear in J. Algebra # # Questions or suggestions are welcome and should be sent to # Herbert.Pahlings@math.rwth-aachen.de ################################################################## # Let N be a normal subgroup of a finite group G and H = G/N. # Let T_1 , ... , T_t be the inertia groups (stabilizers) of the # G-conjugacy classes of irreducible characters of N and # \bar T_m = T_m/N be the inertia factor groups. # The method of Clifford matrices was introduced by B. Fischer # in order to compute the character table of G if the character # tables of the inertia factor groups and their fusions into H # are known. # # We use the notation of the paper [1] cited above. In particular # \phi_1,..,\phi_t are representatives of the G-orbits of Irr(N) and # \tilde\phi_1,..,\tilde\phi_t are the chosen extensions to T_1,...,T_t # (see [1], (11)). # The programs in this file use the following #### Global variables: ############################################ # cts := List of character tables of inertia factorgroups \bar T_m # with cts[1] = character table of H . Length(cts) = t # fus := List of fusions of cts[i] in cts[1] . Length(fus) = t # ctb := character table of an overgroup B of G . # perm := Permutation character of B on the cosets of G . # deco := list (of variable length) of lists of length t; # if deco[n] is bound it gives information about the # restriction of the n-th irreducible character \chi_n of B, namely # \chi_n\vert_G = # \sum_{m=1}^t \sum_{k \in deco[n][m]} (\psi_k^{(m)})^G # At the beginning deco := [ [ [1] , [] , ... , [] ] ] ; # clif := list of records (in which information about the Clifford # matrices and the fusion into B is collected): # clif[i] has the following fields: # clif[i].mat := i-th Clifford matrix (at the beginning # only partially known) # clif[i].rho := row-indices of clif[i].mat (computed by # the function rowindices(i) # clif[i].wei := row-weights of clif[i].mat (computed by # the function rowweights(i) # clif[i].size := Length( clif[i].rho ); (computed by # the function rowindices(i) # clif[i].fus := [...,k_j,... ] fusion; if g_{ij} # is in the k_j th class of B . # (at the beginning not known, i.e = [] # clif is initialized by the function initializeliffordMatrices() . # # To avoid Error-messages like "unbound global variable .. " # these global variables must be preset before reading in # the programs. # Here they are preset in the following ######################## EXAMPLE 1 ################################### # # In the paper [1] these global variables were preset as follows: cts := [ CharacterTable("Co2"), CharacterTable("U6(2).2"), CharacterTable("2^10:m22:2"), CharacterTable("HS.2"), CharacterTable("U4(3).D8"), CharacterTable("2^(1+8):S8"), CharacterTable("Co2") ] ;; ### The character tables of the inertia factor groups (see [1] Section 3). fus := [ [1..Length( Irr(cts[1]) ) ]];; Append( fus, List(cts{ [2..Length(cts) -2] }, t-> Filtered(ComputedClassFusions(t), f ->f.name = "Co2" )[1].map ) ); Append( fus, RepresentativesFusions( AutomorphismsOfTable(cts[6]), PossibleClassFusions(cts[6],cts[1]),AutomorphismsOfTable(cts[1])) ); Append( fus, [ [1..Length( Irr(cts[1]) ) ]] ); ### The list of fusions of the inertia factor groups into H = Co_2. ctb := CharacterTable("B");; perm := Sum( Irr(ctb) { [1,3,5,8,13,15,28,30,37,40] } );; ### see Breuer Lux, Commun Alg. 24 (1996) p. 2308 deco := [ [ [1], [], [], [], [], [], [] ]] ;; clif := List ( [1..Length( Irr(cts[1]) ) ] , i -> rec( size:=[], fus := [] , rho:= [], wei := [], mat := [] ) );; ### Some of the programs will need the first Clifford matrix with fusion ### which was computed in [1] Section 3; so we enter this: clif[1].mat := [ [ 1, 1, 1, 1, 1, 1, 1 ], [ 2300, 2300, -516, 252, -100, 28, -4 ], [ 46575, 46575, 5103, 1519, 175, -81, -17 ], [ 476928, 476928, -20736, 1792, 1024, 0, -256 ], [ 1619200, 1619200, 19712, -2816, 0, 1024, -768 ], [ 2049300, 2049300, -3564, -748, -1100, -972, 1044 ], [ 2048, -2048, 0, 0, 0, 0, 0 ] ];; clif[1].fus := [ 1, 3, 2, 3, 8, 9, 5 ];; ### The character table of G = 2^1+22.co2 is included in the GAP-library ### of character tables and encoded by the Clifford matrices which are ### stored in a packed form. The list of Clifford matrices is obtained by: # # gap> t := CharacterTable( "2^(1+22).Co2" );; # gap> UnpackedCll( ConstructionInfoCharacterTable( t )[2][3][ i ]); # gap> tc := List ( [1..60] , i -> # > UnpackedCll( ConstructionInfoCharacterTable( t )[2][3][ i ]) );; # gap> # gap> tc[1].mat = clif[1].mat; # true ######################## END EXAMPLE ################################# # # ## At the end of this file another example is given (EXAMPLE 24), in which ## the character table of ## 2_+^{1+8}.S_6(2), a maximal subgroup of Co_2 ## is computed using the programs of this file. # # ### Functions initializing the Clifford matrices and computing ########### ### the first two columns rowindices := function( i ) # computes the row-indices for the i-th Clifford matrix local inds, j, inertfus ; inds := []; inertfus := List( fus, f -> Positions(f,i) ); for j in [ 1..Length(fus) ] do if inertfus[j] <> [] then Append( inds , List ( inertfus[j] , x -> [ j , x ] )); fi; od; return( inds ); end; rowweights := function( i ) # computes the row-weights for the i-th Clifford matrix local weights, j, inertfus ; weights := []; inertfus := List( fus, f -> Positions(f,i) ); for j in [1..Length(fus)] do if inertfus[j] <> [] then Append( weights , List( inertfus[j], x -> SizesCentralizers(cts[j])[x] ) ); fi; od; return( weights ); end; ######### EXAMPLE 2 # gap> rowindices( 43 ); # [ [ 1, 43 ], [ 3, 36 ], [ 3, 77 ], [ 6, 46 ], [ 7, 43 ] ] ### This means that the 43-th conjugacy class of H = Co_2 ### intersects the inertia factors \bar T_3 in the 36-th and 77-th class and ### \bar T_6 in the 46-th class. Since H = \bar T_1 = \bar T_7, the first ### and last entries are trivial. # gap> rowweights(43); # [ 28, 28, 28, 28, 28 ] ### All the 5 classes in the inertia factors have the same centralizer order 28 ######## END EXAMPLE column := function( mat, j ) # returns the j-th column of the matrix mat return( List([1..Length(mat)], i -> mat[i][j] ) ); end; initializeCliffordMatrices:= function( ) # The program enters for all i clif[i].rho (row-indices) , # clif[i].wei (row-weights) and clif[i].size. Also the first and # last row and the first two columns of clif[i].mat are entered. # Some Clifford matrices of size 3,4,5 are determined by their first # columns. They are also entered. # local a, i, j, n; for i in [1..Length( Irr(cts[1]) )] do if not IsBound(clif[i].fus) then clif[i].fus := []; fi; clif[i].rho := rowindices (i); n := Length( rowindices (i) ); clif[i].wei := rowweights (i); clif[i].size := n; clif[i].mat[1] := List( [1 .. n] , x -> 1 ); clif[i].mat[n] := List( [1 .. n] , x -> 0 ); for j in [2 .. n - 1] do if not IsBound( clif[i].mat[j] ) then clif[i].mat[j] :=[] ; fi; clif[i].mat[j]{[1,2]} := [ rowweights(i)[1]/rowweights(i)[j] , rowweights(i)[1]/rowweights(i)[j] ] ; od; a := Sqrt( List( column(clif[i].mat,1), x-> x^2)*rowweights(i){[1..n-1]} /rowweights(i)[1] ); clif[i].mat[n]{[1,2]} := [a , -a]; od; for i in [1..Length( Irr(cts[1]) )] do if clif[i].size = 3 then clif[i].mat[2][3] := -1; elif column ( clif[i].mat , 1) = [ 1,1,2,2 ] then clif[i].mat[2]{[3,4]} := [ 1,-1 ]; clif[i].mat[3]{[3,4]} := [ -2,0 ]; elif column ( clif[i].mat , 1) = [ 1,1,1,1,2 ] then clif[i].mat[2]{[3,4,5]} := [ 1,-1,-1 ]; clif[i].mat[3]{[3,4,5]} := [ -1,1,-1 ]; clif[i].mat[4]{[3,4,5]} := [ -1,-1,1 ]; fi; od; return(clif); end; ######### EXAMPLE 3 initializeCliffordMatrices( );; clif [7]; #rec( size := 6, fus := [ ], # rho := [ [ 1, 7 ], [ 2, 8 ], [ 3, 10 ], [ 5, 27 ], [ 6, 5 ], [ 7, 7 ] ], # wei := [ 3096576, 110592, 49152, 24192, 86016, 3096576 ], # mat := [ [ 1, 1, 1, 1, 1, 1 ], [ 28, 28 ], [ 63, 63 ], [ 128, 128 ], # [ 36, 36 ], [ 16, -16, 0, 0, 0, 0 ] ] ) ######## END EXAMPLE ################# Functions giving information about status of clif ########## ## # ## These and all following functions require that clif has been initialized # ## that is, initializeCliffordMatrices() has been called. # ## clifsoflength:= function( i ) return(Filtered([1..Length(clif)] , j -> clif[j].size = i)); end; ###### EXAMPLE 4 # gap> clifsoflength( 2 ); # [ 46, 47, 53, 54, 59, 60 ] ### These are the numbers i such that the i-th Clifford matrix has size 2 ###### END EXAMPLE computedcolumns := function() # Returns List of all pairs [i,j] such that the j-th column of # i-th Clifford matrix has been computed. # local i, j, s, res ; res := [] ; for i in [1 .. Length(clif) ] do if clif[i].mat <> [] then s := Length( clif[i].mat ); for j in [1 .. s ] do if ForAll( [1 .. s] , k -> IsBound( clif[i].mat[k][j] ) ) then Add ( res , [ i, j ] ) ; fi; od; fi; od; return( res ); end; ##### EXAMPLE 5 # gap> initializeCliffordMatrices( );; # gap> c := computedcolumns();; Length(c); c{[1..10]}; # 175 # [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ], [ 1, 6 ], [ 1, 7 ], # [ 2, 1 ], [ 2, 2 ], [ 3, 1 ] ] ### By clif := initializeCliffordMatrices( );; already 175 columns of ### CLifford matrices have been computed, ### among these the first two columns of all Clifford matrices. ###### END EXAMPLE computedcliffordmats := function() # Returns List of all i such that the complete Clifford matrix has # been stored. local i, res ; res := [] ; for i in [1 .. Length(clif) ] do if ForAll( [1 .. clif[i].size ], j -> ForAll( [1 .. clif[i].size ] , k -> IsBound( clif[i].mat[k][j] ) ) ) then Add ( res , i ) ; fi; od; return( res ); end; ###### EXAMPLE 6 # gap> initializeCliffordMatrices( );; # gap> c := computedcliffordmats(); Length(c); # [ 1, 14, 29, 30, 33, 34, 38, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, # 52, 53, 54, 55, 56, 57, 58, 59, 60 ] # 26 ### By clif := initializeCliffordMatrices( );; 25 Clifford matrices were ### determined. ###### END EXAMPLE computedfusions := function() # Returns List of all pairs [i,j] such that the fusion of g_{i,j} into B # has been stored (in cliff[i].fusion). local i, j, res ; res := [] ; for i in [1 .. Length(clif) ] do for j in [1 .. clif[i].size ] do if IsBound( clif[i].fus[j] ) then Add ( res , [i , j] ) ; fi; od; od; return( res ); end; computedallfusions := function() # Returns List of all i such that the fusion of g_{i,j} into B # has been stored (in cliff[i].fusion) for all local i, res ; res := [] ; for i in [1 .. Length(clif) ] do if ForAll( [1 .. clif[i].size ] , j -> IsBound( clif[i].fus[j] ) ) then Add ( res , i ); fi; od; return( res ); end; ############## Functions computing scalar products ###################### scalarproducsrestricted := function( c1, c2 ) # For c1, c2 characters of B the scalar product # ( c1_G , c2_G )_G of the restricted characters is returned. # Uses the permutation character perm of B (on the cosets of G); # local i,j, n,res ; res := 0; for i in [1..Length(Irr(ctb))] do res := res + perm[i]*c1[i]*ComplexConjugate(c2[i])/SizesCentralizers(ctb)[i]; od; return(res); end; ######### EXAMPLE 7 #gap> for i in [1..6] do #> Print("\n",i," : "); #> for j in [1..i] do #> Print(scalarproducsrestricted(Irr(ctb)[i],Irr(ctb)[j])," "); #> od; #> od; # # 1 : 1 # 2 : 0 3 # 3 : 1 0 5 # 4 : 0 2 0 6 # 5 : 1 0 5 0 11 # 6 : 0 0 3 0 5 12 ### the matrix of scalar products of the restrictions of the first 6 ### irreducibles of B. ######## END EXAMPLE sizescentc := function( i, c ) # computes c^i_j := |C_G(g_{i,j})| provided that j-th column c of # i-th Clifford matrix is given local k , n , cento ; cento:= 0; n := Length( c ); for k in [1..n] do cento := cento + ( clif[i].wei[k] * c[k] * ComplexConjugate(c[k]) ); od; return( cento ); end; sizescent := function( i, j ) # computes c^i_j := |C_G(g_{i,j})| provided that j-th column c of # i-th Clifford matrix is stored in clif[i].mat return( sizescentc( i, column( clif[i].mat, j ) ) ); end; ######### EXAMPLE 8 # gap> t := CharacterTable( "2^(1+22).Co2" );; # gap> List( [1..7], j -> sizescent( 1, j ) ) = SizesCentralizers(t){[1..7]}; # true ######## END EXAMPLE scpcols:=function( i, c1, c2 ) # returns scalar product of the vectors c1 , c2 w.r.t. the # row-weights clif[i].wei of the i-th Clifford matrix return( Sum( List( [1..Length(clif[i].mat)] , j -> clif[i].wei[j]*c1[j]* ComplexConjugate(c2[j]) ) ) ); end; scp := function( chi, i, r ) # Returns the scalar product of \chi\vert_G with the r-th row # of the i-th Clifford matrix (see formula (8) of [1]) # where \chi is a character of B. # Requires that the i-th Clifford matrix is stored with the fusion # unless r = clif[i].size, when it is sufficient, that this is stored # for the first two columns. # if not ForAll( [1,2], j -> IsBound( clif[i].fus[j] ) ) then Print("\n ERROR not all fusions stored "); return([]); elif r = clif[i].size then return ( clif[i].wei[r]/clif[i].wei[1] * Sum(List( [1..2] , j -> ( SizesCentralizers(cts[1])[i]/sizescent(i,j) ) * ComplexConjugate(clif[i].mat[r][j] )* chi[clif[i].fus[j]] ) ) ); elif not i in Intersection( computedcliffordmats() , computedallfusions() ) then Print("\n ERROR clif[",i,"].mat not stored"); return([]); else return ( clif[i].wei[r]/clif[i].wei[1] * Sum(List( [1..Length(clif[i].mat)] , j -> ( SizesCentralizers(cts[1])[i]/sizescent(i,j) ) * ComplexConjugate(clif[i].mat[r][j] )* chi[clif[i].fus[j]] ) ) ); fi; end; ######### EXAMPLE 9 # gap> List ( [1..7], k -> scp( Irr(ctb)[2], 1, k) ); # [ 23, 1, 0, 0, 0, 0, 1 ] # ### By [1], Lemma 5 this show that \chi_2^{(1)}(1) = 23, \chi_2^{(2)}(1) = 1 ### and \chi_2^{(7)}(1) = 1 . 2048. ######## END EXAMPLE ############################################################################ #### Functions computing character values of G from column of clif[i].mat ### cliffinduce := function( i, c, m, psi ) # If c is the j-th column of the i-th Clifford matrix (stored # as a row-vector) and psi a character of \bar T_m, the program # returns ( \tilde \phi_m \psi)^G (g_{i,j}) . # local val , rows, l , x , n ; val:= 0; n := Length( c ); rows := Filtered([1..n] , x -> clif[i].rho[x][1] = m ); for l in rows do val:= val + psi[clif[i].rho[l][2]] * c[l]; od; return( val ); end; columnctc := function( i , c ) # If c is the j-th column of the i-th Clifford matrix (stored # as a row-vector), the program returns the column corresponding to (i,j) # of the character table of G. # local k ,col ,m ; col := List( Irr( cts[1] ) , y -> y[i] ); for m in [ 2 .. Length(cts) ] do for k in [1 .. Length(Irr(cts[m])) ] do Add( col , cliffinduce( i, c, m, Irr(cts[m])[k] ) ); od; od; return(col) ; end; columnct := function( i , j ) # Returns the (i,j)-column of the of the character table of G, # provided that the j-th column of the i-th Clifford matrix is stored # (in clif[i].mat ) # return( columnctc( i, column( clif[i].mat, j ) ) ); end; ####### EXAMPLE 10 # gap> t := CharacterTable( "2^(1+22).Co2" );; # gap> columnct( 1, 1 ) = TransposedMat( Irr(t) )[1]; # true ### columnct( 1, 1 ) is the list of irreducible character degrees of G # gap> List( [1..7] , j -> columnct( 1, j) ) = TransposedMat(Irr(t)){[1..7]}; # true # ###### END EXAMPLE psisumc := function( i, c, li ) # Let li be list with li[m] = list of indices of irreducibles of cts[m] # m=1,... , e.g. li := deco[n] for some n . # Let c be (a candidate for) the j-th column of the i-th Clifford matrix. # Function returns \sum_m \sum_{k \in li[m] (\psi_k^{(m)})^G (g_{i,j}) , # provided that c is indeed the j-th column of i-th Clifford matrix. # local val, k, m ; val:= 0; for m in [1..Length(cts)] do if IsBound( li[m] ) and li[m] <> [] then for k in li[m] do val := val + cliffinduce(i, c, m, Irr(cts[m])[k]); od; fi; od; return(val); end; psisum := function( i, j, li ) # Let li be list with li[m] = list of indices of irreducibles of cts[m] # m=1,... , e.g. li:= deco[n] for some n . # Function returns \sum_m \sum_{k \in li[m] (\psi_k^{(m)})^G (g_{i,j}), # provided j-th column of i-th Clifford matrix is stored in clif[i].mat. return( psisumc( i, column( clif[i].mat, j ), li ) ); end; ####### EXAMPLE 11 # gap> li := [ [2], [2], [], [], [], [], [1] ];; y := psisum ( 1, 1, li ); # 4371 # gap> ForAll ( computedfusions() , x -> psisum( x[1], x[2], li ) = # > Irr(ctb)[2][clif[x[1]].fus[x[2]] ] ); # true ###### END EXAMPLE ########## Functions testing columns of Clifford matrices ################ testorth := function( i, mat, pos ) # Assume that the columns of the matrix mat are candidates for # columns of the i-th Clifford matrices. Program tests the orthogonality # relations for the columns of mat (w.r.t.) the row-weights clif[i].wei. # If pos is a list of classes of B, which may contain the g_{i,j} it is also # tested, whether or not the scalar products of the columns with themselves # divide the corresponding centralizer orders in B. Returns true or false # accordingly. (pos is usually computed with pos := posfus( i );) # local w, ii, j, x, m, c, sp, result ; m := clif[i].size; w := clif[i].wei; result := true; c := sizescent( 1, 1 ); for ii in [1..m] do for j in [i..m] do sp:=[]; sp:= List([1..m] , k -> mat[k][ii]*mat[k][j]); x := w * sp; if ii < j and x <> 0 then result := false ; fi; if result then if ii = j and not IsInt(c/x) then result := false ; fi; fi; if result then if ii = j and ForAll( pos , j -> not IsInt(SizesCentralizers(ctb)[j] /x)) then result := false ; fi; fi; od; od; return( result); end; ###### EXAMPLE 12 # gap> testorth( 1, clif[1].mat, clif[1].fus ); # true # ###### END EXAMPLE testcolumnwithclassmult := function ( i, c ) # If c is a candidate for a column of the i-th Clifford matrix # the corresponding (say x-th) column of the character table of G is computed # and it is tested whether or not the corresponding class # multiplication coefficients a_{x,y,z} are non-negative integers # where x y correspond to known columns of the Clifford matrices. # This progam is time-consuming. The computing time is O(n^2) with # n = Length( computedcolumns() ) # local d, q, sc, j, k , a, x , y, yy, z , res; res := true ; d := columnct( 1, 1) ; q := sizescent( 1, 1)/sizescentc( i , c ); x := columnctc( i, c ); for y in computedcolumns() do if res then sc := sizescent( y[1] , y[2] ); yy := columnct( y[1] , y[2] ); for z in computedcolumns() do z := columnct( z[1] , z[2] ); a := 0; for k in [ 1 .. Length(z) ] do a := a + x[k]*yy[k] * ComplexConjugate( z[k] ) / d[k] ; od; if not IsInt( a * q / sc ) or a * q / sc < 0 then res := false; fi; od; fi; od; return( res ); end; ###### EXAMPLE 13 # gap> initializeCliffordMatrices( );; # gap> Length ( computedcolumns() ); # 175 # gap> testcolumnwithclassmult( 1, column( clif[1].mat , 3) ) ; # true # gap> time; # 70337 ######## END EXAMPLE ############### Function finding possible fusions into B ################## missingclasses := function() # Returns list of length |Irr(B)| with k-th entry # |x_k^B \cap G| - \sum | g_{i,j}^G \cap x_k^B | , # where the sum extends over all [i , j] in # computedcolumns \cap computedfusions(). # Useful for finding candidates for fusion of remaining g_{i,j} into B # local x, inters ; inters := List( [1..Length(perm)] , i -> (perm[i] * sizescent(1,1)) / SizesCentralizers(ctb)[i] ); for x in Intersection( computedcolumns(),computedfusions() ) do inters[ clif[ x[1] ].fus[ x[2] ] ] := inters[ clif[ x[1] ].fus[ x[2] ] ] - sizescent( 1, 1 )/sizescent( x[1], x[2] ); od; return(inters); end; ###### EXAMPLE 14 # gap> Sum(missingclasses()) = 2^23 * Size(cts[1]) - 2^23; # true #### Only the fusions of the classes in N = 2^1+22 have been entered, so #### Sum(missingclasses()) = |G| - |N|. At the end, when all fusions have #### been entered, the sum should be zero. ####### END EXAMPLE posfus := function( i ) # Computes possible fusion of g_{i,j} into B for given i (and all j) # local elo, mc, pf; elo:= OrdersClassRepresentatives(cts[1])[i]; mc := missingclasses(); pf := Filtered([1 .. Length( Irr(ctb) )], k -> OrdersClassRepresentatives(ctb)[k] in [ elo, 2*elo, 4*elo ] and mc[k] > 0 and SizesCentralizers(ctb)[k] >= SizesCentralizers(cts[1])[i]); pf := Union( pf, clif[i].fus ); return(pf); end; ###### EXAMPLE 15 # gap> pos:= posfus( 1 ); ClassNames(ctb){pos}; # [ 1, 2, 3, 4, 5, 8, 9 ] # [ "1a", "2a", "2b", "2c", "2d", "4a", "4b" ] ### These are the possible classes of B containing g_{1,1},...,g_{1,t} ### (in the second line the names of the classes are listed). But it ### was shown in [1] Section 3, that none of these is in class "2c". ###### END EXAMPLE posfusdec := function( i, j, dec ) # Returns a list of possible conjugacy classes of B which may # contain g_{i,j} using the restriction of Irr(ctb)[d] for # d in dec. For all d in dec deco[d] (see global variables) must be stored. # Requires also that the j-th column of clif[i].mat is stored. # Typical use: pos:= posfusdec ( i, j, [1..4] ); # local pf, d ; pf := posfus( i ); pf := Filtered( pf , k -> IsInt(SizesCentralizers(ctb)[k]/sizescent(i,j)) and (perm[k] *Size(ctb)) /(SizesCentralizers(ctb)[k] * perm[1]) >= sizescent(1,1)/sizescent(i,j) ); for d in dec do pf := Filtered( pf, k -> Irr(ctb)[d][k] = psisum( i, j, deco[d] ) ); od; return(pf); end; ###### EXAMPLE 16 # gap> posfus( 2 ); # [ 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14 ] # gap> posfusdec( 2, 1, [1] ); # [ 2, 3, 5 ] ### There are 3 possibilities for the fusion of g_{2,1} into B . ### It will be determined using the restriction of \chi_2 \in Irr(B), ### see EXAMPLE ### Observe that the first column of clif2].mat had been stored by ### initializeCliffordMatrices(). ###### END EXAMPLE enterposfusdec := function( dec ) # If dec is a list of numbers d, for which deco[d] is bound, program # stores clif[i].fus[j] for all those i,j of computedcolumns() # for which posfusdec( i, j, dec ) gives a list of length one # (so that the fusion is uniquely determined by deco{dec}). # Typical use: enterposfusdec( [1..4] );; # local x, f ; for x in computedcolumns() do f := posfusdec( x[1] , x[2] , dec ); if Length( f ) = 1 then if IsBound(clif[x[1]].fus[x[2]]) and clif[x[1]].fus[x[2]] <> f[1] then Print("\n ERROR fusion of g_ ",x[1]," ",x[2]," is ", clif[x[1]].fus[x[2]]," or ", f[1] ); else clif[x[1]].fus[x[2]] := f[1]; fi; fi; od; end; ########### Functions decomposing restrictions of characters of B ######### # # The following programs are used to find the decompositions # \chi_n\vert_G = \sum_{m=1}^t \sum_{k=1}^{r_m} a_{k,n}^{(m)} (\psi_k^{(m)})^G # (see [1] Section 6), where \chi_n \in Irr(B), n := 5,6,... . # The results should be stored in the n-th row of deco . # constituents := function( t, char) # If t is a character table of G and char a character of G the function # returns a list such that char = Sum( Irr(t){list} ) local m, i, j, res; m := MatScalarProducts( Irr(t), [char])[1]; res:=[] ; for i in [1..Maximum(m)] do if i in m then for j in [1..i] do Append( res , Positions( m, i) ); od; fi; od; Sort(res); return(res); end; ###### EXAMPLE 17 # gap> constituents( ctb, Irr(ctb)[5] + 2* Irr(ctb)[3] ); # [ 3, 3, 5 ] # ###### END EXAMPLE charcands := function( n ) # Returns list charli = [ charli[1],...,charli[t] ] with # charli[m] = [ \psi \in Irr(\bar T_m) | \psi(1) <= \chi_n^{(m)}(1) # and \psi not constituent of $\chi_k^{(m)} for k < n # with (\chi_n , \chi_k)_G = 0 ] (see Section 6 of [1]) # The first Clifford matrix clif[1].mat must be stored as well # as the fusion clif[1].fus # local charli, m, j, y ; charli:=[]; if not 1 in Intersection(computedcliffordmats(), computedallfusions() ) then Print("ERROR first Clifford matrix must be stored with fusion "); else for m in [1..Length(cts)] do charli[m] := Filtered(Irr(cts[m]) , y -> y[1]<= scp( Irr(ctb)[n], 1, m ) ); od; for j in [1..Length(deco)] do if scalarproducsrestricted( Irr(ctb)[n] , Irr(ctb)[j] ) = 0 then for m in [1..Length(charli)] do if deco[j][m] <> [] then charli[m] := Difference( charli[m] , Irr(cts[m]){deco[j][m]}); fi; od; fi; od; fi; return(charli); end; dispcharli := function( charli ) # If charli is a list with charli[m] a list of characters of \bar T_m # the function returns a list of the same length as charli, with # charli[m] giving the positions in Irr(\bar T_m) of the characters # in charli[m] if they are irreducible and else their contituents # local x, m, p, res; res := []; for m in [1..Length(charli)] do if charli[m] <> [] then res[m] := List( charli[m] , x -> Position(Irr(cts[m]) , x ) ); if fail in res[m] then p := Positions( res[m] , fail ); for x in p do res[m][x] := constituents( cts[m], charli[m][x] ); od; fi; else res[m] := [] ; fi; od; return(res); end; ###### EXAMPLE 18 # gap> charli := charcands( 2 );; # gap> scalarproducsrestricted( Irr(ctb)[2], Irr(ctb)[2] ); # 3 # gap> dispcharli( charli ); # [ [ 2 ], [ 1, 2 ], [ ], [ ], [ ], [ ], [ 1 ] ] ### This means that \chi_2^{(2)} = \psi_1^{(2)} or \psi_2^{(2)} ### (see [1] Section 4), since \chi_2\vert_G has norm 3. We can decide ### this considering the class g_{2,1} : # gap> pos := posfusdec( 2, 1, [1] ); # [ 2, 3, 5 ] # gap> Irr(ctb)[2]{pos}; # [ -493, 275, 19 ] # gap> psisum( 2, 1, [ [ 2 ], [ 1 ], [ ], [ ], [ ], [ ], [ 1 ] ] ); # 531 # gap> psisum( 2, 1, [ [ 2 ], [ 2 ], [ ], [ ], [ ], [ ], [ 1 ] ] ); # 19 # gap> deco[2]:= [ [ 2 ], [ 2 ], [ ], [ ], [ ], [ ], [ 1 ] ];; ### Since \chi_2 does not take the value 531 on any of the classes of B ### which may contain g_{2,1} the second alternative is the correct one ### and entered as deco[2]. Now deco[2] can be used to determine more ### fusions: # gap> enterposfusdec( [1,2] ); # gap> Length(computedfusions() ); # 104 ####### END EXAMPLE charcandsrat := function( n ) # Same as charcands but instead of Irr(T_m) the rationalized matrix is # taken. local charli, rats, m, j, y ; charli:=[]; if not 1 in Intersection(computedcliffordmats(), computedallfusions() ) then Print("ERROR first Clifford matrix must be stored with fusion "); else for m in [1..Length(cts)] do rats := RationalizedMat( Irr(cts[m]) ); charli[m] := Filtered( rats , y -> y[1]<= scp( Irr(ctb)[n], 1, m ) ); od; for j in [1..Length(deco)] do if scalarproducsrestricted( Irr(ctb)[n] , Irr(ctb)[j] ) = 0 then for m in [1..Length(charli)] do if deco[j][m] <> [] then charli[m] := Difference( charli[m] , Irr(cts[m]){deco[j][m]}); fi; od; fi; od; fi; return(charli); end; evalinduced := function( compcol, charli ) # If charli is a list with charli[m] a list of # characters \psi^{(m)} of \hat T_m the program returns a matrix # [ (\tilde \phi_m \psi^{(m)})^G (g_{i,j}) ] with [i,j] in compcol and # columns (m,\psi^{(m)}) with \psi^{(m)} \in charli[m] , m = 1,... . # The j-th column of clif[i].mat must be stored for all [i,j] in compcol. # local x, m, char, row, res; res := []; if IsSubset( computedcolumns(), compcol) then for x in compcol do row:=[]; for m in [1..Length(charli)] do for char in charli[m] do Add(row, cliffinduce(x[1],column(clif[x[1]].mat,x[2]),m,char ) ); od; od; Add( res, row ); od; else Print("\n ERROR not all columns of clif[i] stored"); fi; return(res); end; chifaithful := function( chi ) # Returns for a character chi of B the list scalar products # ( chi|G , \psi_k^{(t)} ) for the faithful irreducible characters # \psi_k^{(t)} of G. See [1], Section 4, where t := Length(cts) = 7. # Requires that first two columns in all Clifford matrices clif[i].mat # are stored with fusion clif[i].fus{[1,2]}. local a, i, j, mult, phi ; mult:= [] ; if not ForAll( [1..Length(clif)] , i -> ForAll( [1..clif[i].size], j -> IsBound( clif[i].mat[j][1]) and IsBound( clif[i].mat[j][2]) ) and ForAll( [1,2] , l -> IsBound( clif[i].fus[l]) ) ) then Print("ERROR first 2 cols of Clifford mats must be stored with fusion "); else for phi in Irr(cts[1]) do a:=0; for i in [1..Length(Irr(cts[1]))] do a := a + clif[i].mat[clif[i].size][1]*phi[i] * (chi[clif[i].fus[1]]/sizescent(i,1) - chi[clif[i].fus[2]]/sizescent(i,2)); od; if a > 0 then for i in [1..a] do Add( mult , Position( Irr(cts[1]) , phi ) ); od; fi; od; fi; return(mult); end; ### see EXAMPLE 20 evalres := function( n, compfus, faithful ) # Let compcol in computedfusions() and \chi_n in Irr(ctb) # If faithful = false, the progam returns [\chi_n(g_{i,j}]_{[i,j] in compfus}. # If faithful = true, the progam returns # [\chi_n(g_{i,j} - \chi_n^{(t)})(g_{ij})]_{[i,j] in compfus} # local rhs, x, y ; rhs := []; if not IsSubset( computedfusions(), compfus) then Print("\n ERROR fusions are missing"); elif faithful = false then for x in compfus do Add( rhs , Irr(ctb)[n][clif[x[1]].fus[x[2]]]); od; else y := Sum( Irr(cts[1]){chifaithful( Irr(ctb)[n] )} ); for x in compfus do Add( rhs , Irr(ctb)[n][clif[x[1]].fus[x[2]]] - clif[x[1]].mat[clif[x[1]].size][x[2]]*y[x[1]] ); od; fi; return(rhs); end; ###### EXAMPLE 19 ### We continue with Example 18: # gap> deco[2]:= [ [ 2 ], [ 2 ], [ ], [ ], [ ], [ ], [ 1 ] ];; # gap> enterposfusdec( [1,2] ); # # mat := evalinduced( computedfusions(), charcands( 3 ));; # gap> Length(mat); Length(mat[1]) ; Rank(mat); # 104 # 7 # 7 ### The matrix mat is a 159 x 6 - matrix with rank 6. The system ### of equations mat x^T = evalres( 3, computedfusions(), false )^T ### has a unique solution which is computed in decomp (or decomps) ### below to find the decomposition of \chi_3|_G ( i.e deco[n] ) for ### n = 3 , ... . See Example 20. ####### END EXAMPLE decomp := function( n, cols, charli, faithful) # Computes decomposition of \chi_n|G = Irr(ctb)[n]|G = # \sum_{m=1}^t ( \sum_{\psi \in charli[m]} a_{\psi} psi^{(m)} )^G # (see [1], Section 6); here charli[m] is a list of characters of \hat T_m, # such that \chi_n^{(m)} is in the span of (\psi^{(m)})_{\psi in charli[m]}, # where \psi^{(m)} = \tilde \phi_m Inf(\psi) (see [1] (14) ) # charli may be obtained by charli := charcands(n) if no addtional # information is available. # Returns [[a_1^1,...a_{m_1}^1],...[a_1^{t-1},...a_{m_1}^{t-1} ] if # Rank( evalinduced( cols, charli) ) = Sum(List(charli, Length)) # and [ ] otherwise. (see [1] Section 6) # local rhs, mat, a, m ,k, kk, sol, solm, res; res:= []; a := 1; if faithful = true then charli := charli{[1..Length(cts)-1]}; fi; rhs := evalres( n, cols, faithful); mat:= evalinduced( cols, charli); if Rank(mat) = Length(mat[1]) then sol := SolutionMat( TransposedMat(mat), rhs ); for m in [1..Length(charli)] do res[m] := []; solm := sol{[a..a + Length(charli[m])-1]}; a := a + Length(charli[m]) ; for k in [1..Length(charli[m])] do if solm[k] > 0 then for kk in [1..solm[k]] do Append( res[m] , constituents(cts[m], charli[m][k] ) ); od; fi; od; od; if Length(res) = Length(cts) -1 then Add( res, chifaithful( Irr(ctb)[n])); fi; else Print(" Rank = " , Rank(mat), ", number of unknowns = ", Length(mat[1]), " " ); fi; return(res); end; decomps := function( n ) # Computes decomposition of \chi_n|G = Irr(ctb)[n]|G = # \sum_{m=1}^t ( \sum_{\psi \in charli[m]} a_{\psi} psi^{(m)} )^G # (see [1], Section 6); here charli[m] is a list of characters of \hat T_m, i # such that \chi_n^{(m)} is in the span of (\psi^{(m)})_{\psi in charli[m]}, # where \psi^{(m)} = \tilde \phi_m Inf(\psi) (see [1] (14) ) # charli may be obtained by charli := charcands(n) if no addtional # information is available. # Returns [[a_1^1,...a_{m_1}^1],...[a_1^{t-1},...a_{m_1}^{t-1} ] if # Rank( evalinduced( cols, charli) ) = Sum(List(charli, Length)) # and [ ] otherwise. (see [1] Section 6) local cols, charli, rhs, mat, a, m ,k, kk, sol, solm, res; res := []; if ForAll( [1..Length(Irr(ctb))] , k -> IsRat(Irr(ctb)[n][k] ) ) then charli := charcandsrat(n); else charli := charcands(n); fi; cols:= Intersection( computedcolumns(), computedfusions() ); if IsSubset( cols, Cartesian( [1..Length(clif)],[1,2] ) ) then charli := charli{[1..Length(charli)-1]};; res:= decomp( n, cols, charli, true ); if res <> [] then Add( res, chifaithful( Irr(ctb)[n]) ); fi; else res := decomp( n, cols, charli, false); fi; return(res); end; ############ EXAMPLE 20 ### We continue with Example 18: # gap> deco[2]:= [ [ 2 ], [ 2 ], [ ], [ ], [ ], [ ], [ 1 ] ];; # gap> enterposfusdec( [1,2] ); # # gap> for n in [3..8] do Print(n," : ",decomps( n ), "\n" ) ; od; # 3 : [ [ 1, 4 ], [ 1 ], [ 1 ], [ ], [ ], [ ], [ 2 ] ] # 4 : [ [ 2 ], [ 4 ], [ 2 ], [ 2 ], [ ], [ ], [ 1, 4 ] ] # 5 : [ [ 1, 4, 6 ], [ 1, 3 ], [ 1, 3 ], [ ], [ 4 ], [ 1 ], [ 2, 7 ] ] # 6 : [ [ 3 ], [ 1, 3 ], [ 22 ], [ 1 ], [ 1, 3 ], [ ], [ 2, 2, 7 ] ] # 7 : [ [ 2, 7 ], [ 2, 2, 4, 8 ], [ 2, 23 ], [ 4 ], [ 5 ], [ 2, 4 ], # [ 1, 3, 4, 4, 6, 14 ] ] # Rank = 82, number of unknowns = 87 8 : [ ] ### The decompositions of the restrictions of \chi_n for n = 3 ... 7 is ### uniquely determined by decomps and the fusions computeds so far. ### We enter the results in the matrix deco and determine further ### fusions: # gap> for n in [3..7] do deco[n] := decomps( n ); od; # gap> enterposfusdec( [1..7] ); Length( computedfusions() ); # 159 # gap> for n in [8..10] do Print(n," : ",decomps( n ), "\n" ) ; od; # 8 : [ [ 1, 4, 14 ], [ 1, 3, 7 ], [ 1, 1, 3, 22, 36 ], [ 1, 3 ], [ 2, 10 ], # [ 1, 2, 3, 23 ], [ 2, 2, 7, 7, 8, 18, 20 ] ] # 9 : [ [ 2, 7, 8 ], [ 2, 2, 4, 4, 8, 16 ], [ 2, 4, 23, 23 ], [ 2, 4, 6 ], # [ 5, 9 ], [ 4, 63, 8 ], [ 1, 1, 3, 4, 4, 4, 6, 6, 14, 17, 19 ] ] # Rank = 108, number of unknowns = 130 10 : [ ] ### So the decompositions of the restrictions of \chi_n for n = 3 ... 9 are ### determined. ### For the program chifaithful we need the fusions for the first two ### columns of all Clifford matrices. These are not all known so far. # gap> unknown := Difference( Cartesian([1..60],[1,2]), computedfusions() ); # [ [ 46, 2 ], [ 47, 2 ], [ 53, 1 ], [ 53, 2 ], [ 54, 1 ], [ 54, 2 ], # [ 59, 1 ], [ 60, 1 ] ] # # gap> for x in unknown do # > Print(x, " ", posfusdec(x[1],x[2],[1..4]), " ", # > ClassNames(ctb){posfusdec(x[1],x[2],[1..4])}, "\n" ); # > od; # [ 46, 2 ] [ 143, 144 ] [ "30g", "30h" ] # [ 47, 2 ] [ 143, 144 ] [ "30g", "30h" ] # [ 53, 1 ] [ 112, 113 ] [ "23a", "23b" ] # [ 53, 2 ] [ 170, 171 ] [ "46a", "46b" ] # [ 54, 1 ] [ 112, 113 ] [ "23a", "23b" ] # [ 54, 2 ] [ 170, 171 ] [ "46a", "46b" ] # [ 59, 1 ] [ 143, 144 ] [ "30g", "30h" ] # [ 60, 1 ] [ 143, 144 ] [ "30g", "30h" ] ### Thus the fusion of all g_{i,1}, g_{i,2} into B is determined with ### these 8 exceptions (compare [1] Section 4), ### for which we have 2 alternatives each. ### (In the last column we see the names of the corresponding ### conjugacy classes of B.) ### In [1] Section 4 a consistent choice was established for ### the so far undetermined cases, which we now enter for further use: # gap> y := [ 143, 144, 112, 170, 113, 171, 143, 144 ];; # gap> for i in [1..8] do # > clif[ unknown[i][1] ].fus[ unknown[i][2] ] := y[i]; # > od; # gap> Length(computedfusions()); # 167 # # gap> li := chifaithful( Irr(ctb)[10] ); # [ 1, 3, 4, 4, 6, 14, 14, 18, 19, 33 ] ### These are (the indices of) the irreducible constituents (with ### multiplicities) of the faithful part of \chi_10|_G . ######################### END EXAMPLE compmatm :=function( n, m ) # Returns [ mat , rhs ] with # mat = [ \hat \psi_k^{(m)}(\bar y_{il}^m) ] (see [1] Lemma 5 (9)) # with rowindices { k | \hat \psi_k^{(m)} \in charcands( n )[m] } and # column indices I = { (i,l) | i \in ccl , [m,l] \in rowindices(i) } # where ccl = { i | clif[i].mat and clif[i].fus known } and # rhs = [ (\chi_n , c_{m,l}^i ) ]_{(i,l) \in I} (see [1] (8) ). # If the system of eqs # mat x = rhs has a unique solution, this gives the decomposition # of \chi_n^{(m)} . This will be computed by decompm below # local charli, mat, k, i, j, x, li , rows, rhs, ccl; charli:= charcands( n )[m]; mat:=[]; rhs := []; ccl := Intersection( computedcliffordmats(), computedallfusions() ); for k in [1..Length(charli)] do mat[k] :=[]; rhs := []; for i in ccl do rows:= Filtered([1..Length(clif[i].mat)], x -> rowindices(i)[x][1] = m ); li := List( Filtered( rowindices(i), x -> x[1] = m ), y -> y[2] ); if li <> [] then Append(mat[k] , charli[k]{li} ); Append(rhs , List( rows , x -> scp( Irr(ctb)[n] , i , x) ) ); fi; od; od; return([mat,rhs]); end; decompm:= function( n, m ) # Returns for \chi_n \in Irr(B) the list res such that # \chi_n^{(m)} = \sum_{k \in res} \psi_k^{(m)} (see Lemma 5 of[1]) # or [], in case Rank(compmatm(n, m)[1]) is too small. # local charli, q, a ,j ,k, sol, res, re, rre; charli := charcands( n)[m]; q := compmatm ( n, m ); res:=[]; if q[1] <> [] then if Rank(q[1]) = Length(charli) then re:= SolutionMat(q[1],q[2]); for j in [1..Length(charli)] do for k in [1..re[j]] do Append(res , constituents( cts[m], charli[j]) ); od; od; else Print("\n Rank = ",Rank(q[1])," , number of unknowns = ",Length(charli), " "); fi; fi; return(res); end; ###### EXAMPLE 21 # gap> deco[2]:= [ [ 2 ], [ 2 ], [ ], [ ], [ ], [ ], [ 1 ] ];; # gap> enterposfusdec( [1,2] ); # gap> for n in [3..7] do deco[n] := decomps( n ); od; # gap> enterposfusdec( [1..7] ); # # gap> decompm( 7, 2 ); # [ 2, 2, 4, 8 ] # gap> last = deco[7][2]; # true ###### END EXAMPLE ####### Programs computing candidates of columns of Clifford matrices #### xmatrix := function( r, i ) # Computes the matrix X_r^i (see [1] Section 6) # Here r <= Length( deco ) local m, n, j, k, x, rows, c; x := []; for n in [1..r] do x[n] := [] ; for m in [1..Length(cts)] do rows := Filtered([1..Length(clif[i].mat)] , j -> rowindices(i)[j][1] = m ); for k in rows do if IsBound( deco[n][m]) and deco[n][m] <> [] then Add(x[n] , Sum(Irr(cts[m]){deco[n][m]})[rowindices(i)[k][2]] ); else Add(x[n] , 0); fi; od; od; od; return(x); end; findlinindrows := function( mat ) # For an m x n (integer) matrix mat of rank r > 0 returns # l := [ i_1 ,..., i_r ] such that mat{l}{[1..n]} has rank r. local i,l,r,ma ; r := Rank(mat); l := Filtered(mat, y -> Rank([y])<> 0); if l <> [] then ma:=[l[1]]; l:=[Position(mat,ma[1])]; i:=1; while Rank(ma) < r do i:=i+1; if Rank(Concatenation(ma,[mat[i]])) > Rank(ma) then Add(ma,mat[i]);Add(l,i); fi; od; fi; return(l); end; candidatesforcolumns := function( r, i ) # If x := xmatrix( r, i ) and Rank(x) = s_i # function returns [ mat , f ] , where # mat is an (s_i x m)-matrix such that the columns 3,..., s_i # of the i-th Clifford matrix are among the columns of mat # and f = [f_1, ... f_m] gives the fusion of the corresponding classes # of G into B . Thus if m = s_i - 2 one obtains # clif[i].mat{[1..s_i]}{[3..s_i]} (with s_i = clif[i].size] and # clif[i].fus{[3..s_i]}. # If Rank(x) < s_i [] is returned and info about Rank(x) printed. # local x, y, z, li, sel, pos ; x := xmatrix( r, i ); pos:= posfus( i ); y := Irr(ctb){[ 1..r ]}{pos}; sel := findlinindrows(x); x := x{sel} ; y := y{sel}; if Length(x) = Length( x[1] ) and Rank(x) = Length(x) then z := x^-1 * y ; li := Filtered([1..Length(z[1])] , j -> column(z,j)[Length(x)] = 0 and ForAll(column(z,j), a -> IsInt(a)) and IsInt( SizesCentralizers(ctb)[pos[j]]/sizescentc(i,column(z,j)) ) and scpcols( i, column(clif[i].mat,1), column(z,j) ) = 0 ); li := Filtered( li, j -> Length(Filtered (li , k -> scpcols( i, column(z,j), column(z,k) ) = 0) ) >= Rank(x) -3 ) ; return( [ z{[1..Length(x)]}{li}, pos{li}] ); else Print("\n i = ",i," rank(X) = ",Rank(x)," s_i = ", Length(x[1]),"\n"); return([]); fi; end; ######################## EXAMPLE 22 # gap> deco[2]:= [ [ 2 ], [ 2 ], [ ], [ ], [ ], [ ], [ 1 ] ];; # gap> enterposfusdec( [1,2] ); # gap> for n in [3..7] do deco[n] := decomps( n ); od; # gap> enterposfusdec( [1..7] ); # gap> for n in [8,9] do deco[n] := decomps( n ); od; # # gap> c :=candidatesforcolumns( 6, 17 ); # [ [ [ 1, 1, 1, 1 ], [ 1, -1, -1, 1 ], [ -4, -2, 2, 0 ], [ 6, 0, 0, -2 ], # [ -4, 2, -2, 0 ], [ 0, 0, 0, 0 ] ], # [ 26, 30, 65, 67 ] ] # gap> clif[17].size; # 6 # gap> ClassNames(ctb){c[2]}; # [ "6g", "6k", "12k", "12m" ] ### For the 4 missing columns of clif[17].mat we have exactly 4 candidates, ### the 4 columns of c[1]. Also the fusion into B has been determined. We ### apply the program to the missing Clifford matrices of Lengths 4 ... 9 ### and enter the uniquely determined Clifford matrices: # gap> l := List( [4..9] , i -> Difference( clifsoflength(i), # computedcliffordmats()) ); # [ [ 5, 16 ], [ ], [ 7, 17, 25, 26, 36 ], [ 23, 35, 37 ], [ 10, 15, 22, 42 ], # [ 13, 18, 28, 31, 39 ] ] # gap> Sum(List (last, Length) ); # 19 ### # gap> for i in Concatenation(l) do # > c :=candidatesforcolumns( 9, i ); # > if c <> [] and Length(c[2]) = clif[i].size -2 then # > for k in [2..clif[i].size -1] do # > Append(clif[i].mat[k],c[1][k]); # > od; # > clif[i].fus{[3..clif[i].size]} := c[2]; # > fi; # > od; # i = 25 rank(X) = 5 s_i = 6 # i = 26 rank(X) = 5 s_i = 6 # i = 10 rank(X) = 7 s_i = 8 # i = 15 rank(X) = 7 s_i = 8 # i = 22 rank(X) = 6 s_i = 8 # i = 42 rank(X) = 6 s_i = 8 # i = 13 rank(X) = 6 s_i = 9 # i = 28 rank(X) = 8 s_i = 9 # i = 31 rank(X) = 8 s_i = 9 # gap> l := List( [4..9] , i -> Difference( clifsoflength(i), # computedcliffordmats()) ); # [ [ ], [ ], [ 25, 26 ], [ ], [ 10, 15, 22, 42 ], [ 13, 28, 31 ] ] # gap> Sum(List (last, Length) ); # 9 ### Thus of the 19 Clifford matrices of Lengths 4 ... 9 only 9 have been ### left open by the procedure. ################# END EXAMPLE findrows := function( r, i ) # Function returns [ pos, res, rownr ] with # rownr <= [ 1..s_i] a subset of the rowindices of clif[i].mat # res is a matrix which contains all possible columns of # the matrix clif[i].mat_{j in rownr , k= 1,..s_i} . # from the matrix res by (possibly) deleting some columns. # pos gives the conjugacy classes of B which correspond to the # columns of res. It contains all entries of clif[i].fus . # local j, k, x, y, yy, n, sel, pos, posn, rownr, res, uv; x := xmatrix( r, i ) ; y := Irr(ctb){[1..r]}{posfus(i)}; sel := findlinindrows( x) ; pos := posfus( i ); for k in Difference( [1..r] , sel ) do pos := pos{Positions( SolutionMat(x{sel}, x[k])*y{sel} - y[k] , 0)}; y := Irr(ctb){[1..r]}{pos}; od; n := Length( x[1] ); rownr := []; res:= []; for k in [ 1..n ] do uv := List([1..n], i -> 0); uv[k] := 1; if not SolutionMat( x{sel} , uv ) = fail then yy := SolutionMat( x{sel} , uv ) * y{sel}; Add( rownr, k ); res[k] := SolutionMat( x{sel} , uv) * y{sel}; fi; od; sel:= []; for k in [1..Length(pos)] do if ForAll( rownr , j -> IsInt (res[j][k]) and AbsInt(res[j][k]) <= clif[i].mat[j][1] ) then Add ( sel, k ); fi; od; pos := pos{sel}; for k in rownr do res[k] := res[k]{sel}; od; return( [ pos, res, rownr ] ); end; ######################## EXAMPLE 23 # gap> deco[2]:= [ [ 2 ], [ 2 ], [ ], [ ], [ ], [ ], [ 1 ] ];; # gap> enterposfusdec( [1,2] ); # gap> for n in [3..7] do deco[n] := decomps( n ); od; # gap> enterposfusdec( [1..7] ); # gap> for n in [8,9] do deco[n] := decomps( n ); od; # gap> i := 26;; c := findrows( 9 , i ); # [ [ 37, 39, 44, 45, 85 ], # [ [ 1, 1, 1, 1, 1 ], [ 1, 1, 1, -1, 1 ], [ 2, 2, 2, 0, -2 ],,, # [ -4, 4, 0, 0, 0 ] ], # [ 1, 2, 3, 6 ] ] # gap> ClassNames(ctb){ c[1] }; # [ "8f", "8h", "8m", "8n", "16c" ] # ### So we have 3 possible classes of B in which the 4 missing classes ### g_{i,3}^G,...g_{i,6}^G fuse. (Recall that the first two columns and ### the fusion of the first two classes are already known.) Also for the ### 4 columns of the submatrix consisting of the rows [ 1, 2, 3, 6 ] and ### columns [3 .. 8] we just have 3 possibilities. Only the values of the ### 4th and 5th rows are not yet known, but these are very easy to find, ### see [1] Section 6. ###### END EXAMPLE ######################## EXAMPLE 24 ################################# # ### Here we compute the character table of 2_+^{1+8}.S_6(2), ### a maximal subgroup of Co_2 , using the table of marks of ### \bar G := S_6(2) . # # gap> t:=TableOfMarks("S6(2)");; ct:=CharacterTable("S6(2)");; # gap> pc:=PermCharsTom(ct,t);; # gap> Display( ct mod 2 ,rec(chars:=[3],powermap:=false,centralizers:=false)); # S6(2)mod2 # 1a 3a 3b 3c 5a 7a 9a 15a # # X.3 8 -4 -1 2 -2 1 -1 1 # ### This is the 2-Brauer character of the irreducible module \bar N = 2^8. ### It shows that the elements of 5a have no fixed points on \bar N \ {0}. ### This helps for finding the transitive permutation characters of \bar G ### on the orbits in \bar N \ {0}: # # gap> pcc:=Filtered(pc,y -> y[1] < 2^8 and y[Position(ClassNames(ct),"5a")]=0); # [ Character( CharacterTable( "S6(2)" ), [ 240, 0, 48, 0, 0, 0, 6, 12, 8, 0, # 0, 8, 0, 0, 0, 0, 6, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 2, 0 ] ), # Character( CharacterTable( "S6(2)" ), [ 135, 15, 39, 15, 7, 0, 0, 9, 3, 3, # 3, 11, 3, 0, 0, 0, 0, 0, 3, 3, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0 ] ), # Character( CharacterTable( "S6(2)" ), [ 120, 0, 24, 0, 8, 0, 3, 6, 12, 0, # 0, 4, 0, 0, 0, 0, 3, 0, 0, 0, 2, 1, 2, 2, 0, 0, 0, 0, 3, 0 ] ) ] # ### Thus \bar G has orbits of length 135 and 120 on \bar N \ {0}. We take ### the stabilizers (from the table of marks) and compute their character ### tables: # gap> ct2 := CharacterTable( RepresentativeTom( t, Position(pc,pcc[2]) ) );; # gap> ct3 := CharacterTable( RepresentativeTom( t, Position(pc,pcc[3]) ) );; # gap> cts := [ ct, ct2, ct3, ct ];; # gap> f2 := RepresentativesFusions( AutomorphismsOfTable(ct2), # > PossibleClassFusions(ct2,ct), AutomorphismsOfTable(ct) );; # gap> f3 := PossibleClassFusions( cts[3], ct );; # gap> [Length(f2),Length(f3)]; # [ 1, 1 ] # gap> fus := [ [1..Length(Irr(ct))], f2[1], f3[1], [1..Length(Irr(ct))] ];; # gap> ctb := CharacterTable("Co2");; # gap> perm := PermChars( ctb , Size(ctb)/(2^9 * Size(ct) ));; Length(perm); # 1 # gap> perm := perm[1];; # gap> deco := [ [[1] , [], [], [] ], # > [[2] , [], [], [1]] ];; # gap> clif := List ( [1..Length( Irr(cts[1]) ) ] , i -> # > rec( size:=[], fus := [] , rho:= [], wei := [], mat := [] ) );; # gap> clif[1].mat{ [2,3] } := [ [ 135, 135, 7, -9], [ 120, 120, -8, 8 ] ];; # gap> clif[1].fus := [ 1, 2, 3, 7 ];; # # # gap> initializeCliffordMatrices();; # gap> enterposfusdec( [ 1, 2 ] );; # gap> for n in [3..9] do deco[n] := decomps(n); od; # gap> for i in Difference([1..Length(clif)],computedcliffordmats()) do # > c := candidatesforcolumns( 9, i ); # > if c <> [] and Length(c[2]) = clif[i].size - 2 then # > for k in [2..clif[i].size -1] do # > Append( clif[i].mat[k], c[1][k]); # > od; # > clif[i].fus{[3..clif[i].size]} := c[2]; # > fi; # > od; # gap> computedcliffordmats() = [1..Length(clif)]; # true # ### All Clifford matrices have been computed. We produce from this the ### character table ctg of G = 2_+^{1+8}.S_6(2) : # # gap> ctg :=[];; # gap> for i in [1..Length(clif)] do # > for j in [1..clif[i].size] do # > Add( ctg , columnct(i,j) ); # > od; # > od; # gap> ctg := TransposedMat( ctg );; # ### We compare this table with the table taken from the library: # # gap> ctlib := CharacterTable( Maxes(ctb)[4] ); # CharacterTable( "2^1+8:s6f2" ) # gap> TransformingPermutations( ctg , Irr(ctlib) ); # rec( columns := (5,57,91,83,48,70,96,9,36,64,99,78,89,76,45,51,73,41,69,97,11, # 34,18,63,98,8,35,17,62,84,46,50,72,95,12,33,16,40,68,7,58,15,39,67,6,56, # 90,82,49,71,94,10,32,20,60,14,38,66)(13,37,65,100,79,86,24,23,31,19, # 59)(21,61,85,47,52,74,43,53,75,42,54,92,81,88,77,44,55,93,80,87,25)(22,30, # 28,27,26), rows := (13,14)(18,19)(31,61,65,69,70,66,79,39,67,64,77,37,86, # 46,73,33,99,59,78,38,72,32,100,60,63,76,36,93,53,95,55,62,80,40,96,56,75, # 35,85,45,74,34,84,43,97,57,83,44,98,58,82,42,88,49,91,51,92,52,68,81,41, # 87,47,90,50,89,48,71)(54,94), group := Group([ (9,11), (42,45) ]) ) # ### Thus the tables agree except for the ordering of the rows and columns. # # ###################### END EXAMPLE ################################## ### end of file