1.18 About Groups

In this section we will show some easy computations with groups. The example uses permutation groups, but this is visible for the user only because the output contains permutations. The functions, like Group, Size or SylowSubgroup (for detailed information, see chapters Domains, Groups), are the same for all kinds of groups, although the algorithms which compute the information of course will be different in most cases.

It is not even necessary to know more about permutations than the two facts that they are elements of permutation groups and that they are written in disjoint cycle notation (see chapter Permutations). So let's construct a permutation group:

    gap> s8:= Group( (1,2), (1,2,3,4,5,6,7,8) );
    Group( (1,2), (1,2,3,4,5,6,7,8) )

We formed the group generated by the permutations (1,2) and (1,2,3,4,5,6,7,8), which is well known as the symmetric group on eight points, and assigned it to the identifier s8. s8 contains the alternating group on eight points which can be described in several ways, e.g., as group of all even permutations in s8, or as its commutator subgroup.

    gap> a8:= CommutatorSubgroup( s8, s8 );
    Subgroup( Group( (1,2), (1,2,3,4,5,6,7,8) ),
    [ (1,3,2), (2,4,3), (2,3)(4,5), (2,4,6,5,3), (2,5,3)(4,7,6),
      (2,3)(5,6,8,7) ] )

The alternating group a8 is printed as instruction to compute that subgroup of the group s8 that is generated by the given six permutations. This representation is much shorter than the internal structure, and it is completely self--explanatory; one could, for example, print such a group to a file and read it into GAP later. But if one object occurs several times it is useful to refer to this object; this can be settled by assigning a name to the group.

    gap> s8.name:= "s8";
    "s8"
    gap> a8;
    Subgroup( s8, [ (1,3,2), (2,4,3), (2,3)(4,5), (2,4,6,5,3),
      (2,5,3)(4,7,6), (2,3)(5,6,8,7) ] )
    gap> a8.name:= "a8";
    "a8"
    gap> a8;
    a8

Whenever a group has a component name, GAP prints this name instead of the group itself. Note that there is no link between the name and the identifier, but it is of course useful to choose name and identifier compatible.

    gap> copya8:= Copy( a8 );
    a8

We examine the group a8. Like all complex GAP structures, it is represented as a record (see Group Records).

    gap> RecFields( a8 );
    [ "isDomain", "isGroup", "parent", "identity", "generators",
      "operations", "isPermGroup", "1", "2", "3", "4", "5", "6",
      "stabChainOptions", "stabChain", "orbit", "transversal",
      "stabilizer", "name" ]

Many functions store information about the group in this group record, this avoids duplicate computations. But we are not interested in the organisation of data but in the group, e.g., some of its properties (see chapter Groups, especially Properties and Property Tests):

    gap> Size( a8 ); IsAbelian( a8 ); IsPerfect( a8 );
    20160
    false
    true

Some interesting subgroups are the Sylow p subgroups for prime divisors p of the group order; a call of SylowSubgroup stores the required subgroup in the group record:

    gap> Set( Factors( Size( a8 ) ) );
    [ 2, 3, 5, 7 ]
    gap> for p in last do
    >      SylowSubgroup( a8, p );
    >    od;
    gap> a8.sylowSubgroups;
    [ , Subgroup( s8, [ (1,5)(7,8), (1,5)(2,6), (3,4)(7,8), (2,3)(4,6),
          (1,7)(2,3)(4,6)(5,8), (1,2)(3,7)(4,8)(5,6) ] ),
      Subgroup( s8, [ (3,8,7), (2,6,4)(3,7,8) ] ),,
      Subgroup( s8, [ (3,7,8,6,4) ] ),,
      Subgroup( s8, [ (2,8,4,5,7,3,6) ] ) ]

The record component sylowSubgroups is a list which stores at the p--th position, if bound, the Sylow p subgroup; in this example this means that there are holes at positions 1, 4 and 6. Note that a call of SylowSubgroup for the cyclic group of order 65521 and for the prime 65521 would cause GAP to store the group at the end of a list of length 65521, so there are special situations where it is possible to bring GAP and yourselves into troubles.

We now can investigate the Sylow 2 subgroup.

    gap> syl2:= last[2];;
    gap> Size( syl2 );
    64
    gap> Normalizer( a8, syl2 );
    Subgroup( s8, [ (3,4)(7,8), (2,3)(4,6), (1,2)(3,7)(4,8)(5,6) ] )
    gap> last = syl2;
    true
    gap> Centre( syl2 );
    Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7, 8) ] )
    gap> cent:= Centralizer( a8, last );
    Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7, 8), (3,4)(7,8), (3,7)(4,8),
      (2,3)(4,6), (1,2)(5,6) ] )
    gap> Size( cent );
    192
    gap> DerivedSeries( cent );
    [ Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7, 8), (3,4)(7,8),
          (3,7)(4,8), (2,3)(4,6), (1,2)(5,6) ] ),
      Subgroup( s8, [ ( 1, 6, 3)( 2, 4, 5), ( 1, 8, 3)( 4, 5, 7),
          ( 1, 7)( 2, 3)( 4, 6)( 5, 8), ( 1, 5)( 2, 6) ] ),
      Subgroup( s8, [ ( 1, 3)( 2, 7)( 4, 5)( 6, 8),
          ( 1, 6)( 2, 5)( 3, 8)( 4, 7), ( 1, 5)( 3, 4), ( 1, 5)( 7, 8) ] )
        , Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7, 8) ] ),
      Subgroup( s8, [  ] ) ]
    gap> List( last, Size );
    [ 192, 96, 32, 2, 1 ]
    gap> low:= LowerCentralSeries( cent );
    [ Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7, 8), (3,4)(7,8),
          (3,7)(4,8), (2,3)(4,6), (1,2)(5,6) ] ),
      Subgroup( s8, [ ( 1, 6, 3)( 2, 4, 5), ( 1, 8, 3)( 4, 5, 7),
          ( 1, 7)( 2, 3)( 4, 6)( 5, 8), ( 1, 5)( 2, 6) ] ) ]

Another kind of subgroups is given by the point stabilizers.

    gap> stab:= Stabilizer( a8, 1 );
    Subgroup( s8, [ (2,5,6), (2,5)(3,6), (2,5,6,4,3), (2,5,3)(4,6,8),
      (2,5)(3,4,7,8) ] )
    gap> Size( stab );
    2520
    gap> Index( a8, stab );
    8

We can fetch an arbitrary group element and look at its centralizer in a8, and then get other subgroups by conjugation and intersection of already known subgroups. Note that we form the subgroups inside a8, but GAP regards these groups as subgroups of s8 because this is the common ``parent'' group of all these groups and of a8 (for the idea of parent groups, see More about Groups and Subgroups).

    gap> Random( a8 );
    (1,6,3,2,7)(4,5,8)
    gap> Random( a8 );
    (1,3,2,4,7,5,6)
    gap> cent:= Centralizer( a8, (1,2)(3,4)(5,8)(6,7) );
    Subgroup( s8, [ (1,2)(3,4)(5,8)(6,7), (5,6)(7,8), (5,7)(6,8),
      (3,4)(6,7), (3,5)(4,8), (1,3)(2,4) ] )
    gap> Size( cent );
    192
    gap> conj:= ConjugateSubgroup( cent, (2,3,4) );
    Subgroup( s8, [ (1,3)(2,4)(5,8)(6,7), (5,6)(7,8), (5,7)(6,8),
      (2,4)(6,7), (2,8)(4,5), (1,4)(2,3) ] )
    gap> inter:= Intersection( cent, conj );
    Subgroup( s8, [ (5,6)(7,8), (5,7)(6,8), (1,2)(3,4), (1,3)(2,4) ] )
    gap> Size( inter );
    16
    gap> IsElementaryAbelian( inter );
    true
    gap> norm:= Normalizer( a8, inter );
    Subgroup( s8, [ (6,7,8), (5,6,8), (3,4)(6,8), (2,3)(6,8), (1,2)(6,8),
      (1,5)(2,6,3,7,4,8) ] )
    gap> Size( norm );
    576

Suppose we do not only look which funny things may appear in our group but want to construct a subgroup, e.g., a group of structure 2^3:L_3(2) in a8. One idea is to look for an appropriate 2^3 which is specified by the fact that all its involutions are fixed point free, and then compute its normalizer in a8:

    gap> elab:= Group( (1,2)(3,4)(5,6)(7,8), (1,3)(2,4)(5,7)(6,8),
    >                  (1,5)(2,6)(3,7)(4,8) );;
    gap> Size( elab );
    8
    gap> IsElementaryAbelian( elab );
    true
    gap> norm:= Normalizer( a8, AsSubgroup( s8, elab ) );
    Subgroup( s8, [ (5,6)(7,8), (5,7)(6,8), (3,4)(7,8), (3,5)(4,6),
      (2,3)(6,7), (1,2)(7,8) ] )
    gap> Size( norm );
    1344

Note that elab was defined as separate group, thus we had to call AsSubgroup to achieve that it has the same parent group as a8. Let's look at some usual misuses:

Normalizer( a8, elab );

Intuitively, it is clear that here again we wanted to compute the normalizer of elab in a8, and in fact we would get it by this call. However, this would be a misuse in the sense that now GAP cannot use some clever method for the computation of the normalizer. So, for larger groups, the computation may be very time consuming. That is the reason why we used the the function AsSubgroup in the preceding example.

Let's have a closer look at that function.

    gap> IsSubgroup( a8, AsSubgroup( a8, elab ) );
    Error, <G> must be a parent group in
    AsSubgroup( a8, elab ) called from
    main loop
    brk> quit;
    gap> IsSubgroup( a8, AsSubgroup( s8, elab ) );
    true

What we tried here was not correct. Since all our computations up to now are done inside s8 which is the parent of a8, it is easy to understand that IsSubgroup works for two subgroups with this parent.

By the way, you should not try the operator < instead of the function IsSubgroup. Something like

    gap> elab < a8;
    false

or

    gap> AsSubgroup( s8, elab ) < a8;
    false

will not cause an error, but the result does not tell anything about the inclusion of one group in another; < looks at the element lists for the two domains which means that it computes them if they are not already stored --which is not desirable to do for large groups-- and then simply compares the lists with respect to lexicographical order (see Comparisons of Domains).

On the other hand, the equality operator = in fact does test the equality of groups. Thus

    gap> elab = AsSubgroup( s8, elab );
    true

means that the two groups are equal in the sense that they have the same elements. Note that they may behave differently since they have different parent groups. In our example, it is necessary to work with subgroups of s8:

    gap> elab:= AsSubgroup( s8, elab );;
    gap> elab.name:= "elab";;

If we are given the subgroup norm of order 1344 and its subgroup elab, the factor group can be considered.

    gap> f:= norm / elab;
    (Subgroup( s8, [ (5,6)(7,8), (5,7)(6,8), (3,4)(7,8), (3,5)(4,6),
      (2,3)(6,7), (1,2)(7,8) ] ) / elab)
    gap> Size( f );
    168

As the output shows, this is not a permutation group. The factor group and its elements can, however, be handled in the usual way.

    gap> Random( f );
    FactorGroupElement( elab, (2,8,7)(3,5,6) )
    gap> Order( f, last );
    3

The natural link between the group norm and its factor group f is the natural homomorphism onto f, mapping each element of norm to its coset modulo the kernel elab. In GAP you can construct the homomorphism, but note that the images lie in f since they are elements of the factor group, but the preimage of each such element is only a coset, not a group element (for cosets, see the relevant sections in chapter Groups, for homomorphisms see chapters Operations of Groups and Mappings).

    gap> f.name:= "f";;
    gap> hom:= NaturalHomomorphism( norm, f );
    NaturalHomomorphism( Subgroup( s8,
    [ (5,6)(7,8), (5,7)(6,8), (3,4)(7,8), (3,5)(4,6), (2,3)(6,7),
      (1,2)(7,8) ] ), (Subgroup( s8,
    [ (5,6)(7,8), (5,7)(6,8), (3,4)(7,8), (3,5)(4,6), (2,3)(6,7),
      (1,2)(7,8) ] ) / elab) )
    gap> Kernel( hom ) = elab;
    true
    gap> x:= Random( norm );
    (1,7,5,8,3,6,2)
    gap> Image( hom, x );
    FactorGroupElement( elab, (2,7,3,4,6,8,5) )
    gap> coset:= PreImages( hom, last );
    (elab*(2,7,3,4,6,8,5))
    gap> IsCoset( coset );
    true
    gap> x in coset;
    true
    gap> coset in f;
    false

The group f acts on its elements (not on the cosets) via right multiplication, yielding the regular permutation representation of f and thus a new permutation group, namely the linear group L_3(2). A more elaborate discussion of operations of groups can be found in section About Operations of Groups and chapter Operations of Groups.

    gap> op:= Operation( f, Elements( f ), OnRight );;
    gap> IsPermGroup( op );
    true
    gap> Maximum( List( op.generators, LargestMovedPointPerm ) );
    168
    gap> IsSimple( op );
    true

norm acts on the seven nontrivial elements of its normal subgroup elab by conjugation, yielding a representation of L_3(2) on seven points. We embed this permutation group in norm and deduce that norm is a split extension of an elementary abelian group 2^3 with L_3(2).

    gap> op:= Operation( norm, Elements( elab ), OnPoints );
    Group( (5,6)(7,8), (5,7)(6,8), (3,4)(7,8), (3,5)(4,6), (2,3)(6,7),
    (3,4)(5,6) )
    gap> IsSubgroup(   a8, AsSubgroup( s8, op ) );
    true
    gap> IsSubgroup( norm, AsSubgroup( s8, op ) );
    true
    gap> Intersection( elab, op );
    Group( () )

Yet another kind of information about our a8 concerns its conjugacy classes.

    gap> ccl:= ConjugacyClasses( a8 );
    [ ConjugacyClass( a8, () ), ConjugacyClass( a8, (1,3)(2,6)(4,7)(5,8) )
        , ConjugacyClass( a8, (1,3)(2,8,5)(6,7) ),
      ConjugacyClass( a8, (2,5,8) ), ConjugacyClass( a8, (1,3)(6,7) ),
      ConjugacyClass( a8, (1,3,2,5,4,7,8) ),
      ConjugacyClass( a8, (1,5,8,2,7,3,4) ),
      ConjugacyClass( a8, (1,5)(2,8,7,4,3,6) ),
      ConjugacyClass( a8, (2,7,3)(4,6,8) ),
      ConjugacyClass( a8, (1,6)(3,8,5,4) ),
      ConjugacyClass( a8, (1,3,5,2)(4,6,8,7) ),
      ConjugacyClass( a8, (1,8,6,2,5) ),
      ConjugacyClass( a8, (1,7,2,4,3)(5,8,6) ),
      ConjugacyClass( a8, (1,2,3,7,4)(5,8,6) ) ]
    gap> Length( ccl );
    14
    gap> reps:= List( ccl, Representative );
    [ (), (1,3)(2,6)(4,7)(5,8), (1,3)(2,8,5)(6,7), (2,5,8), (1,3)(6,7),
      (1,3,2,5,4,7,8), (1,5,8,2,7,3,4), (1,5)(2,8,7,4,3,6),
      (2,7,3)(4,6,8), (1,6)(3,8,5,4), (1,3,5,2)(4,6,8,7), (1,8,6,2,5),
      (1,7,2,4,3)(5,8,6), (1,2,3,7,4)(5,8,6) ]
    gap> List( reps, r -> Order( a8, r ) );
    [ 1, 2, 6, 3, 2, 7, 7, 6, 3, 4, 4, 5, 15, 15 ]
    gap> List( ccl, Size );
    [ 1, 105, 1680, 112, 210, 2880, 2880, 3360, 1120, 2520, 1260, 1344,
      1344, 1344 ]

Note the difference between Order (which means the element order), Size (which means the size of the conjugacy class) and Length (which means the length of a list).

Having the conjugacy classes, we can consider class functions, i.e., maps that are defined on the group elements, and that are constant on each conjugacy class. One nice example is the number of fixed points; here we use that permutations act on points via ^.

    gap> nrfixedpoints:= function( perm, support )
    > return Number( [ 1 .. support ], x -> x^perm = x );
    > end;
    function ( perm, support ) ... end

Note that we must specify the support since a permutation does not know about the group it is an element of; e.g. the trivial permutation () has as many fixed points as the support denotes.

    gap> permchar1:= List( reps, x -> nrfixedpoints( x, 8 ) );
    [ 8, 0, 1, 5, 4, 1, 1, 0, 2, 2, 0, 3, 0, 0 ]

This is the character of the natural permutation representation of a8 (More about characters can be found in chapters Character Tables ff.). In order to get another representation of a8, we consider another action, namely that on the elements of a conjugacy class by conjugation; note that this is denoted by OnPoints, too.

    gap> class := First( ccl, c -> Size(c) = 112 );
    ConjugacyClass( a8, (2,5,8) )
    gap> op:= Operation( a8, Elements( class ), OnPoints );;

We get a permutation representation op on 112 points. It is more useful to look for properties than at the permutations.

    gap> IsPrimitive( op, [ 1 .. 112 ] );
    false
    gap> blocks:= Blocks( op, [ 1 .. 112 ] );
    [ [ 1, 2 ], [ 6, 8 ], [ 14, 19 ], [ 17, 20 ], [ 36, 40 ], [ 32, 39 ],
      [ 3, 5 ], [ 4, 7 ], [ 10, 15 ], [ 65, 70 ], [ 60, 69 ], [ 54, 63 ],
      [ 55, 68 ], [ 50, 67 ], [ 13, 16 ], [ 27, 34 ], [ 22, 29 ],
      [ 28, 38 ], [ 24, 37 ], [ 31, 35 ], [ 9, 12 ], [ 106, 112 ],
      [ 100, 111 ], [ 11, 18 ], [ 93, 104 ], [ 23, 33 ], [ 26, 30 ],
      [ 94, 110 ], [ 88, 109 ], [ 49, 62 ], [ 44, 61 ], [ 43, 56 ],
      [ 53, 58 ], [ 48, 57 ], [ 45, 66 ], [ 59, 64 ], [ 87, 103 ],
      [ 81, 102 ], [ 80, 96 ], [ 92, 98 ], [ 47, 52 ], [ 42, 51 ],
      [ 41, 46 ], [ 82, 108 ], [ 99, 105 ], [ 21, 25 ], [ 75, 101 ],
      [ 74, 95 ], [ 86, 97 ], [ 76, 107 ], [ 85, 91 ], [ 73, 89 ],
      [ 72, 83 ], [ 79, 90 ], [ 78, 84 ], [ 71, 77 ] ]
    gap> op2:= Operation( op, blocks, OnSets );;
    gap> IsPrimitive( op2, [ 1 .. 56 ] );
    true

The action of op on the given block system gave us a new representation on 56 points which is primitive, i.e., the point stabilizer is a maximal subgroup. We compute its preimage in the representation on eight points using homomorphisms (which of course are monomorphisms).

    gap> ophom := OperationHomomorphism( a8, op  );;
    gap> Kernel(ophom);
    Subgroup( s8, [  ] )
    gap> ophom2:= OperationHomomorphism( op, op2 );;
    gap> stab:= Stabilizer( op2, 1 );;
    gap> Size( stab );
    360
    gap> composition:= ophom * ophom2;;
    gap> preim:= PreImage( composition, stab );
    Subgroup( s8, [ (1,3,2), (2,4,3), (1,3)(7,8), (2,3)(4,5), (6,8,7) ] )

And this is the permutation character (with respect to the succession of conjugacy classes in ccl):

    gap> permchar2:= List( reps, x->nrfixedpoints(x^composition,56) );
    [ 56, 0, 3, 11, 12, 0, 0, 0, 2, 2, 0, 1, 1, 1 ]

The normalizer of an element in the conjugacy class class is a group of order 360, too. In fact, it is essentially the same as the maximal

subgroup we had found before:

    gap> sgp:= Normalizer( a8,
    >                      Subgroup( s8, [ Representative(class) ] ) );
    Subgroup( s8, [ (2,5)(3,4), (1,3,4), (2,5,8), (1,3,7)(2,5,8),
      (1,4,7,3,6)(2,5,8) ] )
    gap> Size( sgp );
    360
    gap> IsConjugate( a8, sgp, preim );
    true

The scalar product of permutation characters of two subgroups U, V, say, equals the number of (U,V)--double cosets (again, see chapters Character Tables ff. for the details). For example, the norm of the permutation character permchar1 of degree eight is two since the action of a8 on the cosets of a point stabilizer is at least doubly transitive:

    gap> stab:= Stabilizer( a8, 1 );;
    gap> double:= DoubleCosets( a8, stab, stab );
    [ DoubleCoset( Subgroup( s8, [ (3,8,7), (3,4)(7,8), (3,5,4,8,7),
          (3,6,5)(4,8,7), (2,6,4,5)(7,8) ] ), (), Subgroup( s8,
        [ (3,8,7), (3,4)(7,8), (3,5,4,8,7), (3,6,5)(4,8,7),
          (2,6,4,5)(7,8) ] ) ),
      DoubleCoset( Subgroup( s8, [ (3,8,7), (3,4)(7,8), (3,5,4,8,7),
          (3,6,5)(4,8,7), (2,6,4,5)(7,8) ] ), (1,2)(7,8), Subgroup( s8,
        [ (3,8,7), (3,4)(7,8), (3,5,4,8,7), (3,6,5)(4,8,7),
          (2,6,4,5)(7,8) ] ) ) ]
    gap> Length( double );
    2

We compute the numbers of ('sgp','sgp') and ('sgp','stab') double cosets.

    gap> Length( DoubleCosets( a8, sgp, sgp ) );
    4
    gap> Length( DoubleCosets( a8, sgp, stab ) );
    2

Thus both irreducible constituents of permchar1 are also constituents of permchar2, i.e., the difference of the two permutation characters is a proper character of a8 of norm two.

    gap> permchar2 - permchar1;
    [ 48, 0, 2, 6, 8, -1, -1, 0, 0, 0, 0, -2, 1, 1 ]

Previous Up Top Next
Index

GAP 3.4.4
April 1997