# 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.

GAP 3.4.4
April 1997