diff --git a/doc/ref/ctbl.xml b/doc/ref/ctbl.xml index ab00df103a..f065f723c7 100644 --- a/doc/ref/ctbl.xml +++ b/doc/ref/ctbl.xml @@ -280,6 +280,7 @@ The following few conventions should be noted. <#Include Label="ClassPositionsOfFittingSubgroup"> <#Include Label="ClassPositionsOfLowerCentralSeries"> <#Include Label="ClassPositionsOfUpperCentralSeries"> +<#Include Label="ClassPositionsOfSolvableRadical"> <#Include Label="ClassPositionsOfSupersolvableResiduum"> <#Include Label="ClassPositionsOfPCore"> <#Include Label="ClassPositionsOfNormalClosure"> @@ -606,7 +607,7 @@ gap> SetInfoLevel( InfoCharacterTable, 0 ); <#Include Label="FactorsOfDirectProduct"> <#Include Label="CharacterTableFactorGroup"> <#Include Label="CharacterTableIsoclinic"> - +<#Include Label="CharacterTableOfNormalSubgroup"> <#Include Label="CharacterTableWreathSymmetric"> diff --git a/lib/ctbl.gd b/lib/ctbl.gd index 7fe335e625..8f6f7cfa5a 100644 --- a/lib/ctbl.gd +++ b/lib/ctbl.gd @@ -2039,6 +2039,7 @@ DeclareAttribute( "ClassPositionsOfFittingSubgroup", IsOrdinaryTable ); ## #A ClassPositionsOfSolvableRadical( ) ## +## <#GAPDoc Label="ClassPositionsOfSolvableRadical"> ## ## ## @@ -2052,6 +2053,7 @@ DeclareAttribute( "ClassPositionsOfFittingSubgroup", IsOrdinaryTable ); ## ]]> ## ## +## <#/GAPDoc> ## DeclareAttribute( "ClassPositionsOfSolvableRadical", IsOrdinaryTable ); @@ -3638,7 +3640,7 @@ DeclareGlobalFunction( "PrintCharacterTable" ); ## and return a character table. ## This holds also for . -## note that the return value of ## will in general not know the irreducible Brauer characters, ## and &GAP; might be unable to compute these characters. @@ -3895,24 +3897,65 @@ DeclareAttributeSuppCT( "SourceOfIsoclinicTable", IsNearlyCharacterTable, ## #F CharacterTableOfNormalSubgroup( , ) ## +## <#GAPDoc Label="CharacterTableOfNormalSubgroup"> ## ## ## ## -## returns the restriction of the ordinary character table ordtbl -## to the classes in the list classes. -##

-## In most cases, this table is only an approximation of the character table -## of this normal subgroup, and some classes of the normal subgroup must be -## split (see ) in order to get -## a character table. -## The result is only a table in progress then -## (see ). -##

-## If the classes in classes need not to be split then the result is -## a proper character table. +## Let ordtbl be the ordinary character table of a group G, +## say, and classes be a list of class positions for this table. +## If the classes given by classes form a normal subgroup N, +## say, of G and if these classes are conjugacy classes of N +## then this function returns the character table of N. +## In all other cases, the function returns fail. +##

+## t:= CharacterTable( "Symmetric", 4 ); +## CharacterTable( "Sym(4)" ) +## gap> nsg:= ClassPositionsOfNormalSubgroups( t ); +## [ [ 1 ], [ 1, 3 ], [ 1, 3, 4 ], [ 1 .. 5 ] ] +## gap> rest:= List( nsg, c -> CharacterTableOfNormalSubgroup( t, c ) ); +## [ CharacterTable( "Rest(Sym(4),[ 1 ])" ), fail, fail, +## CharacterTable( "Rest(Sym(4),[ 1 .. 5 ])" ) ] +## ]]> +##

+## Here is a nontrivial example. +## We use for computing the +## two isoclinic variants of 2.A_5.2. +##

+## g:= SchurCoverOfSymmetricGroup( 5, 3, 1 );; +## gap> c:= CyclicGroup( 4 );; +## gap> dp:= DirectProduct( g, c );; +## gap> diag:= First( Elements( Centre( dp ) ), +## > x -> Order( x ) = 2 and +## > not x in Image( Embedding( dp, 1 ) ) and +## > not x in Image( Embedding( dp, 2 ) ) );; +## gap> fact:= Image( NaturalHomomorphismByNormalSubgroup( dp, +## > Subgroup( dp, [ diag ] ) ));; +## gap> t:= CharacterTable( fact );; +## gap> Size( t ); +## 480 +## gap> nsg:= ClassPositionsOfNormalSubgroups( t );; +## gap> rest:= List( nsg, c -> CharacterTableOfNormalSubgroup( t, c ) );; +## gap> index2:= Filtered( rest, x -> x <> fail and Size( x ) = 240 );; +## gap> Length( index2 ); +## 2 +## gap> tg:= CharacterTable( g );; +## gap> IsRecord( +## > TransformingPermutationsCharacterTables( index2[1], tg ) ); +## false +## gap> IsRecord( +## > TransformingPermutationsCharacterTables( index2[2], tg ) ); +## true +## ]]> +##

+## Alternatively, we could construct the character table of the central +## product with character theoretic methods. +## Or we could use . ## ## +## <#/GAPDoc> ## DeclareGlobalFunction( "CharacterTableOfNormalSubgroup" ); @@ -4393,11 +4436,11 @@ DeclareGlobalFunction( "NormalSubgroupClasses" ); ## Character( CharacterTable( S4 ), [ 3, 1, -1, 0, -1 ] ), ## Character( CharacterTable( S4 ), [ 1, 1, 1, 1, 1 ] ) ] ## gap> kernel:= KernelOfCharacter( irr[3] ); -## Group([ (1,2)(3,4), (1,4)(2,3) ]) +## Group([ (1,2)(3,4), (1,3)(2,4) ]) ## gap> HasNormalSubgroupClassesInfo( tbl ); ## true ## gap> NormalSubgroupClassesInfo( tbl ); -## rec( nsg := [ Group([ (1,2)(3,4), (1,4)(2,3) ]) ], +## rec( nsg := [ Group([ (1,2)(3,4), (1,3)(2,4) ]) ], ## nsgclasses := [ [ 1, 3 ] ], nsgfactors := [ ] ) ## gap> ClassPositionsOfNormalSubgroup( tbl, kernel ); ## [ 1, 3 ] diff --git a/lib/ctbl.gi b/lib/ctbl.gi index a6a32c63e9..e5f5fe8856 100644 --- a/lib/ctbl.gi +++ b/lib/ctbl.gi @@ -1235,39 +1235,6 @@ InstallGlobalFunction( CharacterTable_IsNilpotentFactor, function( tbl, N ) end ); -############################################################################# -## -#F CharacterTable_IsNilpotentNormalSubgroup( , ) -## -InstallGlobalFunction( CharacterTable_IsNilpotentNormalSubgroup, - function( tbl, N ) - - local classlengths, # class lengths - orders, # orders of class representatives - ppow, # list of classes of prime power order - part, # one pair `[ prime, exponent ]' - classes; # classes of p power order for a prime p - - # Take the classes of prime power order. - classlengths:= SizesConjugacyClasses( tbl ); - orders:= OrdersClassRepresentatives( tbl ); - ppow:= Filtered( N, i -> IsPrimePowerInt( orders[i] ) ); - - for part in Collected( Factors(Integers, Sum( classlengths{ N }, 0 ) ) ) do - - # Check whether the Sylow p subgroup of `N' is normal in `N', - # i.e., whether the number of elements of p-power is equal to - # the size of a Sylow p subgroup. - classes:= Filtered( ppow, i -> orders[i] mod part[1] = 0 ); - if part[1] ^ part[2] <> Sum( classlengths{ classes }, 0 ) + 1 then - return false; - fi; - - od; - return true; - end ); - - ############################################################################# ## #M IsNilpotentCharacterTable( ) @@ -5006,9 +4973,11 @@ BindGlobal( "CharacterTableDisplayDefault", function( tbl, options ) elif centralizers = true then Print( "\n" ); for i in [col..col+acol-1] do - fak:= Factors(Integers, tbl_centralizers[classes[i]] ); + fak:= Factors( Integers, tbl_centralizers[ classes[i] ] ); for prime in Set( fak ) do - cen[prime][i]:= Number( fak, x -> x = prime ); + if prime <> 1 then + cen[prime][i]:= Number( fak, x -> x = prime ); + fi; od; od; for j in [1..Length(cen)] do @@ -6199,13 +6168,13 @@ InstallGlobalFunction( CharacterTableOfNormalSubgroup, nccl, # no. of classes orders, # repr. orders of the result centralizers, # centralizer orders of the result - result, # result table err, # list of classes that must split - inverse, # inverse map of `classes' - p, # loop over primes irreducibles, # list of irred. characters chi, # loop over irreducibles of `tbl' - char; # one character values list for `result' + char, # one character values list for `result' + result, # result table + inverse, # inverse map of `classes' + p; # loop over primes if not IsOrdinaryTable( tbl ) then Error( " must be an ordinary character table" ); @@ -6215,68 +6184,36 @@ InstallGlobalFunction( CharacterTableOfNormalSubgroup, size:= Sum( sizesclasses ); if Size( tbl ) mod size <> 0 then - Error( " is not a normal subgroup" ); + # does not form a normal subgroup. + return fail; fi; nccl:= Length( classes ); orders:= OrdersClassRepresentatives( tbl ){ classes }; centralizers:= List( sizesclasses, x -> size / x ); - result:= Concatenation( "Rest(", Identifier( tbl ), ",", - String( classes ), ")" ); - ConvertToStringRep( result ); - - result:= rec( - UnderlyingCharacteristic := 0, - Identifier := result, - Size := size, - SizesCentralizers := centralizers, - SizesConjugacyClasses := sizesclasses, - OrdersClassRepresentatives := orders, - ComputedPowerMaps := [] ); - err:= Filtered( [ 1 .. nccl ], - x-> centralizers[x] mod orders[x] <> 0 ); + x -> not IsInt( centralizers[x] / orders[x] ) ); if not IsEmpty( err ) then Info( InfoCharacterTable, 2, "CharacterTableOfNormalSubgroup: classes in " , err, " necessarily split" ); + return fail; fi; - inverse:= InverseMap( classes ); - for p in [ 1 .. Length( ComputedPowerMaps( tbl ) ) ] do - if IsBound( ComputedPowerMaps( tbl )[p] ) then - result.ComputedPowerMaps[p]:= MakeImmutable( - CompositionMaps( inverse, - CompositionMaps( ComputedPowerMaps( tbl )[p], classes ) ) ); + # Compute the irreducibles. + irreducibles:= []; + for chi in Irr( tbl ) do + char:= ValuesOfClassFunction( chi ){ classes }; + if Sum( [ 1 .. nccl ], + i -> sizesclasses[i] * char[i] * GaloisCyc(char[i],-1), 0 ) + = size + and not char in irreducibles then + Add( irreducibles, MakeImmutable( char ) ); fi; od; - # Compute the irreducibles if known. - irreducibles:= []; - if HasIrr( tbl ) then - - for chi in Irr( tbl ) do - char:= ValuesOfClassFunction( chi ){ classes }; - if Sum( [ 1 .. nccl ], - i -> sizesclasses[i] * char[i] * GaloisCyc(char[i],-1), 0 ) - = size - and not char in irreducibles then - Add( irreducibles, MakeImmutable( char ) ); - fi; - od; - - fi; - - if Length( irreducibles ) = nccl then - - result.Irr:= irreducibles; - - # Convert the record into a library table. - ConvertToLibraryCharacterTableNC( result ); - - else - + if Length( irreducibles ) <> nccl then p:= Size( tbl ) / size; if IsPrimeInt( p ) and not IsEmpty( irreducibles ) then Info( InfoCharacterTable, 2, @@ -6286,11 +6223,35 @@ InstallGlobalFunction( CharacterTableOfNormalSubgroup, "#I (now ", Length( classes ), ", after nec. splitting ", Length( classes ) + (p-1) * Length( err ), ")" ); fi; + return fail; + fi; - Error( "tables in progress not yet supported" ); -#T !! + result:= Concatenation( "Rest(", Identifier( tbl ), ",", + String( classes ), ")" ); + ConvertToStringRep( result ); - fi; + result:= rec( + UnderlyingCharacteristic := 0, + Identifier := MakeImmutable( result ), + Size := size, + SizesCentralizers := MakeImmutable( centralizers ), + SizesConjugacyClasses := MakeImmutable( sizesclasses ), + OrdersClassRepresentatives := MakeImmutable( orders ), + ComputedPowerMaps := [], + Irr := irreducibles ); + + inverse:= InverseMap( classes ); + + for p in [ 1 .. Length( ComputedPowerMaps( tbl ) ) ] do + if IsBound( ComputedPowerMaps( tbl )[p] ) then + result.ComputedPowerMaps[p]:= MakeImmutable( + CompositionMaps( inverse, + CompositionMaps( ComputedPowerMaps( tbl )[p], classes ) ) ); + fi; + od; + + # Convert the record into a library table. + ConvertToLibraryCharacterTableNC( result ); # Store the fusion into `tbl'. StoreFusion( result, classes, tbl ); diff --git a/tst/testinstall/ctbl.tst b/tst/testinstall/ctbl.tst index e4de289b9d..95da8d1a9e 100644 --- a/tst/testinstall/ctbl.tst +++ b/tst/testinstall/ctbl.tst @@ -41,6 +41,15 @@ gap> ClassPositionsOfCentre( TrivialCharacter( t ) ); gap> ClassPositionsOfKernel( TrivialCharacter( t ) ); [ 1 ] +# Display for the table of the trivial group +gap> Display( CharacterTable( CyclicGroup( 1 ) ) ); +CT1 + + + 1a + +X.1 1 + # viewing and printing of character tables with stored groups gap> t:= CharacterTable( DihedralGroup( 8 ) );; gap> View( t ); Print( "\n" );