Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/ref/ctbl.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -606,7 +607,7 @@ gap> SetInfoLevel( InfoCharacterTable, 0 );
<#Include Label="FactorsOfDirectProduct">
<#Include Label="CharacterTableFactorGroup">
<#Include Label="CharacterTableIsoclinic">
<!-- %Declaration{CharacterTableOfNormalSubgroup} -->
<#Include Label="CharacterTableOfNormalSubgroup">
<#Include Label="CharacterTableWreathSymmetric">

</Section>
Expand Down
73 changes: 58 additions & 15 deletions lib/ctbl.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,7 @@ DeclareAttribute( "ClassPositionsOfFittingSubgroup", IsOrdinaryTable );
##
#A ClassPositionsOfSolvableRadical( <ordtbl> )
##
## <#GAPDoc Label="ClassPositionsOfSolvableRadical">
## <ManSection>
## <Attr Name="ClassPositionsOfSolvableRadical" Arg='ordtbl'/>
##
Expand All @@ -2052,6 +2053,7 @@ DeclareAttribute( "ClassPositionsOfFittingSubgroup", IsOrdinaryTable );
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareAttribute( "ClassPositionsOfSolvableRadical",
IsOrdinaryTable );
Expand Down Expand Up @@ -3638,7 +3640,7 @@ DeclareGlobalFunction( "PrintCharacterTable" );
## and return a character table.
## This holds also for <Ref Oper="BrauerTable"
## Label="for a character table, and a prime integer"/>.
## note that the return value of <Ref Oper="BrauerTable"
## Note that the return value of <Ref Oper="BrauerTable"
## Label="for a character table, and a prime integer"/>
## will in general not know the irreducible Brauer characters,
## and &GAP; might be unable to compute these characters.
Expand Down Expand Up @@ -3895,24 +3897,65 @@ DeclareAttributeSuppCT( "SourceOfIsoclinicTable", IsNearlyCharacterTable,
##
#F CharacterTableOfNormalSubgroup( <ordtbl>, <classes> )
##
## <#GAPDoc Label="CharacterTableOfNormalSubgroup">
## <ManSection>
## <Func Name="CharacterTableOfNormalSubgroup" Arg='ordtbl, classes'/>
##
## <Description>
## returns the restriction of the ordinary character table <A>ordtbl</A>
## to the classes in the list <A>classes</A>.
## <P/>
## 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&nbsp;<Ref Func="CharacterTableSplitClasses"/>) in order to get
## a character table.
## The result is only a table in progress then
## (see&nbsp;<Ref Sect="Character Table Categories"/>).
## <P/>
## If the classes in <A>classes</A> need not to be split then the result is
## a proper character table.
## Let <A>ordtbl</A> be the ordinary character table of a group <M>G</M>,
## say, and <A>classes</A> be a list of class positions for this table.
## If the classes given by <A>classes</A> form a normal subgroup <M>N</M>,
## say, of <M>G</M> and if these classes are conjugacy classes of <M>N</M>
## then this function returns the character table of <M>N</M>.
## In all other cases, the function returns <K>fail</K>.
## <P/>
## <Example><![CDATA[
## gap> 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 ])" ) ]
## ]]></Example>
## <P/>
## Here is a nontrivial example.
## We use <Ref Func="CharacterTableOfNormalSubgroup"/> for computing the
## two isoclinic variants of <M>2.A_5.2</M>.
## <P/>
## <Example><![CDATA[
## gap> g:= SchurCoverOfSymmetricGroup( 5, 3, 1 );;
## gap> c:= CyclicGroup( 4 );;
## gap> dp:= DirectProduct( g, c );;
## gap> diag:= First( Elements( Centre( dp ) ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: Using Elements here is not needed, it's perfectly fine to do First( 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
## ]]></Example>
## <P/>
## Alternatively, we could construct the character table of the central
## product with character theoretic methods.
## Or we could use <Ref Oper="CharacterTableIsoclinic"/>.
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareGlobalFunction( "CharacterTableOfNormalSubgroup" );

Expand Down Expand Up @@ -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 ]
Expand Down
137 changes: 49 additions & 88 deletions lib/ctbl.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1235,39 +1235,6 @@ InstallGlobalFunction( CharacterTable_IsNilpotentFactor, function( tbl, N )
end );


#############################################################################
##
#F CharacterTable_IsNilpotentNormalSubgroup( <tbl>, <N> )
##
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( <tbl> )
Expand Down Expand Up @@ -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] ] );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: This could also be changed to fak := PrimeDivisors( tbl_centralizers[ classes[i] ] );, then the call to Set in the next line and the check for prime <> 1 later would not be needed.

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
Expand Down Expand Up @@ -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( "<tbl> must be an ordinary character table" );
Expand All @@ -6215,68 +6184,36 @@ InstallGlobalFunction( CharacterTableOfNormalSubgroup,
size:= Sum( sizesclasses );

if Size( tbl ) mod size <> 0 then
Error( "<classes> is not a normal subgroup" );
# <classes> 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,
Expand All @@ -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 );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think calling ConvertToStringRep here is needed (but I see that this was just copied from the existing code, so it's OK to leave it in)


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 );
Expand Down
9 changes: 9 additions & 0 deletions tst/testinstall/ctbl.tst
Original file line number Diff line number Diff line change
Expand Up @@ -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" );
Expand Down