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