Tutorial on the group representation functions in the GAP package 'reps' for handling representations of groups and categories in positive characteristic.

March 2020

In March 2020 there is major new release of the packages reps and catreps in which they are combined as one. Commands common to both groups and categories have been written in objected oriented form by Moriah Elkin. This has been done as a response to the need to interface between the two contexts.

The package has been designed and is maintained by
Peter Webb
School of Mathematics
University of Minnesota
Minneapolis MN 55455

webb@math.umn.edu
http://www.math.umn.edu/~webb
The GAP code is available at: http://www.math.umn.edu/~webb/

The code has been written by Peter Webb, Dan Christensen, Bryan Simpkins, Robert Hank, Brad Froehle, with contributions from several people including Roland Loetscher.

Overview of the package reps

The package 'reps' described here sets up a framework within which matrix representations of finite groups, primarily in positive characteristic, can be stored and examined. Sufficient information is stored so that calculations can be performed, and at the same time little more than this information is stored. It is important that the user should be able to understand quickly the syntax of commands and what the software is doing, and also that the software should not depend unduly on constructions in other parts of GAP that may change.

The basic object of computation is a record with a name such as rep, and fields which include rep.group, rep.genimages, rep.field and rep.dimension. The first of these is the group being represented, and the second is a list of matrices over rep.field which represent the action of the group elements in the list GeneratorsOfGroup(rep.group). Since many of the algorithms used and some of the properties investigated (such as projectivity) depend on the group being represented it is important to store the group. By contrast, the implementation of the meataxe already present in GAP does not store the group. With these record fields it is also possible to distinguish between the zero representation of an arbitrary group and the different representations of the identity group. In the present implementation certain commands will only work when rep.group is a permutation group.

The intention is to make available all algorithms for handling group representations within the above framework. These include the basic meataxe operations for finding a proper invariant subspace and Norton's irreducibility test, but also include many other algorithms, many of them based on the operation of taking fixed points. It is important to understand the limitations of the various algorithms in using them effectively. Thus the meataxe is at its best when given a representation with few, non-isomorphic, composition factors. To find the socle of a representation of a p-group in characteristic p, it may be better to use FixedPoints(rep); which solves some linear equations, rather than SocleRep(rep); which calls the meataxe. The routines which work with spaces of homomorphisms, such as Decompose, tend to be limited by the dimension of the representations; and so on.

The fastest way to become familiar with this package is to read through the worked examples of its use which appear after the list of available commands.

Commands currently available

Look at the worked examples that follow to see how to use these commands.

Commands that return a representation:
Rep(group, list of matrices, (optional field)). . returns a representation in which the generators of the group act by the matrices in the list. This and the following commands are the basic way to input a representation. The function takes two or three arguments. If only two arguments are given the field is taken to be the field of the leading entry of the first matrix, which might be incorrect.
PermutationRep(group, list of permns, field). . returns a permutation representation in which the group generators act via the permutations in the list.
PermutationRepOnCosets(group, subgroup, field). . returns a permutation representation on the cosets of a subgroup.
PermGroupToRep(group, field). . returns the representation on the defining permutation representation.
RegularRep(group, field) returns the group ring as a representation.
FreeRep(group, field, n) returns the direct sum of n copies of the group ring as a representation.
TrivialRep(group, field). . returns a trivial representation.
TrivialRepN(group, field, n).. returns a trivial action on an n-dimensional vector space.
ZeroGroupRep(group, field). . returns the zero representation.
DualRep(rep). . returns a representation which is the dual of rep.
DirectSumRep(rep, rep). . returns a representation which is the direct sum of the two representations.
TensorProductRep(rep, rep). . returns a representation which is the tensor product of the two representations.
SubmoduleRep(rep, list of vecs). . returns the representation on the submodule spanned by the list of vectors. The list of vectors must be a basis for an invariant subspace - this is not checked.
QuotientRep(rep, list of vecs). . returns the representation on the quotient module by the submodule spanned by the list of vectors. The list of vectors must be a basis for an invariant subspace - this is not checked.
SectionRep(rep, list of vectors, list of vectors). .returns the representation on the quotient of the submodule spanned by the first list of vectors, by the submodule spanned by the second list of vectors. The two lists should be independent sets, and should be bases for submodules of rep, the second submodule contained in the first. This is not checked.
RestrictedRep(group, subgroup, rep of group). . returns the restriction of the representation.
InducedRep(group, subgroup, rep of subgroup). . returns the induced representation.
SymmetricPowerRep(rep, n). . returns the representation on the nth symmetric power of the given representation. This code was written by Brad Froehle.
CompositionFactorsRep(rep). . returns a list of representations which are the composition factors of rep. This function calls the meataxe routine MTX.CompositionFactors which is already implemented in GAP.
ProjectiveFreeCore(rep). . returns a representation isomorphic to a maximal summand of rep that has no projective summand. It is only guaranteed to work when the group is a p-group in characteristic p. In other cases it may give a correct answer, and if it does not then an error message is returned. The algorithm uses fewer resources than ProjectiveFreeSummand.
ProjectiveFreeSummand(rep). . returns a representation isomorphic to a maximal summand of rep that has no projective summand. The algorithm decomposes rep and tests summands for projectivity. This is computationally expensive.
FixedPointRep(rep, subgroup of rep.group). .returns the representation of the normalizer of the subgroup on the fixed points of the subgroup.
BrauerRep(rep, p-subgroup of rep.group). .returns the representation of the normalizer of the p-subgroup on the Brauer quotient at that subgroup (quotient of the fixed points by the images of trace maps from proper subgroups).
RemoveFromBottom(rep1, rep2). .returns a representation with the sum of all images of rep2 in rep1 factored out from rep1.
RemoveFromTop(rep1, rep2). .returns a representation that is the common kernel of all homomorphisms from rep1 to rep2.

Commands that return lists of vectors:
FixedPoints(rep). . returns a list of vectors which form a basis for the fixed points of rep.
FixedQuotient(rep). . returns a list of vectors which form a basis for the augmentation ideal times rep.
SubFixedQuotient(rep, list of vectors). . returns a list of vectors which form a basis for the augmentation ideal times the submodule spanned by the list of vectors.
BrauerTraceImage(rep, p-subgroup of rep.group). .returns a list of vectors that forms a basis for the sum of images of trace maps from fixed points of proper subgroups of the p-subgroup.
Spin(rep, list of vectors) . . returns a basis for the submodule generated by the vectors in the list
CoSpin(rep, list of vectors) . . .returns a basis for the largest submodule contained in the vector subspace spanned by the vectors in the list.
SumOfImages(rep,rep). .returns a basis for the sum of images of all module homomorphisms A -> B
KernelIntersection(rep,rep) . . returns a basis for the intersection of the kernels of all module homomorphisms A -> B.
Decompose(rep) . . returns a list of bases of summands in a direct sum decomposition of rep. The summands are probably indecomposable. This code was written by Bryan Simpkins and Robert Hank. Warning: only summands which are defined over the field generated by the matrix entries in rep are found. It is possible to modify the code to find decompositions over extension fields, but this has not been done.
DecomposeSubmodule(rep, list of vectors) . . Returns a list of two bases for summands of the submodule spanned by the list of vectors (it does not check that the span is invariant) if the submodule is decomposable. If the submodule is indecomposable it returns a list whose only element is the given basis. A probabilistic algorithm is used. The routine is called by Decompose.
ProjectiveDecomposition(rep). .returns a list of two bases, for a submodule which is projective, and for a submodule with probably no non-zero projective summands, whose direct sum is the whole representation.
ProjectiveSummand(rep). .returns a basis for a maximal projective direct summand of rep. It is only guaranteed to work when the group is a p-group in characteristic p. In other cases it may give a correct answer, and if it does not then an error message is returned. It does not use Decompose.
ProperSubmodule(rep). . returns a list of vectors which form a basis for a proper submodule of rep if there is one, and otherwise returns the empty list []. This function calls the meataxe routine MTX.ProperSubmoduleBasis which is already implemented in GAP.
RadicalRep(rep). . returns a list of vectors which form a basis for the radical of rep. This function calls the meataxe routine MTX.BasisRadical which is already implemented in GAP.
SocleRep(rep). . returns a list of vectors which form a basis for the socle of rep. This function calls the meataxe routine MTX.BasisSocle which is already implemented in GAP.
RadicalSeries(rep) returns a list with two entries [bases, reps] where bases is a list of bases of the successive powers of the radical rep = rad^0(rep), rad^1(rep), ... in descending order. The last term in the list is the empty list. reps is a list of the representations on the radical quotients rep/rad^1(rep), rad^1(rep)/rad^2(rep). ... all of which are semisimple. The last term is the last nonzero representation, and so the list is one shorter than bases.
SocleSeries(rep). .returns a list with two entries [bases, reps] where bases is a list of bases of the higher socles rep = soc^t(rep), soc^(t-1)(rep), ... in DESCENDING order. The last term in the list is the empty list. reps is a list of the representations on the socle quotients rep/soc^(t-1)(rep), soc^(t-1)(rep)/soc^(t-2)(rep). ... all of which are semisimple. The last term is the last nonzero representation, and so the list is one shorter than bases.
ButterflyFactors(rep, descending filtration, descending filtration) returns a matrix whose entries are the representations that appear as sections in Zassenhaus' Butterfly Lemma. Each descending filtration is a list of bases of submodules of rep, forming a descending chain. The representations in the output are the factors in a common refinement of the two filtrations, and their position in the refinement is indicated by their position in the matrix.
BasesCompositionSeriesRep(rep). . returns a list of bases of submodules which form a composition series of rep. This function calls the meataxe routine MTX.BasesCompositionSeries which is already implemented in GAP.
MatrixOfElement(rep, group element). . returns the matrix which represents the group element.
MatricesOfElements(rep, list of group elements). . returns the list of matrices which represent the group elements.


Commands that handle output:
DisplayMatrix(matrix). . Prints matrices over prime fields nicely.
PrintRep(rep). . Prints representations nicely.

Commands for homomorphisms:
RepToGHBI(rep). . Converts a representation to a group homomorphism by images.
HomBasis(rep,rep) . . returns a basis for the space of module homomorphisms A -> B. The elements of this basis are matrices.
DimHom(rep,rep) . . returns the dimension of the space of module homomorphisms A -> B.
IsHom(rep1, rep2, mat). . returns true if the matrix mat represents a homomorphism from rep1 to rep2 and false otherwise.
ProjectiveHomBasis(rep, rep) . . returns a basis for the space of module homomorphisms A -> B which factor through a projective module. The elements of this basis are matrices.
TensorProductMorphism(mat1,mat2). . returns the matrix of the tensor product of two morphisms, using the same basis as TensorProductRep.
InducedInclusion(group, subgroup, rep of subgroup). . returns the natural homomorphism from rep to RestrictedRep(G, H, InducedRep(G, H, rep)).
InducedProjection(group, subgroup, rep of subgroup). . returns the natural projection from RestrictedRep(G, H, InducedRep(G, H, rep)) to rep.

Trace, norm and principal idempotent:
RelativeTrace(group,subgroup,rep). . returns the matrix of the relative trace map. This should only be applied to fixed points for it to be well-defined.
NormRep(rep). . returns the matrix which represents the sum of the group elements.
PrincipalIdempotent(group,prime). . returns a vector in the representation space of RegularRep(group, GF(prime)) that is the block idempotent of the principal block.

Tests:
IsIrreducibleRep(rep). . returns true if the representation is irreducible and false otherwise. This function calls the meataxe routine MTX.IsIrreducible which is already implemented in GAP.
IsAbsolutelyIrreducibleRep(rep). . returns true if the representation is absolutely irreducible and false otherwise. This function calls the meataxe routine MTX.IsAbsolutelyIrreducible which is already implemented in GAP.
IsProjectiveRep(rep). . returns true if the representation is projective and false otherwise. This function restricts the representation to a Sylow p-subgroup and tests whether its dimension equals |G| times the rank of the norm map.
IsIsomorphicSummmand(rep1, rep2). . returns true if rep1 is isomorphic to a direct summand of rep2, false otherwise. It only works when rep1 is indecomposable of dimension prime to the field characteristic. It relies on a result of Benson and Carlson.

Interface to the Meataxe:
The purpose of these commands is to allow further meataxe commands, other than the ones already listed above, to be used.
RepToMeataxeModule(rep). . converts a representation to a meataxe module.
MeataxeModuleToRep(rep,meataxemodule). . converts a meataxe module to a representation. Because the meataxe module does not store the group being represented, this is obtained from a representation called rep whose only property is that rep.group is the required group.

Commands under development:
ExteriorPower(rep,n)

Worked Examples

Example 1: In the first example we examine the structure of the permutation module for S_4 on the unordered pairs of elements from [1..4]. This module of dimension 6 is in fact the Young module parametrized by the partition [2,2]. We assume at the start of the calculation that over the field of 2 elements S_4 has two simple modules, of dimensions 1 and 2. They are constructed near the start of the calculation. We will conclude from the calculation that this permutation module is indecomposable with socle and top each the direct sum of 1 and 2, and that the socle equals the radical. We will also conclude that there are non-split extensions between the 2 in the socle and both 1 and 2 in the top, and also non-split extensions between the 2 in the top and both the 1 and 2 in the socle. However, the extension between the 1 in the top and the 1 in the socle is split.

We load reps either by having it available as a package or by creating a file in the home directory called reps containing the routines.
gap> Read("reps");
This assumes that the GAP code for the routines to be used is stored in the file reps.
gap> g:=SymmetricGroup(4);
Sym( [ 1 .. 4 ] )
gap> GeneratorsOfGroup(g);
[ (1,2,3,4), (1,2) ]
Before constructing the 6-dimensional representation we will investigate, we construct the irreducible 2-dimensional representation over GF(2). This can be done in various ways. One way which works with small groups is to construct the regular representation and find its composition factors.
gap> reg:=RegularRep(g,GF(2));;
gap> comp:=CompositionFactorsRep(reg);;
gap> List(comp,x->x.dimension);
[ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2 ]
gap> two:=comp[3];
rec( group := Sym( [ 1 .. 4 ] ),
genimages := [ <an immutable 2x2 matrix over GF2>,
<an immutable 2x2 matrix over GF2> ], field := GF(2), dimension := 2,
isRepresentation := true )
We may print a representation more nicely using PrintRep.
gap> PrintRep(two);
Representation( SymmetricGroup( [ 1 .. 4 ] ), Images
[ [ 1, 0 ],
[ 1, 1 ] ]
[ [ 1, 1 ],
[ 0, 1 ] ]
)
For larger groups it would be heavy-handed to take composition factors of the regular representation. Just to illustrate, we now construct the 2-dimensional simple module from the natural permutation representation of S_4. This representation is uniserial with composition factors 1,2,1.
gap> four:=PermutationRep(g,GeneratorsOfGroup(g),GF(2));;
gap> RepPrint(four);
Representation( SymmetricGroup( [ 1 .. 4 ] ), Images
[ [ 0, 1, 0, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 1 ],
[ 1, 0, 0, 0 ] ]
[ [ 0, 1, 0, 0 ],
[ 1, 0, 0, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 1 ] ]
)
gap> FixedQuotient(four);
[ <an immutable GF2 vector of length 4>, <an immutable GF2 vector of length 4>,
<an immutable GF2 vector of length 4> ]
These three vectors span a submodule which has as its quotient the largest image with trivial action. The submodule is uniserial with composition factors 1,2.
gap> three:=SubmoduleRep(four,last);;
gap> RepPrint(three);
Representation( SymmetricGroup( [ 1 .. 4 ] ), Images
[ [ 1, 1, 0 ],
[ 1, 0, 1 ],
[ 1, 0, 0 ] ]
[ [ 0, 1, 0 ],
[ 1, 0, 0 ],
[ 0, 0, 1 ] ]
)
gap> FixedPoints(three);
[ <an immutable GF2 vector of length 3> ]
gap> two:=QuotientRep(three,last);;
gap> RepPrint(two);
Representation( SymmetricGroup( [ 1 .. 4 ] ), Images
[ [ 1, 0 ],
[ 1, 1 ] ]
[ [ 1, 1 ],
[ 0, 1 ] ]
)
Here two is the 2-dimensional simple module for S_4. We could show that it is this module by computing that it has zero fixed points or doing:
gap> IsIrreducibleRep(two);
true
We now construct a 6-dimensional permutation representation.
gap> Orbit(g,[1,2],OnSets);
[ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ], [ 1, 3 ], [ 1, 4 ], [ 2, 4 ] ]
gap> Action(g,last,OnSets);
Group([ (1,2,3,5)(4,6), (2,4)(5,6) ])
gap> six:=PermutationRep(g,GeneratorsOfGroup(last),GF(2));;
gap> RepPrint(six);
Representation( SymmetricGroup( [ 1 .. 4 ] ), Images
[ [ 0, 1, 0, 0, 0, 0 ],
[ 0, 0, 1, 0, 0, 0 ],
[ 0, 0, 0, 0, 1, 0 ],
[ 0, 0, 0, 0, 0, 1 ],
[ 1, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 1, 0, 0 ] ]
[ [ 1, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 1, 0, 0 ],
[ 0, 0, 1, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 1 ],
[ 0, 0, 0, 0, 1, 0 ] ]
)
We will now analyze the structure of the represenntation six.
gap> FixedPoints(six);
[ <an immutable GF2 vector of length 6> ]
gap> DimHom(two,six);
1
We conclude that the socle of six is the direct sum of 1 and 2. This could also have been done using the meataxe socle command and decomposing it:
gap> socle:=SubmoduleRep(six,SocleRep(six));;
gap> Decompose(socle);
[ [ <a GF2 vector of length 3> ],
[ <a GF2 vector of length 3>, <a GF2 vector of length 3> ] ]
gap> IsIrreducibleRep(SubmoduleRep(socle,last[2]));
true
In a similar way we analyze the radical quotient of six.
gap> DimHom(six,two);
1
gap> FixedQuotient(six);
[ <an immutable GF2 vector of length 6>, <an immutable GF2 vector of length 6>,
<an immutable GF2 vector of length 6>, <an immutable GF2 vector of length 6>,
<an immutable GF2 vector of length 6> ]
We conclude that the radical quotient of six is also the direct sum of 1 and 2. We now construct a 4-dimension section of 6 called sub.
gap> FixedPoints(six);
[ <an immutable GF2 vector of length 6> ]
gap> quot:=QuotientRep(six,last);;
gap> FixedPoints(quot);
[ ]
gap> FixedQuotient(quot);
[ <an immutable GF2 vector of length 5>, <an immutable GF2 vector of length 5>,
<an immutable GF2 vector of length 5>, <an immutable GF2 vector of length 5> ]
gap> sub:=SubmoduleRep(quot,last);;
gap> DimHom(two,sub);
1
gap> DimHom(sub,two);
1
gap> FixedQuotient(sub);
[ <an immutable GF2 vector of length 4>, <an immutable GF2 vector of length 4>,
<an immutable GF2 vector of length 4>, <an immutable GF2 vector of length 4> ]
gap> FixedPoints(sub);
[ ]
From this we conclude that sub is a uniserial module with composition factors 2,2. This means (in this situation) that the extension of 2 by 2 is non-split. We next factor out a submodule 2 from six.
gap> SumOfImages(two,six);
<a 2x6 matrix over GF2>
gap> quot:=QuotientRep(six,last);;
gap> FixedPoints(quot);
[ <an immutable GF2 vector of length 4>, <an immutable GF2 vector of length 4> ]
The fact that the fixed points have dimension 2 shows that the extension of 1 by 1 is split. From all this we may deduce also that six is indecomposable: if it were a direct sum, enumeration of the possible structures of direct summands leads to contradiction in every case.

Example 2: We examine the projective modules for the alternating group A_5 over GF(2). This illustrates some things which can happen with Decompose which can be puzzling, and which arise because GF(2) is not a splitting field for A_5.
gap> a5:=AlternatingGroup(5);
Alt( [ 1 .. 5 ] )
gap> reg:=RegularRep(a5,GF(2));;
Having constructed the regular representation, we now construct the augmentation ideal.
gap> aug:=SubmoduleRep(reg,FixedQuotient(reg));;
gap> Decompose(aug);;
Note that Decompose stores its output as aug.summands. The output is a list of bases of summands of aug which are probably indecomposable.
gap> List(aug.summands,Length);
[ 4, 4, 4, 16, 4, 11, 16 ]
The augmentation ideal breaks up as the direct sum of the indecomposable projectives other than the projective cover P_1 of the trivial module, direct sum the radical of P_1. From a knowledge of the representation theory of A_5 the result may be a surprise because over a splitting field in characteristic 2 A_5 has the trivial representation, two irreducibles of dimension 2 and a block of defect zero of dimension 4. Over a splitting field this gives 9 summands of the regular representation (each projective occurs with multiplicity equal to the degree of the corresponding irreducible representation). In fact over GF(2) there is a 4-dimensional simple module which over GF(4) is the direct sum of the two 2-dimensional simple modules. The computational output shows that reg has 7 summands, of the dimensions indicated.
gap> four:=SubmoduleRep(aug,aug.summands[1]);;
gap> PrintRep(four);
Representation( AlternatingGroup( [ 1 .. 5 ] ), Images
[ [ 0, 1, 1, 1 ],
[ 0, 0, 1, 0 ],
[ 1, 0, 0, 0 ],
[ 0, 0, 1, 1 ] ]
[ [ 0, 1, 0, 0 ],
[ 0, 0, 1, 0 ],
[ 1, 0, 0, 0 ],
[ 1, 1, 0, 1 ] ]
)
gap> IsIrreducibleRep(four);
true
gap> IsProjectiveRep(four);
true
We see from this that four is the block of defect zero. We now construct the other 4-dimensional irreducible module.
gap> sixteen:=SubmoduleRep(aug,aug.summands[4]);;
gap> socle:=SubmoduleRep(sixteen,SocleRep(sixteen));;
gap> IsIrreducibleRep(socle);
true
gap> DimHom(four,socle);
0
Thus four and socle are not isomorphic. The following shows that splitting fields for four and socle have degrees 1 and 2 over GF(2).
gap> IsAbsolutelyIrreducibleRep(four);
true
gap> IsAbsolutelyIrreducibleRep(socle);
false
gap> DimHom(socle,socle);
2
Next we examine P_1. Over a splitting field its radical modulo its socle is the direct sum of two uniserial modules. Over GF(2) this module has simple socle and radical quotient isomorphic to the representation called socle, as the following implies.
gap> eleven:=SubmoduleRep(aug,aug.summands[6]);;
gap> ten:=QuotientRep(eleven,FixedPoints(eleven));;
gap> ten.dimension;
10
gap> FixedPoints(ten);
[ ]
gap> Length(FixedQuotient(ten));
10