# [GAP Forum] re: some simple and obvious and MISSING items for the FAQ

Steve Linton sal at dcs.st-and.ac.uk
Tue Oct 12 11:42:39 BST 2004

```Dear GAP Forum,

Shane Miller asked a number of questions. "Mowsey" has already provided a
number of excellent answers. We will think about ways to include some of
these points in the tutorial documentation. Let me here expand on a few points
further, and include some examples:

The first point, which answers several of them is that the group operation in
GAP is always multiplication, written with *.

This works for groups of permutations, and matrices and for more abstract
groups given by generators and relations.

While you can construct a number of groups of permutations, they all have the
same multiplication, in the sense that if two permutations p1 and p2 are both
in two permutation groups, their product in each group will be the permutation
p1*p2 given by applying p1 followed by p2.

In fact, this essentially works the other way round. GAP first defines
elements, such as permutations, matrices or words in abstract generators, with
their operations such as multiplication and inverse, then it allows you to
define groups of such objects, using the objects multiplication as the group
operation.

groups) but they are not the same, for GAP's purposes,  as "groups" which are
always multiplicative. for example `SylowSubgroup' cannot be used to compute a
Sylow subgroup of an additive group. Thus, (Z/3Z, +) is, for GAP purposes, not
a group. You can construct an isomorphic multiplicative group in a variety of
ways, most simply using the CyclicGroup constructor, and solve any mathematical
problem you want in that isomorphic group, but you cannot actually have a
GAP group whose operation is addition.

Although they cannot be an additive group, GAP does support
computation in the integers mod n, in a number of ways. You can
do individual computations using the mod operator (3 + 5) mod 7 will be 1, for
instance, or you can construct the whole ring of integers modulo n using
ZmodnZ (see the manual section).

Next, GAP's group constructors will generally, and by default, construct a
group of the specified isomorphism type, in whatever form is most efficient for
computation. No specific nomenclature for the elements if guaranteed.

So

gap> q8 := SmallGroup(8,4);
<pc group of size 8 with 3 generators>
gap> AsList(q8);
[ <identity> of ..., f1, f2, f3, f1*f2, f1*f3, f2*f3, f1*f2*f3 ]
gap>

is a perfectly good description of a group of order 8 isomorphic to the group
generated by the quaternions i and j.

We can actually see that by making the group of quaternions:

gap> q := QuaternionAlgebra(Rationals);
<algebra-with-one of dimension 4 over Rationals>
gap> gens := GeneratorsOfAlgebraWithOne(q);
[ e, i, j, k ]
gap> e := gens[1]; i := gens[2]; j := gens[3]; k := gens[4];
e
i
j
k
gap> g := Group(i,j);
#I  default `IsGeneratorsOfMagmaWithInverses' method returns `true' for
[ i, j ]
<group with 2 generators>
gap> AsList(g);
[ (-1)*e, (-1)*i, (-1)*j, (-1)*k, k, j, i, e ]
gap> IsomorphismGroups(q8,g);
[ f1, f2, f3 ] -> [ j, i, (-1)*e ]

Here we construct the group q8 that you were expecting, list its elements and,
in the last line, demonstrate an isomorphism between the library group
SmallGroup(8,4) and the group of quaternions.

Using this group g, we can, for instance print the normal subgroups

gap> Print(NormalSubgroups(g),"\n");;
[ Group( [ i, j ] ), Group( [ (-1)*k, (-1)*e ]), Group( [ (-1)*j, (-1)*e ] ),
Group( [ i, (-1)*e ] ), Group( [(-1)*e ] ), Group( e ) ]

Each subgroup is still given only in terms of generating elements because as
soon as your groups get much larger you almost never actually want the complete
list of elements. If you want them in this case, you can do

gap> for n in NormalSubgroups(g) do Print(AsList(n),"\n"); od;
[ (-1)*e, (-1)*i, (-1)*j, (-1)*k, k, j, i, e ]
[ (-1)*e, (-1)*k, k, e ]
[ (-1)*e, (-1)*j, j, e ]
[ (-1)*e, (-1)*i, i, e ]
[ (-1)*e, e ]
[ e ]
gap>

In general, if you want to see the elements of your group in some
particular notation, you need to construct the group from elements of
that kind. Then, if you ask for a subgroup or coset `AsList', you will
get what you want.  AsList is better than `Elements' because it does
not insist that the elements be sorted, and can, as a result be
considerably faster in many cases.  For instance, when you say you
want the generating elements for a particular subgroup of D16, in what
form do you want them? The standard representation (because it's the
best for computing), is as words in what are called polycylic
generators. If you would prefer permutations, you can specify this
when constructing the group:

gap> DihedralGroup(IsPermGroup,16);
Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ])

or see IsomorphismPermGroup in the manual for a more general approach.

D16 might also be thought of as a finitely-presented group in at least two
ways:

As the group generated by an element of order 8 (a rotation) and an element of
order 2 which reverses it (a reflection)

gap> f := FreeGroup("a","b");
<free group on the generators [ a, b ]>
gap> a := f.1; b := f.2;
a
b
gap> g := f/[a^8, b^2,b^-1*a*b*a];
<fp group on the generators [ a, b ]>
gap> Size(g);
16
gap> AsList(g);
[ <identity ...>, b, a^7*b, a, a^7, a*b, a^6*b, a^2, a^6, a^2*b, a^5*b, a^3,
a^5,  a^3*b, a^4*b, a^4 ]

As the group generated by two elements of order 2 with product of order 8:

gap> f := FreeGroup("s","t");
<free group on the generators [ s, t ]>
gap> s := f.1; t := f.2;
s
t
gap> g2 := f/[s^2,t^2,(s*t)^8];
<fp group on the generators [ s, t ]>
gap> Size(g2);
16
gap> AsList(g2);
[ <identity ...>, t, s, t*s, s*t, t*s*t, s*t*s, t*s*t*s, s*t*s*t, t*s*t*s*t,
s*t*s*t*s, t*s*t*s*t*s, s*t*s*t*s*t, t*s*t*s*t*s*t, s*t*s*t*s*t*s,
s*t*s*t*s*t*s*t ]
gap> IsomorphismGroups(g,g2);
[ a, b ] -> [ s^-1*t*s^2, t^-1*s^-1*t*s^2 ]

Finally, to get groups from the GraphicSubgroupLattice back into GAP you can
use the"selected groups to GAP" option on the "Subgroups" menu. This sets the
GAP variable last to a list containing all the selected subgroups. This is
described in the manual for the XGAP package.

In general, if you want to enter elements of any pc group as they print you
need to do something like:

gap> g := DihedralGroup(16);
<pc group of size 16 with 4 generators>
gap> gens := GeneratorsOfGroup(g);
[ f1, f2, f3, f4 ]
gap> f1 := gens[1]; f2 := gens[2]; f3 := gens[3]; f4 := gens[4];
f1
f2
f3
f4

After which you can do things like:

gap> Group([f1]);
<pc group with 1 generators>
gap> AsList(last);
[ <identity> of ..., f1 ]

In practise, however, you almost never need to do this.

I hope this all helps.  If you have any further difficulties, please feel free
to contact support, or continue discussion on the forum.

Steve Linton

--
Steve Linton	School of Computer Science  &
Centre for Interdisciplinary Research in Computational Algebra
University of St Andrews 	 Tel   +44 (1334) 463269
http://www.dcs.st-and.ac.uk/~sal	 Fax   +44 (1334) 463278

```