1.19 About Operations of Groups

One of the most important tools in group theory is the operation or action of a group on a certain set.

We say that a group G operates on a set D if we have a function that takes each pair (d,g) with d in D and g in G to another element d^g in D, which we call the image of d under g, such that d^{identity} = d and (d^g)^h = d^{gh} for each d in D and g,h in G.

This is equivalent to saying that an operation is a homomorphism of the group G into the full symmetric group on D. We usually call D the domain of the operation and its elements points.

In this section we will demonstrate how you can compute with operations of groups. For an example we will use the alternating group on 8 points.

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

It is important to note however, that the applicability of the functions from the operation package is not restricted to permutation groups. All the functions mentioned in this section can also be used to compute with the operation of a matrix group on the vectors, etc. We only use a permutation group here because this makes the examples more compact.

The standard operation in GAP is always denoted by the caret (^) operator. That means that when no other operation is specified (we will see below how this can be done) all the functions from the operations package will compute the image of a point p under an element g as p^g. Note that this can already denote different operations, depending on the type of points and the type of elements. For example if the group elements are permutations it can either denote the normal operation when the points are integers or the conjugation when the points are permutations themselves (see Operations for Permutations). For another example if the group elements are matrices it can either denote the multiplication from the right when the points are vectors or again the conjugation when the points are matrices (of the same dimension) themselves (see Operations for Matrices). Which operations are available through the caret operator for a particular type of group elements is described in the chapter for this type of group elements.

    gap> 2 ^ (1,2,3);
    3
    gap> 1 ^ a8.2;
    1
    gap> (2,4) ^ (1,2,3);
    (3,4) 

The most basic function of the operations package is the function Orbit, which computes the orbit of a point under the operation of the group.

    gap> Orbit( a8, 2 );
    [ 2, 3, 1, 4, 5, 6, 7, 8 ] 

Note that the orbit is not a set, because it is not sorted. See Orbit for the definition in which order the points appear in an orbit.

We will try to find several subgroups in a8 using the operations package. One subgroup is immediately available, namely the stabilizer of one point. The index of the stabilizer must of course be equal to the length of the orbit, i.e., 8.

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

This gives us a hint how to find further subgroups. Each subgroup is the stabilizer of a point of an appropriate transitive operation (namely the operation on the cosets of that subgroup or another operation that is equivalent to this operation).

So the question is how to find other operations. The obvious thing is to operate on pairs of points. So using the function Tuples (see Tuples) we first generate a list of all pairs.

    gap> pairs := Tuples( [1..8], 2 );
    [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ], [ 1, 6 ],
      [ 1, 7 ], [ 1, 8 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ], [ 2, 4 ],
      [ 2, 5 ], [ 2, 6 ], [ 2, 7 ], [ 2, 8 ], [ 3, 1 ], [ 3, 2 ],
      [ 3, 3 ], [ 3, 4 ], [ 3, 5 ], [ 3, 6 ], [ 3, 7 ], [ 3, 8 ],
      [ 4, 1 ], [ 4, 2 ], [ 4, 3 ], [ 4, 4 ], [ 4, 5 ], [ 4, 6 ],
      [ 4, 7 ], [ 4, 8 ], [ 5, 1 ], [ 5, 2 ], [ 5, 3 ], [ 5, 4 ],
      [ 5, 5 ], [ 5, 6 ], [ 5, 7 ], [ 5, 8 ], [ 6, 1 ], [ 6, 2 ],
      [ 6, 3 ], [ 6, 4 ], [ 6, 5 ], [ 6, 6 ], [ 6, 7 ], [ 6, 8 ],
      [ 7, 1 ], [ 7, 2 ], [ 7, 3 ], [ 7, 4 ], [ 7, 5 ], [ 7, 6 ],
      [ 7, 7 ], [ 7, 8 ], [ 8, 1 ], [ 8, 2 ], [ 8, 3 ], [ 8, 4 ],
      [ 8, 5 ], [ 8, 6 ], [ 8, 7 ], [ 8, 8 ] ] 

Now we would like to have a8 operate on this domain. But we cannot use the default operation (denoted by the caret) because list ^ perm is not defined. So we must tell the functions from the operations package how the group elements operate on the elements of the domain. In our example we can do this by simply passing OnPairs as optional last argument. All functions from the operations package accept such an optional argument that describes the operation. See Other Operations for a list of the available nonstandard operations.

Note that those operations are in fact simply functions that take an element of the domain and an element of the group and return the image of the element of the domain under the group element. So to compute the image of the pair [1,2] under the permutation (1,4,5) we can simply write

    gap> OnPairs( [1,2], (1,4,5) );
    [ 4, 2 ] 

As was mentioned above we have to make sure that the operation is transitive. So we check this.

    gap> IsTransitive( a8, pairs, OnPairs );
    false 

The operation is not transitive, so we want to find out what the orbits are. The function Orbits does that for you. It returns a list of all the orbits.

    gap> orbs := Orbits( a8, pairs, OnPairs );
    [ [ [ 1, 1 ], [ 2, 2 ], [ 3, 3 ], [ 4, 4 ], [ 5, 5 ], [ 6, 6 ],
          [ 7, 7 ], [ 8, 8 ] ],
      [ [ 1, 2 ], [ 2, 3 ], [ 1, 3 ], [ 3, 1 ], [ 3, 4 ], [ 2, 1 ],
          [ 1, 4 ], [ 4, 1 ], [ 4, 5 ], [ 3, 2 ], [ 2, 4 ], [ 1, 5 ],
          [ 4, 2 ], [ 5, 1 ], [ 5, 6 ], [ 4, 3 ], [ 3, 5 ], [ 2, 5 ],
          [ 1, 6 ], [ 5, 3 ], [ 5, 2 ], [ 6, 1 ], [ 6, 7 ], [ 5, 4 ],
          [ 4, 6 ], [ 3, 6 ], [ 2, 6 ], [ 1, 7 ], [ 6, 4 ], [ 6, 3 ],
          [ 6, 2 ], [ 7, 1 ], [ 7, 8 ], [ 6, 5 ], [ 5, 7 ], [ 4, 7 ],
          [ 3, 7 ], [ 2, 7 ], [ 1, 8 ], [ 7, 5 ], [ 7, 4 ], [ 7, 3 ],
          [ 7, 2 ], [ 8, 1 ], [ 8, 2 ], [ 7, 6 ], [ 6, 8 ], [ 5, 8 ],
          [ 4, 8 ], [ 3, 8 ], [ 2, 8 ], [ 8, 6 ], [ 8, 5 ], [ 8, 4 ],
          [ 8, 3 ], [ 8, 7 ] ] ] 

The operation of a8 on the first orbit is of course equivalent to the original operation, so we ignore it and work with the second orbit.

    gap> u56 := Stabilizer( a8, [1,2], OnPairs );
    Subgroup( a8, [ (3,8,7), (3,6)(4,7,5,8), (6,7,8) ] )
    gap> Index( a8, u56 );
    56 

So now we have found a second subgroup. To make the following computations a little bit easier and more efficient we would now like to work on the points [1..56] instead of the list of pairs. The function Operation does what we need. It creates a new group that operates on [1..56] in the same way that a8 operates on the second orbit.

    gap> a8_56 := Operation( a8, orbs[2], OnPairs );
    Group( ( 1, 2, 4)( 3, 6,10)( 5, 7,11)( 8,13,16)(12,18,17)(14,21,20)
    (19,27,26)(22,31,30)(28,38,37)(32,43,42)(39,51,50)(44,45,55),
    ( 1, 3, 7,12,19,28,39)( 2, 5, 9,15,23,33,45)( 4, 8,14,22,32,44, 6)
    (10,16,24,34,46,56,51)(11,17,25,35,47,43,55)(13,20,29,40,52,38,50)
    (18,26,36,48,31,42,54)(21,30,41,53,27,37,49) )
    gap> a8_56.name := "a8_56";;

We would now like to know if the subgroup u56 of index 56 that we found is maximal or not. Again we can make use of a function from the operations package. Namely a subgroup is maximal if the operation on the cosets of this subgroup is primitive, i.e., if there is no partition of the set of cosets into subsets such that the group operates setwise on those subsets.

    gap> IsPrimitive( a8_56, [1..56] );
    false 

Note that we must specify the domain of the operation. You might think that in the last example IsPrimitive could use [1..56] as default domain if no domain was given. But this is not so simple, for example would the default domain of Group( (2,3,4) ) be [1..4] or [2..4]? To avoid confusion, all operations package functions require that you specify the domain of operation.

We see that a8_56 is not primitive. This means of course that the operation of a8 on orb[2] is not primitive, because those two operations are equivalent. So the stabilizer u56 is not maximal. Let us try to find its supergroups. We use the function Blocks to find a block system. The (optional) third argument in the following example tells Blocks that we want a block system where 1 and 10 lie in one block. There are several other block systems, which we could compute by specifying a different pair, it just turns out that [1,10] makes the following computation more interesting.

    gap> blocks := Blocks( a8_56, [1..56], [1,10] );
    [ [ 1, 10, 13, 21, 31, 43, 45 ], [ 2, 3, 16, 20, 30, 42, 55 ],
      [ 4, 6, 8, 14, 22, 32, 44 ], [ 5, 7, 11, 24, 29, 41, 54 ],
      [ 9, 12, 17, 18, 34, 40, 53 ], [ 15, 19, 25, 26, 27, 46, 52 ],
      [ 23, 28, 35, 36, 37, 38, 56 ], [ 33, 39, 47, 48, 49, 50, 51 ] ] 

The result is a list of sets, i.e., sorted lists, such that a8_56 operates on those sets. Now we would like the stabilizer of this operation on the sets. Because we wanted to operate on the sets we have to pass OnSets as third argument.

    gap> u8_56 := Stabilizer( a8_56, blocks[1], OnSets );
    Subgroup( a8_56,
    [ (15,35,48)(19,28,39)(22,32,44)(23,33,52)(25,36,49)(26,37,50)
        (27,38,51)(29,41,54)(30,42,55)(31,43,45)(34,40,53)(46,56,47),
      ( 9,25)(12,19)(14,22)(15,34)(17,26)(18,27)(20,30)(21,31)(23,48)
        (24,29)(28,39)(32,44)(33,56)(35,47)(36,49)(37,50)(38,51)(40,52)
        (41,54)(42,55)(43,45)(46,53), ( 5,17)( 7,12)( 8,14)( 9,24)(11,18)
        (13,21)(15,25)(16,20)(23,47)(28,39)(29,34)(32,44)(33,56)(35,49)
        (36,48)(37,50)(38,51)(40,54)(41,53)(42,55)(43,45)(46,52),
      ( 2,11)( 3, 7)( 4, 8)( 5,16)( 9,17)(10,13)(20,24)(23,47)(25,26)
        (28,39)(29,30)(32,44)(33,56)(35,48)(36,50)(37,49)(38,51)(40,53)
        (41,55)(42,54)(43,45)(46,52), ( 1,10)( 2, 6)( 3, 4)( 5, 7)( 8,16)
        (12,17)(14,20)(19,26)(22,30)(23,47)(28,50)(32,55)(33,56)(35,48)
        (36,49)(37,39)(38,51)(40,53)(41,54)(42,44)(43,45)(46,52) ] )
    gap> Index( a8_56, u8_56 );
    8 

Now we have a problem. We have found a new subgroup, but not as a subgroup of a8, instead it is a subgroup of a8_56. We know that a8_56 is isomorphic to a8 (in general the result of Operation is only isomorphic to a factor group of the original group, but in this case it must be isomorphic to a8, because a8 is simple and has only the full group as nontrivial factor group). But we only know that an isomorphism exists, we do not know it.

Another function comes to our rescue. OperationHomomorphism returns the homomorphism of a group onto the group that was constructed by Operation. A later section in this chapter will introduce mappings and homomorphisms in general, but for the moment we can just regard the result of OperationHomomorphism as a black box that we can use to transfer information from a8 to a8_56 and back.

    gap> h56 := OperationHomomorphism( a8, a8_56 );
    OperationHomomorphism( a8, a8_56 )
    gap> u8b := PreImages( h56, u8_56 );
    Subgroup( a8, [ (6,7,8), (5,6)(7,8), (4,5)(7,8), (3,4)(7,8),
      (1,3)(7,8) ] )
    gap> Index( a8, u8b );
    8
    gap> u8 = u8b;
    false 

So we have in fact found a new subgroup. However if we look closer we note that u8b is not totally new. It fixes the point 2, thus it lies in the stabilizer of 2, and because it has the same index as this stabilizer it must in fact be the stabilizer. Thus u8b is conjugated to u8. A nice way to check this is to check that the operation on the 8 blocks is equivalent to the original operation.

    gap> IsEquivalentOperation( a8, [1..8], a8_56, blocks, OnSets );
    true 

Now the choice of the third argument [1,10] of Blocks becomes clear. Had we not given that argument we would have obtained the block system that has [1,3,7,12,19,28,39] as first block. The preimage of the stabilizer of this set would have been u8 itself, and we would not have been able to introduce IsEquivalentOperation. Of course we could also use the general function IsConjugate, but we want to demonstrate IsEquivalentOperation.

Actually there is a third block system of a8_56 that gives rise to a third subgroup.

    gap> blocks := Blocks( a8_56, [1..56], [1,6] );
    [ [ 1, 6 ], [ 2, 10 ], [ 3, 4 ], [ 5, 16 ], [ 7, 8 ], [ 9, 24 ],
      [ 11, 13 ], [ 12, 14 ], [ 15, 34 ], [ 17, 20 ], [ 18, 21 ],
      [ 19, 22 ], [ 23, 46 ], [ 25, 29 ], [ 26, 30 ], [ 27, 31 ],
      [ 28, 32 ], [ 33, 56 ], [ 35, 40 ], [ 36, 41 ], [ 37, 42 ],
      [ 38, 43 ], [ 39, 44 ], [ 45, 51 ], [ 47, 52 ], [ 48, 53 ],
      [ 49, 54 ], [ 50, 55 ] ]
    gap> u28_56 := Stabilizer( a8_56, [1,6], OnSets );
    Subgroup( a8_56,
    [ ( 2,38,51)( 3,28,39)( 4,32,44)( 5,41,54)(10,43,45)(16,36,49)
        (17,40,53)(20,35,48)(23,47,30)(26,46,52)(33,55,37)(42,56,50),
      ( 5,17,26,37,50)( 7,12,19,28,39)( 8,14,22,32,44)( 9,15,23,33,54)
        (11,18,27,38,51)(13,21,31,43,45)(16,20,30,42,55)(24,34,46,56,49)
        (25,35,47,41,53)(29,40,52,36,48),
      ( 1, 6)( 2,39,38,19,18, 7)( 3,51,28,27,12,11)( 4,45,32,31,14,13)
        ( 5,55,33,23,15, 9)( 8,10,44,43,22,21)(16,50,56,46,34,24)
        (17,54,42,47,35,25)(20,49,37,52,40,29)(26,53,41,30,48,36) ] )
    gap> u28 := PreImages( h56, u28_56 );
    Subgroup( a8, [ (3,7,8), (4,5,6,7,8), (1,2)(3,8,7,6,5,4) ] )
    gap> Index( a8, u28 );
    28 

We know that the subgroup u28 of index 28 is maximal, because we know that a8 has no subgroups of index 2, 4, or 7. However we can also quickly verify this by checking that a8_56 operates primitively on the 28 blocks.

    gap> IsPrimitive( a8_56, blocks, OnSets );
    true 

There is a different way to obtain u28. Instead of operating on the 56 pairs [ [1,2], [1,3], ..., [8,7] ] we could operate on the 28 sets of two elements from [1..8]. But suppose we make a small mistake.

    gap> OrbitLength( a8, [2,1], OnSets );
    Error, OnSets: <tuple> must be a set 

It is your responsibility to make sure that the points that you pass to functions from the operations package are in normal form. That means that they must be sets if you operate on sets with OnSets, they must be lists of length 2 if you operate on pairs with OnPairs, etc. This also applies to functions that accept a domain of operation, e.g., Operation and IsPrimitive. All points in such a domain must be in normal form. It is not guaranteed that a violation of this rule will signal an error, you may obtain incorrect results.

Note that Stabilizer is not only applicable to groups like a8 but also to their subgroups like u56. So another method to find a new subgroup is to compute the stabilizer of another point in u56. Note that u56 already leaves 1 and 2 fixed.

    gap> u336 := Stabilizer( u56, 3 );
    Subgroup( a8, [ (4,6,5), (5,6)(7,8), (6,7,8) ] )
    gap> Index( a8, u336 );
    336 

Other functions are also applicable to subgroups. In the following we show that u336 operates regularly on the 60 triples of [4..8] which contain no element twice, which means that this operation is equivalent to the operations of u336 on its 60 elements from the right. Note that OnTuples is a generalization of OnPairs.

    gap> IsRegular( u336, Orbit( u336, [4,5,6], OnTuples ), OnTuples );
    true 

Just as we did in the case of the operation on the pairs above, we now construct a new permutation group that operates on [1..336] in the same way that a8 operates on the cosets of u336. Note that the operation of a group on the cosets is by multiplication from the right, thus we have to specify OnRight.

    gap> a8_336 := Operation( a8, Cosets( a8, u336 ), OnRight );;
    gap> a8_336.name := "a8_336";;

To find subgroups above u336 we again check if the operation is primitive.

    gap> blocks := Blocks( a8_336, [1..336], [1,43] );
    [ [ 1, 43, 85 ], [ 2, 102, 205 ], [ 3, 95, 165 ], [ 4, 106, 251 ],
      [ 5, 117, 334 ], [ 6, 110, 294 ], [ 7, 122, 127 ], [ 8, 144, 247 ],
      [ 9, 137, 207 ], [ 10, 148, 293 ], [ 11, 45, 159 ],
      [ 12, 152, 336 ], [ 13, 164, 169 ], [ 14, 186, 289 ],
      [ 15, 179, 249 ], [ 16, 190, 335 ], [ 17, 124, 201 ],
      [ 18, 44, 194 ], [ 19, 206, 211 ], [ 20, 228, 331 ],
      [ 21, 221, 291 ], [ 22, 46, 232 ], [ 23, 166, 243 ],
      [ 24, 126, 236 ], [ 25, 248, 253 ], [ 26, 48, 270 ],
      [ 27, 263, 333 ], [ 28, 125, 274 ], [ 29, 208, 285 ],
      [ 30, 168, 278 ], [ 31, 290, 295 ], [ 32, 121, 312 ],
      [ 33, 47, 305 ], [ 34, 167, 316 ], [ 35, 250, 327 ],
      [ 36, 210, 320 ], [ 37, 74, 332 ], [ 38, 49, 163 ], [ 39, 81, 123 ],
      [ 40, 59, 209 ], [ 41, 70, 292 ], [ 42, 66, 252 ], [ 50, 142, 230 ],
      [ 51, 138, 196 ], [ 52, 146, 266 ], [ 53, 87, 131 ],
      [ 54, 153, 302 ], [ 55, 160, 174 ], [ 56, 182, 268 ],
      [ 57, 178, 234 ], [ 58, 189, 304 ], [ 60, 86, 199 ],
      [ 61, 198, 214 ], [ 62, 225, 306 ], [ 63, 218, 269 ],
      [ 64, 88, 235 ], [ 65, 162, 245 ], [ 67, 233, 254 ],
      [ 68, 90, 271 ], [ 69, 261, 301 ], [ 71, 197, 288 ],
      [ 72, 161, 281 ], [ 73, 265, 297 ], [ 75, 89, 307 ],
      [ 76, 157, 317 ], [ 77, 229, 328 ], [ 78, 193, 324 ],
      [ 79, 116, 303 ], [ 80, 91, 158 ], [ 82, 101, 195 ],
      [ 83, 112, 267 ], [ 84, 108, 231 ], [ 92, 143, 237 ],
      [ 93, 133, 200 ], [ 94, 150, 273 ], [ 96, 154, 309 ],
      [ 97, 129, 173 ], [ 98, 184, 272 ], [ 99, 180, 238 ],
      [ 100, 188, 308 ], [ 103, 202, 216 ], [ 104, 224, 310 ],
      [ 105, 220, 276 ], [ 107, 128, 241 ], [ 109, 240, 256 ],
      [ 111, 260, 311 ], [ 113, 204, 287 ], [ 114, 130, 277 ],
      [ 115, 275, 296 ], [ 118, 132, 313 ], [ 119, 239, 330 ],
      [ 120, 203, 323 ], [ 134, 185, 279 ], [ 135, 175, 242 ],
      [ 136, 192, 315 ], [ 139, 171, 215 ], [ 140, 226, 314 ],
      [ 141, 222, 280 ], [ 145, 244, 258 ], [ 147, 262, 318 ],
      [ 149, 170, 283 ], [ 151, 282, 298 ], [ 155, 246, 329 ],
      [ 156, 172, 319 ], [ 176, 227, 321 ], [ 177, 217, 284 ],
      [ 181, 213, 257 ], [ 183, 264, 322 ], [ 187, 286, 300 ],
      [ 191, 212, 325 ], [ 219, 259, 326 ], [ 223, 255, 299 ] ] 

To find the subgroup of index 112 that belongs to this operation we could use the same methods as before, but we actually use a different trick. From the above we see that the subgroup is the union of u336 with its 43rd and its 85th coset. Thus we simply add a representative of the 43rd coset to the generators of u336.

    gap> u112 := Closure( u336, Representative( Cosets(a8,u336)[43] ) );
    Subgroup( a8, [ (4,6,5), (5,6)(7,8), (6,7,8), (1,3,2) ] )
    gap> Index( a8, u112 );
    112 

Above this subgroup of index 112 lies a subgroup of index 56, which is not conjugate to u56. In fact, unlike u56 it is maximal. We obtain this subgroup in the same way that we obtained u112, this time forcing two points, namely 39 and 43 into the first block.

    gap> blocks := Blocks( a8_336, [1..336], [1,39,43] );;
    gap> Length( blocks );
    56
    gap> u56b := Closure( u112, Representative( Cosets(a8,u336)[39] ) );
    Subgroup( a8, [ (4,6,5), (5,6)(7,8), (6,7,8), (1,3,2), (2,3)(7,8) ] )
    gap> Index( a8, u56b );
    56
    gap> IsPrimitive( a8_336, blocks, OnSets );
    true 

We already mentioned in the beginning that there is another standard operation of permutations, namely the conjugation. E.g., because no other operation is specified in the following example OrbitLength simply operates using the caret operator and because perm1^perm2 is defined as the conjugation of perm2 on perm1 we effectively compute the length of the conjugacy class of (1,2)(3,4)(5,6)(7,8). (In fact element1^element2 is always defined as the conjugation if element1 and element2 are group elements of the same type. So the length of a conjugacy class of any element elm in an arbitrary group G can be computed as OrbitLength( G, elm ). In general however this may not be a good idea, Size( ConjugacyClass( G, elm ) ) is probably more efficient.)

    gap> OrbitLength( a8, (1,2)(3,4)(5,6)(7,8) );
    105
    gap> orb := Orbit( a8, (1,2)(3,4)(5,6)(7,8) );;
    gap> u105 := Stabilizer( a8, (1,2)(3,4)(5,6)(7,8) );
    Subgroup( a8, [ (5,6)(7,8), (1,2)(3,4)(5,6)(7,8), (5,7)(6,8),
      (3,4)(7,8), (3,5)(4,6), (1,3)(2,4) ] )
    gap> Index( a8, u105 );
    105 

Of course the last stabilizer is in fact the centralizer of the element (1,2)(3,4)(5,6)(7,8). Stabilizer notices that and computes the stabilizer using the centralizer algorithm for permutation groups.

In the usual way we now look for the subgroups that lie above u105.

    gap> blocks := Blocks( a8, orb );;
    gap> Length( blocks );
    15
    gap> blocks[1];
    [ (1,2)(3,4)(5,6)(7,8), (1,3)(2,4)(5,7)(6,8), (1,4)(2,3)(5,8)(6,7),
      (1,5)(2,6)(3,7)(4,8), (1,6)(2,5)(3,8)(4,7), (1,7)(2,8)(3,5)(4,6),
      (1,8)(2,7)(3,6)(4,5) ]

To find the subgroup of index 15 we again use closure. Now we must be a little bit careful to avoid confusion. u105 is the stabilizer of (1,2)(3,4)(5,6)(7,8). We know that there is a correspondence between the points of the orbit and the cosets of u105. The point (1,2)(3,4)(5,6)(7,8) corresponds to u105. To get the subgroup of index 15 we must add to u105 an element of the coset that corresponds to the point (1,3)(2,4)(5,7)(6,8) (or any other point in the first block). That means that we must use an element of a8 that maps (1,2)(3,4)(5,6)(7,8) to (1,3)(2,4)(5,7)(6,8). The important thing is that (1,3)(2,4)(5,7)(6,8) will not do, in fact (1,3)(2,4)(5,7)(6,8) lies in u105.

The function RepresentativeOperation does what we need. It takes a group and two points and returns an element of the group that maps the first point to the second. In fact it also allows you to specify the operation as optional fourth argument as usual, but we do not need this here. If no such element exists in the group, i.e., if the two points do not lie in one orbit under the group, RepresentativeOperation returns false.

    gap> rep := RepresentativeOperation( a8, (1,2)(3,4)(5,6)(7,8),
    >                                         (1,3)(2,4)(5,7)(6,8) );
    (2,3)(6,7)
    gap> u15 := Closure( u105, rep );
    Subgroup( a8, [ (5,6)(7,8), (1,2)(3,4)(5,6)(7,8), (5,7)(6,8),
      (3,4)(7,8), (3,5)(4,6), (1,3)(2,4), (2,3)(6,7) ] )
    gap> Index( a8, u15 );
    15 

u15 is of course a maximal subgroup, because a8 has no subgroups of index 3 or 5.

There is in fact another class of subgroups of index 15 above u105 that we get by adding (2,3)(6,8) to u105.

    gap> u15b := Closure( u105, (2,3)(6,8) );
    Subgroup( a8, [ (5,6)(7,8), (1,2)(3,4)(5,6)(7,8), (5,7)(6,8),
      (3,4)(7,8), (3,5)(4,6), (1,3)(2,4), (2,3)(6,8) ] )
    gap> Index( a8, u15b );
    15 

We now show that u15 and u15b are not conjugate. We showed that u8 and u8b are conjugate by showing that the operations on the cosets where equivalent. We could show that u15 and u15b are not conjugate by showing that the operations on their cosets are not equivalent. Instead we simply call RepresentativeOperation again.

    gap> RepresentativeOperation( a8, u15, u15b );
    false 

RepresentativeOperation tells us that there is no element g in a8 such that u15^g = u15b. Because ^ also denotes the conjugation of subgroups this tells us that u15 and u15b are not conjugate. Note that this operation should only be used rarely, because it is usually not very efficient. The test in this case is however reasonable efficient, and is in fact the one employed by IsConjugate (see IsConjugate).

This concludes our example. In this section we demonstrated some functions from the operations package. There is a whole class of functions that we did not mention, namely those that take a single element instead of a whole group as first argument, e.g., Cycle and Operations of Groups.

Previous Up Top Next
Index

GAP 3.4.4
April 1997