This chapter introduces class functions and group characters in GAP3.
First section Why Group Characters tells about the ideas why to use these structures besides the characters and character tables described in chapters Character Tables and Characters.
The subsequent section More about Class Functions tells details about the implementation of group characters and class functions in GAP3.
Sections Operators for Class Functions and Functions for Class Functions tell about the operators and functions for class functions and (virtual) characters.
Sections ClassFunction, VirtualCharacter, Character, and Irr describe how to construct such class functions and group characters.
Sections IsClassFunction, IsVirtualCharacter, and IsCharacter describe the characteristic functions of class functions and virtual characters.
Then sections InertiaSubgroup and OrbitsCharacters describe other functions for characters.
Then sections Storing Subgroup Information, NormalSubgroupClasses, ClassesNormalSubgroup, and FactorGroupNormalSubgroupClasses tell about some functions and record components to access and store frequently used (normal) subgroups.
The final section Class Function Records describes the records that implement class functions.
In this chapter, all examples use irreducible characters of the symmetric group S4. For running the examples, you must first define the group and its characters as follows.
gap> S4:= SolvableGroup( "S4" );; gap> irr:= Irr( S4 );;
When one says ``χ is a character of a group G'' then this object χ carries a lot of information. χ has certain properties such as being irreducible or not. Several subgroups of G are related to χ, such as the kernel and the centre of χ. And one can apply operators to χ, such as forming the conjugate character under the action of an automorphism of G, or computing the determinant of χ.
In GAP3, the characters known from chapters Character Tables and Characters are just lists of character values. This has several disadvantages. Firstly one cannot store knowledge about a character directly in the character, and secondly for every computation that requires more than just the character values one has to regard this list explicitly as a character belonging to a character table. In practice this means that the user has the task to put the objects into the right context, or --more concrete-- the user has to supply lots of arguments.
This works nicely for characters that are used without groups, like characters of library tables. And if one deals with incomplete character tables often it is necessary to specify the arguments explicitly, for example one has to choose a fusion map or power map from a set of possibilities.
But for dealing with a group and its characters, and maybe also subgroups and their characters, it is desirable that GAP3 keeps track of the interpretation of characters.
Because of this it seems to be useful to introduce an alternative concept where a group character in GAP3 is represented as a record that contains the character values, the underlying group or character table, an appropriate operations record, and all the knowledge about the group character.
Together with characters, also the more general class functions and virtual characters are implemented.
Here is an example that shows both approaches. First we define the groups.
gap> S4:= SolvableGroup( "S4" );; gap> D8:= SylowSubgroup( S4, 2 );; D8.name:= "D8";;
We do some computations using the functions described in chapters Characters and Character Tables.
gap> t := CharTable( S4 );; gap> tD8 := CharTable( D8 );; gap> FusionConjugacyClasses( D8, S4 );; gap> chi:= tD8.irreducibles[2]; [ 1, -1, 1, 1, -1 ] gap> Tensored( [ chi ], [ chi ] )[1]; [ 1, 1, 1, 1, 1 ] gap> ind:= Induced( tD8, t, [ chi ] )[1]; [ 3, -1, 0, 1, -1 ] gap> List( t.irreducibles, x -> ScalarProduct( t, x, ind ) ); [ 0, 0, 0, 1, 0 ] gap> det:= DeterminantChar( t, ind ); [ 1, 1, 1, -1, -1 ] gap> cent:= CentralChar( t, ind ); [ 1, -1, 0, 2, -2 ] gap> rest:= Restricted( t, tD8, [ cent ] )[1]; [ 1, -1, -1, 2, -2 ]
And now we do the same calculations with the class function records.
gap> irr := Irr( S4 );; gap> irrD8 := Irr( D8 );; gap> chi:= irrD8[2]; Character( D8, [ 1, -1, 1, 1, -1 ] ) gap> chi * chi; Character( D8, [ 1, 1, 1, 1, 1 ] ) gap> ind:= chi ^ S4; Character( S4, [ 3, -1, 0, 1, -1 ] ) gap> List( irr, x -> ScalarProduct( x, ind ) ); [ 0, 0, 0, 1, 0 ] gap> det:= Determinant( ind ); Character( S4, [ 1, 1, 1, -1, -1 ] ) gap> cent:= Omega( ind ); ClassFunction( S4, [ 1, -1, 0, 2, -2 ] ) gap> rest:= Character( D8, cent ); Character( D8, [ 1, -1, -1, 2, -2 ] )
Of course we could have used the Induce
and Restricted
function
also for lists of class functions.
gap> Induced( tD8, t, tD8.irreducibles{ [ 1, 3 ] } ); [ [ 3, 3, 0, 1, 1 ], [ 3, 3, 0, -1, -1 ] ] gap> Induced( irrD8{ [ 1, 3 ] }, S4 ); [ Character( S4, [ 3, 3, 0, 1, 1 ] ), Character( S4, [ 3, 3, 0, -1, -1 ] ) ]
If one deals with complete character tables then often the table provides enough information, so it is possible to use the table instead of the group.
gap> s5 := CharTable( "A5.2" );; irrs5 := Irr( s5 );; gap> m11:= CharTable( "M11" );; irrm11:= Irr( m11 );; gap> irrs5[2]; Character( CharTable( "A5.2" ), [ 1, 1, 1, 1, -1, -1, -1 ] ) gap> irrs5[2] ^ m11; Character( CharTable( "M11" ), [ 66, 2, 3, -2, 1, -1, 0, 0, 0, 0 ] ) gap> Determinant( irrs5[4] ); Character( CharTable( "A5.2" ), [ 1, 1, 1, 1, -1, -1, -1 ] )
In this case functions that compute normal subgroups related to characters will return the list of class positions corresponding to that normal subgroup.
gap> Kernel( irrs5[2] ); [ 1, 2, 3, 4 ]
But if we ask for non-normal subgroups of course there is no chance to get an answer without the group, for example inertia subgroups cannot be computed from character tables.
54.2 More about Class Functions
Let G be a finite group. A class function of G is a function from G into the complex numbers (or a subfield of the complex numbers) that is constant on conjugacy classes of G. Addition, multiplication, and scalar multiplication of class functions are defined pointwise. Thus the set of all class functions of G is an algebra (or ring, or vector space).
Class functions and (virtual) group characters
Every mapping with source G that is constant on conjugacy classes of G is called a class function of G. Differences of characters of G are called virtual characters of G.
Class functions occur in a natural way when one deals with characters. For example, the central character of a group character is only a class function.
Every character is a virtual character, and every virtual character is a
class function.
Any function or operator that is applicable to a class function can of
course be applied to a (virtual) group character. There are functions
only for (virtual) group characters, like IsIrreducible
, which doesn't
make sense for a general class function, and there are also functions
that do not make sense for virtual characters but only for characters,
like Determinant
.
Class functions as mappings
In GAP3, class functions of a group G are mappings (see chapter
Mappings) with source G and range Cyclotomics
(or a subfield).
All operators and functions for mappings (like Image Image
, PreImages
PreImages
) can be applied to class functions.
Note, however, that the operators *
and ^
allow also other
arguments than mappings do (see Operators for Class Functions).
54.3 Operators for Class Functions
chi = psi
chi < psi
Equality and comparison of class functions are defined as for mappings
(see Comparisons of Mappings); in case of equal source and range the
values
components are used to compute the result.
gap> irr[1]; irr[2]; Character( S4, [ 1, 1, 1, 1, 1 ] ) Character( S4, [ 1, 1, 1, -1, -1 ] ) gap> irr[1] < irr[2]; false gap> irr[1] > irr[2]; true gap> irr[1] = Irr( SolvableGroup( "S4" ) )[1]; false # The groups are different.
chi + psi
chi - psi
+
and -
denote the addition and subtraction of class functions.
n * chi
chi * psi
*
denotes (besides the composition of mappings,
see Operations for Mappings) the multiplication of a class function
chi with a scalar n and the tensor product of two class functions.
chi / n
/
denotes the division of the class function chi by a scalar n.
gap> psi:= irr[3] * irr[4]; Character( S4, [ 6, -2, 0, 0, 0 ] ) gap> psi:= irr[3] - irr[1]; VirtualCharacter( S4, [ 1, 1, -2, -1, -1 ] ) gap> phi:= psi * irr[4]; VirtualCharacter( S4, [ 3, -1, 0, -1, 1 ] ) gap> IsCharacter( phi ); phi; true Character( S4, [ 3, -1, 0, -1, 1 ] ) gap> psi:= ( 3 * irr[2] - irr[3] ) * irr[4]; VirtualCharacter( S4, [ 3, -1, 0, -3, 3 ] ) gap> 2 * psi ; VirtualCharacter( S4, [ 6, -2, 0, -6, 6 ] ) gap> last / 3; ClassFunction( S4, [ 2, -2/3, 0, -2, 2 ] )
chi ^ n
g ^ chi
denote the tensor power by a nonnegative integer n and the image of the group element g, like for all mappings (see Operations for Mappings).
chi ^ g
is the conjugate class function by the group element g, that must
be an element of the parent of the source of chi or something else that
acts on the source via ^
.
If chi.source
is not a permutation group then g may also be a
permutation that is interpreted as acting by permuting the classes
(This maybe useful for table characters.).
chi ^ G
is the induced class function.
gap> V4:= Subgroup( S4, S4.generators{ [ 3, 4 ] } ); Subgroup( S4, [ c, d ] ) gap> V4.name:= "V4";; gap> V4irr:= Irr( V4 );; gap> chi:= V4irr[3]; Character( V4, [ 1, -1, 1, -1 ] ) gap> chi ^ S4; Character( S4, [ 6, -2, 0, 0, 0 ] ) gap> chi ^ S4.2; Character( V4, [ 1, -1, -1, 1 ] ) gap> chi ^ ( S4.2 ^ 2 ); Character( V4, [ 1, 1, -1, -1 ] ) gap> S4.3 ^ chi; S4.4 ^ chi; 1 -1 gap> chi ^ 2; Character( V4, [ 1, 1, 1, 1 ] )
54.4 Functions for Class Functions
Besides the usual mapping functions (see chapter Mappings for
the details.), the following polymorphic functions are overlaid in
the operations
records of class functions and (virtual) characters.
They are listed in alphabetical order.
Centre( chi )
:
Constituents( chi )
:
Degree( chi )
:
Determinant( chi )
:
Display( chi )
:
Induced( list, G )
:
IsFaithful( chi )
:
IsIrreducible( chi )
:
Kernel( chi )
:
Norm( chi )
:
Omega( chi )
:
Print( chi )
:
Restricted( list, H )
:
ScalarProduct( chi, psi )
:
ClassFunction( G, values )
returns the class function of the group G with values list values.
ClassFunction( G, chi )
returns the class function of G corresponding to the class function chi of H. The group H can be a factor group of G, or G can be a subgroup or factor group of H.
gap> phi:= ClassFunction( S4, [ 1, -1, 0, 2, -2 ] ); ClassFunction( S4, [ 1, -1, 0, 2, -2 ] ) gap> coeff:= List( irr, x -> ScalarProduct( x, phi ) ); [ -1/12, -1/12, -1/6, 5/4, -3/4 ] gap> ClassFunction( S4, coeff ); ClassFunction( S4, [ -1/12, -1/12, -1/6, 5/4, -3/4 ] ) gap> syl2:= SylowSubgroup( S4, 2 );; gap> ClassFunction( syl2, phi ); ClassFunction( D8, [ 1, -1, -1, 2, -2 ] )
VirtualCharacter( G, values )
returns the virtual character of the group G with values list values.
VirtualCharacter( G, chi )
returns the virtual character of G corresponding to the virtual character chi of H. The group H can be a factor group of G, or G can be a subgroup or factor group of H.
gap> syl2:= SylowSubgroup( S4, 2 );; gap> psi:= VirtualCharacter( S4, [ 0, 0, 3, 0, 0 ] ); VirtualCharacter( S4, [ 0, 0, 3, 0, 0 ] ) gap> VirtualCharacter( syl2, psi ); VirtualCharacter( D8, [ 0, 0, 0, 0, 0 ] ) gap> S3:= S4 / V4; Group( a, b ) gap> VirtualCharacter( S3, irr[3] ); VirtualCharacter( Group( a, b ), [ 2, -1, 0 ] )
Note that it is not checked whether the result is really a virtual character.
Character( repres )
returns the character of the group representation repres.
Character( G, values )
returns the character of the group G with values list values.
Character( G, chi )
returns the character of G corresponding to the character chi with source H. The group H can be a factor group of G, or G can be a subgroup or factor group of H.
gap> syl2:= SylowSubgroup( S4, 2 );; gap> Character( syl2, irr[3] ); Character( D8, [ 2, 2, 2, 0, 0 ] ) gap> S3:= S4 / V4; Group( a, b ) gap> Character( S3, irr[3] ); Character( Group( a, b ), [ 2, -1, 0 ] ) gap> reg:= Character( S4, [ 24, 0, 0, 0, 0 ] ); Character( S4, [ 24, 0, 0, 0, 0 ] )
Note that it is not checked whether the result is really a character.
IsClassFunction( obj )
returns true
if obj is a class function, and false
otherwise.
gap> chi:= S4.charTable.irreducibles[3]; [ 2, 2, -1, 0, 0 ] gap> IsClassFunction( chi ); false gap> irr[3]; Character( S4, [ 2, 2, -1, 0, 0 ] ) gap> IsClassFunction( irr[3] ); true
IsVirtualCharacter( obj )
returns true
if obj is a virtual character, and false
otherwise.
For a class function obj that does not know whether it is a virtual
character, the scalar products with all irreducible characters of the
source of obj are computed. If they are all integral then
obj is turned into a virtual character record.
gap> psi:= irr[3] - irr[1]; VirtualCharacter( S4, [ 1, 1, -2, -1, -1 ] ) gap> cf:= ClassFunction( S4, [ 1, 1, -2, -1, -1 ] ); ClassFunction( S4, [ 1, 1, -2, -1, -1 ] ) gap> IsVirtualCharacter( cf ); true gap> IsCharacter( cf ); false gap> cf; VirtualCharacter( S4, [ 1, 1, -2, -1, -1 ] )
IsCharacter( obj )
returns true
if obj is a character, and false
otherwise.
For a class function obj that does not know whether it is a
character, the scalar products with all irreducible characters of the
source of obj are computed. If they are all integral and nonegative then
obj is turned into a character record.
gap> psi:= ClassFunction( S4, S4.charTable.centralizers ); ClassFunction( S4, [ 24, 8, 3, 4, 4 ] ) gap> IsCharacter( psi ); psi; true Character( S4, [ 24, 8, 3, 4, 4 ] ) gap> cf:= ClassFunction( S4, irr[3] - irr[1] ); ClassFunction( S4, [ 1, 1, -2, -1, -1 ] ) gap> IsCharacter( cf ); cf; false VirtualCharacter( S4, [ 1, 1, -2, -1, -1 ] )
Irr( G )
returns the list of irreducible characters of the group G.
If necessary the character table of G is computed.
The succession of characters is the same as in CharTable( G )
.
gap> Irr( SolvableGroup( "S4" ) ); [ Character( S4, [ 1, 1, 1, 1, 1 ] ), Character( S4, [ 1, 1, 1, -1, -1 ] ), Character( S4, [ 2, 2, -1, 0, 0 ] ), Character( S4, [ 3, -1, 0, 1, -1 ] ), Character( S4, [ 3, -1, 0, -1, 1 ] ) ]
InertiaSubgroup( G, chi )
For a class function chi of a normal subgroup N of the group G,
InertiaSubgroup( G, chi )
returns the inertia subgroup IG(chi),
that is, the subgroup of all those elements g ∈ G that satisfy
<chi> \g = chi.
gap> V4:= Subgroup( S4, S4.generators{ [ 3, 4 ] } ); Subgroup( S4, [ c, d ] ) gap> irrsub:= Irr( V4 ); #W Warning: Group has no name [ Character( Subgroup( S4, [ c, d ] ), [ 1, 1, 1, 1 ] ), Character( Subgroup( S4, [ c, d ] ), [ 1, 1, -1, -1 ] ), Character( Subgroup( S4, [ c, d ] ), [ 1, -1, 1, -1 ] ), Character( Subgroup( S4, [ c, d ] ), [ 1, -1, -1, 1 ] ) ] gap> List( irrsub, x -> InertiaSubgroup( S4, x ) ); [ Subgroup( S4, [ a, b, c, d ] ), Subgroup( S4, [ a*b^2, c, d ] ), Subgroup( S4, [ a*b, c, d ] ), Subgroup( S4, [ a, c, d ] ) ]
OrbitsCharacters( irr )
returns a list of orbits of the characters irr under the action of Galois automorphisms and multiplication with linear characters in irr. This is used for functions that need to consider only representatives under the operation of this group, like TestSubnormallyMonomial.
OrbitsCharacters
works also for irr a list of character value lists.
In this case the result contains orbits of these lists.
Note that OrbitsCharacters
does not require that irr is closed
under the described action, so the function may also be used to
complete the orbits.
gap> irr:= Irr( SolvableGroup( "S4" ) );; gap> OrbitsCharacters( irr ); [ [ Character( S4, [ 1, 1, 1, -1, -1 ] ), Character( S4, [ 1, 1, 1, 1, 1 ] ) ], [ Character( S4, [ 2, 2, -1, 0, 0 ] ) ], [ Character( S4, [ 3, -1, 0, -1, 1 ] ), Character( S4, [ 3, -1, 0, 1, -1 ] ) ] ] gap> OrbitsCharacters( List( irr{ [1,2,4] }, x -> x.values ) ); [ [ [ 1, 1, 1, -1, -1 ], [ 1, 1, 1, 1, 1 ] ], [ [ 3, -1, 0, 1, -1 ], [ 3, -1, 0, -1, 1 ] ] ]
54.14 Storing Subgroup Information
Many computations for a group character χ of a group G, such as that of kernel or centre of χ, involve computations in (normal) subgroups or factor groups of G.
There are two aspects that make it reasonable to store relevant information used in these computations.
First it is possible to use the character table of a group for computations with the group. For example, suppose we know for every normal subgroup N the list of positions of conjugacy classes that form N. Then we can compute the intersection of normal subgroups efficiently by intersecting the corresponding lists.
Second one should try to reuse (expensive) information one has computed. Suppose you need the character table of a certain subgroup U that was constructed for example as inertia subgroup of a character. Then it may be probable that this group has been constructed already. So one should look whether U occurs in a list of interesting subgroups for that the tables are already known.
This section lists several data structures that support storing and using information about subgroups.
Storing Normal Subgroup Information
In some cases a question about a normal subgroup N can be answered efficiently if one knows the character table of G and the G-conjugacy classes that form N, e.g., the question whether a character of G restricts irreducibly to N. But other questions require the computation of the group N or even more information, e.g., if we want to know whether a character restricts homogeneously to N this will in general require the computation of the character table of N.
In order to do such computations only once, we introduce three components in the group record of G to store normal subgroups, the corresponding lists of conjugacy classes, and (if known) the factor groups, namely
nsg
:
nsgclasses
:nsg
component,
nsgfactors
:nsg
component.
The functions
NormalSubgroupClasses
,
FactorGroupNormalSubgroupClasses
,
ClassesNormalSubgroup
initialize these components and update them. They are the only functions that do this.
So if you need information about a normal subgroup of G for that you know
the G-conjugacy classes, you should get it using NormalSubgroupClasses
.
If the normal subgroup was already stored it is just returned, with all the
knowledge it contains. Otherwise the normal subgroup is computed and
added to the lists, and will be available for the next call.
Storing information for computing conjugate class functions
The computation of conjugate class functions requires the computation of
permutatins of the list of conjugacy classes. In order to minimize the
number of membership tests in conjugacy classes it is useful to store
a partition of classes that is respected by every admissible permutation.
This is stored in the component globalPartitionClasses
.
If the normalizer N of H in its parent is stored in H, or if H is
normal in its parent then the component permClassesHomomorphism
is used.
It holds the group homomorphism mapping every element of N to the
induced permutation of classes.
Both components are generated automatically when they are needed.
Storing inertia subgroup information
Let N be the normalizer of H in its parent, and χ a character
of H. The inertia subgroup IN(χ) is the stabilizer
in N of χ under conjugation of class functions. Characters with
same value distribution, like Galois conjugate characters, have the
same inertia subgroup. It seems to be useful to store this information.
For that, the inertiaInfo
component of H is initialized when needed,
a record with components partitions
and stabilizers
, both lists.
The stabilizers
component contains the stabilizer in N of the
corresponding partition.
NormalSubgroupClasses( G, classes )
returns the normal subgroup of the group G that consists of the conjugacy classes whose positions are in the list classes.
If G.nsg
does not contain the required normal subgroup, and if G
contains the component G.normalSubgroups
then the result and the
group in G.normalSubgroups
will be identical.
gap> ccl:= ConjugacyClasses( S4 ); [ ConjugacyClass( S4, IdAgWord ), ConjugacyClass( S4, d ), ConjugacyClass( S4, b ), ConjugacyClass( S4, a ), ConjugacyClass( S4, a*d ) ] gap> NormalSubgroupClasses( S4, [ 1, 2 ] ); Subgroup( S4, [ c, d ] )
The list of classes corresponding to a normal subgroup is returned by ClassesNormalSubgroup.
ClassesNormalSubgroup( G, N )
returns the list of positions of conjugacy classes of the group G that are contained in the normal subgroup N of G.
gap> ccl:= ConjugacyClasses( S4 ); [ ConjugacyClass( S4, IdAgWord ), ConjugacyClass( S4, d ), ConjugacyClass( S4, b ), ConjugacyClass( S4, a ), ConjugacyClass( S4, a*d ) ] gap> V4:= NormalClosure( S4, Subgroup( S4, [ S4.4 ] ) ); Subgroup( S4, [ c, d ] ) gap> ClassesNormalSubgroup( S4, V4 ); [ 1, 2 ]
The normal subgroup corresponding to a list of classes is returned by NormalSubgroupClasses.
54.17 FactorGroupNormalSubgroupClasses
FactorGroupNormalSubgroupClasses( G, classes )
returns the factor group of the group G modulo the normal subgroup of G that consists of the conjugacy classes whose positions are in the list classes.
gap> ccl:= ConjugacyClasses( S4 ); [ ConjugacyClass( S4, IdAgWord ), ConjugacyClass( S4, d ), ConjugacyClass( S4, b ), ConjugacyClass( S4, a ), ConjugacyClass( S4, a*d ) ] gap> S3:= FactorGroupNormalSubgroupClasses( S4, [ 1, 2 ] ); Group( a, b )
Every class function has the components
isClassFunction
:true
,
source
:
values
:conjugacyClasses
component of source
,
operations
:ClassFunctionOps
, VirtualCharacterOps
, CharacterOps
.
Optional components are
isVirtualCharacter
:
isCharacter
:gap3-jm