Manual
User Manual:
Open the PDF directly: View PDF .
Page Count: 1930
GAP
Groups, Algorithms and Programming
version 3.4.4 distribution gap3-jm
Martin Schönert
with
Hans Ulrich Besche, Thomas Breuer, Frank Celler, Bettina Eick
Volkmar Felsch, Alexander Hulpke, Jürgen Mnich, Werner Nickel
Götz Pfeiffer, Udo Polis, Heiko Theißen
Lehrstuhl D für Mathematik, RWTH Aachen
Alice Niemeyer
Department of Mathematics, University of Western Australia
Jean Michel
Department of Mathematics, University Paris-Diderot, France
GAP 3.4.4 of 20 Dec. 1995, gap3-jm of 19 Feb. 2018
Copyright c 1992 by Lehrstuhl D für Mathematik
RWTH, Templergraben 64, D 5100 Aachen, Germany
GAP3 can be copied and distributed freely for any non-commercial purpose.
If you copy GAP3 for somebody else, you may ask this person for refund of your expenses.
This should cover cost of media, copying and shipping. You are not allowed to ask for more
than this. In any case you must give a copy of this copyright notice along with the program.
If you obtain GAP3 please send us a short notice to that effect, e.g., an e-mail message to the
address gap@samson.math.rwth-aachen.de, containing your full name and address. This
allows us to keep track of the number of GAP3 users.
If you publish a mathematical result that was partly obtained using GAP3, please cite GAP3,
just as you would cite another paper that you used. Also we would appreciate it if you could
inform us about such a paper.
You are permitted to modify and redistribute GAP3, but you are not allowed to restrict
further redistribution. That is to say proprietary modifications will not be allowed. We
want all versions of GAP3 to remain free.
If you modify any part of GAP3 and redistribute it, you must supply a README document.
This should specify what modifications you made in which files. We do not want to take
credit or be blamed for your modifications.
Of course we are interested in all of your modifications. In particular we would like to see
bug-fixes, improvements and new functions. So again we would appreciate it if you would
inform us about all modifications you make.
GAP3 is distributed by us without any warranty, to the extent permitted by applicable state
law. We distribute GAP3 as is without warranty of any kind, either expressed or implied,
including, but not limited to, the implied warranties of merchantability and fitness for a
particular purpose.
The entire risk as to the quality and performance of the program is with you. Should GAP3
prove defective, you assume the cost of all necessary servicing, repair or correction.
In no case unless required by applicable law will we, and/or any other party who may
modify and redistribute GAP3 as permitted above, be liable to you for damages, including
lost profits, lost monies or other special, incidental or consequential damages arising out of
the use or inability to use GAP3.
Preface
Welcome to the first release of GAP3 from St Andrews. In the two years since the release of
GAP3 3.4.3, most of the efforts of the GAP3 team in Aachen have been devoted to the forthcoming major release, GAP4.1, which will feature a re-engineered kernel with many extra
facilities, a completely new scheme for structuring the library, many new and enhanced
algorithms and algorithms for new structures such as algebras and semigroups.
While this was going on, however, our users were not idle, and a number of bugs and
blemishes in the system were found, while a substantial number of new or improved share
packages have been submitted and accepted. Once it was decided that the computational
algebra group at St Andrews would take over GAP3 development, we agreed, as a learning
exercise, to release a new upgrade of GAP3 3.4, incorporating the bug fixes and new packages.
Assembling the release has indeed been a learning experience, and has, of course, taken
much longer than we hoped. The release incorporates fixes to all known bugs in the library
and kernel. In addition, there are two large new data libraries:of transitivie permutation
groups up to degree 23; and of all groups of order up to 1000, except those of order 512 or
768 and some others have been extended. This release includes a number of share packages
that are new since 3.4.3:
autag
for computing the automorphism groups of soluble groups;
CHEVIE
for computing with finite Coxeter groups, Hecke algebras, Chevalley groups and related structures;
CrystGap
for computing with crystallographic groups;
glissando
for comnputing with near-rings and semigroups;
grim
for computing with rational and integer matrix groups;
kbmag
linking to Knuth-Bendix package for monoids and groups;
matrix
for analysing matrix groups over finite fields, replacing smash and classic;
pcqa
linking to a polycyclic quotient program;
3
4
PREFACE
specht
for computing the representation theory of the symmetric group and related structures; and
xmod
for computing with crossed modules.
A number of other share packages have also been updated. Full details of all of these can
be found in the updated manual, which is now also supplied in an HTML version.
Despite the tribulations of this release, we are looking forward to taking over a central role
in GAP3 development in the future, and to working with the users and contributors who are
so essential a part of making GAP3 what it is.
St Andrews, April 18.,1997,
Steve Linton.
In the distribution gap3-jm, there are the following additional packages:
anupq
The p-quotient algorithm, to work with p-groups.
anusq
The soluble quotient algorithm.
arep
Constructive representation theory.
cohomolo
Cohomology and extensions of finite groups.
dce
Double coset enumeration.
grape
Computing with graphs and group.
guava
Coding theory algorithms.
meataxe
Splitting modular representations.
monoid
Computing with monoids and semigroups.
nq
The nilpotent quotient algorithm.
sisyphos
Modular group algebras of p-groups.
ve
Vector enumeration, for representations of finitely presented algebras.
algebra
Finite-dimensional algebras.
vkcurve
Fundamental group of the complement of a complex hypersurface. Also provides
multivariate polynomials and rational fractions.
PREFACE
5
GAP3 stands for Groups, Algorithms and Programming. The name was chosen to
reflect the aim of the system, which is introduced in this manual.
Until well into the eighties the interest of pure mathematicians in computational group theory was stirred by, but in most cases also confined to the information that was produced by
group theoretical software for their special research problems – and hampered by the uneasy
feeling that one was using black boxes of uncontrollable reliability. However the last years
have seen a rapid spread of interest in the understanding, design and even implementation
of group theoretical algorithms. These are gradually becoming accepted both as standard
tools for a working group theoretician, like certain methods of proof, and as worthwhile
objects of study, like connections between notions expressed in theorems.
GAP3 was started as an attempt to meet this interest. Therefore a primary design goal
has been to give its user full access to algorithms and the data structures used by them,
thus allowing critical study as well as modification of existing methods. We also intend to
relieve the user from unwanted technical chores and to assist him in the programming, thus
supporting invention and implementation of new algorithms as well as experimentation with
them.
We have tried to achieve these goals by a design which in addition makes GAP3 easily
portable, even to computers such as Atari ST and Amiga, and at the same time facilitates
the maintenance of GAP3 with the limited resources of an academic environment.
While I had felt for some time rather strongly the wish for such a truly open system for
computational group theory, the concrete idea of GAP3 was born when, together with a larger
group of students, among whom were Johannes Meier, Werner Nickel, Alice Niemeyer, and
Martin Schönert who eventually wrote the first version of GAP3, I had my first contact with
the Maple system at the EUROCAL meeting in Linz/Austria in 1985. Maple demonstrated
to us the feasibility of a strong and efficient computer algebra system built from a small
kernel, with an interpreted library of routines written in a problem-adapted language. The
discussion of the plan of a system for computational group theory organized in a similar
way started in the fall of 1985, programming only in the second half of 1986. A first
version of GAP3 was operational by the end of 1986. The system was first presented at
the Oberwolfach meeting on computational group theory in May 1988. Version 2.4 was the
first officially to be given away from Aachen starting in December 1988. The strong interest
in this version, in spite of its still rather small collection of group theoretical routines, as
well as constructive criticism by many colleagues, confirmed our belief in the general design
principles of the system. Nevertheless over three years had passed until in April 1992 version
3.1 was released, which was followed in February 1993 by version 3.2, in November 1993 by
version 3.3 and is now in June 1994 followed by version 3.4.
A main reason for the long time between versions 2.4 and 3.1 and the fact that there had not
been intermediate releases was that we had found it advisable to make a number of changes
to basic data structures until with version 3.1 we hoped to have reached a state where we
could maintain upward compatibility over further releases, which were planned to follow
much more frequently. Both goals have been achieved over the last two years. Of course the
time has also been used to extend the scope of the methods implemented in GAP3. A rough
estimate puts the size of the program library of version 3.4 at about sixteen times the size
of that of version 2.4, while for version 3.1 the factor was about eight. Compared to GAP3
3.2, which was the last version with major additions, new features of GAP3 3.4 include the
following:
6
PREFACE
- New data types (and extensions of methods) for algebras, modules and characters
- Further methods for working with finite presentations (IMD, a fast size function)
- Some “Almost linear” methods and (rational) conjugacy classes for permutation groups
- Methods based on “special AG systems” for finite soluble groups
- A package for the calculation of Galois groups and field extensions
- Extensions of the library of data (transitive permutation groups, crystallographic groups)
- An X-window based X-GAP3 for display of subgroup lattices
- Five further share libraries (ANU SQ, MEATAXE, SISYPHOS, VECTORENUMERATOR, SMASH)
Work on the extension of GAP3 is going on in Aachen as well as in an increasing number
of other places. We hope to be able to have the next release of GAP3 after about 9 months
again, that is in the first half of 1995.
The system that you are getting now consists of four parts:
1. A comparatively small kernel, written in C, which provides the user with:
- automatic dynamic storage management, which the user needn’t bother about in
his programming;
- a set of time-critical basic functions, e.g. “arithmetic” operations for integers, finite
fields, permutations and words, as well as natural operations for lists and records;
- an interpreter for the GAP3 language, which belongs to the Pascal family, but, while
allowing additional types for group theoretical objects, does not require type
declarations;
- a set of programming tools for testing, debugging, and timing algorithms.
2. A much larger library of GAP3 functions that implement group theoretical and
other algorithms. Since this is written entirely in the GAP3 language, in contrast to
the situation in older group theoretical software, the GAP3 language is both the main
implementation language and the user language of the system. Therefore the user can
as easily as the original programmers investigate and vary algorithms of the library
and add new ones to it, first for own use and eventually for the benefit of all GAP3
users. We hope that moreover the structuring of the library using the concept of
domains and the techniques used for their handling that have been introduced into
GAP3 3.1 by Martin Schönert will be further helpful in this respect.
3. A library of group theoretical data which already contains various libraries of
groups (cf. chapter 38), large libraries of ordinary character tables, including all of
the Cambridge Atlas of Finite Groups and modular tables (cf. chapter 53), and a
library of tables of marks. We hope to extend this collection further with the help
of colleagues who have undertaken larger classifications of groups.
PREFACE
7
4. The documentation. This is available as a file that can either be used for on-line
help or be printed out to form this manual. Some advice for using this manual may
be helpful. The first chapter About GAP is really an introduction to the use of the
system, starting from scratch and, for the beginning, assuming neither much knowledge
about group theory nor much versatility in using a computer. Some of the later
sections of chapter 1 assume more, however. For instance section About Character
Tables definitely assumes familiarity with representation theory of finite groups, while
in particular sections About the Implementation of Domains to About Defining
New Group Elements address more advanced users who want to extend the system
to meet their special needs. The further chapters of the manual give then a full
description of the functions presently available in GAP3.
Together with the system we distribute GAP share libraries, which are separate packages
which have been written by various groups of people and remain under their responsibility.
Some of these packages are written completely in the GAP3 language, others totally or in
parts in C (or even other languages). However the functions in these packages can be called
directly from GAP3 and results are returned to GAP3. At present there are 10 such share
libraries (cf. chapter 57).
The policy for the further development of GAP3 is to keep the kernel as small as possible,
extending the set of basic functions only by very selected ones that have proved to be
time-critical and, wherever feasible, of general use. In the interest of the possibility of
exchanging functions written in the GAP3 language the kernel has to be maintained in a
single place which in the foreseeable future will be Aachen. On the other hand we hoped
from the beginning that the design of GAP3 would allow the library of GAP3 functions and
the library of data to grow not only by continued work in Aachen but, as does any other
part of mathematics, by contributions from many sides, and these hopes have been fulfilled
very well.
There are some other points to make on further policy:
- When we began work on GAP3 the typical user that we had in mind was the one wanting to
implement his own algorithmic ideas. While we certainly hope that we still serve such
users well it has become clear from the experience of the last years that there are even
more users of two different species, on the one hand the established theorist, sometimes
with little experience in the use of computers, who wants an easily understandable tool,
on the other hand the student, often quite familiar with computers, who wants to get
assistance in learning the theory by being able to do nontrivial examples. We think
that in fact GAP3 can well be used by both, but we realize that for each a special
introduction would be desirable. We apologize that we have not had the time yet to
write such, however have learned (through the GAP3 forum) that in a couple of places
work on the development of Laboratory Manuals for the use of GAP3 alongside with
standard Algebra texts is undertaken.
- When we began work on GAP3, we designed it as a system for doing group theory. It
has already turned out that in fact the design of the system is general enough, and
some of its functions are also useful, for doing work in other neighbouring areas. For
instance Leonard Soicher has used GAP3 to develop a system GRAPE for working with
graphs, which meanwhile is available as a share library. We certainly enjoy seeing
8
PREFACE
this happen, but we want to emphasize that in Aachen our primary interest is the
development of a group theory system and that we do not plan to try to extend it
beyond our abilities into a general computer algebra system.
- Rather we hope to provide tools for linking GAP3 to other systems that represent years of
work and experience in areas such as commutative algebra, or to very efficient special
purpose stand-alone programs. A link of this kind exists e.g. to the MOC system for
the work with modular characters.
- We invite you to further extend GAP3. We are willing either to include such extensions
into GAP3 or to make them available through the same channels as GAP3 in the form of
the above mentioned share libraries. Of course, we will do this only if the extension
can be distributed free of charge like GAP3. The copyright for such share libraries
shall remain with you.
- Finally to answer an often asked question: The GAP3 language is in principle designed
to be compilable. Work on a compiler is on the way, but this is not yet ready for
inclusion with this release.
GAP3 is given away under the conditions that have always been in use between mathematicians, i.e. in particular completely in source and free of charge. We hope that the
possibility offered by modern technology of depositing GAP3 on a number of computers to
be fetched from them by ftp, will assist us in this policy. We want to emphasize, however,
two points. GAP3 is not public domain software; we want to maintain a copyright that in
particular forbids commercialization of GAP3. Further we ask that use of GAP3 be quoted
in publications like the use of any other mathematical work, and we would be grateful if we
could keep track of where GAP3 is implemented. Therefore we ask you to notify us if you have
got GAP3, e.g., by sending a short e-mail message to gap@samson.math.rwth-aachen.de.
The simple reason, on top of our curiosity, is that as anybody else in an academic environment we have from time to time to prove that we are doing meaningful work.
We have established a GAP3 forum, where interested users can discuss GAP3 related topics
by e-mail. In particular this forum is for questions about GAP3, general comments, bug
reports, and maybe bug fixes. We will read this forum and answer questions and comments,
and distribute bug fixes. Of course others are also invited to answer questions, etc. We will
also announce future releases of GAP3 in this forum.
To subscribe send an e-mail message to miles@samson.math.rwth-aachen.de containing
the line subscribe gap-forum your-name, where your-name should be your full name,
not your e-mail address. You will receive an acknowledgement, and from then on all e-mail
messages sent to gap-forum@samson.math.rwth-aachen.de.
miles@samson.math.rwth-aachen.de also accepts the following requests. help for a short
help on how to use miles, unsubscribe gap-forum to unsubscribe, recipients gap-forum
to get a list of subscribers, and statistics gap-forum to see how many e-mail messages
each subscriber has sent so far.
The reliability of large systems of computer programs is a well known general problem and,
although over the past year the record of GAP3 in this respect has not been too bad, of
course GAP3 is not exempt from this problem. We therefore feel that it is mandatory that
we, but also other users, are warned of bugs that have been encountered in GAP3 or when
PREFACE
9
doubts have arisen. We ask all users of GAP3 to use the GAP3 forum for issuing such
warnings.
We have also established an e-mail address gap-trouble to which technical problems of
a more local character such as installation problems can be sent. Together with some
experienced GAP3 users abroad we try to give advice on such problems.
GAP3 was started as a joint Diplom project of four students whose names have already been
mentioned. Since then many more finished Diplom projects have contributed to GAP3 as
well as other members of Lehrstuhl D and colleagues from other institutes. Their individual
contributions to the programs and to the manual are documented in the respective files.
To all of them as well as to all who have helped proofreading and improving this manual I
want to express my thanks for their engagement and enthusiasm as well as to many users
of GAP3 who have helped us by pointing out deficiencies and suggesting improvements.
Very special thanks however go to Martin Schönert. Not only does GAP3 owe many of its
basic design features to his profound knowledge of computer languages and the techniques
for their implementation, but in many long discussions he has in the name of future users
always been the strongest defender of clarity of the design against my impatience and the
temptation for “quick and dirty” solutions.
Since 1992 the development of GAP3 has been financially supported by the Deutsche Forschungsgemeinschaft in the context of the Forschungsschwerpunkt “Algorithmische Zahlentheorie
und Algebra”. This very important help is gratefully acknowledged.
As with the previous versions we send this version out hoping for further feedback of constructive criticism. Of course we ask to be notified about bugs, but moreover we shall
appreciate any suggestion for the improvement of the basic system as well as of the algorithms in the library. Most of all, however, we hope that in spite of such criticism you will
enjoy working with GAP3.
Aachen, June 1.,1994,
Joachim Neubüser.
Contents
1
About GAP
75
2
The Programming Language
197
3
Environment
215
4
Domains
227
5
Rings
241
6
Fields
257
7
Groups
267
8
Operations of Groups
335
9
Vector Spaces
355
10 Integers
361
11 Number Theory
373
12 Rationals
379
13 Cyclotomics
385
14 Gaussians
395
15 Subfields of Cyclotomic Fields
401
16 Algebraic extensions of fields
411
17 Unknowns
419
18 Finite Fields
423
19 Polynomials
431
20 Permutations
447
10
CONTENTS
11
21 Permutation Groups
453
22 Words in Abstract Generators
475
23 Finitely Presented Groups
483
24 Words in Finite Polycyclic Groups
519
25 Finite Polycyclic Groups
527
26 Special Ag Groups
575
27 Lists
583
28 Sets
607
29 Boolean Lists
613
30 Strings and Characters
619
31 Ranges
625
32 Vectors
629
33 Row Spaces
633
34 Matrices
647
35 Integral matrices and lattices
657
36 Matrix Rings
665
37 Matrix Groups
667
38 Group Libraries
671
39 Algebras
723
40 Finitely Presented Algebras
739
41 Matrix Algebras
747
42 Modules
753
43 Mappings
763
44 Homomorphisms
781
45 Booleans
787
46 Records
791
12
CONTENTS
47 Combinatorics
805
48 Tables of Marks
819
49 Character Tables
831
50 Generic Character Tables
875
51 Characters
879
52 Maps and Parametrized Maps
907
53 Character Table Libraries
927
54 Class Functions
943
55 Monomiality Questions
955
56 Getting and Installing GAP
965
57 Share Libraries
981
58 ANU Pq
1009
59 Automorphism Groups of Special Ag Groups
1019
60 Cohomology
1029
61 CrystGap–The Crystallographic Groups Package
1035
62 The Double Coset Enumerator
1049
63 GLISSANDO
1073
64 Grape
1109
65 GRIM (Groups of Rational and Integer Matrices)
1135
66 GUAVA
1137
67 KBMAG
1217
68 The Matrix Package
1233
69 The MeatAxe
1281
70 The Polycyclic Quotient Algorithm Package
1297
71 Sisyphos
1305
72 Decomposition numbers of Hecke algebras of type A
1313
Decomposition numbers of the symmetric groups . . . . . . . . . . . . .1319
CONTENTS
13
Hecke algebras over fields of positive characteristic . . . . . . . . . . . . .1319
The Fock space and Hecke algebras over fields of characteristic zero . . .1320
73 Vector Enumeration
1351
74 AREP
1359
75 Monoids and Semigroups
1445
76 Binary Relations
1455
77 Transformations
1465
78 Transformation Monoids
1471
79 Actions of Monoids
1481
80 XMOD
1487
81 The CHEVIE Package Version 4 – a short introduction
1553
82 Reflections, and reflection groups
1557
83 Coxeter groups
1563
84 Finite Reflection Groups
1577
85 Root systems and finite Coxeter groups
1591
86 Algebraic groups and semi-simple elements
1601
87 Classes and representations for reflection groups
1613
88 Reflection subgroups
1627
89 Garside and braid monoids and groups
1635
90 Cyclotomic Hecke algebras
1655
91 Iwahori-Hecke algebras
1663
Parameterized bases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1674
92 Representations of Iwahori-Hecke algebras
1677
93 Kazhdan-Lusztig polynomials and bases
1685
94 Parabolic modules for Iwahori-Hecke algebras
1697
95 Reflection cosets
1701
96 Coxeter cosets
1711
97 Hecke cosets
1727
98 Unipotent characters of finite reductive groups and Spetses
1729
99 Eigenspaces and d-Harish-Chandra series
1749
100 Unipotent classes of reductive groups
1753
101 Unipotent elements of reductive groups
1763
102 Affine Coxeter groups and Hecke algebras
1769
103 CHEVIE utility functions
1773
104 CHEVIE String and Formatting functions
1781
105 CHEVIE Matrix utility functions
1785
106 Cyclotomic polynomials
1791
107 Partitions and symbols
1797
108 Signed permutations
1803
109 CHEVIE utility functions – Decimal and complex numbers
1807
110 Posets and relations
1813
111 The VKCURVE package
1819
112 Multivariate polynomials and rational fractions
1825
113 The VKCURVE functions
1835
114 Some VKCURVE utility functions
1845
115 Algebra package — finite dimensional algebras
1851
Contents
1
About GAP
1.1
About Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2
About Starting and Leaving GAP . . . . . . . . . . . . . . . . . . . . .
14
75
76
76
CONTENTS
1.3
1.4
1.5
1.6
1.7
1.8
1.9
1.10
1.11
1.12
1.13
1.14
1.15
1.16
1.17
1.18
1.19
1.20
1.21
1.22
1.23
1.24
1.25
1.26
1.27
1.28
1.29
1.30
2
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
About
15
First Steps . . . . . . . . . . . . . . . . . . .
Help . . . . . . . . . . . . . . . . . . . . . . .
Syntax Errors . . . . . . . . . . . . . . . . . .
Constants and Operators . . . . . . . . . . .
Variables and Assignments . . . . . . . . . .
Functions . . . . . . . . . . . . . . . . . . . .
Lists . . . . . . . . . . . . . . . . . . . . . . .
Identical Lists . . . . . . . . . . . . . . . . .
Sets . . . . . . . . . . . . . . . . . . . . . . .
Vectors and Matrices . . . . . . . . . . . . . .
Records . . . . . . . . . . . . . . . . . . . . .
Ranges . . . . . . . . . . . . . . . . . . . . .
Loops . . . . . . . . . . . . . . . . . . . . . .
Further List Operations . . . . . . . . . . . .
Writing Functions . . . . . . . . . . . . . . .
Groups . . . . . . . . . . . . . . . . . . . . .
Operations of Groups . . . . . . . . . . . . .
Finitely Presented Groups and Presentations
Fields . . . . . . . . . . . . . . . . . . . . . .
Matrix Groups . . . . . . . . . . . . . . . . .
Domains and Categories . . . . . . . . . . . .
Mappings and Homomorphisms . . . . . . . .
Character Tables . . . . . . . . . . . . . . . .
Group Libraries . . . . . . . . . . . . . . . .
the Implementation of Domains . . . . . . . .
Defining New Domains . . . . . . . . . . . .
Defining New Parametrized Domains . . . . .
Defining New Group Elements . . . . . . . .
The Programming Language
2.1
Lexical Structure . . . . . . . . . . . . . .
2.2
Language Symbols . . . . . . . . . . . . .
2.3
Whitespaces . . . . . . . . . . . . . . . .
2.4
Keywords . . . . . . . . . . . . . . . . . .
2.5
Identifiers . . . . . . . . . . . . . . . . . .
2.6
Expressions . . . . . . . . . . . . . . . . .
2.7
Variables . . . . . . . . . . . . . . . . . .
2.8
Function Calls . . . . . . . . . . . . . . .
2.9
Comparisons . . . . . . . . . . . . . . . .
2.10
Operations . . . . . . . . . . . . . . . . .
2.11
Statements . . . . . . . . . . . . . . . . .
2.12
Assignments . . . . . . . . . . . . . . . .
2.13
Procedure Calls . . . . . . . . . . . . . . .
2.14
If . . . . . . . . . . . . . . . . . . . . . . .
2.15
While . . . . . . . . . . . . . . . . . . . .
2.16
Repeat . . . . . . . . . . . . . . . . . . .
2.17
For . . . . . . . . . . . . . . . . . . . . . .
2.18
Functions . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
77
78
78
78
80
82
83
85
87
88
90
91
92
94
95
99
107
115
120
124
125
133
138
153
159
168
176
180
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
197
198
198
199
200
200
200
201
202
203
204
204
205
206
206
207
207
208
209
16
CONTENTS
2.19
2.20
3
4
5
Return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The Syntax in BNF . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Environment
3.1
Main Loop . . . . . . . . . . .
3.2
Break Loops . . . . . . . . . .
3.3
Error . . . . . . . . . . . . . .
3.4
Line Editing . . . . . . . . . .
3.5
Help . . . . . . . . . . . . . . .
3.6
Reading Sections . . . . . . . .
3.7
Format of Sections . . . . . . .
3.8
Browsing through the Sections
3.9
Redisplaying a Section . . . . .
3.10
Abbreviating Section Names .
3.11
Help Index . . . . . . . . . . .
3.12
Read . . . . . . . . . . . . . . .
3.13
ReadLib . . . . . . . . . . . . .
3.14
Print . . . . . . . . . . . . . . .
3.15
PrintTo . . . . . . . . . . . . .
3.16
AppendTo . . . . . . . . . . . .
3.17
LogTo . . . . . . . . . . . . . .
3.18
LogInputTo . . . . . . . . . . .
3.19
SizeScreen . . . . . . . . . . . .
3.20
Runtime . . . . . . . . . . . . .
3.21
Profile . . . . . . . . . . . . . .
3.22
Exec . . . . . . . . . . . . . . .
3.23
Edit . . . . . . . . . . . . . . .
211
211
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
215
215
217
217
217
219
219
219
220
221
221
221
222
223
223
223
224
224
224
224
224
225
226
226
Domains
4.1
Domain Records . . . . . . . . . . . . . . .
4.2
Dispatchers . . . . . . . . . . . . . . . . . .
4.3
More about Dispatchers . . . . . . . . . . .
4.4
An Example of a Computation in a Domain
4.5
Domain . . . . . . . . . . . . . . . . . . . .
4.6
Elements . . . . . . . . . . . . . . . . . . .
4.7
Comparisons of Domains . . . . . . . . . .
4.8
Membership Test for Domains . . . . . . .
4.9
IsFinite . . . . . . . . . . . . . . . . . . . .
4.10
Size . . . . . . . . . . . . . . . . . . . . . .
4.11
IsSubset . . . . . . . . . . . . . . . . . . . .
4.12
Intersection . . . . . . . . . . . . . . . . . .
4.13
Union . . . . . . . . . . . . . . . . . . . . .
4.14
Difference . . . . . . . . . . . . . . . . . . .
4.15
Representative . . . . . . . . . . . . . . . .
4.16
Random . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
227
228
228
229
230
231
232
232
234
234
235
235
235
236
237
238
238
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Rings
241
5.1
IsRing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
CONTENTS
6
17
5.2
5.3
5.4
5.5
5.6
5.7
5.8
5.9
5.10
5.11
5.12
5.13
5.14
5.15
5.16
5.17
5.18
5.19
5.20
5.21
5.22
5.23
5.24
5.25
5.26
5.27
5.28
5.29
Ring . . . . . . . . . . . . . . .
DefaultRing . . . . . . . . . . .
Comparisons of Ring Elements
Operations for Ring Elements .
Quotient . . . . . . . . . . . .
IsCommutativeRing . . . . . .
IsIntegralRing . . . . . . . . .
IsUniqueFactorizationRing . .
IsEuclideanRing . . . . . . . .
IsUnit . . . . . . . . . . . . . .
Units . . . . . . . . . . . . . .
IsAssociated . . . . . . . . . .
StandardAssociate . . . . . . .
Associates . . . . . . . . . . . .
IsIrreducible . . . . . . . . . .
IsPrime . . . . . . . . . . . . .
Factors . . . . . . . . . . . . .
EuclideanDegree . . . . . . . .
EuclideanRemainder . . . . . .
EuclideanQuotient . . . . . . .
QuotientRemainder . . . . . .
Mod . . . . . . . . . . . . . . .
QuotientMod . . . . . . . . . .
PowerMod . . . . . . . . . . .
Gcd . . . . . . . . . . . . . . .
GcdRepresentation . . . . . . .
Lcm . . . . . . . . . . . . . . .
Ring Records . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
242
242
243
243
244
244
244
245
245
246
246
246
247
247
248
248
248
249
249
250
250
251
251
252
252
253
253
254
Fields
6.1
6.2
6.3
6.4
6.5
6.6
6.7
6.8
6.9
6.10
6.11
6.12
6.13
6.14
6.15
6.16
6.17
IsField . . . . . . . . . . . . . . . . . . . . . . .
Field . . . . . . . . . . . . . . . . . . . . . . . .
DefaultField . . . . . . . . . . . . . . . . . . .
Fields over Subfields . . . . . . . . . . . . . . .
Comparisons of Field Elements . . . . . . . . .
Operations for Field Elements . . . . . . . . .
GaloisGroup . . . . . . . . . . . . . . . . . . .
MinPol . . . . . . . . . . . . . . . . . . . . . .
CharPol . . . . . . . . . . . . . . . . . . . . . .
Norm . . . . . . . . . . . . . . . . . . . . . . .
Trace . . . . . . . . . . . . . . . . . . . . . . .
Conjugates . . . . . . . . . . . . . . . . . . . .
Field Homomorphisms . . . . . . . . . . . . . .
IsFieldHomomorphism . . . . . . . . . . . . . .
KernelFieldHomomorphism . . . . . . . . . . .
Mapping Functions for Field Homomorphisms .
Field Records . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
257
257
258
258
259
259
260
260
261
261
262
263
263
264
264
265
265
266
18
7
CONTENTS
Groups
7.1
Group Elements . . . . . . . . . . .
7.2
Comparisons of Group Elements . .
7.3
Operations for Group Elements . . .
7.4
IsGroupElement . . . . . . . . . . .
7.5
Order . . . . . . . . . . . . . . . . .
7.6
More about Groups and Subgroups .
7.7
IsParent . . . . . . . . . . . . . . . .
7.8
Parent . . . . . . . . . . . . . . . . .
7.9
Group . . . . . . . . . . . . . . . . .
7.10
AsGroup . . . . . . . . . . . . . . .
7.11
IsGroup . . . . . . . . . . . . . . . .
7.12
Subgroup . . . . . . . . . . . . . . .
7.13
AsSubgroup . . . . . . . . . . . . . .
7.14
Subgroups . . . . . . . . . . . . . . .
7.15
Agemo . . . . . . . . . . . . . . . . .
7.16
Centralizer . . . . . . . . . . . . . .
7.17
Centre . . . . . . . . . . . . . . . . .
7.18
Closure . . . . . . . . . . . . . . . .
7.19
CommutatorSubgroup . . . . . . . .
7.20
ConjugateSubgroup . . . . . . . . .
7.21
Core . . . . . . . . . . . . . . . . . .
7.22
DerivedSubgroup . . . . . . . . . . .
7.23
FittingSubgroup . . . . . . . . . . .
7.24
FrattiniSubgroup . . . . . . . . . . .
7.25
NormalClosure . . . . . . . . . . . .
7.26
NormalIntersection . . . . . . . . . .
7.27
Normalizer . . . . . . . . . . . . . .
7.28
PCore . . . . . . . . . . . . . . . . .
7.29
PrefrattiniSubgroup . . . . . . . . .
7.30
Radical . . . . . . . . . . . . . . . .
7.31
SylowSubgroup . . . . . . . . . . . .
7.32
TrivialSubgroup . . . . . . . . . . .
7.33
FactorGroup . . . . . . . . . . . . .
7.34
FactorGroupElement . . . . . . . . .
7.35
CommutatorFactorGroup . . . . . .
7.36
Series of Subgroups . . . . . . . . .
7.37
DerivedSeries . . . . . . . . . . . . .
7.38
CompositionSeries . . . . . . . . . .
7.39
ElementaryAbelianSeries . . . . . .
7.40
JenningsSeries . . . . . . . . . . . .
7.41
LowerCentralSeries . . . . . . . . . .
7.42
PCentralSeries . . . . . . . . . . . .
7.43
SubnormalSeries . . . . . . . . . . .
7.44
UpperCentralSeries . . . . . . . . . .
7.45
Properties and Property Tests . . .
7.46
AbelianInvariants . . . . . . . . . .
7.47
DimensionsLoewyFactors . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
267
268
268
268
269
270
270
271
271
272
273
273
273
274
274
274
275
275
276
277
277
277
278
278
279
279
279
279
280
280
281
281
281
281
282
283
283
283
284
284
284
285
285
285
286
286
287
287
CONTENTS
7.48
7.49
7.50
7.51
7.52
7.53
7.54
7.55
7.56
7.57
7.58
7.59
7.60
7.61
7.62
7.63
7.64
7.65
7.66
7.67
7.68
7.69
7.70
7.71
7.72
7.73
7.74
7.75
7.76
7.77
7.78
7.79
7.80
7.81
7.82
7.83
7.84
7.85
7.86
7.87
7.88
7.89
7.90
7.91
7.92
7.93
7.94
7.95
EulerianFunction . . . . . . . . . . . .
Exponent . . . . . . . . . . . . . . . .
Factorization . . . . . . . . . . . . . .
Index . . . . . . . . . . . . . . . . . .
IsAbelian . . . . . . . . . . . . . . . .
IsCentral . . . . . . . . . . . . . . . .
IsConjugate . . . . . . . . . . . . . . .
IsCyclic . . . . . . . . . . . . . . . . .
IsElementaryAbelian . . . . . . . . . .
IsNilpotent . . . . . . . . . . . . . . .
IsNormal . . . . . . . . . . . . . . . .
IsPerfect . . . . . . . . . . . . . . . . .
IsSimple . . . . . . . . . . . . . . . . .
IsSolvable . . . . . . . . . . . . . . . .
IsSubgroup . . . . . . . . . . . . . . .
IsSubnormal . . . . . . . . . . . . . .
IsTrivial for Groups . . . . . . . . . .
GroupId . . . . . . . . . . . . . . . . .
PermutationCharacter . . . . . . . . .
Conjugacy Classes . . . . . . . . . . .
ConjugacyClasses . . . . . . . . . . .
ConjugacyClass . . . . . . . . . . . . .
PositionClass . . . . . . . . . . . . . .
IsConjugacyClass . . . . . . . . . . . .
Set Functions for Conjugacy Classes .
Conjugacy Class Records . . . . . . .
ConjugacyClassesSubgroups . . . . . .
Lattice . . . . . . . . . . . . . . . . .
ConjugacyClassSubgroups . . . . . . .
IsConjugacyClassSubgroups . . . . . .
Set Functions for Subgroup Conjugacy
Subgroup Conjugacy Class Records .
ConjugacyClassesMaximalSubgroups .
MaximalSubgroups . . . . . . . . . . .
NormalSubgroups . . . . . . . . . . .
ConjugateSubgroups . . . . . . . . . .
Cosets of Subgroups . . . . . . . . . .
RightCosets . . . . . . . . . . . . . . .
RightCoset . . . . . . . . . . . . . . .
IsRightCoset . . . . . . . . . . . . . .
Set Functions for Right Cosets . . . .
Right Cosets Records . . . . . . . . .
LeftCosets . . . . . . . . . . . . . . . .
LeftCoset . . . . . . . . . . . . . . . .
IsLeftCoset . . . . . . . . . . . . . . .
DoubleCosets . . . . . . . . . . . . . .
DoubleCoset . . . . . . . . . . . . . .
IsDoubleCoset . . . . . . . . . . . . .
19
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Classes
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
288
288
288
289
289
289
290
290
290
291
291
292
292
292
293
293
294
294
297
297
298
298
299
299
299
300
300
301
307
307
308
308
309
309
310
310
310
311
311
312
312
313
314
314
315
315
316
316
20
CONTENTS
7.96
7.97
7.98
7.99
7.100
7.101
7.102
7.103
7.104
7.105
7.106
7.107
7.108
7.109
7.110
7.111
7.112
7.113
7.114
7.115
7.116
7.117
7.118
8
Set Functions for Double Cosets . . . . . . . .
Double Coset Records . . . . . . . . . . . . . .
Group Constructions . . . . . . . . . . . . . . .
DirectProduct . . . . . . . . . . . . . . . . . .
DirectProduct for Groups . . . . . . . . . . . .
SemidirectProduct . . . . . . . . . . . . . . . .
SemidirectProduct for Groups . . . . . . . . .
SubdirectProduct . . . . . . . . . . . . . . . .
WreathProduct . . . . . . . . . . . . . . . . . .
WreathProduct for Groups . . . . . . . . . . .
Group Homomorphisms . . . . . . . . . . . . .
IsGroupHomomorphism . . . . . . . . . . . . .
KernelGroupHomomorphism . . . . . . . . . .
Mapping Functions for Group Homomorphisms
NaturalHomomorphism . . . . . . . . . . . . .
ConjugationGroupHomomorphism . . . . . . .
InnerAutomorphism . . . . . . . . . . . . . . .
GroupHomomorphismByImages . . . . . . . .
Set Functions for Groups . . . . . . . . . . . .
Elements for Groups . . . . . . . . . . . . . . .
Intersection for Groups . . . . . . . . . . . . .
Operations for Groups . . . . . . . . . . . . . .
Group Records . . . . . . . . . . . . . . . . . .
Operations of Groups
8.1
Other Operations . . . . .
8.2
Cycle . . . . . . . . . . .
8.3
CycleLength . . . . . . .
8.4
Cycles . . . . . . . . . . .
8.5
CycleLengths . . . . . . .
8.6
MovedPoints . . . . . . .
8.7
NrMovedPoints . . . . . .
8.8
Permutation . . . . . . .
8.9
IsFixpoint . . . . . . . . .
8.10
IsFixpointFree . . . . . .
8.11
DegreeOperation . . . . .
8.12
IsTransitive . . . . . . . .
8.13
Transitivity . . . . . . . .
8.14
IsRegular . . . . . . . . .
8.15
IsSemiRegular . . . . . .
8.16
Orbit . . . . . . . . . . .
8.17
OrbitLength . . . . . . .
8.18
Orbits . . . . . . . . . . .
8.19
OrbitLengths . . . . . . .
8.20
Operation . . . . . . . . .
8.21
OperationHomomorphism
8.22
Blocks . . . . . . . . . . .
8.23
IsPrimitive . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
316
317
318
318
319
319
320
321
322
322
323
323
324
324
326
326
327
327
329
330
331
331
332
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
335
336
337
337
338
339
339
339
340
340
341
341
342
343
343
344
345
346
346
347
348
349
350
350
CONTENTS
8.24
8.25
8.26
8.27
9
21
Stabilizer . . . . . . . . .
RepresentativeOperation
RepresentativesOperation
IsEquivalentOperation . .
Vector Spaces
9.1
VectorSpace . . . . . . .
9.2
IsVectorSpace . . . . . .
9.3
Vector Space Records .
9.4
Set Functions for Vector
9.5
IsSubspace . . . . . . .
9.6
Base . . . . . . . . . . .
9.7
AddBase . . . . . . . .
9.8
Dimension . . . . . . . .
9.9
LinearCombination . . .
9.10
Coefficients . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
351
352
352
353
. . . .
. . . .
. . . .
Spaces
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
355
355
356
356
357
357
357
358
359
359
360
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
361
362
362
363
363
364
364
364
364
365
365
365
365
366
366
367
367
369
369
369
370
370
370
371
371
372
372
10 Integers
10.1
Comparisons of Integers . .
10.2
Operations for Integers . .
10.3
QuoInt . . . . . . . . . . .
10.4
RemInt . . . . . . . . . . .
10.5
IsInt . . . . . . . . . . . . .
10.6
Int . . . . . . . . . . . . . .
10.7
AbsInt . . . . . . . . . . . .
10.8
SignInt . . . . . . . . . . .
10.9
IsOddInt . . . . . . . . . .
10.10
IsEvenInt . . . . . . . . . .
10.11
ChineseRem . . . . . . . .
10.12
LogInt . . . . . . . . . . . .
10.13
RootInt . . . . . . . . . . .
10.14
SmallestRootInt . . . . . .
10.15
Set Functions for Integers .
10.16
Ring Functions for Integers
10.17
Primes . . . . . . . . . . . .
10.18
IsPrimeInt . . . . . . . . .
10.19
IsPrimePowerInt . . . . . .
10.20
NextPrimeInt . . . . . . . .
10.21
PrevPrimeInt . . . . . . . .
10.22
FactorsInt . . . . . . . . . .
10.23
DivisorsInt . . . . . . . . .
10.24
Sigma . . . . . . . . . . . .
10.25
Tau . . . . . . . . . . . . .
10.26
MoebiusMu . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11 Number Theory
373
11.1
PrimeResidues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
11.2
Phi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
22
CONTENTS
11.3
11.4
11.5
11.6
11.7
11.8
11.9
11.10
Lambda . . . . . . .
OrderMod . . . . . .
IsPrimitiveRootMod
PrimitiveRootMod .
Jacobi . . . . . . . .
Legendre . . . . . .
RootMod . . . . . .
RootsUnityMod . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
374
375
375
376
376
376
377
377
12 Rationals
12.1
IsRat . . . . . . . . . . . . .
12.2
Numerator . . . . . . . . . .
12.3
Denominator . . . . . . . . .
12.4
Floor . . . . . . . . . . . . .
12.5
Mod1 . . . . . . . . . . . . .
12.6
Comparisons of Rationals . .
12.7
Operations for Rationals . . .
12.8
Set Functions for Rationals .
12.9
Field Functions for Rationals
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
379
379
380
380
381
381
381
382
382
382
13 Cyclotomics
13.1
More about Cyclotomics . . .
13.2
Cyclotomic Integers . . . . .
13.3
IntCyc . . . . . . . . . . . . .
13.4
RoundCyc . . . . . . . . . . .
13.5
IsCyc . . . . . . . . . . . . .
13.6
IsCycInt . . . . . . . . . . . .
13.7
NofCyc . . . . . . . . . . . .
13.8
CoeffsCyc . . . . . . . . . . .
13.9
Comparisons of Cyclotomics
13.10
Operations for Cyclotomics .
13.11
GaloisCyc . . . . . . . . . . .
13.12
Galois . . . . . . . . . . . . .
13.13
ATLAS irrationalities . . . .
13.14
StarCyc . . . . . . . . . . . .
13.15
Quadratic . . . . . . . . . . .
13.16
GaloisMat . . . . . . . . . . .
13.17
RationalizedMat . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
385
385
386
387
387
387
387
388
388
388
389
389
390
390
392
392
393
394
14 Gaussians
14.1
Comparisons of Gaussians . . . . . . . .
14.2
Operations for Gaussians . . . . . . . .
14.3
IsGaussRat . . . . . . . . . . . . . . . .
14.4
IsGaussInt . . . . . . . . . . . . . . . .
14.5
Set Functions for Gaussians . . . . . . .
14.6
Field Functions for Gaussian Rationals
14.7
Ring Functions for Gaussian Integers . .
14.8
TwoSquares . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
395
395
396
397
397
397
398
398
399
CONTENTS
23
15 Subfields of Cyclotomic Fields
15.1
IsNumberField . . . . . . . . . . . . . . . . . .
15.2
IsCyclotomicField . . . . . . . . . . . . . . . .
15.3
Number Field Records . . . . . . . . . . . . . .
15.4
Cyclotomic Field Records . . . . . . . . . . . .
15.5
DefaultField and Field for Cyclotomics . . . .
15.6
DefaultRing and Ring for Cyclotomic Integers
15.7
GeneratorsPrimeResidues . . . . . . . . . . . .
15.8
GaloisGroup for Number Fields . . . . . . . . .
15.9
ZumbroichBase . . . . . . . . . . . . . . . . . .
15.10
Integral Bases for Number Fields . . . . . . . .
15.11
NormalBaseNumberField . . . . . . . . . . . .
15.12
Coefficients for Number Fields . . . . . . . . .
15.13
Domain Functions for Number Fields . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
401
402
402
402
403
404
405
405
406
406
407
408
408
409
16 Algebraic extensions of fields
16.1
AlgebraicExtension . . . . . . . . . . . .
16.2
IsAlgebraicExtension . . . . . . . . . . .
16.3
RootOf . . . . . . . . . . . . . . . . . .
16.4
Algebraic Extension Elements . . . . . .
16.5
Set functions for Algebraic Extensions .
16.6
IsNormalExtension . . . . . . . . . . . .
16.7
MinpolFactors . . . . . . . . . . . . . .
16.8
GaloisGroup for Extension Fields . . . .
16.9
ExtensionAutomorphism . . . . . . . .
16.10
Field functions for Algebraic Extensions
16.11
Algebraic Extension Records . . . . . .
16.12
Extension Element Records . . . . . . .
16.13
IsAlgebraicElement . . . . . . . . . . . .
16.14
Algebraic extensions of the Rationals .
16.15
DefectApproximation . . . . . . . . . .
16.16
GaloisType . . . . . . . . . . . . . . . .
16.17
ProbabilityShapes . . . . . . . . . . . .
16.18
DecomPoly . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
411
411
412
412
412
412
413
413
413
414
414
415
415
415
415
416
416
416
416
17 Unknowns
17.1
Unknown . . . . . . . . . .
17.2
IsUnknown . . . . . . . . .
17.3
Comparisons of Unknowns
17.4
Operations for Unknowns .
18 Finite
18.1
18.2
18.3
18.4
18.5
18.6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
419
420
420
421
421
Fields
Finite Field Elements . . . . . . . . .
Comparisons of Finite Field Elements
Operations for Finite Field Elements .
IsFFE . . . . . . . . . . . . . . . . . .
CharFFE . . . . . . . . . . . . . . . .
DegreeFFE . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
423
423
424
425
426
426
427
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
24
CONTENTS
18.7
18.8
18.9
18.10
18.11
18.12
18.13
OrderFFE . . . . . . . . . . . . .
IntFFE . . . . . . . . . . . . . .
LogFFE . . . . . . . . . . . . . .
GaloisField . . . . . . . . . . . .
FrobeniusAutomorphism . . . . .
Set Functions for Finite Fields .
Field Functions for Finite Fields
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
427
427
428
428
429
429
430
19 Polynomials
19.1
Multivariate Polynomials . . . . . . . . . . .
19.2
Indeterminate . . . . . . . . . . . . . . . . . .
19.3
Polynomial . . . . . . . . . . . . . . . . . . .
19.4
IsPolynomial . . . . . . . . . . . . . . . . . .
19.5
Comparisons of Polynomials . . . . . . . . .
19.6
Operations for Polynomials . . . . . . . . . .
19.7
Degree . . . . . . . . . . . . . . . . . . . . . .
19.8
Valuation . . . . . . . . . . . . . . . . . . . .
19.9
LeadingCoefficient . . . . . . . . . . . . . . .
19.10
Coefficient . . . . . . . . . . . . . . . . . . .
19.11
Value . . . . . . . . . . . . . . . . . . . . . .
19.12
Derivative . . . . . . . . . . . . . . . . . . . .
19.13
Resultant . . . . . . . . . . . . . . . . . . . .
19.14
Discriminant . . . . . . . . . . . . . . . . . .
19.15
InterpolatedPolynomial . . . . . . . . . . . .
19.16
ConwayPolynomial . . . . . . . . . . . . . . .
19.17
CyclotomicPolynomial . . . . . . . . . . . . .
19.18
PolynomialRing . . . . . . . . . . . . . . . .
19.19
IsPolynomialRing . . . . . . . . . . . . . . .
19.20
LaurentPolynomialRing . . . . . . . . . . . .
19.21
IsLaurentPolynomialRing . . . . . . . . . . .
19.22
Ring Functions for Polynomial Rings . . . . .
19.23
Ring Functions for Laurent Polynomial Rings
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
431
433
433
434
434
434
435
437
438
438
438
439
439
439
439
440
440
440
441
441
441
442
442
444
20 Permutations
20.1
Comparisons of Permutations
20.2
Operations for Permutations
20.3
IsPerm . . . . . . . . . . . .
20.4
LargestMovedPointPerm . . .
20.5
SmallestMovedPointPerm . .
20.6
SignPerm . . . . . . . . . . .
20.7
SmallestGeneratorPerm . . .
20.8
ListPerm . . . . . . . . . . .
20.9
PermList . . . . . . . . . . .
20.10
RestrictedPerm . . . . . . . .
20.11
MappingPermListList . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
447
448
448
449
449
450
450
450
450
451
451
451
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
21 Permutation Groups
453
21.1
IsPermGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
CONTENTS
21.2
21.3
21.4
21.5
21.6
21.7
21.8
21.9
21.10
21.11
21.12
21.13
21.14
21.15
21.16
21.17
21.18
21.19
21.20
21.21
21.22
21.23
21.24
21.25
25
PermGroupOps.MovedPoints . . . . . . . .
PermGroupOps.SmallestMovedPoint . . . .
PermGroupOps.LargestMovedPoint . . . .
PermGroupOps.NrMovedPoints . . . . . . .
Stabilizer Chains . . . . . . . . . . . . . . .
StabChain . . . . . . . . . . . . . . . . . .
MakeStabChain . . . . . . . . . . . . . . .
ExtendStabChain . . . . . . . . . . . . . .
ReduceStabChain . . . . . . . . . . . . . .
MakeStabChainStrongGenerators . . . . . .
Base for Permutation Groups . . . . . . . .
PermGroupOps.Indices . . . . . . . . . . .
PermGroupOps.StrongGenerators . . . . .
ListStabChain . . . . . . . . . . . . . . . .
PermGroupOps.ElementProperty . . . . . .
PermGroupOps.SubgroupProperty . . . . .
CentralCompositionSeriesPPermGroup . .
PermGroupOps.PgGroup . . . . . . . . . .
Set Functions for Permutation Groups . . .
Group Functions for Permutation Groups .
Operations of Permutation Groups . . . . .
Homomorphisms for Permutation Groups .
Random Methods for Permutation Groups
Permutation Group Records . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
454
454
454
454
455
456
457
458
458
458
459
459
459
460
460
461
462
462
462
463
467
468
470
472
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
475
476
476
477
477
478
479
479
479
480
480
480
481
23 Finitely Presented Groups
23.1
FreeGroup . . . . . . . . . . . . . . . . . . . .
23.2
Set Functions for Finitely Presented Groups . .
23.3
Group Functions for Finitely Presented Groups
23.4
CosetTableFpGroup . . . . . . . . . . . . . . .
23.5
OperationCosetsFpGroup . . . . . . . . . . . .
23.6
IsIdenticalPresentationFpGroup . . . . . . . .
23.7
LowIndexSubgroupsFpGroup . . . . . . . . . .
23.8
Presentation Records . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
483
484
484
485
488
489
489
490
491
22 Words in Abstract Generators
22.1
AbstractGenerator . . . . .
22.2
AbstractGenerators . . . .
22.3
Comparisons of Words . . .
22.4
Operations for Words . . .
22.5
IsWord . . . . . . . . . . .
22.6
LengthWord . . . . . . . .
22.7
ExponentSumWord . . . .
22.8
Subword . . . . . . . . . . .
22.9
PositionWord . . . . . . . .
22.10
SubstitutedWord . . . . . .
22.11
EliminatedWord . . . . . .
22.12
MappedWord . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
26
CONTENTS
23.9
23.10
23.11
23.12
23.13
23.14
Changing Presentations
Group Presentations . .
Subgroup Presentations
SimplifiedFpGroup . . .
Tietze Transformations
DecodeTree . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
495
495
497
501
502
515
Groups
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
519
519
520
521
521
521
522
522
522
523
523
524
524
524
525
525
Polycyclic Groups
More about Ag Groups . . . . . . . . . .
Construction of Ag Groups . . . . . . . .
Ag Group Operations . . . . . . . . . . .
Ag Group Records . . . . . . . . . . . . .
Set Functions for Ag Groups . . . . . . .
Elements for Ag Groups . . . . . . . . . .
Intersection for Ag Groups . . . . . . . .
Size for Ag Groups . . . . . . . . . . . . .
Group Functions for Ag Groups . . . . .
AsGroup for Ag Groups . . . . . . . . . .
Group for Ag Groups . . . . . . . . . . .
CommutatorSubgroup for Ag Groups . .
Normalizer for Ag Groups . . . . . . . . .
IsCyclic for Ag Groups . . . . . . . . . .
IsNormal for Ag Groups . . . . . . . . . .
IsSubgroup for Ag Groups . . . . . . . . .
Stabilizer for Ag Groups . . . . . . . . . .
CyclicGroup for Ag Groups . . . . . . . .
ElementaryAbelianGroup for Ag Groups .
DirectProduct for Ag Groups . . . . . . .
WreathProduct for Ag Groups . . . . . .
RightCoset for Ag Groups . . . . . . . . .
FpGroup for Ag Groups . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
527
527
528
528
529
529
530
530
530
531
534
535
535
535
535
536
536
536
536
537
537
537
538
539
24 Words in Finite Polycyclic
24.1
More about Ag Words
24.2
Ag Word Comparisons
24.3
CentralWeight . . . .
24.4
CompositionLength .
24.5
Depth . . . . . . . . .
24.6
IsAgWord . . . . . . .
24.7
LeadingExponent . . .
24.8
RelativeOrder . . . . .
24.9
CanonicalAgWord . .
24.10
DifferenceAgWord . .
24.11
ReducedAgWord . . .
24.12
SiftedAgWord . . . .
24.13
SumAgWord . . . . .
24.14
ExponentAgWord . .
24.15
ExponentsAgWord . .
25 Finite
25.1
25.2
25.3
25.4
25.5
25.6
25.7
25.8
25.9
25.10
25.11
25.12
25.13
25.14
25.15
25.16
25.17
25.18
25.19
25.20
25.21
25.22
25.23
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
25.24
25.25
25.26
25.27
25.28
25.29
25.30
25.31
25.32
25.33
25.34
25.35
25.36
25.37
25.38
25.39
25.40
25.41
25.42
25.43
25.44
25.45
25.46
25.47
25.48
25.49
25.50
25.51
25.52
25.53
25.54
25.55
25.56
25.57
25.58
25.59
25.60
25.61
25.62
25.63
25.64
25.65
25.66
25.67
25.68
25.69
25.70
25.71
Ag Group Functions . . . . . . . . . . .
AgGroup . . . . . . . . . . . . . . . . .
IsAgGroup . . . . . . . . . . . . . . . .
AgGroupFpGroup . . . . . . . . . . . .
IsConsistent . . . . . . . . . . . . . . . .
IsElementaryAbelianAgSeries . . . . . .
MatGroupAgGroup . . . . . . . . . . .
PermGroupAgGroup . . . . . . . . . . .
RefinedAgSeries . . . . . . . . . . . . .
ChangeCollector . . . . . . . . . . . . .
The Prime Quotient Algorithm . . . . .
PQuotient . . . . . . . . . . . . . . . . .
Save . . . . . . . . . . . . . . . . . . . .
PQp . . . . . . . . . . . . . . . . . . . .
InitPQp . . . . . . . . . . . . . . . . . .
FirstClassPQp . . . . . . . . . . . . . .
NextClassPQp . . . . . . . . . . . . . .
Weight . . . . . . . . . . . . . . . . . .
Factorization for PQp . . . . . . . . . .
The Solvable Quotient Algorithm . . . .
SolvableQuotient . . . . . . . . . . . . .
InitSQ . . . . . . . . . . . . . . . . . . .
ModulesSQ . . . . . . . . . . . . . . . .
NextModuleSQ . . . . . . . . . . . . . .
Generating Systems of Ag Groups . . .
AgSubgroup . . . . . . . . . . . . . . .
Cgs . . . . . . . . . . . . . . . . . . . .
Igs . . . . . . . . . . . . . . . . . . . . .
IsNormalized . . . . . . . . . . . . . . .
Normalize . . . . . . . . . . . . . . . . .
Normalized . . . . . . . . . . . . . . . .
MergedCgs . . . . . . . . . . . . . . . .
MergedIgs . . . . . . . . . . . . . . . . .
Factor Groups of Ag Groups . . . . . .
FactorGroup for AgGroups . . . . . . .
CollectorlessFactorGroup . . . . . . . .
FactorArg . . . . . . . . . . . . . . . . .
Subgroups and Properties of Ag Groups
CompositionSubgroup . . . . . . . . . .
HallSubgroup . . . . . . . . . . . . . . .
PRump . . . . . . . . . . . . . . . . . .
RefinedSubnormalSeries . . . . . . . . .
SylowComplements . . . . . . . . . . . .
SylowSystem . . . . . . . . . . . . . . .
SystemNormalizer . . . . . . . . . . . .
MinimalGeneratingSet . . . . . . . . . .
IsElementAgSeries . . . . . . . . . . . .
IsPNilpotent . . . . . . . . . . . . . . .
27
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
539
539
539
540
540
541
541
542
542
542
543
543
545
546
546
546
546
547
547
547
547
549
549
550
550
551
551
552
552
552
552
552
553
553
554
554
554
555
555
556
556
556
557
557
558
559
559
559
28
CONTENTS
25.72
25.73
25.74
25.75
25.76
25.77
25.78
25.79
25.80
25.81
25.82
25.83
25.84
25.85
25.86
25.87
25.88
25.89
25.90
25.91
25.92
25.93
25.94
NumberConjugacyClasses . . . . . .
Exponents . . . . . . . . . . . . . . .
FactorsAgGroup . . . . . . . . . . .
MaximalElement . . . . . . . . . . .
Orbitalgorithms of Ag Groups . . .
AffineOperation . . . . . . . . . . .
AgOrbitStabilizer . . . . . . . . . .
LinearOperation . . . . . . . . . . .
Intersections of Ag Groups . . . . .
ExtendedIntersectionSumAgGroup .
IntersectionSumAgGroup . . . . . .
SumAgGroup . . . . . . . . . . . . .
SumFactorizationFunctionAgGroup
One Cohomology Group . . . . . . .
OneCoboundaries . . . . . . . . . .
OneCocycles . . . . . . . . . . . . .
Complements . . . . . . . . . . . . .
Complement . . . . . . . . . . . . .
Complementclasses . . . . . . . . . .
CoprimeComplement . . . . . . . . .
ComplementConjugatingAgWord . .
HallConjugatingWordAgGroup . . .
Example, normal closure . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
559
560
560
561
561
561
562
562
563
563
564
565
565
566
566
567
569
569
569
570
570
571
571
26 Special Ag Groups
26.1
More about Special Ag Groups . . . . . . .
26.2
Construction of Special Ag Groups . . . . .
26.3
Restricted Special Ag Groups . . . . . . . .
26.4
Special Ag Group Records . . . . . . . . . .
26.5
MatGroupSagGroup . . . . . . . . . . . . .
26.6
DualMatGroupSagGroup . . . . . . . . . .
26.7
Ag Group Functions for Special Ag Groups
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
575
575
577
577
578
579
580
580
27 Lists
27.1
27.2
27.3
27.4
27.5
27.6
27.7
27.8
27.9
27.10
27.11
27.12
27.13
27.14
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
583
584
584
585
585
586
587
588
589
589
591
591
592
593
593
IsList . . . . . . . .
List . . . . . . . . .
ApplyFunc . . . . .
List Elements . . . .
Length . . . . . . .
List Assignment . .
Add . . . . . . . . .
Append . . . . . . .
Identical Lists . . .
IsIdentical . . . . . .
Enlarging Lists . . .
Comparisons of Lists
Operations for Lists
In . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
27.15
27.16
27.17
27.18
27.19
27.20
27.21
27.22
27.23
27.24
27.25
27.26
27.27
27.28
27.29
27.30
27.31
27.32
27.33
27.34
27.35
27.36
27.37
27.38
27.39
27.40
27.41
27.42
27.43
27.44
27.45
27.46
27.47
27.48
28 Sets
28.1
28.2
28.3
28.4
28.5
28.6
28.7
28.8
28.9
28.10
29
Position . . . . . .
PositionSorted . .
PositionSet . . . .
Positions . . . . .
PositionProperty .
PositionsProperty
PositionSublist . .
Concatenation . .
Flat . . . . . . . .
Reversed . . . . .
Sublist . . . . . . .
Cartesian . . . . .
Number . . . . . .
Collected . . . . .
CollectBy . . . . .
Filtered . . . . . .
Zip . . . . . . . . .
ForAll . . . . . . .
ForAny . . . . . .
First . . . . . . . .
Sort . . . . . . . .
SortParallel . . . .
SortBy . . . . . .
Sortex . . . . . . .
SortingPerm . . .
PermListList . . .
Permuted . . . . .
Product . . . . . .
Sum . . . . . . . .
ValuePol . . . . .
Maximum . . . . .
Minimum . . . . .
Iterated . . . . . .
RandomList . . . .
IsSet . . . . . . .
Set . . . . . . . .
IsEqualSet . . .
AddSet . . . . .
RemoveSet . . .
UniteSet . . . . .
IntersectSet . . .
SubtractSet . . .
Set Functions for
More about Sets
29 Boolean Lists
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
594
595
595
596
596
596
597
597
597
598
598
598
599
599
600
600
600
600
601
601
601
602
602
603
603
603
604
604
604
605
605
605
606
606
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
Sets
. . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
607
608
608
608
609
609
609
610
610
610
611
613
30
CONTENTS
29.1
29.2
29.3
29.4
29.5
29.6
29.7
29.8
29.9
29.10
29.11
29.12
BlistList . . . . . . . . . .
ListBlist . . . . . . . . . .
IsBlist . . . . . . . . . . .
SizeBlist . . . . . . . . . .
IsSubsetBlist . . . . . . .
UnionBlist . . . . . . . .
IntersectionBlist . . . . .
DifferenceBlist . . . . . .
UniteBlist . . . . . . . . .
IntersectBlist . . . . . . .
SubtractBlist . . . . . . .
More about Boolean Lists
30 Strings and Characters
30.1
String . . . . . . . . . .
30.2
ConcatenationString . .
30.3
SubString . . . . . . . .
30.4
Comparisons of Strings
30.5
IsString . . . . . . . . .
30.6
Join . . . . . . . . . . .
30.7
SPrint . . . . . . . . . .
30.8
PrintToString . . . . . .
30.9
Split . . . . . . . . . . .
30.10
StringDate . . . . . . .
30.11
StringTime . . . . . . .
30.12
StringPP . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
613
614
614
614
615
615
615
616
616
616
616
617
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
619
621
621
622
622
623
623
623
623
624
624
624
624
31 Ranges
625
31.1
IsRange . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626
31.2
More about Ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626
32 Vectors
32.1
Operations for Vectors
32.2
IsVector . . . . . . . .
32.3
NormedVector . . . .
32.4
More about Vectors .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
629
630
631
631
631
33 Row Spaces
33.1
More about Row Spaces . . .
33.2
Row Space Bases . . . . . . .
33.3
Row Space Cosets . . . . . .
33.4
Quotient Spaces . . . . . . .
33.5
Subspaces and Parent Spaces
33.6
RowSpace . . . . . . . . . . .
33.7
Operations for Row Spaces .
33.8
Functions for Row Spaces . .
33.9
IsRowSpace . . . . . . . . . .
33.10
Subspace . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
633
633
634
634
635
635
636
636
637
638
638
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
33.11
33.12
33.13
33.14
33.15
33.16
33.17
33.18
33.19
33.20
33.21
33.22
33.23
33.24
33.25
33.26
33.27
33.28
33.29
33.30
31
AsSubspace . . . . . . . . . . . .
AsSpace . . . . . . . . . . . . . .
NormedVectors . . . . . . . . . .
Coefficients for Row Space Bases
SiftedVector . . . . . . . . . . . .
Basis . . . . . . . . . . . . . . . .
CanonicalBasis . . . . . . . . . .
SemiEchelonBasis . . . . . . . .
IsSemiEchelonBasis . . . . . . .
NumberVector . . . . . . . . . .
ElementRowSpace . . . . . . . .
Operations for Row Space Cosets
Functions for Row Space Cosets
IsSpaceCoset . . . . . . . . . . .
Operations for Quotient Spaces .
Functions for Quotient Spaces .
Row Space Records . . . . . . .
Row Space Basis Records . . . .
Row Space Coset Records . . . .
Quotient Space Records . . . . .
34 Matrices
34.1
Operations for Matrices
34.2
IsMat . . . . . . . . . .
34.3
IdentityMat . . . . . . .
34.4
NullMat . . . . . . . . .
34.5
TransposedMat . . . . .
34.6
KroneckerProduct . . .
34.7
DimensionsMat . . . . .
34.8
IsDiagonalMat . . . . .
34.9
IsLowerTriangularMat .
34.10
IsUpperTriangularMat .
34.11
DiagonalOfMat . . . . .
34.12
DiagonalMat . . . . . .
34.13
PermutationMat . . . .
34.14
TraceMat . . . . . . . .
34.15
DeterminantMat . . . .
34.16
RankMat . . . . . . . .
34.17
OrderMat . . . . . . . .
34.18
TriangulizeMat . . . . .
34.19
BaseMat . . . . . . . .
34.20
NullspaceMat . . . . . .
34.21
SolutionMat . . . . . .
34.22
DiagonalizeMat . . . . .
34.23
ElementaryDivisorsMat
34.24
PrintArray . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
35 Integral matrices and lattices
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
638
639
639
639
639
640
640
641
641
642
642
642
643
643
644
644
644
645
645
646
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
647
647
649
650
650
651
651
651
651
652
652
652
652
653
653
653
654
654
654
655
655
655
655
656
656
657
32
CONTENTS
35.1
35.2
35.3
35.4
35.5
35.6
35.7
35.8
35.9
35.10
35.11
35.12
35.13
35.14
35.15
35.16
35.17
35.18
NullspaceIntMat . . . . . . . . . . . . . .
SolutionIntMat . . . . . . . . . . . . . . .
SolutionNullspaceIntMat . . . . . . . . .
BaseIntMat . . . . . . . . . . . . . . . . .
BaseIntersectionIntMats . . . . . . . . . .
ComplementIntMat . . . . . . . . . . . .
TriangulizedIntegerMat . . . . . . . . . .
TriangulizedIntegerMatTransform . . . .
TriangulizeIntegerMat . . . . . . . . . . .
HermiteNormalFormIntegerMat . . . . . .
HermiteNormalFormIntegerMatTransform
SmithNormalFormIntegerMat . . . . . . .
SmithNormalFormIntegerMatTransforms
DiagonalizeIntMat . . . . . . . . . . . . .
NormalFormIntMat . . . . . . . . . . . .
AbelianInvariantsOfList . . . . . . . . . .
Determinant of an integer matrix . . . . .
Diaconis-Graham normal form . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
657
657
657
658
658
658
659
659
659
659
660
660
660
661
661
662
662
662
36 Matrix Rings
665
36.1
Set Functions for Matrix Rings . . . . . . . . . . . . . . . . . . . . . . . 665
36.2
Ring Functions for Matrix Rings . . . . . . . . . . . . . . . . . . . . . . 666
37 Matrix Groups
667
37.1
Set Functions for Matrix Groups . . . . . . . . . . . . . . . . . . . . . . 667
37.2
Group Functions for Matrix Groups . . . . . . . . . . . . . . . . . . . . 668
37.3
Matrix Group Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669
38 Group Libraries
38.1
The Basic Groups Library . . . . . . . . . . . . . .
38.2
Selection Functions . . . . . . . . . . . . . . . . . .
38.3
Example Functions . . . . . . . . . . . . . . . . . .
38.4
Extraction Functions . . . . . . . . . . . . . . . . .
38.5
The Primitive Groups Library . . . . . . . . . . .
38.6
The Transitive Groups Library . . . . . . . . . . .
38.7
The Solvable Groups Library . . . . . . . . . . . .
38.8
The 2-Groups Library . . . . . . . . . . . . . . . .
38.9
The 3-Groups Library . . . . . . . . . . . . . . . .
38.10
The Irreducible Solvable Linear Groups Library . .
38.11
The Library of Finite Perfect Groups . . . . . . .
38.12
Irreducible Maximal Finite Integral Matrix Groups
38.13
The Crystallographic Groups Library . . . . . . .
38.14
The Small Groups Library . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
671
672
675
676
677
678
680
682
683
685
687
689
696
705
721
39 Algebras
723
39.1
More about Algebras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 724
39.2
Algebras and Unital Algebras . . . . . . . . . . . . . . . . . . . . . . . . 724
39.3
Parent Algebras and Subalgebras . . . . . . . . . . . . . . . . . . . . . . 725
CONTENTS
39.4
39.5
39.6
39.7
39.8
39.9
39.10
39.11
39.12
39.13
39.14
39.15
39.16
39.17
39.18
39.19
39.20
39.21
39.22
39.23
39.24
39.25
39.26
39.27
39.28
39.29
33
Algebra . . . . . . . . . . . . . . . . . . . . . . .
UnitalAlgebra . . . . . . . . . . . . . . . . . . .
IsAlgebra . . . . . . . . . . . . . . . . . . . . . .
IsUnitalAlgebra . . . . . . . . . . . . . . . . . . .
Subalgebra . . . . . . . . . . . . . . . . . . . . .
UnitalSubalgebra . . . . . . . . . . . . . . . . . .
IsSubalgebra . . . . . . . . . . . . . . . . . . . .
AsAlgebra . . . . . . . . . . . . . . . . . . . . . .
AsUnitalAlgebra . . . . . . . . . . . . . . . . . .
AsSubalgebra . . . . . . . . . . . . . . . . . . . .
AsUnitalSubalgebra . . . . . . . . . . . . . . . .
Operations for Algebras . . . . . . . . . . . . . .
Zero and One for Algebras . . . . . . . . . . . .
Set Theoretic Functions for Algebras . . . . . . .
Property Tests for Algebras . . . . . . . . . . . .
Vector Space Functions for Algebras . . . . . . .
Algebra Functions for Algebras . . . . . . . . . .
TrivialSubalgebra . . . . . . . . . . . . . . . . .
Operation for Algebras . . . . . . . . . . . . . .
OperationHomomorphism for Algebras . . . . . .
Algebra Homomorphisms . . . . . . . . . . . . .
Mapping Functions for Algebra Homomorphisms
Algebra Elements . . . . . . . . . . . . . . . . .
IsAlgebraElement . . . . . . . . . . . . . . . . .
Algebra Records . . . . . . . . . . . . . . . . . .
FFList . . . . . . . . . . . . . . . . . . . . . . . .
40 Finitely Presented Algebras
40.1
More about Finitely Presented Algebras .
40.2
FreeAlgebra . . . . . . . . . . . . . . . . .
40.3
FpAlgebra . . . . . . . . . . . . . . . . .
40.4
IsFpAlgebra . . . . . . . . . . . . . . . . .
40.5
Operators for Finitely Presented Algebras
40.6
Functions for Finitely Presented Algebras
40.7
PrintDefinitionFpAlgebra . . . . . . . . .
40.8
MappedExpression . . . . . . . . . . . . .
40.9
Elements of Finitely Presented Algebras .
40.10
ElementAlgebra . . . . . . . . . . . . . .
40.11
NumberAlgebraElement . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
726
726
727
727
727
728
728
729
729
729
730
730
731
731
732
732
733
734
734
735
735
735
736
737
737
738
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
739
739
740
741
741
742
742
743
743
743
745
745
41 Matrix Algebras
41.1
More about Matrix Algebras . . . . . . . . .
41.2
Bases for Matrix Algebras . . . . . . . . . . .
41.3
IsMatAlgebra . . . . . . . . . . . . . . . . . .
41.4
Zero and One for Matrix Algebras . . . . . .
41.5
Functions for Matrix Algebras . . . . . . . .
41.6
Algebra Functions for Matrix Algebras . . . .
41.7
RepresentativeOperation for Matrix Algebras
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
747
747
748
748
748
748
749
749
.
.
.
.
.
.
.
.
.
.
.
34
CONTENTS
41.8
41.9
41.10
41.11
MatAlgebra . .
NullAlgebra . .
Fingerprint . .
NaturalModule
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
749
750
750
751
42 Modules
42.1
More about Modules . . . . . . .
42.2
Row Modules . . . . . . . . . . .
42.3
Free Modules . . . . . . . . . . .
42.4
Module . . . . . . . . . . . . . .
42.5
Submodule . . . . . . . . . . . .
42.6
AsModule . . . . . . . . . . . . .
42.7
AsSubmodule . . . . . . . . . . .
42.8
AsSpace for Modules . . . . . . .
42.9
IsModule . . . . . . . . . . . . .
42.10
IsFreeModule . . . . . . . . . . .
42.11
Operations for Row Modules . .
42.12
Functions for Row Modules . . .
42.13
StandardBasis for Row Modules
42.14
IsEquivalent for Row Modules .
42.15
IsIrreducible for Row Modules .
42.16
FixedSubmodule . . . . . . . . .
42.17
Module Homomorphisms . . . .
42.18
Row Module Records . . . . . .
42.19
Module Homomorphism Records
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
753
753
754
754
755
755
756
756
756
756
757
757
758
758
758
759
759
759
760
761
43 Mappings
43.1
IsGeneralMapping . . . .
43.2
IsMapping . . . . . . . .
43.3
IsInjective . . . . . . . . .
43.4
IsSurjective . . . . . . . .
43.5
IsBijection . . . . . . . .
43.6
Comparisons of Mappings
43.7
Operations for Mappings
43.8
Image . . . . . . . . . . .
43.9
Images . . . . . . . . . . .
43.10
ImagesRepresentative . .
43.11
PreImage . . . . . . . . .
43.12
PreImages . . . . . . . . .
43.13
PreImagesRepresentative
43.14
CompositionMapping . .
43.15
PowerMapping . . . . . .
43.16
InverseMapping . . . . . .
43.17
IdentityMapping . . . . .
43.18
MappingByFunction . . .
43.19
Mapping Records . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
763
764
764
765
765
766
767
768
770
772
773
773
775
776
776
777
778
778
779
779
44 Homomorphisms
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
781
CONTENTS
44.1
44.2
44.3
44.4
44.5
44.6
44.7
IsHomomorphism .
IsMonomorphism .
IsEpimorphism . .
IsIsomorphism . .
IsEndomorphism .
IsAutomorphism .
Kernel . . . . . . .
35
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
781
782
783
783
784
784
785
45 Booleans
787
45.1
Comparisons of Booleans . . . . . . . . . . . . . . . . . . . . . . . . . . 787
45.2
Operations for Booleans . . . . . . . . . . . . . . . . . . . . . . . . . . . 788
45.3
IsBool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 789
46 Records
46.1
Accessing Record Elements
46.2
Record Assignment . . . . .
46.3
Identical Records . . . . . .
46.4
Comparisons of Records . .
46.5
Operations for Records . .
46.6
In for Records . . . . . . .
46.7
Printing of Records . . . .
46.8
IsRec . . . . . . . . . . . .
46.9
IsBound . . . . . . . . . . .
46.10
Unbind . . . . . . . . . . .
46.11
Copy . . . . . . . . . . . .
46.12
ShallowCopy . . . . . . . .
46.13
RecFields . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
791
792
792
793
795
797
798
799
800
800
801
801
802
803
47 Combinatorics
47.1
Factorial . . . . . .
47.2
Binomial . . . . . .
47.3
Bell . . . . . . . . .
47.4
Stirling1 . . . . . . .
47.5
Stirling2 . . . . . . .
47.6
Combinations . . . .
47.7
Arrangements . . . .
47.8
UnorderedTuples . .
47.9
Tuples . . . . . . . .
47.10
PermutationsList . .
47.11
Derangements . . .
47.12
PartitionsSet . . . .
47.13
Partitions . . . . . .
47.14
OrderedPartitions .
47.15
RestrictedPartitions
47.16
SignPartition . . . .
47.17
AssociatedPartition
47.18
BetaSet . . . . . . .
47.19
Dominates . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
805
805
806
806
807
807
808
808
809
810
810
811
811
812
813
813
814
814
814
815
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
36
CONTENTS
47.20
47.21
47.22
47.23
47.24
47.25
PowerPartition
PartitionTuples
Fibonacci . . .
Lucas . . . . .
Bernoulli . . .
Permanent . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
815
815
816
816
817
817
48 Tables of Marks
48.1
More about Tables of Marks .
48.2
Table of Marks Records . . . .
48.3
The Library of Tables of Marks
48.4
TableOfMarks . . . . . . . . .
48.5
Marks . . . . . . . . . . . . . .
48.6
NrSubs . . . . . . . . . . . . .
48.7
WeightsTom . . . . . . . . . .
48.8
MatTom . . . . . . . . . . . . .
48.9
TomMat . . . . . . . . . . . . .
48.10
DecomposedFixedPointVector .
48.11
TestTom . . . . . . . . . . . .
48.12
DisplayTom . . . . . . . . . . .
48.13
NormalizerTom . . . . . . . . .
48.14
IntersectionsTom . . . . . . . .
48.15
IsCyclicTom . . . . . . . . . .
48.16
FusionCharTableTom . . . . .
48.17
PermCharsTom . . . . . . . . .
48.18
MoebiusTom . . . . . . . . . .
48.19
CyclicExtensionsTom . . . . .
48.20
IdempotentsTom . . . . . . . .
48.21
ClassTypesTom . . . . . . . . .
48.22
ClassNamesTom . . . . . . . .
48.23
TomCyclic . . . . . . . . . . .
48.24
TomDihedral . . . . . . . . . .
48.25
TomFrobenius . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
819
819
820
820
821
822
822
822
823
823
823
824
824
825
825
826
826
826
826
827
827
827
827
828
828
829
49 Character Tables
49.1
Some Notes on Character Theory in GAP . . . . . .
49.2
Character Table Records . . . . . . . . . . . . . . .
49.3
Brauer Table Records . . . . . . . . . . . . . . . . .
49.4
IsCharTable . . . . . . . . . . . . . . . . . . . . . . .
49.5
PrintCharTable . . . . . . . . . . . . . . . . . . . . .
49.6
TestCharTable . . . . . . . . . . . . . . . . . . . . .
49.7
Operations Records for Character Tables . . . . . .
49.8
Functions for Character Tables . . . . . . . . . . . .
49.9
Operators for Character Tables . . . . . . . . . . . .
49.10
Conventions for Character Tables . . . . . . . . . . .
49.11
Getting Character Tables . . . . . . . . . . . . . . .
49.12
CharTable . . . . . . . . . . . . . . . . . . . . . . . .
49.13
Advanced Methods for Dixon Schneider Calculations
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
831
832
833
837
839
839
839
840
840
841
841
842
843
846
CONTENTS
49.14
49.15
49.16
49.17
49.18
49.19
49.20
49.21
49.22
49.23
49.24
49.25
49.26
49.27
49.28
49.29
49.30
49.31
49.32
49.33
49.34
49.35
49.36
49.37
49.38
49.39
49.40
49.41
49.42
49.43
49.44
49.45
49.46
49.47
49.48
49.49
49.50
49.51
49.52
49.53
49.54
An Example of Advanced Dixon Schneider Calculations
CharTableFactorGroup . . . . . . . . . . . . . . . . . .
CharTableNormalSubgroup . . . . . . . . . . . . . . . .
CharTableDirectProduct . . . . . . . . . . . . . . . . .
CharTableWreathSymmetric . . . . . . . . . . . . . . .
CharTableRegular . . . . . . . . . . . . . . . . . . . . .
CharTableIsoclinic . . . . . . . . . . . . . . . . . . . . .
CharTableSplitClasses . . . . . . . . . . . . . . . . . . .
CharTableCollapsedClasses . . . . . . . . . . . . . . . .
CharDegAgGroup . . . . . . . . . . . . . . . . . . . . .
CharTableSSGroup . . . . . . . . . . . . . . . . . . . . .
MatRepresentationsPGroup . . . . . . . . . . . . . . . .
CharTablePGroup . . . . . . . . . . . . . . . . . . . . .
InitClassesCharTable . . . . . . . . . . . . . . . . . . .
InverseClassesCharTable . . . . . . . . . . . . . . . . . .
ClassNamesCharTable . . . . . . . . . . . . . . . . . . .
ClassMultCoeffCharTable . . . . . . . . . . . . . . . . .
MatClassMultCoeffsCharTable . . . . . . . . . . . . . .
ClassStructureCharTable . . . . . . . . . . . . . . . . .
RealClassesCharTable . . . . . . . . . . . . . . . . . . .
ClassOrbitCharTable . . . . . . . . . . . . . . . . . . . .
ClassRootsCharTable . . . . . . . . . . . . . . . . . . .
NrPolyhedralSubgroups . . . . . . . . . . . . . . . . . .
DisplayCharTable . . . . . . . . . . . . . . . . . . . . .
SortCharactersCharTable . . . . . . . . . . . . . . . . .
SortClassesCharTable . . . . . . . . . . . . . . . . . . .
SortCharTable . . . . . . . . . . . . . . . . . . . . . . .
MatAutomorphisms . . . . . . . . . . . . . . . . . . . .
TableAutomorphisms . . . . . . . . . . . . . . . . . . .
TransformingPermutations . . . . . . . . . . . . . . . .
TransformingPermutationsCharTables . . . . . . . . . .
GetFusionMap . . . . . . . . . . . . . . . . . . . . . . .
StoreFusion . . . . . . . . . . . . . . . . . . . . . . . . .
FusionConjugacyClasses . . . . . . . . . . . . . . . . . .
MAKElb11 . . . . . . . . . . . . . . . . . . . . . . . . .
ScanMOC . . . . . . . . . . . . . . . . . . . . . . . . . .
MOCChars . . . . . . . . . . . . . . . . . . . . . . . . .
GAPChars . . . . . . . . . . . . . . . . . . . . . . . . .
MOCTable . . . . . . . . . . . . . . . . . . . . . . . . .
PrintToMOC . . . . . . . . . . . . . . . . . . . . . . . .
PrintToCAS . . . . . . . . . . . . . . . . . . . . . . . .
37
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
848
849
850
851
852
853
853
854
856
856
857
857
858
859
859
859
860
860
861
861
861
861
862
862
864
865
866
867
868
868
869
869
870
871
871
871
872
872
872
873
874
50 Generic Character Tables
875
50.1
More about Generic Character Tables . . . . . . . . . . . . . . . . . . . 875
50.2
Examples of Generic Character Tables . . . . . . . . . . . . . . . . . . . 876
50.3
CharTableSpecialized . . . . . . . . . . . . . . . . . . . . . . . . . . . . 878
51 Characters
879
38
CONTENTS
51.1
51.2
51.3
51.4
51.5
51.6
51.7
51.8
51.9
51.10
51.11
51.12
51.13
51.14
51.15
51.16
51.17
51.18
51.19
51.20
51.21
51.22
51.23
51.24
51.25
51.26
51.27
51.28
51.29
51.30
51.31
51.32
51.33
51.34
51.35
51.36
51.37
51.38
51.39
51.40
51.41
51.42
51.43
51.44
51.45
ScalarProduct . . . . . . . . . . . .
MatScalarProducts . . . . . . . . . .
Decomposition . . . . . . . . . . . .
Subroutines of Decomposition . . . .
KernelChar . . . . . . . . . . . . . .
PrimeBlocks . . . . . . . . . . . . .
Indicator . . . . . . . . . . . . . . .
Eigenvalues . . . . . . . . . . . . . .
MolienSeries . . . . . . . . . . . . .
Reduced . . . . . . . . . . . . . . . .
ReducedOrdinary . . . . . . . . . . .
Tensored . . . . . . . . . . . . . . .
Symmetrisations . . . . . . . . . . .
SymmetricParts . . . . . . . . . . .
AntiSymmetricParts . . . . . . . . .
MinusCharacter . . . . . . . . . . .
OrthogonalComponents . . . . . . .
SymplecticComponents . . . . . . .
IrreducibleDifferences . . . . . . . .
Restricted . . . . . . . . . . . . . . .
Inflated . . . . . . . . . . . . . . . .
Induced . . . . . . . . . . . . . . . .
InducedCyclic . . . . . . . . . . . .
CollapsedMat . . . . . . . . . . . . .
Power . . . . . . . . . . . . . . . . .
Permutation Character Candidates .
IsPermChar . . . . . . . . . . . . . .
PermCharInfo . . . . . . . . . . . .
Inequalities . . . . . . . . . . . . . .
PermBounds . . . . . . . . . . . . .
PermChars . . . . . . . . . . . . . .
Faithful Permutation Characters . .
LLLReducedBasis . . . . . . . . . .
LLLReducedGramMat . . . . . . . .
LLL . . . . . . . . . . . . . . . . . .
OrthogonalEmbeddings . . . . . . .
ShortestVectors . . . . . . . . . . . .
Extract . . . . . . . . . . . . . . . .
Decreased . . . . . . . . . . . . . . .
DnLattice . . . . . . . . . . . . . . .
ContainedDecomposables . . . . . .
ContainedCharacters . . . . . . . . .
ContainedSpecialVectors . . . . . . .
ContainedPossibleCharacters . . . .
ContainedPossibleVirtualCharacters
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
52 Maps and Parametrized Maps
52.1
More about Maps and Parametrized Maps
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
879
880
880
881
882
882
883
883
884
884
885
885
886
886
887
887
887
888
888
889
889
890
890
891
891
892
892
892
893
894
894
895
896
897
898
898
900
900
901
902
903
904
904
905
905
. . . . . . . . . . . . . . . .
907
907
CONTENTS
52.2
52.3
52.4
52.5
52.6
52.7
52.8
52.9
52.10
52.11
52.12
52.13
52.14
52.15
52.16
52.17
52.18
52.19
52.20
52.21
52.22
52.23
52.24
52.25
52.26
52.27
52.28
52.29
52.30
52.31
39
CompositionMaps . . . . . . . . . . .
InverseMap . . . . . . . . . . . . . . .
ProjectionMap . . . . . . . . . . . . .
Parametrized . . . . . . . . . . . . . .
ContainedMaps . . . . . . . . . . . . .
UpdateMap . . . . . . . . . . . . . . .
CommutativeDiagram . . . . . . . . .
TransferDiagram . . . . . . . . . . . .
Indeterminateness . . . . . . . . . . .
PrintAmbiguity . . . . . . . . . . . . .
Powermap . . . . . . . . . . . . . . . .
SubgroupFusions . . . . . . . . . . . .
InitPowermap . . . . . . . . . . . . . .
Congruences . . . . . . . . . . . . . .
ConsiderKernels . . . . . . . . . . . .
ConsiderSmallerPowermaps . . . . . .
InitFusion . . . . . . . . . . . . . . . .
CheckPermChar . . . . . . . . . . . .
CheckFixedPoints . . . . . . . . . . .
TestConsistencyMaps . . . . . . . . .
ConsiderTableAutomorphisms . . . .
PowermapsAllowedBySymmetrisations
FusionsAllowedByRestrictions . . . . .
OrbitFusions . . . . . . . . . . . . . .
OrbitPowermaps . . . . . . . . . . . .
RepresentativesFusions . . . . . . . .
RepresentativesPowermaps . . . . . .
Indirected . . . . . . . . . . . . . . . .
Powmap . . . . . . . . . . . . . . . . .
ElementOrdersPowermap . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
908
908
909
909
909
910
910
911
912
912
913
913
914
915
916
916
917
917
918
918
919
919
920
921
922
922
923
923
924
924
53 Character Table Libraries
53.1
Contents of the Table Libraries . . . . . . . . . .
53.2
Selecting Library Tables . . . . . . . . . . . . . .
53.3
ATLAS Tables . . . . . . . . . . . . . . . . . . .
53.4
Examples of the ATLAS format for GAP tables
53.5
CAS Tables . . . . . . . . . . . . . . . . . . . . .
53.6
Organization of the Table Libraries . . . . . . . .
53.7
How to Extend a Table Library . . . . . . . . . .
53.8
FirstNameCharTable . . . . . . . . . . . . . . . .
53.9
FileNameCharTable . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
927
927
929
930
933
937
937
939
940
940
54 Class
54.1
54.2
54.3
54.4
54.5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
943
943
945
946
947
948
Functions
Why Group Characters . . .
More about Class Functions .
Operators for Class Functions
Functions for Class Functions
ClassFunction . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
40
CONTENTS
54.6
54.7
54.8
54.9
54.10
54.11
54.12
54.13
54.14
54.15
54.16
54.17
54.18
VirtualCharacter . . . . . . . . . . .
Character . . . . . . . . . . . . . . .
IsClassFunction . . . . . . . . . . . .
IsVirtualCharacter . . . . . . . . . .
IsCharacter . . . . . . . . . . . . . .
Irr . . . . . . . . . . . . . . . . . . .
InertiaSubgroup . . . . . . . . . . .
OrbitsCharacters . . . . . . . . . . .
Storing Subgroup Information . . .
NormalSubgroupClasses . . . . . . .
ClassesNormalSubgroup . . . . . . .
FactorGroupNormalSubgroupClasses
Class Function Records . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
949
949
950
950
950
951
951
951
952
953
954
954
954
55 Monomiality Questions
55.1
More about Monomiality Questions
55.2
Alpha . . . . . . . . . . . . . . . . .
55.3
Delta . . . . . . . . . . . . . . . . .
55.4
BergerCondition . . . . . . . . . . .
55.5
TestHomogeneous . . . . . . . . . .
55.6
TestQuasiPrimitive . . . . . . . . . .
55.7
IsPrimitive for Characters . . . . . .
55.8
TestInducedFromNormalSubgroup .
55.9
TestSubnormallyMonomial . . . . .
55.10
TestMonomialQuick . . . . . . . . .
55.11
TestMonomial . . . . . . . . . . . .
55.12
TestRelativelySM . . . . . . . . . . .
55.13
IsMinimalNonmonomial . . . . . . .
55.14
MinimalNonmonomialGroup . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
955
955
956
957
957
957
958
959
959
960
961
961
962
963
963
56 Getting and Installing GAP
56.1
Getting GAP . . . . . . . . . . . .
56.2
GAP for UNIX . . . . . . . . . . .
56.3
Installation of GAP for UNIX . . .
56.4
Features of GAP for UNIX . . . .
56.5
GAP for Windows . . . . . . . . .
56.6
Copyright of GAP for Windows . .
56.7
Installation of GAP for Windows .
56.8
Features of GAP for Windows . .
56.9
GAP for Mac/OSX . . . . . . . .
56.10
Copyright of GAP for Mac/OSX .
56.11
Installation of GAP for Mac/OSX
56.12
Features of GAP for Mac/OSX . .
56.13
Porting GAP . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
965
965
966
966
967
970
970
971
974
977
977
977
977
977
.
.
.
.
.
.
.
.
.
.
.
.
.
57 Share Libraries
981
57.1
RequirePackage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 982
57.2
ANU pq Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983
CONTENTS
57.3
57.4
57.5
57.6
57.7
57.8
57.9
57.10
57.11
57.12
57.13
57.14
57.15
57.16
41
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
984
990
992
994
995
998
998
1000
1001
1003
1003
1005
1006
1008
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1009
1009
1010
1010
1013
1014
1014
1016
1016
1017
59 Automorphism Groups of Special Ag Groups
59.1
AutGroupSagGroup . . . . . . . . . . . . . . .
59.2
Automorphism Group Elements . . . . . . . .
59.3
Operations for Automorphism Group Elements
59.4
AutGroupStructure . . . . . . . . . . . . . . .
59.5
AutGroupFactors . . . . . . . . . . . . . . . . .
59.6
AutGroupSeries . . . . . . . . . . . . . . . . .
59.7
AutGroupConverted . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1019
1020
1021
1021
1023
1025
1025
1026
60 Cohomology
60.1
CHR . . . . . . . . . . . . . .
60.2
SchurMultiplier . . . . . . . .
60.3
CoveringGroup . . . . . . . .
60.4
FirstCohomologyDimension .
60.5
SecondCohomologyDimension
60.6
SplitExtension . . . . . . . .
60.7
NonsplitExtension . . . . . .
60.8
CalcPres . . . . . . . . . . .
60.9
PermRep . . . . . . . . . . .
60.10
Further Information . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1029
1030
1030
1030
1030
1030
1031
1031
1031
1032
1032
58 ANU
58.1
58.2
58.3
58.4
58.5
58.6
58.7
58.8
58.9
Installing the ANU pq Package . . . . . . .
ANU Sq Package . . . . . . . . . . . . . . .
Installing the ANU Sq Package . . . . . . .
GRAPE Package . . . . . . . . . . . . . . .
Installing the GRAPE Package . . . . . . .
MeatAxe Package . . . . . . . . . . . . . .
Installing the MeatAxe Package . . . . . . .
NQ Package . . . . . . . . . . . . . . . . . .
Installing the NQ Package . . . . . . . . . .
SISYPHOS Package . . . . . . . . . . . . .
Installing the SISYPHOS Package . . . . .
Vector Enumeration Package . . . . . . . .
Installing the Vector Enumeration Package
The XGap Package . . . . . . . . . . . . . .
Pq
Pq . . . . . . . . . . . . . . .
PqHomomorphism . . . . . .
PqDescendants . . . . . . . .
PqList . . . . . . . . . . . . .
SavePqList . . . . . . . . . .
StandardPresentation . . . .
IsomorphismPcpStandardPcp
AutomorphismsPGroup . . .
IsIsomorphicPGroup . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
61 CrystGap–The Crystallographic Groups Package
1035
42
CONTENTS
61.1
61.2
61.3
61.4
61.5
61.6
61.7
61.8
61.9
61.10
61.11
61.12
61.13
61.14
61.15
61.16
61.17
61.18
61.19
61.20
61.21
61.22
61.23
61.24
61.25
61.26
61.27
61.28
61.29
61.30
61.31
61.32
61.33
61.34
61.35
61.36
61.37
61.38
61.39
61.40
Crystallographic Groups . . . . . . . .
Space Groups . . . . . . . . . . . . . .
More about Crystallographic Groups .
CrystGroup . . . . . . . . . . . . . . .
IsCrystGroup . . . . . . . . . . . . . .
PointGroup . . . . . . . . . . . . . . .
TranslationsCrystGroup . . . . . . . .
AddTranslationsCrystGroup . . . . .
CheckTranslations . . . . . . . . . . .
ConjugatedCrystGroup . . . . . . . .
FpGroup for point groups . . . . . . .
FpGroup for CrystGroups . . . . . . .
MaximalSubgroupsRepresentatives . .
IsSpaceGroup . . . . . . . . . . . . . .
IsSymmorphicSpaceGroup . . . . . . .
SpaceGroupsPointGroup . . . . . . . .
Wyckoff Positions . . . . . . . . . . .
WyckoffPositions . . . . . . . . . . . .
WyckoffPositionsByStabilizer . . . . .
WyckoffPositionsQClass . . . . . . . .
WyckoffOrbit . . . . . . . . . . . . . .
WyckoffLattice . . . . . . . . . . . . .
NormalizerGL . . . . . . . . . . . . .
CentralizerGL . . . . . . . . . . . . .
PointGroupsBravaisClass . . . . . . .
TranslationNormalizer . . . . . . . . .
AffineNormalizer . . . . . . . . . . . .
AffineInequivalentSubgroups . . . . .
Other functions for CrystGroups . . .
Color Groups . . . . . . . . . . . . . .
ColorGroup . . . . . . . . . . . . . . .
IsColorGroup . . . . . . . . . . . . . .
ColorSubgroup . . . . . . . . . . . . .
ColorCosets . . . . . . . . . . . . . . .
ColorOfElement . . . . . . . . . . . .
ColorPermGroup . . . . . . . . . . . .
ColorHomomorphism . . . . . . . . .
Subgroup for color groups . . . . . . .
PointGroup for color CrystGroups . .
Inequivalent colorings of space groups
62 The Double Coset Enumerator
62.1
Double Coset Enumeration . . . . .
62.2
Authorship and Contact Information
62.3
Installing the DCE Package . . . . .
62.4
Mathematical Introduction . . . . .
62.5
Gain Group Representation . . . . .
62.6
DCE Words . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1036
1036
1037
1038
1038
1038
1038
1038
1039
1039
1039
1039
1040
1040
1040
1040
1040
1041
1041
1041
1042
1042
1043
1043
1043
1043
1043
1044
1044
1045
1045
1045
1046
1046
1046
1046
1046
1046
1046
1047
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1049
1049
1050
1050
1052
1053
1054
CONTENTS
62.7
62.8
62.9
62.10
62.11
62.12
62.13
62.14
62.15
62.16
62.17
62.18
62.19
62.20
62.21
62.22
62.23
62.24
62.25
62.26
62.27
43
DCE Presentations . . . . . . . . . . . . . . . . . . . . . .
Examples of Double Coset Enumeration . . . . . . . . . .
The DCE Universe . . . . . . . . . . . . . . . . . . . . . .
Informational Messages from DCE . . . . . . . . . . . . .
DCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
DCESetup . . . . . . . . . . . . . . . . . . . . . . . . . .
DCEPerm . . . . . . . . . . . . . . . . . . . . . . . . . . .
DCEPerms . . . . . . . . . . . . . . . . . . . . . . . . . .
DCEWrite . . . . . . . . . . . . . . . . . . . . . . . . . .
DCERead . . . . . . . . . . . . . . . . . . . . . . . . . . .
Example of DCE Functions . . . . . . . . . . . . . . . . .
Strategies for Double Coset Enumeration . . . . . . . . .
Example of Double Coset Enumeration Strategies . . . .
Functions for Analyzing Double Coset Tables . . . . . . .
DCEColAdj . . . . . . . . . . . . . . . . . . . . . . . . . .
DCEHOrbits . . . . . . . . . . . . . . . . . . . . . . . . .
DCEColAdjSingle . . . . . . . . . . . . . . . . . . . . . .
Example of DCEColAdj . . . . . . . . . . . . . . . . . . .
Double Coset Enumeration and Symmetric Presentations
SetupSymmetricPresentation . . . . . . . . . . . . . . . .
Examples of DCE and Symmetric Presentations . . . . .
63 GLISSANDO
63.1
Installing the Glissando Package . .
63.2
Transformations . . . . . . . . . . .
63.3
Transformation . . . . . . . . . . . .
63.4
AsTransformation . . . . . . . . . .
63.5
IsTransformation . . . . . . . . . . .
63.6
IsSetTransformation . . . . . . . . .
63.7
IsGroupTransformation . . . . . . .
63.8
IdentityTransformation . . . . . . .
63.9
Kernel for transformations . . . . .
63.10
Rank for transformations . . . . . .
63.11
Operations for transformations . . .
63.12
DisplayTransformation . . . . . . . .
63.13
Transformation records . . . . . . .
63.14
Transformation Semigroups . . . . .
63.15
TransformationSemigroup . . . . . .
63.16
IsSemigroup . . . . . . . . . . . . . .
63.17
IsTransformationSemigroup . . . . .
63.18
Elements for semigroups . . . . . . .
63.19
Size for semigroups . . . . . . . . . .
63.20
DisplayCayleyTable for semigroups .
63.21
IdempotentElements for semigroups
63.22
IsCommutative for semigroups . . .
63.23
Identity for semigroups . . . . . . .
63.24
SmallestIdeal . . . . . . . . . . . . .
63.25
IsSimple for semigroups . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1054
1055
1057
1058
1058
1059
1059
1059
1059
1059
1059
1061
1062
1066
1066
1067
1067
1067
1068
1068
1069
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1073
1073
1073
1074
1074
1074
1075
1075
1075
1076
1076
1076
1077
1077
1078
1078
1079
1079
1080
1080
1080
1081
1081
1081
1082
1082
44
CONTENTS
63.26
63.27
63.28
63.29
63.30
63.31
63.32
63.33
63.34
63.35
63.36
63.37
63.38
63.39
63.40
63.41
63.42
63.43
63.44
63.45
63.46
63.47
63.48
63.49
63.50
63.51
63.52
63.53
63.54
63.55
63.56
63.57
63.58
63.59
63.60
63.61
63.62
63.63
63.64
63.65
63.66
63.67
63.68
63.69
63.70
63.71
63.72
63.73
Green . . . . . . . . . . . . . . . .
Rank for semigroups . . . . . . . .
LibrarySemigroup . . . . . . . . .
Transformation semigroup records
Near-rings . . . . . . . . . . . . . .
IsNrMultiplication . . . . . . . . .
Nearring . . . . . . . . . . . . . . .
IsNearring . . . . . . . . . . . . . .
IsTransformationNearring . . . . .
LibraryNearring . . . . . . . . . .
DisplayCayleyTable for near-rings
Elements for near-rings . . . . . .
Size for near-rings . . . . . . . . .
Endomorphisms for near-rings . .
Automorphisms for near-rings . . .
FindGroup . . . . . . . . . . . . .
NearringIdeals . . . . . . . . . . .
InvariantSubnearrings . . . . . . .
Subnearrings . . . . . . . . . . . .
Identity for near-rings . . . . . . .
Distributors . . . . . . . . . . . . .
DistributiveElements . . . . . . . .
IsDistributiveNearring . . . . . . .
ZeroSymmetricElements . . . . . .
IsAbstractAffineNearring . . . . .
IdempotentElements for near-rings
IsBooleanNearring . . . . . . . . .
NilpotentElements . . . . . . . . .
IsNilNearring . . . . . . . . . . . .
IsNilpotentNearring . . . . . . . .
IsNilpotentFreeNearring . . . . . .
IsCommutative for near-rings . . .
IsDgNearring . . . . . . . . . . . .
IsIntegralNearring . . . . . . . . .
IsPrimeNearring . . . . . . . . . .
QuasiregularElements . . . . . . .
IsQuasiregularNearring . . . . . .
RegularElements . . . . . . . . . .
IsRegularNearring . . . . . . . . .
IsPlanarNearring . . . . . . . . . .
IsNearfield . . . . . . . . . . . . .
LibraryNearringInfo . . . . . . . .
Nearring records . . . . . . . . . .
Supportive Functions for Groups .
DisplayCayleyTable for groups . .
Endomorphisms for groups . . . .
Automorphisms for groups . . . .
InnerAutomorphisms . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1083
1084
1084
1085
1086
1086
1087
1089
1089
1089
1090
1090
1091
1091
1091
1092
1092
1092
1093
1093
1094
1094
1094
1094
1095
1095
1095
1095
1095
1096
1096
1096
1096
1096
1097
1097
1097
1097
1098
1098
1098
1098
1099
1100
1100
1101
1101
1102
CONTENTS
63.74
63.75
63.76
63.77
63.78
64 Grape
64.1
64.2
64.3
64.4
64.5
64.6
64.7
64.8
64.9
64.10
64.11
64.12
64.13
64.14
64.15
64.16
64.17
64.18
64.19
64.20
64.21
64.22
64.23
64.24
64.25
64.26
64.27
64.28
64.29
64.30
64.31
64.32
64.33
64.34
64.35
64.36
64.37
64.38
64.39
64.40
64.41
SmallestGeneratingSystem . . . . . . . . . . . . . .
IsIsomorphicGroup . . . . . . . . . . . . . . . . . . .
Predefined groups . . . . . . . . . . . . . . . . . . .
How to find near-rings with certain properties . . . .
Defining near-rings with known multiplication table
45
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1102
1102
1103
1103
1106
Functions to construct and modify graphs . . . . . . .
Graph . . . . . . . . . . . . . . . . . . . . . . . . . . .
EdgeOrbitsGraph . . . . . . . . . . . . . . . . . . . .
NullGraph . . . . . . . . . . . . . . . . . . . . . . . .
CompleteGraph . . . . . . . . . . . . . . . . . . . . .
JohnsonGraph . . . . . . . . . . . . . . . . . . . . . .
AddEdgeOrbit . . . . . . . . . . . . . . . . . . . . . .
RemoveEdgeOrbit . . . . . . . . . . . . . . . . . . . .
AssignVertexNames . . . . . . . . . . . . . . . . . . .
Functions to inspect graphs, vertices and edges . . . .
IsGraph . . . . . . . . . . . . . . . . . . . . . . . . . .
OrderGraph . . . . . . . . . . . . . . . . . . . . . . . .
IsVertex . . . . . . . . . . . . . . . . . . . . . . . . . .
VertexName . . . . . . . . . . . . . . . . . . . . . . .
Vertices . . . . . . . . . . . . . . . . . . . . . . . . . .
VertexDegree . . . . . . . . . . . . . . . . . . . . . . .
VertexDegrees . . . . . . . . . . . . . . . . . . . . . .
IsLoopy . . . . . . . . . . . . . . . . . . . . . . . . . .
IsSimpleGraph . . . . . . . . . . . . . . . . . . . . . .
Adjacency . . . . . . . . . . . . . . . . . . . . . . . . .
IsEdge . . . . . . . . . . . . . . . . . . . . . . . . . . .
DirectedEdges . . . . . . . . . . . . . . . . . . . . . .
UndirectedEdges . . . . . . . . . . . . . . . . . . . . .
Distance . . . . . . . . . . . . . . . . . . . . . . . . . .
Diameter . . . . . . . . . . . . . . . . . . . . . . . . .
Girth . . . . . . . . . . . . . . . . . . . . . . . . . . .
IsConnectedGraph . . . . . . . . . . . . . . . . . . . .
IsBipartite . . . . . . . . . . . . . . . . . . . . . . . .
IsNullGraph . . . . . . . . . . . . . . . . . . . . . . .
IsCompleteGraph . . . . . . . . . . . . . . . . . . . . .
Functions to determine regularity properties of graphs
IsRegularGraph . . . . . . . . . . . . . . . . . . . . .
LocalParameters . . . . . . . . . . . . . . . . . . . . .
GlobalParameters . . . . . . . . . . . . . . . . . . . .
IsDistanceRegular . . . . . . . . . . . . . . . . . . . .
CollapsedAdjacencyMat . . . . . . . . . . . . . . . . .
OrbitalGraphIntersectionMatrices . . . . . . . . . . .
Some special vertex subsets of a graph . . . . . . . . .
ConnectedComponent . . . . . . . . . . . . . . . . . .
ConnectedComponents . . . . . . . . . . . . . . . . .
Bicomponents . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1109
1110
1110
1111
1112
1112
1113
1113
1114
1114
1115
1115
1115
1115
1116
1116
1116
1116
1116
1117
1117
1117
1117
1118
1118
1118
1119
1119
1119
1120
1120
1120
1121
1121
1121
1121
1122
1122
1122
1122
1123
1123
46
CONTENTS
64.42
64.43
64.44
64.45
64.46
64.47
64.48
64.49
64.50
64.51
64.52
64.53
64.54
64.55
64.56
64.57
64.58
64.59
64.60
64.61
64.62
64.63
64.64
64.65
64.66
DistanceSet . . . . . . . . . . . . . . . . . .
Layers . . . . . . . . . . . . . . . . . . . . .
IndependentSet . . . . . . . . . . . . . . . .
Functions to construct new graphs from old
InducedSubgraph . . . . . . . . . . . . . . .
DistanceSetInduced . . . . . . . . . . . . .
DistanceGraph . . . . . . . . . . . . . . . .
ComplementGraph . . . . . . . . . . . . . .
PointGraph . . . . . . . . . . . . . . . . . .
EdgeGraph . . . . . . . . . . . . . . . . . .
UnderlyingGraph . . . . . . . . . . . . . . .
QuotientGraph . . . . . . . . . . . . . . . .
BipartiteDouble . . . . . . . . . . . . . . .
GeodesicsGraph . . . . . . . . . . . . . . .
CollapsedIndependentOrbitsGraph . . . . .
CollapsedCompleteOrbitsGraph . . . . . .
NewGroupGraph . . . . . . . . . . . . . . .
Vertex-Colouring and Complete Subgraphs
VertexColouring . . . . . . . . . . . . . . .
CompleteSubgraphs . . . . . . . . . . . . .
CompleteSubgraphsOfGivenSize . . . . . .
Functions depending on nauty . . . . . . .
AutGroupGraph . . . . . . . . . . . . . . .
IsIsomorphicGraph . . . . . . . . . . . . . .
An example . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1123
1123
1124
1124
1124
1124
1125
1125
1126
1126
1127
1127
1128
1128
1129
1129
1130
1130
1131
1131
1131
1132
1132
1132
1133
65 GRIM (Groups of Rational and Integer Matrices)
65.1
Functions to test finiteness and integrality . . . . .
65.2
IsFinite for rational matrix groups . . . . . . . . .
65.3
InvariantLattice for rational matrix groups . . . .
65.4
IsFiniteDeterministic for integer matrix groups . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1135
1135
1135
1136
1136
66 GUAVA
66.1
Loading GUAVA . . . . . .
66.2
Codewords . . . . . . . . .
66.3
Codeword . . . . . . . . . .
66.4
IsCodeword . . . . . . . . .
66.5
Comparisons of Codewords
66.6
Operations for Codewords .
66.7
VectorCodeword . . . . . .
66.8
PolyCodeword . . . . . . .
66.9
TreatAsVector . . . . . . .
66.10
TreatAsPoly . . . . . . . .
66.11
NullWord . . . . . . . . . .
66.12
DistanceCodeword . . . . .
66.13
Support . . . . . . . . . . .
66.14
WeightCodeword . . . . . .
66.15
Codes . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1137
1138
1138
1139
1140
1140
1141
1141
1142
1142
1142
1143
1143
1143
1144
1144
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
66.16
66.17
66.18
66.19
66.20
66.21
66.22
66.23
66.24
66.25
66.26
66.27
66.28
66.29
66.30
66.31
66.32
66.33
66.34
66.35
66.36
66.37
66.38
66.39
66.40
66.41
66.42
66.43
66.44
66.45
66.46
66.47
66.48
66.49
66.50
66.51
66.52
66.53
66.54
66.55
66.56
66.57
66.58
66.59
66.60
66.61
66.62
66.63
IsCode . . . . . . . . . . . . . .
IsLinearCode . . . . . . . . . .
IsCyclicCode . . . . . . . . . .
Comparisons of Codes . . . . .
Operations for Codes . . . . .
Basic Functions for Codes . . .
Domain Functions for Codes .
Printing and Saving Codes . .
GeneratorMat . . . . . . . . .
CheckMat . . . . . . . . . . . .
GeneratorPol . . . . . . . . . .
CheckPol . . . . . . . . . . . .
RootsOfCode . . . . . . . . . .
WordLength . . . . . . . . . .
Redundancy . . . . . . . . . .
MinimumDistance . . . . . . .
WeightDistribution . . . . . . .
InnerDistribution . . . . . . . .
OuterDistribution . . . . . . .
DistancesDistribution . . . . .
IsPerfectCode . . . . . . . . . .
IsMDSCode . . . . . . . . . . .
IsSelfDualCode . . . . . . . . .
IsSelfOrthogonalCode . . . . .
IsEquivalent . . . . . . . . . .
CodeIsomorphism . . . . . . .
AutomorphismGroup . . . . .
Decode . . . . . . . . . . . . .
Syndrome . . . . . . . . . . . .
SyndromeTable . . . . . . . . .
StandardArray . . . . . . . . .
Display . . . . . . . . . . . . .
CodewordNr . . . . . . . . . .
Generating Unrestricted Codes
ElementsCode . . . . . . . . .
HadamardCode . . . . . . . . .
ConferenceCode . . . . . . . .
MOLSCode . . . . . . . . . . .
RandomCode . . . . . . . . . .
NordstromRobinsonCode . . .
GreedyCode . . . . . . . . . .
LexiCode . . . . . . . . . . . .
Generating Linear Codes . . .
GeneratorMatCode . . . . . . .
CheckMatCode . . . . . . . . .
HammingCode . . . . . . . . .
ReedMullerCode . . . . . . . .
ExtendedBinaryGolayCode . .
47
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1146
1146
1147
1147
1147
1149
1149
1150
1151
1152
1152
1152
1153
1153
1154
1154
1155
1155
1155
1156
1156
1157
1157
1157
1158
1158
1158
1159
1159
1160
1160
1161
1161
1162
1162
1162
1163
1164
1164
1165
1165
1165
1166
1166
1167
1167
1167
1168
48
CONTENTS
66.64
66.65
66.66
66.67
66.68
66.69
66.70
66.71
66.72
66.73
66.74
66.75
66.76
66.77
66.78
66.79
66.80
66.81
66.82
66.83
66.84
66.85
66.86
66.87
66.88
66.89
66.90
66.91
66.92
66.93
66.94
66.95
66.96
66.97
66.98
66.99
66.100
66.101
66.102
66.103
66.104
66.105
66.106
66.107
66.108
66.109
66.110
66.111
ExtendedTernaryGolayCode
AlternantCode . . . . . . . .
GoppaCode . . . . . . . . . .
GeneralizedSrivastavaCode .
SrivastavaCode . . . . . . . .
CordaroWagnerCode . . . . .
RandomLinearCode . . . . .
BestKnownLinearCode . . .
Generating Cyclic Codes . .
GeneratorPolCode . . . . . .
CheckPolCode . . . . . . . .
BinaryGolayCode . . . . . .
TernaryGolayCode . . . . . .
RootsCode . . . . . . . . . .
BCHCode . . . . . . . . . . .
ReedSolomonCode . . . . . .
QRCode . . . . . . . . . . . .
FireCode . . . . . . . . . . .
WholeSpaceCode . . . . . . .
NullCode . . . . . . . . . . .
RepetitionCode . . . . . . . .
CyclicCodes . . . . . . . . . .
Manipulating Codes . . . . .
ExtendedCode . . . . . . . .
PuncturedCode . . . . . . . .
EvenWeightSubcode . . . . .
PermutedCode . . . . . . . .
ExpurgatedCode . . . . . . .
AugmentedCode . . . . . . .
RemovedElementsCode . . .
AddedElementsCode . . . . .
ShortenedCode . . . . . . . .
LengthenedCode . . . . . . .
ResidueCode . . . . . . . . .
ConstructionBCode . . . . .
DualCode . . . . . . . . . . .
ConversionFieldCode . . . . .
CosetCode . . . . . . . . . .
ConstantWeightSubcode . . .
StandardFormCode . . . . .
DirectSumCode . . . . . . . .
UUVCode . . . . . . . . . . .
DirectProductCode . . . . .
IntersectionCode . . . . . . .
UnionCode . . . . . . . . . .
Code Records . . . . . . . . .
Bounds on codes . . . . . . .
UpperBoundSingleton . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1168
1168
1168
1169
1169
1170
1170
1170
1171
1171
1172
1172
1172
1173
1173
1174
1174
1175
1175
1175
1176
1176
1177
1177
1178
1178
1179
1179
1179
1180
1180
1181
1182
1182
1182
1183
1183
1184
1184
1185
1185
1186
1186
1186
1187
1187
1190
1190
CONTENTS
66.112
66.113
66.114
66.115
66.116
66.117
66.118
66.119
66.120
66.121
66.122
66.123
66.124
66.125
66.126
66.127
66.128
66.129
66.130
66.131
66.132
66.133
66.134
66.135
66.136
66.137
66.138
66.139
66.140
66.141
66.142
66.143
66.144
66.145
66.146
66.147
66.148
66.149
66.150
66.151
66.152
66.153
66.154
66.155
66.156
66.157
66.158
66.159
UpperBoundHamming . . . . . . . . . . . .
UpperBoundJohnson . . . . . . . . . . . . .
UpperBoundPlotkin . . . . . . . . . . . . .
UpperBoundElias . . . . . . . . . . . . . .
UpperBoundGriesmer . . . . . . . . . . . .
UpperBound . . . . . . . . . . . . . . . . .
LowerBoundMinimumDistance . . . . . . .
UpperBoundMinimumDistance . . . . . . .
BoundsMinimumDistance . . . . . . . . . .
Special matrices in GUAVA . . . . . . . . .
KrawtchoukMat . . . . . . . . . . . . . . .
GrayMat . . . . . . . . . . . . . . . . . . .
SylvesterMat . . . . . . . . . . . . . . . . .
HadamardMat . . . . . . . . . . . . . . . .
MOLS . . . . . . . . . . . . . . . . . . . . .
PutStandardForm . . . . . . . . . . . . . .
IsInStandardForm . . . . . . . . . . . . . .
PermutedCols . . . . . . . . . . . . . . . . .
VerticalConversionFieldMat . . . . . . . . .
HorizontalConversionFieldMat . . . . . . .
IsLatinSquare . . . . . . . . . . . . . . . . .
AreMOLS . . . . . . . . . . . . . . . . . . .
Miscellaneous functions . . . . . . . . . . .
SphereContent . . . . . . . . . . . . . . . .
Krawtchouk . . . . . . . . . . . . . . . . . .
PrimitiveUnityRoot . . . . . . . . . . . . .
ReciprocalPolynomial . . . . . . . . . . . .
CyclotomicCosets . . . . . . . . . . . . . .
WeightHistogram . . . . . . . . . . . . . . .
Extensions to GUAVA . . . . . . . . . . . .
Some functions for the covering radius . . .
CoveringRadius . . . . . . . . . . . . . . . .
BoundsCoveringRadius . . . . . . . . . . .
SetCoveringRadius . . . . . . . . . . . . . .
IncreaseCoveringRadiusLowerBound . . . .
ExhaustiveSearchCoveringRadius . . . . . .
GeneralLowerBoundCoveringRadius . . . .
GeneralUpperBoundCoveringRadius . . . .
LowerBoundCoveringRadiusSphereCovering
LowerBoundCoveringRadiusVanWee1 . . .
LowerBoundCoveringRadiusVanWee2 . . .
LowerBoundCoveringRadiusCountingExcess
LowerBoundCoveringRadiusEmbedded1 . .
LowerBoundCoveringRadiusEmbedded2 . .
LowerBoundCoveringRadiusInduction . . .
UpperBoundCoveringRadiusRedundancy .
UpperBoundCoveringRadiusDelsarte . . . .
UpperBoundCoveringRadiusStrength . . . .
49
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1190
1191
1191
1192
1192
1192
1192
1193
1193
1194
1194
1195
1195
1195
1196
1197
1197
1198
1198
1198
1199
1199
1199
1199
1200
1200
1200
1201
1201
1202
1202
1203
1204
1204
1204
1205
1205
1205
1205
1206
1206
1207
1207
1207
1208
1208
1208
1208
50
CONTENTS
66.160
66.161
66.162
66.163
66.164
66.165
66.166
66.167
66.168
66.169
66.170
66.171
66.172
66.173
66.174
66.175
66.176
66.177
66.178
66.179
66.180
66.181
66.182
66.183
UpperBoundCoveringRadiusGriesmerLike . .
UpperBoundCoveringRadiusCyclicCode . . .
New code constructions . . . . . . . . . . . .
ExtendedDirectSumCode . . . . . . . . . . .
AmalgatedDirectSumCode . . . . . . . . . .
BlockwiseDirectSumCode . . . . . . . . . . .
PiecewiseConstantCode . . . . . . . . . . . .
Gabidulin codes . . . . . . . . . . . . . . . .
Some functions related to the norm of a code
CoordinateNorm . . . . . . . . . . . . . . . .
CodeNorm . . . . . . . . . . . . . . . . . . .
IsCoordinateAcceptable . . . . . . . . . . . .
GeneralizedCodeNorm . . . . . . . . . . . . .
IsNormalCode . . . . . . . . . . . . . . . . .
DecreaseMinimumDistanceLowerBound . . .
New miscellaneous functions . . . . . . . . .
CodeWeightEnumerator . . . . . . . . . . . .
CodeDistanceEnumerator . . . . . . . . . . .
CodeMacWilliamsTransform . . . . . . . . .
IsSelfComplementaryCode . . . . . . . . . . .
IsAffineCode . . . . . . . . . . . . . . . . . .
IsAlmostAffineCode . . . . . . . . . . . . . .
IsGriesmerCode . . . . . . . . . . . . . . . .
CodeDensity . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1208
1209
1209
1209
1210
1210
1211
1211
1212
1212
1212
1213
1213
1213
1213
1214
1214
1214
1215
1215
1215
1215
1216
1216
67 KBMAG
67.1
Creating a rewriting system . . . . . . . . . .
67.2
Elementary functions on rewriting systems .
67.3
Setting the ordering . . . . . . . . . . . . . .
67.4
Control parameters . . . . . . . . . . . . . . .
67.5
The Knuth-Bendix program . . . . . . . . . .
67.6
The automatic groups program . . . . . . . .
67.7
Word reduction . . . . . . . . . . . . . . . . .
67.8
Counting and enumerating irreducible words
67.9
Rewriting System Examples . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1217
1218
1219
1220
1220
1222
1222
1223
1223
1224
68 The Matrix Package
68.1
Aim of the matrix package . . . . . . . . . . .
68.2
Contents of the matrix package . . . . . . . . .
68.3
The Developers of the matrix package . . . . .
68.4
Basic conventions employed in matrix package
68.5
Organisation of this manual . . . . . . . . . . .
68.6
GModule . . . . . . . . . . . . . . . . . . . . .
68.7
IsGModule . . . . . . . . . . . . . . . . . . . .
68.8
IsIrreducible for GModules . . . . . . . . . . .
68.9
IsAbsolutelyIrreducible . . . . . . . . . . . . .
68.10
IsSemiLinear . . . . . . . . . . . . . . . . . . .
68.11
IsPrimitive for GModules . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1233
1233
1233
1234
1234
1235
1236
1236
1236
1236
1236
1237
CONTENTS
68.12
68.13
68.14
68.15
68.16
68.17
68.18
68.19
68.20
68.21
68.22
68.23
68.24
68.25
68.26
68.27
68.28
68.29
68.30
68.31
68.32
68.33
68.34
68.35
68.36
68.37
68.38
68.39
68.40
68.41
68.42
68.43
68.44
68.45
68.46
68.47
68.48
68.49
68.50
68.51
68.52
68.53
51
IsTensor . . . . . . . . . . . . . . . . . . . . . .
SmashGModule . . . . . . . . . . . . . . . . . .
HomGModule . . . . . . . . . . . . . . . . . . .
IsomorphismGModule . . . . . . . . . . . . . .
CompositionFactors . . . . . . . . . . . . . . .
Examples . . . . . . . . . . . . . . . . . . . . .
ClassicalForms . . . . . . . . . . . . . . . . . .
RecogniseClassical . . . . . . . . . . . . . . . .
ConstructivelyRecogniseClassical . . . . . . . .
RecogniseMatrixGroup . . . . . . . . . . . . .
RecogniseClassicalCLG . . . . . . . . . . . . .
RecogniseClassicalNP . . . . . . . . . . . . . .
InducedAction . . . . . . . . . . . . . . . . . .
FieldGenCentMat . . . . . . . . . . . . . . . .
MinimalSubGModules . . . . . . . . . . . . . .
SpinBasis . . . . . . . . . . . . . . . . . . . . .
SemiLinearDecomposition . . . . . . . . . . . .
TensorProductDecomposition . . . . . . . . . .
SymTensorProductDecomposition . . . . . . .
ExtraSpecialDecomposition . . . . . . . . . . .
MinBlocks . . . . . . . . . . . . . . . . . . . . .
BlockSystemFlag . . . . . . . . . . . . . . . . .
Components of a G-module record . . . . . . .
ApproximateKernel . . . . . . . . . . . . . . .
RandomRelations . . . . . . . . . . . . . . . .
DisplayMatRecord . . . . . . . . . . . . . . . .
The record returned by RecogniseMatrixGroup
DualGModule . . . . . . . . . . . . . . . . . . .
InducedGModule . . . . . . . . . . . . . . . . .
PermGModule . . . . . . . . . . . . . . . . . .
TensorProductGModule . . . . . . . . . . . . .
ImprimitiveWreathProduct . . . . . . . . . . .
WreathPower . . . . . . . . . . . . . . . . . . .
PermGroupRepresentation . . . . . . . . . . .
GeneralOrthogonalGroup . . . . . . . . . . . .
OrderMat – enhanced . . . . . . . . . . . . . .
PseudoRandom . . . . . . . . . . . . . . . . . .
InitPseudoRandom . . . . . . . . . . . . . . . .
IsPpdElement . . . . . . . . . . . . . . . . . .
SpinorNorm . . . . . . . . . . . . . . . . . . . .
Other utility functions . . . . . . . . . . . . . .
References . . . . . . . . . . . . . . . . . . . . .
69 The MeatAxe
69.1
More about the MeatAxe in GAP . . . .
69.2
GapObject . . . . . . . . . . . . . . . . .
69.3
Using the MeatAxe in GAP. An Example
69.4
MeatAxe Matrices . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1237
1239
1239
1239
1240
1240
1245
1248
1250
1251
1258
1261
1266
1266
1267
1267
1267
1267
1268
1268
1269
1269
1269
1270
1271
1271
1271
1272
1272
1273
1273
1273
1273
1273
1274
1275
1276
1276
1276
1277
1278
1279
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1281
1282
1282
1283
1285
52
CONTENTS
69.5
69.6
69.7
69.8
69.9
69.10
69.11
69.12
69.13
69.14
69.15
69.16
69.17
69.18
69.19
69.20
69.21
69.22
MeatAxeMat . . . . . . . . . . . . . . . . . . .
Operations for MeatAxe Matrices . . . . . . .
Functions for MeatAxe Matrices . . . . . . . .
BrauerCharacterValue . . . . . . . . . . . . . .
MeatAxe Permutations . . . . . . . . . . . . .
MeatAxePerm . . . . . . . . . . . . . . . . . .
Operations for MeatAxe Permutations . . . . .
Functions for MeatAxe Permutations . . . . . .
MeatAxe Matrix Groups . . . . . . . . . . . . .
Functions for MeatAxe Matrix Groups . . . . .
MeatAxe Matrix Algebras . . . . . . . . . . . .
Functions for MeatAxe Matrix Algebras . . . .
MeatAxe Modules . . . . . . . . . . . . . . . .
Set Theoretic Functions for MeatAxe Modules
Vector Space Functions for MeatAxe Modules .
Module Functions for MeatAxe Modules . . . .
MeatAxe.Unbind . . . . . . . . . . . . . . . . .
MeatAxe Object Records . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1285
1286
1287
1288
1288
1288
1289
1289
1289
1289
1290
1290
1291
1291
1291
1291
1293
1293
70 The Polycyclic Quotient Algorithm Package
70.1
Installing the PCQA Package . . . . . . . .
70.2
Input format . . . . . . . . . . . . . . . . .
70.3
CallPCQA . . . . . . . . . . . . . . . . . .
70.4
ExtendPCQA . . . . . . . . . . . . . . . . .
70.5
AbelianComponent . . . . . . . . . . . . . .
70.6
HirschLength . . . . . . . . . . . . . . . . .
70.7
ModuleAction . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1297
1297
1300
1300
1301
1302
1302
1303
71 Sisyphos
71.1
PrintSISYPHOSWord . . . . . . . .
71.2
PrintSisyphosInputPGroup . . . . .
71.3
IsCompatiblePCentralSeries . . . . .
71.4
SAutomorphisms . . . . . . . . . . .
71.5
AgNormalizedAutomorphisms . . . .
71.6
AgNormalizedOuterAutomorphisms
71.7
IsIsomorphic . . . . . . . . . . . . .
71.8
Isomorphisms . . . . . . . . . . . . .
71.9
CorrespondingAutomorphism . . . .
71.10
AutomorphismGroupElements . . .
71.11
NormalizedUnitsGroupRing . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1305
1305
1306
1307
1307
1308
1308
1308
1309
1310
1310
1310
. . .
. . .
. . .
zero
. . .
. . .
.
.
.
.
.
.
.
.
.
.
.
.
1313
1316
1319
1319
1320
1321
1322
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
72 Decomposition numbers of Hecke algebras of type A
72.1
Specht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Decomposition numbers of the symmetric groups . . . . . . .
Hecke algebras over fields of positive characteristic . . . . . . .
The Fock space and Hecke algebras over fields of characteristic
72.2
Schur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72.3
DecompositionMatrix . . . . . . . . . . . . . . . . . . . . . . .
CONTENTS
72.4
CrystalizedDecompositionMatrix
72.5
DecompositionNumber . . . . . .
Partitions in Specht . . . . . . . . . . . .
Inducing and restricting modules . . . . .
72.6
InducedModule . . . . . . . . . .
72.7
SInducedModule . . . . . . . . .
72.8
RestrictedModule . . . . . . . .
72.9
SRestrictedModule . . . . . . . .
Operations on decomposition matrices . .
72.10
InducedDecompositionMatrix . .
72.11
IsNewIndecomposable . . . . . .
72.12
InvertDecompositionMatrix . . .
72.13
AdjustmentMatrix . . . . . . . .
72.14
SaveDecompositionMatrix . . . .
72.15
CalculateDecompositionMatrix .
72.16
MatrixDecompositionMatrix . .
72.17
DecompositionMatrixMatrix . .
72.18
AddIndecomposable . . . . . . .
72.19
RemoveIndecomposable . . . . .
72.20
MissingIndecomposables . . . . .
Calculating dimensions . . . . . . . . . . .
72.21
SimpleDimension . . . . . . . . .
72.22
SpechtDimension . . . . . . . . .
Combinatorics on Young diagrams . . . .
72.23
Schaper . . . . . . . . . . . . . .
72.24
IsSimpleModule . . . . . . . . .
72.25
MullineuxMap . . . . . . . . . .
72.26
MullineuxSymbol . . . . . . . . .
72.27
PartitionMullineuxSymbol . . . .
72.28
GoodNodes . . . . . . . . . . . .
72.29
NormalNodes . . . . . . . . . . .
72.30
GoodNodeSequence . . . . . . .
72.31
PartitionGoodNodeSequence . .
72.32
GoodNodeLatticePath . . . . . .
72.33
LittlewoodRichardsonRule . . . .
72.34
InverseLittlewoodRichardsonRule
72.35
EResidueDiagram . . . . . . . .
72.36
HookLengthDiagram . . . . . . .
72.37
RemoveRimHook . . . . . . . . .
72.38
AddRimHook . . . . . . . . . . .
Operations on partitions . . . . . . . . . .
72.39
ECore . . . . . . . . . . . . . . .
72.40
IsECore . . . . . . . . . . . . . .
72.41
EQuotient . . . . . . . . . . . . .
72.42
CombineEQuotientECore . . . .
72.43
EWeight . . . . . . . . . . . . . .
72.44
ERegularPartitions . . . . . . . .
72.45
IsERegular . . . . . . . . . . . .
53
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1323
1324
1324
1325
1325
1327
1327
1328
1328
1329
1329
1331
1331
1332
1332
1333
1333
1334
1334
1334
1335
1335
1335
1335
1336
1336
1337
1338
1338
1338
1339
1339
1339
1340
1340
1341
1341
1342
1342
1343
1343
1343
1344
1344
1344
1344
1345
1345
54
CONTENTS
72.46
ConjugatePartition . . . . . .
72.47
PartitionBetaSet . . . . . . .
72.48
ETopLadder . . . . . . . . .
72.49
LengthLexicographic . . . . .
72.50
Lexicographic . . . . . . . . .
72.51
ReverseDominance . . . . . .
Miscellaneous functions on modules . .
72.52
Specialized . . . . . . . . . .
72.53
ERegulars . . . . . . . . . . .
72.54
SplitECores . . . . . . . . . .
72.55
Coefficient of Specht module
72.56
InnerProduct . . . . . . . . .
72.57
SpechtPrettyPrint . . . . . .
Semi–standard and standard tableaux
72.58
SemistandardTableaux . . . .
72.59
StandardTableaux . . . . . .
72.60
ConjugateTableau . . . . . .
72.61
ShapeTableau . . . . . . . . .
72.62
TypeTableau . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1345
1345
1345
1346
1346
1346
1347
1347
1347
1348
1348
1349
1349
1349
1349
1350
1350
1350
1350
73 Vector Enumeration
73.1
Operation for Finitely Presented Algebras . .
73.2
More about Vector Enumeration . . . . . . .
73.3
Examples of Vector Enumeration . . . . . . .
73.4
Using Vector Enumeration with the MeatAxe
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1351
1351
1352
1354
1357
74 AREP
74.1
Loading AREP . . . . . . .
74.2
Mons . . . . . . . . . . . .
74.3
Comparison of Mons . . . .
74.4
Basic Operations for Mons
74.5
Mon . . . . . . . . . . . . .
74.6
IsMon . . . . . . . . . . . .
74.7
IsPermMon . . . . . . . . .
74.8
IsDiagMon . . . . . . . . .
74.9
PermMon . . . . . . . . . .
74.10
MatMon . . . . . . . . . . .
74.11
MonMat . . . . . . . . . . .
74.12
DegreeMon . . . . . . . . .
74.13
CharacteristicMon . . . . .
74.14
OrderMon . . . . . . . . . .
74.15
TransposedMon . . . . . . .
74.16
DeterminantMon . . . . . .
74.17
TraceMon . . . . . . . . . .
74.18
GaloisMon . . . . . . . . .
74.19
DirectSumMon . . . . . . .
74.20
TensorProductMon . . . . .
74.21
CharPolyCyclesMon . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1359
1360
1360
1361
1362
1362
1363
1364
1364
1364
1364
1364
1365
1365
1365
1365
1366
1366
1366
1366
1367
1368
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
74.22
74.23
74.24
74.25
74.26
74.27
74.28
74.29
74.30
74.31
74.32
74.33
74.34
74.35
74.36
74.37
74.38
74.39
74.40
74.41
74.42
74.43
74.44
74.45
74.46
74.47
74.48
74.49
74.50
74.51
74.52
74.53
74.54
74.55
74.56
74.57
74.58
74.59
74.60
74.61
74.62
74.63
74.64
74.65
74.66
74.67
74.68
74.69
AMats . . . . . . . . . . . . . . . . .
AMatPerm . . . . . . . . . . . . . .
AMatMon . . . . . . . . . . . . . . .
AMatMat . . . . . . . . . . . . . . .
IsAMat . . . . . . . . . . . . . . . .
IdentityPermAMat . . . . . . . . . .
IdentityMonAMat . . . . . . . . . .
IdentityMatAMat . . . . . . . . . .
IdentityAMat . . . . . . . . . . . . .
AllOneAMat . . . . . . . . . . . . .
NullAMat . . . . . . . . . . . . . . .
DiagonalAMat . . . . . . . . . . . .
DFTAMat . . . . . . . . . . . . . .
SORAMat . . . . . . . . . . . . . .
ScalarMultipleAMat . . . . . . . . .
Product and Quotient of AMats . .
PowerAMat . . . . . . . . . . . . . .
ConjugateAMat . . . . . . . . . . .
DirectSumAMat . . . . . . . . . . .
TensorProductAMat . . . . . . . . .
GaloisConjugateAMat . . . . . . . .
Comparison of AMats . . . . . . . .
Converting AMats . . . . . . . . . .
IsIdentityMat . . . . . . . . . . . . .
IsPermMat . . . . . . . . . . . . . .
IsMonMat . . . . . . . . . . . . . . .
PermAMat . . . . . . . . . . . . . .
MonAMat . . . . . . . . . . . . . . .
MatAMat . . . . . . . . . . . . . . .
PermAMatAMat . . . . . . . . . . .
MonAMatAMat . . . . . . . . . . .
MatAMatAMat . . . . . . . . . . . .
Functions for AMats . . . . . . . . .
InverseAMat . . . . . . . . . . . . .
TransposedAMat . . . . . . . . . . .
DeterminantAMat . . . . . . . . . .
TraceAMat . . . . . . . . . . . . . .
RankAMat . . . . . . . . . . . . . .
SimplifyAMat . . . . . . . . . . . .
kbsAMat . . . . . . . . . . . . . . .
kbsDecompositionAMat . . . . . . .
AMatSparseMat . . . . . . . . . . .
SubmatrixAMat . . . . . . . . . . .
UpperBoundLinearComplexityAMat
AReps . . . . . . . . . . . . . . . . .
GroupWithGenerators . . . . . . . .
TrivialPermARep . . . . . . . . . . .
TrivialMonARep . . . . . . . . . . .
55
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1368
1370
1371
1371
1371
1372
1372
1372
1373
1373
1374
1374
1375
1375
1376
1376
1377
1377
1378
1378
1379
1380
1380
1381
1381
1381
1382
1382
1382
1383
1383
1383
1384
1384
1384
1385
1385
1385
1386
1387
1387
1388
1389
1389
1389
1392
1393
1393
56
CONTENTS
74.70
74.71
74.72
74.73
74.74
74.75
74.76
74.77
74.78
74.79
74.80
74.81
74.82
74.83
74.84
74.85
74.86
74.87
74.88
74.89
74.90
74.91
74.92
74.93
74.94
74.95
74.96
74.97
74.98
74.99
74.100
74.101
74.102
74.103
74.104
74.105
74.106
74.107
74.108
74.109
74.110
74.111
74.112
74.113
74.114
74.115
74.116
74.117
TrivialMatARep . . . . . . . . . . . . . . .
RegularARep . . . . . . . . . . . . . . . . .
NaturalARep . . . . . . . . . . . . . . . . .
ARepByImages . . . . . . . . . . . . . . . .
ARepByHom . . . . . . . . . . . . . . . . .
ARepByCharacter . . . . . . . . . . . . . .
ConjugateARep . . . . . . . . . . . . . . .
DirectSumARep . . . . . . . . . . . . . . .
InnerTensorProductARep . . . . . . . . . .
OuterTensorProductARep . . . . . . . . . .
RestrictionARep . . . . . . . . . . . . . . .
InductionARep . . . . . . . . . . . . . . . .
ExtensionARep . . . . . . . . . . . . . . . .
GaloisConjugateARep . . . . . . . . . . . .
Basic Functions for AReps . . . . . . . . .
Comparison of AReps . . . . . . . . . . . .
ImageARep . . . . . . . . . . . . . . . . . .
IsEquivalentARep . . . . . . . . . . . . . .
CharacterARep . . . . . . . . . . . . . . . .
IsIrreducibleARep . . . . . . . . . . . . . .
KernelARep . . . . . . . . . . . . . . . . . .
IsFaithfulARep . . . . . . . . . . . . . . . .
ARepWithCharacter . . . . . . . . . . . . .
GeneralFourierTransform . . . . . . . . . .
Converting AReps . . . . . . . . . . . . . .
IsPermRep . . . . . . . . . . . . . . . . . .
IsMonRep . . . . . . . . . . . . . . . . . . .
PermARepARep . . . . . . . . . . . . . . .
MonARepARep . . . . . . . . . . . . . . .
MatARepARep . . . . . . . . . . . . . . . .
Higher Functions for AReps . . . . . . . . .
IsRestrictedCharacter . . . . . . . . . . . .
AllExtendingCharacters . . . . . . . . . . .
OneExtendingCharacter . . . . . . . . . . .
IntertwiningSpaceARep . . . . . . . . . . .
IntertwiningNumberARep . . . . . . . . . .
UnderlyingPermRep . . . . . . . . . . . . .
IsTransitiveMonRep . . . . . . . . . . . . .
IsPrimitiveMonRep . . . . . . . . . . . . .
TransitivityDegreeMonRep . . . . . . . . .
OrbitDecompositionMonRep . . . . . . . .
TransitiveToInductionMonRep . . . . . . .
InsertedInductionARep . . . . . . . . . . .
ConjugationPermReps . . . . . . . . . . . .
ConjugationTransitiveMonReps . . . . . . .
TransversalChangeInductionARep . . . . .
OuterTensorProductDecompositionMonRep
InnerConjugationARep . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1394
1394
1395
1395
1397
1397
1398
1398
1399
1400
1400
1401
1402
1403
1403
1403
1404
1404
1405
1405
1406
1406
1406
1407
1407
1408
1408
1408
1409
1409
1410
1410
1410
1411
1411
1412
1412
1413
1413
1413
1414
1414
1415
1416
1417
1417
1418
1419
CONTENTS
74.118
74.119
74.120
74.121
74.122
74.123
74.124
74.125
74.126
74.127
74.128
74.129
74.130
74.131
74.132
74.133
74.134
74.135
74.136
74.137
74.138
74.139
74.140
74.141
74.142
74.143
74.144
74.145
74.146
74.147
74.148
74.149
74.150
74.151
74.152
74.153
74.154
74.155
74.156
74.157
74.158
74.159
74.160
74.161
74.162
74.163
74.164
74.165
RestrictionInductionARep . . . . . . . . . . .
kbsARep . . . . . . . . . . . . . . . . . . . .
RestrictionToSubmoduleARep . . . . . . . .
kbsDecompositionARep . . . . . . . . . . . .
ExtensionOnedimensionalAbelianRep . . . .
DecompositionMonRep . . . . . . . . . . . .
Symmetry of Matrices . . . . . . . . . . . . .
PermPermSymmetry . . . . . . . . . . . . . .
MonMonSymmetry . . . . . . . . . . . . . . .
PermIrredSymmetry . . . . . . . . . . . . . .
Discrete Signal Transforms . . . . . . . . . .
DiscreteFourierTransform . . . . . . . . . . .
InverseDiscreteFourierTransform . . . . . . .
DiscreteHartleyTransform . . . . . . . . . . .
InverseDiscreteHartleyTransform . . . . . . .
DiscreteCosineTransform . . . . . . . . . . .
InverseDiscreteCosineTransform . . . . . . .
DiscreteCosineTransformIV . . . . . . . . . .
InverseDiscreteCosineTransformIV . . . . . .
DiscreteCosineTransformI . . . . . . . . . . .
InverseDiscreteCosineTransformI . . . . . . .
WalshHadamardTransform . . . . . . . . . .
InverseWalshHadamardTransform . . . . . .
SlantTransform . . . . . . . . . . . . . . . . .
InverseSlantTransform . . . . . . . . . . . . .
HaarTransform . . . . . . . . . . . . . . . . .
InverseHaarTransform . . . . . . . . . . . . .
RationalizedHaarTransform . . . . . . . . . .
InverseRationalizedHaarTransform . . . . . .
Matrix Decomposition . . . . . . . . . . . . .
MatrixDecompositionByPermPermSymmetry
MatrixDecompositionByMonMonSymmetry .
MatrixDecompositionByPermIrredSymmetry
Complex Numbers . . . . . . . . . . . . . . .
ImaginaryUnit . . . . . . . . . . . . . . . . .
Re . . . . . . . . . . . . . . . . . . . . . . . .
Im . . . . . . . . . . . . . . . . . . . . . . . .
AbsSqr . . . . . . . . . . . . . . . . . . . . .
Sqrt . . . . . . . . . . . . . . . . . . . . . . .
ExpIPi . . . . . . . . . . . . . . . . . . . . .
CosPi . . . . . . . . . . . . . . . . . . . . . .
SinPi . . . . . . . . . . . . . . . . . . . . . .
TanPi . . . . . . . . . . . . . . . . . . . . . .
Functions for Matrices and Permutations . .
TensorProductMat . . . . . . . . . . . . . . .
MatPerm . . . . . . . . . . . . . . . . . . . .
PermMat . . . . . . . . . . . . . . . . . . . .
PermutedMat . . . . . . . . . . . . . . . . . .
57
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1420
1420
1421
1421
1422
1423
1425
1425
1426
1428
1429
1430
1430
1430
1431
1431
1431
1431
1432
1432
1432
1433
1433
1433
1433
1434
1434
1434
1435
1435
1435
1437
1438
1440
1440
1440
1440
1441
1441
1441
1441
1441
1441
1442
1442
1442
1442
1442
58
CONTENTS
74.166
74.167
74.168
74.169
DirectSummandsPermutedMat
kbs . . . . . . . . . . . . . . . .
DirectSumPerm . . . . . . . .
TensorProductPerm . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1443
1443
1444
1444
75 Monoids and Semigroups
75.1
Comparisons of Monoid Elements . . . .
75.2
Operations for Monoid Elements . . . . .
75.3
IsMonoidElement . . . . . . . . . . . . . .
75.4
SemiGroup . . . . . . . . . . . . . . . . .
75.5
IsSemiGroup . . . . . . . . . . . . . . . .
75.6
Monoid . . . . . . . . . . . . . . . . . . .
75.7
IsMonoid . . . . . . . . . . . . . . . . . .
75.8
Set Functions for Monoids . . . . . . . . .
75.9
Green Classes . . . . . . . . . . . . . . . .
75.10
RClass . . . . . . . . . . . . . . . . . . . .
75.11
IsRClass . . . . . . . . . . . . . . . . . . .
75.12
RClasses . . . . . . . . . . . . . . . . . .
75.13
LClass . . . . . . . . . . . . . . . . . . . .
75.14
IsLClass . . . . . . . . . . . . . . . . . . .
75.15
LClasses . . . . . . . . . . . . . . . . . . .
75.16
DClass . . . . . . . . . . . . . . . . . . . .
75.17
IsDClass . . . . . . . . . . . . . . . . . . .
75.18
DClasses . . . . . . . . . . . . . . . . . .
75.19
HClass . . . . . . . . . . . . . . . . . . . .
75.20
IsHClass . . . . . . . . . . . . . . . . . . .
75.21
HClasses . . . . . . . . . . . . . . . . . .
75.22
Set Functions for Green Classes . . . . . .
75.23
Green Class Records . . . . . . . . . . . .
75.24
SchutzenbergerGroup . . . . . . . . . . .
75.25
Idempotents . . . . . . . . . . . . . . . .
75.26
Monoid Homomorphisms . . . . . . . . .
75.27
Monoid Records and Semigroup Records .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1445
1446
1446
1447
1447
1447
1447
1448
1448
1448
1448
1449
1449
1449
1449
1449
1450
1450
1450
1450
1451
1451
1451
1451
1452
1452
1452
1453
76 Binary Relations
76.1
More about Relations . .
76.2
Relation . . . . . . . . . .
76.3
IsRelation . . . . . . . . .
76.4
IdentityRelation . . . . .
76.5
EmptyRelation . . . . . .
76.6
Degree of a Relation . . .
76.7
Comparisons of Relations
76.8
Operations for Relations .
76.9
IsReflexive . . . . . . . .
76.10
ReflexiveClosure . . . . .
76.11
IsSymmetric . . . . . . .
76.12
SymmetricClosure . . . .
76.13
IsTransitiveRel . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1455
1456
1457
1457
1457
1457
1458
1458
1458
1459
1460
1460
1460
1460
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
76.14
76.15
76.16
76.17
76.18
76.19
76.20
76.21
76.22
76.23
59
TransitiveClosure . . .
IsAntisymmetric . . .
IsPreOrder . . . . . .
IsPartialOrder . . . .
IsEquivalence . . . . .
EquivalenceClasses . .
HasseDiagram . . . .
RelTrans . . . . . . .
TransRel . . . . . . .
Monoids of Relations .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1461
1461
1461
1461
1462
1462
1462
1462
1462
1463
77 Transformations
77.1
More about Transformations . .
77.2
Transformation . . . . . . . . . .
77.3
IdentityTransformation . . . . .
77.4
Comparisons of Transformations
77.5
Operations for Transformations .
77.6
IsTransformation . . . . . . . . .
77.7
Degree of a Transformation . . .
77.8
Rank of a Transformation . . . .
77.9
Image of a Transformation . . .
77.10
Kernel of a Transformation . . .
77.11
PermLeftQuoTrans . . . . . . . .
77.12
TransPerm . . . . . . . . . . . .
77.13
PermTrans . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1465
1466
1466
1466
1467
1467
1468
1468
1468
1469
1469
1469
1469
1470
78 Transformation Monoids
78.1
IsTransMonoid . . . . . . . . . . . . . . . . . . . .
78.2
Degree of a Transformation Monoid . . . . . . . .
78.3
FullTransMonoid . . . . . . . . . . . . . . . . . . .
78.4
PartialTransMonoid . . . . . . . . . . . . . . . . .
78.5
ImagesTransMonoid . . . . . . . . . . . . . . . . .
78.6
KernelsTransMonoid . . . . . . . . . . . . . . . . .
78.7
Set Functions for Transformation Monoids . . . . .
78.8
Monoid Functions for Transformation Monoids . .
78.9
SchutzenbergerGroup for Transformation Monoids
78.10
H Classes for Transformation Monoids . . . . . . .
78.11
R Classes for Transformation Monoids . . . . . . .
78.12
L Classes for Transformation Monoids . . . . . . .
78.13
D Classes for Transformation Monoids . . . . . . .
78.14
Display a Transformation Monoid . . . . . . . . .
78.15
Transformation Monoid Records . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1471
1472
1472
1472
1472
1473
1473
1473
1474
1474
1474
1475
1476
1477
1478
1479
79 Actions of Monoids
79.1
Other Actions . .
79.2
Orbit for Monoids
79.3
StrongOrbit . . . .
79.4
GradedOrbit . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1481
1481
1483
1483
1484
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
60
CONTENTS
79.5
79.6
79.7
ShortOrbit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1484
Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1484
ActionWithZero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1485
80 XMOD
80.1
About XMOD . . . . . . . . . . . . . . . . .
80.2
About crossed modules . . . . . . . . . . . .
80.3
The XMod Function . . . . . . . . . . . . . .
80.4
IsXMod . . . . . . . . . . . . . . . . . . . . .
80.5
XModPrint . . . . . . . . . . . . . . . . . . .
80.6
ConjugationXMod . . . . . . . . . . . . . . .
80.7
XModName . . . . . . . . . . . . . . . . . . .
80.8
CentralExtensionXMod . . . . . . . . . . . .
80.9
AutomorphismXMod . . . . . . . . . . . . .
80.10
InnerAutomorphismXMod . . . . . . . . . . .
80.11
TrivialActionXMod . . . . . . . . . . . . . .
80.12
IsRModule for groups . . . . . . . . . . . . .
80.13
RModuleXMod . . . . . . . . . . . . . . . . .
80.14
XModSelect . . . . . . . . . . . . . . . . . . .
80.15
Operations for crossed modules . . . . . . . .
80.16
Print for crossed modules . . . . . . . . . . .
80.17
Size for crossed modules . . . . . . . . . . . .
80.18
Elements for crossed modules . . . . . . . . .
80.19
IsConjugation for crossed modules . . . . . .
80.20
IsAspherical . . . . . . . . . . . . . . . . . . .
80.21
IsSimplyConnected . . . . . . . . . . . . . . .
80.22
IsCentralExtension . . . . . . . . . . . . . . .
80.23
IsAutomorphismXMod . . . . . . . . . . . . .
80.24
IsTrivialAction . . . . . . . . . . . . . . . . .
80.25
IsZeroBoundary . . . . . . . . . . . . . . . .
80.26
IsRModule for crossed modules . . . . . . . .
80.27
WhatTypeXMod . . . . . . . . . . . . . . . .
80.28
DirectProduct for crossed modules . . . . . .
80.29
XModMorphism . . . . . . . . . . . . . . . .
80.30
IsXModMorphism . . . . . . . . . . . . . . .
80.31
XModMorphismPrint . . . . . . . . . . . . .
80.32
XModMorphismName . . . . . . . . . . . . .
80.33
Operations for morphisms of crossed modules
80.34
IdentitySubXMod . . . . . . . . . . . . . . .
80.35
SubXMod . . . . . . . . . . . . . . . . . . . .
80.36
IsSubXMod . . . . . . . . . . . . . . . . . . .
80.37
InclusionMorphism for crossed modules . . .
80.38
IsNormalSubXMod . . . . . . . . . . . . . . .
80.39
NormalSubXMods . . . . . . . . . . . . . . .
80.40
Factor crossed module . . . . . . . . . . . . .
80.41
Kernel of a crossed module morphism . . . .
80.42
Image for a crossed module morphism . . . .
80.43
InnerAutomorphism of a crossed module . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1487
1487
1488
1490
1491
1491
1491
1492
1492
1492
1493
1493
1494
1494
1495
1495
1496
1496
1496
1496
1497
1497
1497
1497
1497
1497
1498
1498
1498
1499
1499
1500
1500
1500
1501
1501
1501
1501
1502
1502
1503
1503
1503
1504
CONTENTS
80.44
80.45
80.46
80.47
80.48
80.49
80.50
80.51
80.52
80.53
80.54
80.55
80.56
80.57
80.58
80.59
80.60
80.61
80.62
80.63
80.64
80.65
80.66
80.67
80.68
80.69
80.70
80.71
80.72
80.73
80.74
80.75
80.76
80.77
80.78
80.79
80.80
80.81
80.82
80.83
80.84
80.85
80.86
80.87
80.88
80.89
80.90
80.91
Order of a crossed module morphism . . .
CompositeMorphism for crossed modules
SourceXModXPModMorphism . . . . . .
About cat1-groups . . . . . . . . . . . . .
Cat1 . . . . . . . . . . . . . . . . . . . . .
IsCat1 . . . . . . . . . . . . . . . . . . . .
Cat1Print . . . . . . . . . . . . . . . . . .
Cat1Name . . . . . . . . . . . . . . . . .
ConjugationCat1 . . . . . . . . . . . . . .
Operations for cat1-groups . . . . . . . .
Size for cat1-groups . . . . . . . . . . . .
Elements for cat1-groups . . . . . . . . .
XModCat1 . . . . . . . . . . . . . . . . .
Cat1XMod . . . . . . . . . . . . . . . . .
SemidirectCat1XMod . . . . . . . . . . .
Cat1List . . . . . . . . . . . . . . . . . . .
Cat1Select . . . . . . . . . . . . . . . . .
Cat1Morphism . . . . . . . . . . . . . . .
IsCat1Morphism . . . . . . . . . . . . . .
Cat1MorphismName . . . . . . . . . . . .
Cat1MorphismPrint . . . . . . . . . . . .
Operations for morphisms of cat1-groups
Cat1MorphismSourceHomomorphism . .
ReverseCat1 . . . . . . . . . . . . . . . .
ReverseIsomorphismCat1 . . . . . . . . .
Cat1MorphismXModMorphism . . . . . .
XModMorphismCat1Morphism . . . . . .
CompositeMorphism for cat1-groups . . .
IdentitySubCat1 . . . . . . . . . . . . . .
SubCat1 . . . . . . . . . . . . . . . . . . .
InclusionMorphism for cat1-groups . . . .
NormalSubCat1s . . . . . . . . . . . . . .
AllCat1s . . . . . . . . . . . . . . . . . . .
About derivations and sections . . . . . .
XModDerivationByImages . . . . . . . . .
IsDerivation . . . . . . . . . . . . . . . . .
DerivationImage . . . . . . . . . . . . . .
DerivationImages . . . . . . . . . . . . . .
InnerDerivation . . . . . . . . . . . . . . .
ListInnerDerivations . . . . . . . . . . . .
Operations for derivations . . . . . . . . .
Cat1SectionByImages . . . . . . . . . . .
IsSection . . . . . . . . . . . . . . . . . .
IsRegular for Crossed Modules . . . . . .
Operations for sections . . . . . . . . . .
RegularDerivations . . . . . . . . . . . . .
AllDerivations . . . . . . . . . . . . . . .
DerivationsSorted . . . . . . . . . . . . .
61
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1504
1505
1505
1506
1507
1508
1508
1508
1509
1510
1510
1510
1510
1511
1511
1512
1512
1514
1514
1515
1515
1515
1515
1516
1516
1516
1517
1517
1518
1518
1518
1519
1519
1520
1523
1523
1523
1523
1523
1524
1524
1524
1525
1525
1525
1525
1526
1526
62
CONTENTS
80.92
80.93
80.94
80.95
80.96
80.97
80.98
80.99
80.100
80.101
80.102
80.103
80.104
80.105
80.106
80.107
80.108
80.109
80.110
80.111
80.112
80.113
80.114
80.115
80.116
80.117
80.118
80.119
80.120
80.121
80.122
80.123
80.124
80.125
80.126
80.127
80.128
80.129
80.130
80.131
80.132
80.133
80.134
80.135
80.136
80.137
80.138
80.139
DerivationTable . . . . . . . . . . . . . . . . .
AreDerivations . . . . . . . . . . . . . . . . . .
RegularSections . . . . . . . . . . . . . . . . .
AllSections . . . . . . . . . . . . . . . . . . . .
AreSections . . . . . . . . . . . . . . . . . . . .
SectionDerivation . . . . . . . . . . . . . . . .
DerivationSection . . . . . . . . . . . . . . . .
CompositeDerivation . . . . . . . . . . . . . . .
CompositeSection . . . . . . . . . . . . . . . .
WhiteheadGroupTable . . . . . . . . . . . . . .
WhiteheadMonoidTable . . . . . . . . . . . . .
InverseDerivations . . . . . . . . . . . . . . . .
ListInverseDerivations . . . . . . . . . . . . . .
SourceEndomorphismDerivation . . . . . . . .
TableSourceEndomorphismDerivations . . . . .
RangeEndomorphismDerivation . . . . . . . . .
TableRangeEndomorphismDerivations . . . . .
XModEndomorphismDerivation . . . . . . . .
SourceEndomorphismSection . . . . . . . . . .
RangeEndomorphismSection . . . . . . . . . .
Cat1EndomorphismSection . . . . . . . . . . .
About actors . . . . . . . . . . . . . . . . . . .
ActorSquareRecord . . . . . . . . . . . . . . .
WhiteheadPermGroup . . . . . . . . . . . . . .
Whitehead crossed module . . . . . . . . . . .
AutomorphismPermGroup for crossed modules
XModMorphismAutoPerm . . . . . . . . . . .
ImageAutomorphismDerivation . . . . . . . . .
Norrie crossed module . . . . . . . . . . . . . .
Lue crossed module . . . . . . . . . . . . . . .
Actor crossed module . . . . . . . . . . . . . .
InnerMorphism for crossed modules . . . . . .
Centre for crossed modules . . . . . . . . . . .
InnerActor for crossed modules . . . . . . . . .
Actor for cat1-groups . . . . . . . . . . . . . .
About induced constructions . . . . . . . . . .
InducedXMod . . . . . . . . . . . . . . . . . .
AllInducedXMods . . . . . . . . . . . . . . . .
InducedCat1 . . . . . . . . . . . . . . . . . . .
About utilities . . . . . . . . . . . . . . . . . .
InclusionMorphism . . . . . . . . . . . . . . . .
ZeroMorphism . . . . . . . . . . . . . . . . . .
EndomorphismClasses . . . . . . . . . . . . . .
EndomorphismImages . . . . . . . . . . . . . .
IdempotentImages . . . . . . . . . . . . . . . .
InnerAutomorphismGroup . . . . . . . . . . .
IsAutomorphismGroup . . . . . . . . . . . . .
AutomorphismPair . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1526
1527
1527
1527
1528
1528
1528
1529
1529
1529
1529
1530
1530
1530
1530
1531
1531
1531
1532
1532
1532
1533
1534
1535
1535
1536
1536
1536
1537
1537
1538
1538
1539
1539
1539
1541
1542
1544
1544
1545
1546
1547
1547
1548
1548
1548
1549
1549
CONTENTS
80.140
80.141
80.142
80.143
80.144
80.145
80.146
80.147
80.148
80.149
80.150
IsAutomorphismPair . . . .
AutomorphismPermGroup
FpPair . . . . . . . . . . . .
IsFpPair . . . . . . . . . . .
SemidirectPair . . . . . . .
IsSemidirectPair . . . . . .
PrintList . . . . . . . . . .
DistinctRepresentatives . .
CommonRepresentatives . .
CommonTransversal . . . .
IsCommonTransversal . . .
63
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
81 The CHEVIE Package Version 4 – a short introduction
82 Reflections, and reflection groups
82.1
Reflection . . . . . . . . . . . .
82.2
AsReflection . . . . . . . . . .
82.3
CartanMat . . . . . . . . . . .
82.4
Rank . . . . . . . . . . . . . .
82.5
SemisimpleRank . . . . . . . .
1549
1549
1550
1551
1551
1551
1551
1552
1552
1552
1552
1553
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1557
1558
1559
1560
1560
1560
83 Coxeter groups
83.1
CoxeterGroupSymmetricGroup . . .
83.2
CoxeterGroupHyperoctaedralGroup
83.3
CoxeterMatrix . . . . . . . . . . . .
83.4
CoxeterGroupByCoxeterMatrix . . .
83.5
CoxeterGroupByCartanMatrix . . .
83.6
CartanMatFromCoxeterMatrix . . .
83.7
Functions for general Coxeter groups
83.8
IsLeftDescending . . . . . . . . . . .
83.9
FirstLeftDescending . . . . . . . . .
83.10
LeftDescentSet . . . . . . . . . . . .
83.11
RightDescentSet . . . . . . . . . . .
83.12
EltWord . . . . . . . . . . . . . . . .
83.13
CoxeterWord . . . . . . . . . . . . .
83.14
CoxeterLength . . . . . . . . . . . .
83.15
ReducedCoxeterWord . . . . . . . .
83.16
BrieskornNormalForm . . . . . . . .
83.17
LongestCoxeterElement . . . . . . .
83.18
LongestCoxeterWord . . . . . . . . .
83.19
CoxeterElements . . . . . . . . . . .
83.20
CoxeterWords . . . . . . . . . . . .
83.21
Bruhat . . . . . . . . . . . . . . . .
83.22
BruhatSmaller . . . . . . . . . . . .
83.23
BruhatPoset . . . . . . . . . . . . .
83.24
ReducedInRightCoset . . . . . . . .
83.25
ForEachElement . . . . . . . . . . .
83.26
ForEachCoxeterWord . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1563
1565
1567
1567
1567
1567
1568
1568
1569
1569
1569
1569
1570
1570
1570
1571
1571
1571
1572
1572
1572
1572
1573
1573
1573
1574
1574
.
.
.
.
.
.
.
.
.
.
64
CONTENTS
83.27
83.28
83.29
84 Finite
84.1
84.2
84.3
84.4
84.5
84.6
84.7
84.8
84.9
84.10
84.11
84.12
84.13
84.14
84.15
84.16
84.17
84.18
84.19
84.20
84.21
84.22
84.23
84.24
84.25
84.26
84.27
StandardParabolicClass . . . . . . . . . . . . . . . . . . . . . . . . . . . 1574
ParabolicRepresentatives . . . . . . . . . . . . . . . . . . . . . . . . . . 1575
ReducedExpressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1575
Reflection Groups
Functions for finite reflection groups . . . . .
PermRootGroup . . . . . . . . . . . . . . . .
ReflectionType . . . . . . . . . . . . . . . . .
ReflectionName . . . . . . . . . . . . . . . . .
IsomorphismType . . . . . . . . . . . . . . .
ComplexReflectionGroup . . . . . . . . . . .
Reflections . . . . . . . . . . . . . . . . . . .
MatXPerm . . . . . . . . . . . . . . . . . . .
PermMatX . . . . . . . . . . . . . . . . . . .
MatYPerm . . . . . . . . . . . . . . . . . . .
InvariantForm for finite reflection groups . .
ReflectionEigenvalues . . . . . . . . . . . . .
ReflectionLength . . . . . . . . . . . . . . . .
ReflectionWord . . . . . . . . . . . . . . . . .
HyperplaneOrbits . . . . . . . . . . . . . . .
BraidRelations . . . . . . . . . . . . . . . . .
PrintDiagram . . . . . . . . . . . . . . . . . .
ReflectionCharValue . . . . . . . . . . . . . .
ReflectionCharacter . . . . . . . . . . . . . .
ReflectionDegrees . . . . . . . . . . . . . . .
ReflectionCoDegrees . . . . . . . . . . . . . .
GenericOrder . . . . . . . . . . . . . . . . . .
TorusOrder . . . . . . . . . . . . . . . . . . .
ParabolicRepresentatives for reflection groups
Invariants . . . . . . . . . . . . . . . . . . . .
Discriminant . . . . . . . . . . . . . . . . . .
Catalan . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1577
1578
1579
1580
1581
1581
1582
1582
1582
1583
1583
1584
1584
1584
1584
1585
1586
1586
1586
1586
1587
1587
1587
1587
1588
1588
1589
1589
85 Root systems and finite Coxeter groups
85.1
CartanMat for Dynkin types . . . . . . . . . . . .
85.2
CoxeterGroup . . . . . . . . . . . . . . . . . . . .
85.3
Operations and functions for finite Coxeter groups
85.4
HighestShortRoot . . . . . . . . . . . . . . . . . .
85.5
BadPrimes . . . . . . . . . . . . . . . . . . . . . .
85.6
PermMatY . . . . . . . . . . . . . . . . . . . . . .
85.7
Inversions . . . . . . . . . . . . . . . . . . . . . . .
85.8
ElementWithInversions . . . . . . . . . . . . . . .
85.9
DescribeInvolution . . . . . . . . . . . . . . . . . .
85.10
ParabolicSubgroups . . . . . . . . . . . . . . . . .
85.11
ExtendedReflectionGroup . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1591
1594
1595
1596
1598
1598
1598
1599
1599
1599
1600
1600
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
86 Algebraic groups and semi-simple elements
1601
86.1
CoxeterGroup (extended form) . . . . . . . . . . . . . . . . . . . . . . . 1603
CONTENTS
86.2
86.3
86.4
86.5
86.6
86.7
86.8
86.9
86.10
86.11
86.12
86.13
86.14
86.15
86.16
86.17
RootDatum . . . . . . . . . . . . . . . .
Dual for root Data . . . . . . . . . . . .
Torus . . . . . . . . . . . . . . . . . . .
FundamentalGroup for algebraic groups
IntermediateGroup . . . . . . . . . . . .
SemisimpleElement . . . . . . . . . . . .
Operations for semisimple elements . .
Centralizer for semisimple elements . . .
SubTorus . . . . . . . . . . . . . . . . .
Operations for Subtori . . . . . . . . . .
AlgebraicCentre . . . . . . . . . . . . .
SemisimpleSubgroup . . . . . . . . . . .
IsIsolated . . . . . . . . . . . . . . . . .
IsQuasiIsolated . . . . . . . . . . . . . .
QuasiIsolatedRepresentatives . . . . . .
SemisimpleCentralizerRepresentatives .
65
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1604
1604
1604
1605
1605
1606
1606
1607
1608
1608
1609
1609
1610
1610
1610
1611
87 Classes and representations for reflection groups
87.1
ChevieClassInfo . . . . . . . . . . . . . . . . . .
87.2
WordsClassRepresentatives . . . . . . . . . . . .
87.3
CharNames for reflection groups . . . . . . . . .
87.4
CharParams for reflection groups . . . . . . . . .
87.5
ChevieCharInfo . . . . . . . . . . . . . . . . . . .
87.6
FakeDegrees . . . . . . . . . . . . . . . . . . . .
87.7
FakeDegree . . . . . . . . . . . . . . . . . . . . .
87.8
LowestPowerFakeDegrees . . . . . . . . . . . . .
87.9
HighestPowerFakeDegrees . . . . . . . . . . . . .
87.10
Representations . . . . . . . . . . . . . . . . . .
87.11
LowestPowerGenericDegrees . . . . . . . . . . .
87.12
HighestPowerGenericDegrees . . . . . . . . . . .
87.13
PositionDet . . . . . . . . . . . . . . . . . . . . .
87.14
DetPerm . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1613
1619
1620
1621
1621
1621
1623
1624
1624
1624
1624
1625
1625
1625
1625
88 Reflection subgroups
88.1
ReflectionSubgroup . . . . . . . . . . . . . . . . . . . . . . . .
88.2
Functions for reflection subgroups . . . . . . . . . . . . . . . .
88.3
ReducedRightCosetRepresentatives . . . . . . . . . . . . . . . .
88.4
PermCosetsSubgroup . . . . . . . . . . . . . . . . . . . . . . .
88.5
StandardParabolic . . . . . . . . . . . . . . . . . . . . . . . . .
88.6
jInductionTable for Macdonald-Lusztig-Spaltenstein induction
88.7
JInductionTable . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1627
1629
1630
1631
1631
1632
1632
1633
89 Garside and braid monoids and groups
89.1
Operations for (locally) Garside monoid elements
89.2
Records for( locally) Garside monoids . . . . . .
89.3
GarsideWords . . . . . . . . . . . . . . . . . . . .
89.4
Presentation . . . . . . . . . . . . . . . . . . . .
89.5
ShrinkGarsideGeneratingSet . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1635
1640
1641
1643
1643
1644
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
66
CONTENTS
89.6
89.7
89.8
89.9
89.10
89.11
89.12
89.13
89.14
89.15
89.16
89.17
89.18
89.19
89.20
89.21
89.22
89.23
89.24
89.25
89.26
89.27
locally Garside monoid and Garside group
AsWord . . . . . . . . . . . . . . . . . . .
GarsideAlpha . . . . . . . . . . . . . . . .
LeftGcd . . . . . . . . . . . . . . . . . . .
LeftLcm . . . . . . . . . . . . . . . . . . .
ReversedWord . . . . . . . . . . . . . . .
RightGcd . . . . . . . . . . . . . . . . . .
RightLcm . . . . . . . . . . . . . . . . . .
AsFraction . . . . . . . . . . . . . . . . .
LeftDivisorsSimple . . . . . . . . . . . . .
EltBraid . . . . . . . . . . . . . . . . . . .
The Artin-Tits braid monoids and groups
Construction of braids . . . . . . . . . . .
Operations for braids . . . . . . . . . . .
GoodCoxeterWord . . . . . . . . . . . . .
BipartiteDecomposition . . . . . . . . . .
DualBraidMonoid . . . . . . . . . . . . .
DualBraid . . . . . . . . . . . . . . . . . .
Operations for dual braids . . . . . . . . .
ConjugacySet . . . . . . . . . . . . . . . .
CentralizerGenerators . . . . . . . . . . .
RepresentativeConjugation . . . . . . . .
elements records
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1644
1645
1645
1645
1645
1646
1646
1646
1646
1647
1647
1647
1648
1648
1649
1649
1649
1650
1651
1651
1651
1652
90 Cyclotomic Hecke algebras
90.1
Hecke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
90.2
Operations for cyclotomic Hecke algebras . . . . . . . . . .
90.3
SchurElements . . . . . . . . . . . . . . . . . . . . . . . . .
90.4
SchurElement . . . . . . . . . . . . . . . . . . . . . . . . . .
90.5
FactorizedSchurElements . . . . . . . . . . . . . . . . . . .
90.6
FactorizedSchurElement . . . . . . . . . . . . . . . . . . . .
90.7
Functions and operations for FactorizedSchurElements . . .
90.8
LowestPowerGenericDegrees for cyclotomic Hecke algebras
90.9
HighestPowerGenericDegrees for cyclotomic Hecke algebras
90.10
HeckeCentralMonomials . . . . . . . . . . . . . . . . . . . .
90.11
Representations for cyclotomic Hecke algebras . . . . . . .
90.12
HeckeCharValues for cyclotomic Hecke algebras . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1655
1656
1657
1658
1658
1658
1659
1659
1660
1660
1661
1661
1662
91 Iwahori-Hecke algebras
91.1
Hecke for Coxeter groups . . . . . . . . . . . . . . .
91.2
Operations and functions for Iwahori-Hecke algebras
91.3
RootParameter . . . . . . . . . . . . . . . . . . . . .
91.4
HeckeSubAlgebra . . . . . . . . . . . . . . . . . . . .
91.5
Construction of Hecke elements of the T basis . . . .
91.6
Operations for Hecke elements of the T basis . . . .
91.7
HeckeClassPolynomials . . . . . . . . . . . . . . . .
91.8
HeckeCharValues . . . . . . . . . . . . . . . . . . . .
91.9
Specialization from one Hecke algebra to another . .
91.10
CreateHeckeBasis . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1663
1665
1666
1666
1667
1667
1669
1671
1671
1671
1672
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
67
Parameterized bases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1674
92 Representations of Iwahori-Hecke algebras
92.1
HeckeReflectionRepresentation . . . . . . . . .
92.2
CheckHeckeDefiningRelations . . . . . . . . . .
92.3
CharTable for Hecke algebras . . . . . . . . . .
92.4
Representations for Hecke algebras . . . . . . .
92.5
PoincarePolynomial . . . . . . . . . . . . . . .
92.6
SchurElements for Iwahori-Hecke algebras . . .
92.7
SchurElement for Iwahori-Hecke algebras . . .
92.8
GenericDegrees . . . . . . . . . . . . . . . . . .
92.9
LowestPowerGenericDegrees for Hecke algebras
92.10
HeckeCharValuesGood . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1677
1678
1678
1679
1680
1681
1681
1682
1682
1682
1683
93 Kazhdan-Lusztig polynomials and bases
93.1
KazhdanLusztigPolynomial . . . . . .
93.2
CriticalPair . . . . . . . . . . . . . . .
93.3
KazhdanLusztigCoefficient . . . . . .
93.4
KazhdanLusztigMue . . . . . . . . . .
93.5
LeftCells . . . . . . . . . . . . . . . .
93.6
LeftCell . . . . . . . . . . . . . . . . .
93.7
Functions for LeftCells . . . . . . . . .
93.8
W-Graphs . . . . . . . . . . . . . . . .
93.9
WGraph . . . . . . . . . . . . . . . . .
93.10
WGraphToRepresentation . . . . . . .
93.11
Hecke elements of the C basis . . . . .
93.12
Hecke elements of the primed C basis
93.13
Hecke elements of the D basis . . . . .
93.14
Hecke elements of the primed D basis
93.15
Asymptotic algebra . . . . . . . . . .
93.16
Lusztigaw . . . . . . . . . . . . . . . .
93.17
LusztigAw . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1685
1687
1687
1688
1688
1688
1689
1689
1690
1691
1691
1692
1693
1693
1694
1694
1695
1695
94 Parabolic modules for Iwahori-Hecke algebras
94.1
Construction of Hecke module elements of the M T basis . . . . .
94.2
Construction of Hecke module elements of the primed M C basis
94.3
Operations for Hecke module elements . . . . . . . . . . . . . . .
94.4
CreateHeckeModuleBasis . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1697
1697
1698
1699
1699
95 Reflection cosets
95.1
ReflectionCoset . . . . . . . . . . . . .
95.2
Spets . . . . . . . . . . . . . . . . . .
95.3
ReflectionSubCoset . . . . . . . . . . .
95.4
SubSpets . . . . . . . . . . . . . . . .
95.5
Functions for Reflection cosets . . . .
95.6
ChevieCharInfo for reflection cosets .
95.7
ReflectionType for reflection cosets . .
95.8
ReflectionDegrees for reflection cosets
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1701
1703
1704
1704
1704
1704
1706
1707
1708
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
68
CONTENTS
95.9
95.10
95.11
Twistings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1708
ChevieClassInfo for Reflection cosets . . . . . . . . . . . . . . . . . . . . 1709
CharTable for Reflection cosets . . . . . . . . . . . . . . . . . . . . . . . 1709
96 Coxeter cosets
96.1
CoxeterCoset . . . . . . . . . . . . . . . . . . . . . . .
96.2
CoxeterSubCoset . . . . . . . . . . . . . . . . . . . . .
96.3
Functions on Coxeter cosets . . . . . . . . . . . . . . .
96.4
ReflectionType for Coxeter cosets . . . . . . . . . . .
96.5
ChevieClassInfo for Coxeter cosets . . . . . . . . . . .
96.6
CharTable for Coxeter cosets . . . . . . . . . . . . . .
96.7
Frobenius . . . . . . . . . . . . . . . . . . . . . . . . .
96.8
Twistings for Coxeter cosets . . . . . . . . . . . . . .
96.9
RootDatum for Coxeter cosets . . . . . . . . . . . . .
96.10
Torus for Coxeter cosets . . . . . . . . . . . . . . . . .
96.11
StructureRationalPointsConnectedCentre . . . . . . .
96.12
ClassTypes . . . . . . . . . . . . . . . . . . . . . . . .
96.13
Quasi-Semisimple elements of non-connected reductive
96.14
Centralizer for quasisemisimple elements . . . . . . . .
96.15
QuasiIsolatedRepresentatives for Coxeter cosets . . . .
96.16
IsIsolated for Coxeter cosets . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
groups .
. . . . .
. . . . .
. . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1711
1714
1715
1716
1718
1718
1719
1719
1720
1721
1721
1722
1722
1724
1725
1725
1726
97 Hecke cosets
1727
97.1
Hecke for Coxeter cosets . . . . . . . . . . . . . . . . . . . . . . . . . . . 1727
97.2
Operations and functions for Hecke cosets . . . . . . . . . . . . . . . . . 1728
98 Unipotent characters of finite reductive groups and
98.1
UnipotentCharacters . . . . . . . . . . . . . . . . .
98.2
Operations for UnipotentCharacters . . . . . . . .
98.3
UnipotentCharacter . . . . . . . . . . . . . . . . .
98.4
Operations for Unipotent Characters . . . . . . . .
98.5
UnipotentDegrees . . . . . . . . . . . . . . . . . .
98.6
CycPolUnipotentDegrees . . . . . . . . . . . . . .
98.7
DeligneLusztigCharacter . . . . . . . . . . . . . . .
98.8
AlmostCharacter . . . . . . . . . . . . . . . . . . .
98.9
LusztigInduction . . . . . . . . . . . . . . . . . . .
98.10
LusztigRestriction . . . . . . . . . . . . . . . . . .
98.11
LusztigInductionTable . . . . . . . . . . . . . . . .
98.12
DeligneLusztigLefschetz . . . . . . . . . . . . . . .
98.13
Families of unipotent characters . . . . . . . . . .
98.14
Family . . . . . . . . . . . . . . . . . . . . . . . . .
98.15
Operations for families . . . . . . . . . . . . . . . .
98.16
IsFamily . . . . . . . . . . . . . . . . . . . . . . . .
98.17
OnFamily . . . . . . . . . . . . . . . . . . . . . . .
98.18
FamiliesClassical . . . . . . . . . . . . . . . . . . .
98.19
FamilyImprimitive . . . . . . . . . . . . . . . . . .
98.20
DrinfeldDouble . . . . . . . . . . . . . . . . . . . .
98.21
NrDrinfeldDouble . . . . . . . . . . . . . . . . . .
Spetses
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1729
1732
1734
1736
1736
1737
1737
1738
1738
1738
1739
1739
1740
1741
1742
1742
1743
1743
1744
1744
1744
1746
CONTENTS
98.22
69
FusionAlgebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1747
99 Eigenspaces and d-Harish-Chandra series
99.1
RelativeDegrees . . . . . . . . . . . . .
99.2
RegularEigenvalues . . . . . . . . . . . .
99.3
PositionRegularClass . . . . . . . . . . .
99.4
EigenspaceProjector . . . . . . . . . . .
99.5
SplitLevis . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1749
1750
1750
1751
1751
1751
100 Unipotent classes of reductive groups
100.1
UnipotentClasses . . . . . . . . . .
100.2
ICCTable . . . . . . . . . . . . . .
100.3
SpecialPieces . . . . . . . . . . . .
100.4
InducedLinearForm . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1753
1757
1760
1761
1762
101 Unipotent elements of reductive groups
101.1
UnipotentGroup . . . . . . . . . . . .
101.2
Operations for Unipotent elements . .
101.3
IsUnipotentElement . . . . . . . . . .
101.4
UnipotentDecompose . . . . . . . . .
101.5
UnipotentAbelianPart . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1763
1765
1767
1767
1767
1768
102 Affine
102.1
102.2
102.3
.
.
.
.
Coxeter groups and Hecke algebras
1769
Affine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1771
Operations and functions for Affine Weyl groups . . . . . . . . . . . . . 1771
AffineRootAction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1771
103 CHEVIE utility functions
103.1
SymmetricDifference . . . . . . .
103.2
DifferenceMultiSet . . . . . . . .
103.3
Rotation . . . . . . . . . . . . .
103.4
Rotations . . . . . . . . . . . . .
103.5
Inherit . . . . . . . . . . . . . . .
103.6
Dictionary . . . . . . . . . . . .
103.7
GetRoot . . . . . . . . . . . . . .
103.8
CharParams . . . . . . . . . . .
103.9
CharName . . . . . . . . . . . .
103.10 PositionId . . . . . . . . . . . . .
103.11 InductionTable . . . . . . . . . .
103.12 CharRepresentationWords . . . .
103.13 PointsAndRepresentativesOrbits
103.14 AbelianGenerators . . . . . . . .
104 CHEVIE String and
104.1
Replace . . . .
104.2
IntListToString
104.3
FormatTable .
104.4
Format . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1773
1773
1773
1773
1774
1774
1774
1775
1776
1776
1776
1777
1778
1778
1779
Formatting functions
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1781
1781
1781
1782
1783
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
70
CONTENTS
105 CHEVIE Matrix utility functions
105.1
EigenvaluesMat . . . . . . . . . . . .
105.2
DecomposedMat . . . . . . . . . . .
105.3
BlocksMat . . . . . . . . . . . . . .
105.4
RepresentativeDiagonalConjugation
105.5
Transporter . . . . . . . . . . . . . .
105.6
ProportionalityCoefficient . . . . . .
105.7
ExteriorPower . . . . . . . . . . . .
105.8
SymmetricPower . . . . . . . . . . .
105.9
SchurFunctor . . . . . . . . . . . . .
105.10 IsNormalizing . . . . . . . . . . . . .
105.11 IndependentLines . . . . . . . . . . .
105.12 OnMatrices . . . . . . . . . . . . . .
105.13 PermutedByCols . . . . . . . . . . .
105.14 PermMatMat . . . . . . . . . . . . .
105.15 RepresentativeRowColPermutation .
105.16 BigCellDecomposition . . . . . . . .
106 Cyclotomic polynomials
106.1
AsRootOfUnity . . . .
106.2
CycPol . . . . . . . .
106.3
IsCycPol . . . . . . .
106.4
Functions for CycPols
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1785
1785
1785
1786
1786
1786
1787
1787
1787
1788
1788
1788
1788
1789
1789
1789
1789
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1791
1791
1792
1792
1792
107 Partitions and symbols
107.1
Compositions . . . . . . . . . . . . .
107.2
PartBeta . . . . . . . . . . . . . . .
107.3
ShiftBeta . . . . . . . . . . . . . . .
107.4
PartitionTupleToString . . . . . . .
107.5
Tableaux . . . . . . . . . . . . . . .
107.6
DefectSymbol . . . . . . . . . . . . .
107.7
RankSymbol . . . . . . . . . . . . .
107.8
Symbols . . . . . . . . . . . . . . . .
107.9
SymbolsDefect . . . . . . . . . . . .
107.10 CycPolGenericDegreeSymbol . . . .
107.11 CycPolFakeDegreeSymbol . . . . . .
107.12 LowestPowerGenericDegreeSymbol .
107.13 HighestPowerGenericDegreeSymbol
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1797
1798
1798
1798
1798
1799
1799
1799
1799
1800
1800
1801
1801
1801
108 Signed permutations
108.1
SignPermuted . . . . . .
108.2
SignedPermutationMat
108.3
SignedPerm . . . . . . .
108.4
CyclesSignedPerm . . .
108.5
SignedPermListList . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1803
1803
1803
1804
1804
1805
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
109 CHEVIE utility functions – Decimal and complex numbers
1807
109.1
Complex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1807
CONTENTS
109.2
109.3
109.4
109.5
109.6
109.7
109.8
109.9
109.10
109.11
71
Operations for complex numbers
ComplexConjugate . . . . . . . .
IsComplex . . . . . . . . . . . .
evalf . . . . . . . . . . . . . . . .
Rational . . . . . . . . . . . . . .
SetDecimalPrecision . . . . . . .
Operations for decimal numbers
Pi . . . . . . . . . . . . . . . . .
Exp . . . . . . . . . . . . . . . .
IsDecimal . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1808
1808
1808
1809
1809
1810
1810
1810
1811
1811
110 Posets and relations
110.1
TransitiveClosure of incidence matrix
110.2
LcmPartitions . . . . . . . . . . . . .
110.3
GcdPartitions . . . . . . . . . . . . . .
110.4
Poset . . . . . . . . . . . . . . . . . .
110.5
Hasse . . . . . . . . . . . . . . . . . .
110.6
Incidence . . . . . . . . . . . . . . . .
110.7
LinearExtension . . . . . . . . . . . .
110.8
Functions for Posets . . . . . . . . . .
110.9
Partition for posets . . . . . . . . . .
110.10 Restricted for Posets . . . . . . . . . .
110.11 Reversed for Posets . . . . . . . . . .
110.12 IsJoinLattice . . . . . . . . . . . . . .
110.13 IsMeetLattice . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1813
1813
1814
1814
1814
1815
1815
1815
1816
1816
1816
1816
1817
1817
111 The VKCURVE package
1819
111.1
FundamentalGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1822
111.2
PrepareFundamentalGroup . . . . . . . . . . . . . . . . . . . . . . . . . 1823
112 Multivariate polynomials and
112.1
Mvp . . . . . . . . . . . .
112.2
Operations for Mvp . . .
112.3
IsMvp . . . . . . . . . . .
112.4
ScalMvp . . . . . . . . . .
112.5
Variables for Mvp . . . .
112.6
LaurentDenominator . . .
112.7
OnPolynomials . . . . . .
112.8
FactorizeQuadraticForm .
112.9
MvpGcd . . . . . . . . . .
112.10 MvpLcm . . . . . . . . .
112.11 RatFrac . . . . . . . . . .
112.12 Operations for RatFrac .
112.13 IsRatFrac . . . . . . . . .
rational fractions
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1825
1825
1826
1830
1830
1831
1831
1831
1831
1832
1832
1832
1832
1833
113 The VKCURVE functions
1835
113.1
Discy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1835
113.2
ResultantMat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1835
72
CONTENTS
113.3
113.4
113.5
113.6
113.7
113.8
113.9
113.10
113.11
113.12
113.13
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1836
1836
1836
1837
1837
1838
1840
1840
1841
1841
1842
VKCURVE utility functions
BigNorm . . . . . . . . . . . .
DecimalLog . . . . . . . . . . .
ComplexRational . . . . . . . .
Dispersal . . . . . . . . . . . .
ConjugatePresentation . . . . .
TryConjugatePresentation . . .
FindRoots . . . . . . . . . . . .
Cut . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1845
1845
1845
1845
1846
1846
1846
1848
1848
115 Algebra package — finite dimensional algebras
115.1
Digits . . . . . . . . . . . . . . . . . . . . . . . . . . .
115.2
ByDigits . . . . . . . . . . . . . . . . . . . . . . . . .
115.3
SignedCompositions . . . . . . . . . . . . . . . . . . .
115.4
SignedPartitions . . . . . . . . . . . . . . . . . . . . .
115.5
PiPart . . . . . . . . . . . . . . . . . . . . . . . . . . .
115.6
CyclotomicModP . . . . . . . . . . . . . . . . . . . . .
115.7
PiComponent . . . . . . . . . . . . . . . . . . . . . . .
115.8
PiSections . . . . . . . . . . . . . . . . . . . . . . . . .
115.9
PiPrimeSections . . . . . . . . . . . . . . . . . . . . .
115.10 PRank . . . . . . . . . . . . . . . . . . . . . . . . . . .
115.11 PBlocks . . . . . . . . . . . . . . . . . . . . . . . . . .
115.12 Finite-dimensional algebras over fields . . . . . . . . .
115.13 Elements of finite dimensional algebras . . . . . . . .
115.14 Operations for elements of finite dimensional algebras
115.15 IsAlgebraElement for finite dimensional algebras . . .
115.16 IsAbelian for finite dimensional algebras . . . . . . . .
115.17 IsAssociative for finite dimensional algebras . . . . . .
115.18 AlgebraHomomorphismByLinearity . . . . . . . . . .
115.19 SubAlgebra for finite-dimensional algebras . . . . . . .
115.20 CentralizerAlgebra . . . . . . . . . . . . . . . . . . . .
115.21 Center for algebras . . . . . . . . . . . . . . . . . . . .
115.22 Ideals . . . . . . . . . . . . . . . . . . . . . . . . . . .
115.23 QuotientAlgebra . . . . . . . . . . . . . . . . . . . . .
115.24 Radical for algebras . . . . . . . . . . . . . . . . . . .
115.25 RadicalPower . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1851
1851
1851
1852
1852
1852
1852
1853
1853
1853
1854
1854
1854
1855
1855
1856
1856
1856
1856
1857
1857
1857
1858
1858
1858
1858
114 Some
114.1
114.2
114.3
114.4
114.5
114.6
114.7
114.8
NewtonRoot . . . . . . .
SeparateRootsInitialGuess
SeparateRoots . . . . . .
LoopsAroundPunctures .
FollowMonodromy . . . .
ApproxFollowMonodromy
LBraidToWord . . . . . .
BnActsOnFn . . . . . . .
VKQuotient . . . . . . . .
Display for presentations
ShrinkPresentation . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
115.26 LoewyLength . . . . . . . . . . . . . . . . .
115.27 CharTable for algebras . . . . . . . . . . . .
115.28 CharacterDecomposition . . . . . . . . . . .
115.29 Idempotents for finite dimensional algebras
115.30 LeftIndecomposableProjectives . . . . . . .
115.31 CartanMatrix . . . . . . . . . . . . . . . . .
115.32 PolynomialQuotientAlgebra . . . . . . . . .
Group algebras . . . . . . . . . . . . . . . . . . . . .
115.33 GroupAlgebra . . . . . . . . . . . . . . . .
115.34 Augmentation . . . . . . . . . . . . . . . .
Grothendieck Rings . . . . . . . . . . . . . . . . . .
115.35 GrothendieckRing . . . . . . . . . . . . . .
115.36 Degree for elements of Grothendieck rings .
115.37 Solomon algebras . . . . . . . . . . . . . . .
115.38 SolomonAlgebra . . . . . . . . . . . . . . .
115.39 Generalized Solomon algebras . . . . . . . .
115.40 GeneralizedSolomonAlgebra . . . . . . . . .
115.41 SolomonHomomorphism . . . . . . . . . . .
115.42 ZeroHeckeAlgebra . . . . . . . . . . . . . .
115.43 Performance . . . . . . . . . . . . . . . . .
73
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1859
1859
1860
1860
1861
1861
1861
1862
1862
1862
1862
1863
1863
1863
1864
1865
1865
1866
1866
1866
74
CONTENTS
Chapter 1
About GAP
This chapter introduces you to the GAP3 system. It describes how to start GAP3 (you may
have to ask your system administrator to install it correctly) and how to leave it. Then a
step by step introduction should give you an impression of how the GAP3 system works.
Further sections will give an overview about the features of GAP3. After reading this chapter
the reader should know what kind of problems can be handled with GAP3 and how they
can be handled.
There is some repetition in this chapter and much of the material is repeated in later
chapters in a more compact and precise way. Yes, there are even some little inaccuracies
in this chapter simplifying things for better understanding. It should be used as a tutorial
introduction while later chapters form the reference manual.
GAP3 is an interactive system. It continuously executes a read–evaluate–print cycle. Each
expression you type at the keyboard is read by GAP3, evaluated, and then the result is
printed.
The interactive nature of GAP3 allows you to type an expression at the keyboard and see
its value immediately. You can define a function and apply it to arguments to see how
it works. You may even write whole programs containing lots of functions and test them
without leaving the program.
When your program is large it will be more convenient to write it on a file and then read that
file into GAP3. Preparing your functions in a file has several advantages. You can compose
your functions more carefully in a file (with your favorite text editor), you can correct errors
without retyping the whole function and you can keep a copy for later use. Moreover you
can write lots of comments into the program text, which are ignored by GAP3, but are very
useful for human readers of your program text.
GAP3 treats input from a file in the same way that it treats input from the keyboard.
The printed examples in this first chapter encourage you to try running GAP3 on your
computer. This will support your feeling for GAP3 as a tool, which is the leading aim of
this chapter. Do not believe any statement in this chapter so long as you cannot verify it
for your own version of GAP3. You will learn to distinguish between small deviations of the
behavior of your personal GAP3 from the printed examples and serious nonsense.
75
76
CHAPTER 1. ABOUT GAP
Since the printing routines of GAP3 are in some sense machine dependent you will for
instance encounter a different layout of the printed objects in different environments. But
the contents should always be the same.
In case you encounter serious nonsense it is highly recommended that you send a bug report
to gap-forum@samson.math.rwth-aachen.de.
If you read this introduction on-line you should now enter ?> to read the next section.
1.1
About Conventions
Throughout this manual both the input given to GAP3 and the output that GAP3 returns
are printed in typewriter font just as if they were typed at the keyboard.
An italic font is used for keys that have no printed representation, such as e.g. the newline
key and the ctl key. This font is also used for the formal parameters of functions that are
described in later chapters.
A combination like ctl -P means pressing both keys, that is holding the control key ctl and
pressing the key P while ctl is still pressed.
New terms are introduced in bold face.
In most places whitespace characters (i.e. spaces, tabs and newlines) are insignificant
for the meaning of GAP3 input. Identifiers and keywords must however not contain any
whitespace. On the other hand, sometimes there must be whitespace around identifiers and
keywords to separate them from each other and from numbers. We will use whitespace to
format more complicated commands for better readability.
A comment in GAP3 starts with the symbol # and continues to the end of the line. Comments are treated like whitespace by GAP3.
Besides of such comments which are part of the input of a GAP3 session, we use additional
comments which are part of the manual description, but not of the respective GAP3 session.
In the printed version of this manual these comments will be printed in a normal font for
better readability, hence they start with the symbol #.
The examples of GAP3 sessions given in any particular chapter of this manual have been
run in one continuous session, starting with the two commands
SizeScreen( [ 72, ] );
LogTo( "erg.log" );
which are used to set the line length to 72 and to save a listing of the session on some file.
If you choose any chapter and rerun its examples in the given order, you should be able to
reproduce our results except of a few lines of output which we have edited a little bit with
respect to blanks or line breaks in order to improve the readability. However, as soon as
random processes are involved, you may get different results if you extract single examples
and run them separately.
1.2
About Starting and Leaving GAP
If the program is correctly installed then you start GAP3 by simply typing gap at the prompt
of your operating system followed by the return or the newline key.
$ gap
1.3. ABOUT FIRST STEPS
77
GAP3 answers your request with its beautiful banner (which you can surpress with the
command line option -b) and then it shows its own prompt gap> asking you for further
input.
gap>
The usual way to end a GAP3 session is to type quit; at the gap> prompt. Do not omit
the semicolon!
gap> quit;
$
On some systems you may as well type ctl -D to yield the same effect. In any situation GAP3
is ended by typing ctl -C twice within a second.
1.3
About First Steps
A simple calculation with GAP3 is as easy as one can imagine. You type the problem just
after the prompt, terminate it with a semicolon and then pass the problem to the program
with the return key. For example, to multiply the difference between 9 and 7 by the sum of
5 and 6, that is to calculate (9 − 7) ∗ (5 + 6), you type exactly this last sequence of symbols
followed by ; and return.
gap> (9 - 7) * (5 + 6);
22
gap>
Then GAP3 echoes the result 22 on the next line and shows with the prompt that it is ready
for the next problem.
If you did omit the semicolon at the end of the line but have already typed return, then
GAP3 has read everything you typed, but does not know that the command is complete.
The program is waiting for further input and indicates this with a partial prompt >. This
little problem is solved by simply typing the missing semicolon on the next line of input.
Then the result is printed and the normal prompt returns.
gap> (9 - 7) * (5 + 6)
> ;
22
gap>
Whenever you see this partial prompt and you cannot decide what GAP3 is still waiting for,
then you have to type semicolons until the normal prompt returns.
In every situation this is the exact meaning of the prompt gap> : the program is waiting
for a new problem. In the following examples we will omit this prompt on the line after the
result. Considering each example as a continuation of its predecessor this prompt occurs in
the next example.
In this section you have seen how simple arithmetic problems can be solved by GAP3 by
simply typing them in. You have seen that it doesn’t matter whether you complete your
input on one line. GAP3 reads your input line by line and starts evaluating if it has seen
the terminating semicolon and return.
It is, however, also possible (and might be advisable for large amounts of input data) to
write your input first into a file, and then read this into GAP3; see 3.23 and 3.12 for this.
Also in GAP3, there is the possibility to edit the input data, see 3.4.
78
1.4
CHAPTER 1. ABOUT GAP
About Help
The contents of the GAP3 manual is also available as on-line help, see 3.5–3.11. If you need
information about a section of the manual, just enter a question mark followed by the header
of the section. E.g., entering ?About Help will print the section you are reading now.
??topic will print all entries in GAP3’s index that contain the substring topic.
1.5
About Syntax Errors
Even if you mistyped the command you do not have to type it all again as GAP3 permits a lot
of command line editing. Maybe you mistyped or forgot the last closing parenthesis. Then
your command is syntactically incorrect and GAP3 will notice it, incapable of computing
the desired result.
gap> (9 - 7) * (5 + 6;
Syntax error: ) expected
(9 - 7) * (5 + 6;
^
Instead of the result an error message occurs indicating the place where an unexpected
symbol occurred with an arrow sign ^ under it. As a computer program cannot know what
your intentions really were, this is only a hint. But in this case GAP3 is right by claiming
that there should be a closing parenthesis before the semicolon. Now you can type ctl -P
to recover the last line of input. It will be written after the prompt with the cursor in the
first position. Type ctl -E to take the cursor to the end of the line, then ctl -B to move the
cursor one character back. The cursor is now on the position of the semicolon. Enter the
missing parenthesis by simply typing ). Now the line is correct and may be passed to GAP3
by hitting the newline key. Note that for this action it is not necessary to move the cursor
past the last character of the input line.
Each line of commands you type is sent to GAP3 for evaluation by pressing newline regardless
of the position of the cursor in that line. We will no longer mention the newline key from
now on.
Sometimes a syntax error will cause GAP3 to enter a break loop. This is indicated by the
special prompt brk>. You can leave the break loop by either typing return; or by hitting
ctl -D. Then GAP3 will return to its normal state and show its normal prompt again.
In this section you learned that mistyped input will not lead to big confusion. If GAP3
detects a syntax error it will print an error message and return to its normal state. The
command line editing allows you in a comfortable way to manipulate earlier input lines.
For the definition of the GAP3 syntax see chapter 2. A complete list of command line editing
facilities is found in 3.4. The break loop is described in 3.2.
1.6
About Constants and Operators
In an expression like (9 - 7) * (5 + 6) the constants 5, 6, 7, and 9 are being composed
by the operators +, * and - to result in a new value.
There are three kinds of operators in GAP3, arithmetical operators, comparison operators,
and logical operators. You have already seen that it is possible to form the sum, the
1.6. ABOUT CONSTANTS AND OPERATORS
79
difference, and the product of two integer values. There are some more operators applicable
to integers in GAP3. Of course integers may be divided by each other, possibly resulting in
noninteger rational values.
gap> 12345/25;
2469/5
Note that the numerator and denominator are divided by their greatest common divisor
and that the result is uniquely represented as a division instruction.
We haven’t met negative numbers yet. So consider the following self–explanatory examples.
gap> -3; 17 - 23;
-3
-6
The exponentiation operator is written as ^. This operation in particular might lead to very
large numbers. This is no problem for GAP3 as it can handle numbers of (almost) arbitrary
size.
gap> 3^132;
955004950796825236893190701774414011919935138974343129836853841
The mod operator allows you to compute one value modulo another.
gap> 17 mod 3;
2
Note that there must be whitespace around the keyword mod in this example since 17mod3
or 17mod would be interpreted as identifiers.
GAP3 knows a precedence between operators that may be overridden by parentheses.
gap> (9 - 7) * 5 = 9 - 7
false
* 5;
Besides these arithmetical operators there are comparison operators in GAP3. A comparison
results in a boolean value which is another kind of constant. Every two objects within
GAP3 are comparable via =, <>, <, <=, > and >=, that is the tests for equality, inequality,
less than, less than or equal, greater than and greater than or equal. There is an ordering
defined on the set of all GAP3 objects that respects orders on subsets that one might expect.
For example the integers are ordered in the usual way.
gap> 10^5 < 10^4;
false
The boolean values true and false can be manipulated via logical operators, i. e., the
unary operator not and the binary operators and and or. Of course boolean values can be
compared, too.
gap> not true; true and false; true or false;
false
false
true
gap> 10 > 0 and 10 < 100;
true
Another important type of constants in GAP3 are permutations. They are written in cycle
notation and they can be multiplied.
80
CHAPTER 1. ABOUT GAP
gap> (1,2,3);
(1,2,3)
gap> (1,2,3) * (1,2);
(2,3)
The inverse of the permutation (1,2,3) is denoted by (1,2,3)^-1. Moreover the caret
operator ^ is used to determine the image of a point under a permutation and to conjugate
one permutation by another.
gap> (1,2,3)^-1;
(1,3,2)
gap> 2^(1,2,3);
3
gap> (1,2,3)^(1,2);
(1,3,2)
The last type of constants we want to introduce here are the characters, which are simply
objects in GAP3 that represent arbitrary characters from the character set of the operating
system. Character literals can be entered in GAP3 by enclosing the character in singlequotes ’.
gap> ’a’;
’a’
gap> ’*’;
’*’
There are no operators defined for characters except that characters can be compared.
In this section you have seen that values may be preceded by unary operators and combined
by binary operators placed between the operands. There are rules for precedence which
may be overridden by parentheses. It is possible to compare any two objects. A comparison
results in a boolean value. Boolean values are combined via logical operators. Moreover you
have seen that GAP3 handles numbers of arbitrary size. Numbers and boolean values are
constants. There are other types of constants in GAP3 like permutations. You are now in a
position to use GAP3 as a simple desktop calculator.
Operators are explained in more detail in 2.9 and 2.10. Moreover there are sections about
operators and comparisons for special types of objects in almost every chapter of this manual.
You will find more information about boolean values in chapters 45 and 29. Permutations
are described in chapter 20 and characters are described in chapter 30.
1.7
About Variables and Assignments
Values may be assigned to variables. A variable enables you to refer to an object via a name.
The name of a variable is called an identifier. The assignment operator is :=. There must
be no white space between the : and the =. Do not confuse the assignment operator :=
with the single equality sign = which is in GAP3 only used for the test of equality.
gap> a:= (9 - 7) * (5 + 6);
22
gap> a;
22
gap> a * (a + 1);
1.7. ABOUT VARIABLES AND ASSIGNMENTS
81
506
gap> a:= 10;
10
gap> a * (a + 1);
110
After an assignment the assigned value is echoed on the next line. The printing of the value
of a statement may be in every case prevented by typing a double semicolon.
gap> w:= 2;;
After the assignment the variable evaluates to that value if evaluated. Thus it is possible to
refer to that value by the name of the variable in any situation.
This is in fact the whole secret of an assignment. An identifier is bound to a value and
from this moment points to that value. Nothing more. This binding is changed by the next
assignment to that identifier. An identifier does not denote a block of memory as in some
other programming languages. It simply points to a value, which has been given its place
in memory by the GAP3 storage manager. This place may change during a GAP3 session,
but that doesn’t bother the identifier.
The identifier points to the value, not to a place in the memory.
For the same reason it is not the identifier that has a type but the object. This means on
the other hand that the identifier a which now is bound to an integer value may in the same
session point to any other value regardless of its type.
Identifiers may be sequences of letters and digits containing at least one letter. For example
abc and a0bc1 are valid identifiers. But also 123a is a valid identifier as it cannot be
confused with any number. Just 1234 indicates the number 1234 and cannot be at the same
time the name of a variable.
Since GAP3 distinguishes upper and lower case, a1 and A1 are different identifiers. Keywords
such as quit must not be used as identifiers. You will see more keywords in the following
sections.
In the remaining part of this manual we will ignore the difference between variables, their
names (identifiers), and the values they point at. It may be useful to think from time to
time about what is really meant by terms such as the integer w.
There are some predefined variables coming with GAP3. Many of them you will find in the
remaining chapters of this manual, since functions are also referred to via identifiers.
This seems to be the right place to state the following rule.
The name of every function in the GAP3 library starts with a capital letter.
Thus if you choose only names starting with a small letter for your own variables you will
not overwrite any predefined function.
But there are some further interesting variables one of which shall be introduced now.
Whenever GAP3 returns a value by printing it on the next line this value is assigned to the
variable last. So if you computed
gap> (9 - 7) * (5 + 6);
22
and forgot to assign the value to the variable a for further use, you can still do it by the
following assignment.
82
CHAPTER 1. ABOUT GAP
gap> a:= last;
22
Moreover there are variables last2 and last3, guess their values.
In this section you have seen how to assign values to variables. These values can later
be accessed through the name of the variable, its identifier. You have also encountered the
useful concept of the last variables storing the latest returned values. And you have learned
that a double semicolon prevents the result of a statement from being printed.
Variables and assignments are described in more detail in 2.7 and 2.12. A complete list of
keywords is contained in 2.4.
1.8
About Functions
A program written in the GAP3 language is called a function. Functions are special GAP3
objects. Most of them behave like mathematical functions. They are applied to objects and
will return a new object depending on the input. The function Factorial, for example, can
be applied to an integer and will return the factorial of this integer.
gap> Factorial(17);
355687428096000
Applying a function to arguments means to write the arguments in parentheses following
the function. Several arguments are separated by commas, as for the function Gcd which
computes the greatest common divisor of two integers.
gap> Gcd(1234, 5678);
2
There are other functions that do not return a value but only produce a side effect. They
change for example one of their arguments. These functions are sometimes called procedures.
The function Print is only called for the side effect to print something on the screen.
gap> Print(1234, "\n");
1234
In order to be able to compose arbitrary text with Print, this function itself will not produce
a line break after printing. Thus we had another newline character "\n" printed to start a
new line.
Some functions will both change an argument and return a value such as the function Sortex
that sorts a list and returns the permutation of the list elements that it has performed.
You will not understand right now what it means to change an object. We will return to
this subject several times in the next sections.
A comfortable way to define a function is given by the maps–to operator -> consisting of a
minus sign and a greater sign with no whitespace between them. The function cubed which
maps a number to its cube is defined on the following line.
gap> cubed:= x -> x^3;
function ( x ) ... end
After the function has been defined, it can now be applied.
gap> cubed(5);
125
1.9. ABOUT LISTS
83
Not every GAP3 function can be defined in this way. You will see how to write your own
GAP3 functions in a later section.
In this section you have seen GAP3 objects of type function. You have learned how to apply
a function to arguments. This yields as result a new object or a side effect. A side effect
may change an argument of the function. Moreover you have seen an easy way to define a
function in GAP3 with the maps-to operator.
Function calls are described in 2.8 and in 2.13. The functions of the GAP3 library are
described in detail in the remaining chapters of this manual, the Reference Manual.
1.9
About Lists
A list is a collection of objects separated by commas and enclosed in brackets. Let us for
example construct the list primes of the first 10 prime numbers.
gap> primes:= [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
The next two primes are 31 and 37. They may be appended to the existing list by the function Append which takes the existing list as its first and another list as a second argument.
The second argument is appended to the list primes and no value is returned. Note that
by appending another list the object primes is changed.
gap> Append(primes, [31, 37]);
gap> primes;
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 ]
You can as well add single new elements to existing lists by the function Add which takes
the existing list as its first argument and a new element as its second argument. The new
element is added to the list primes and again no value is returned but the list primes is
changed.
gap> Add(primes, 41);
gap> primes;
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ]
Single elements of a list are referred to by their position in the list. To get the value of the
seventh prime, that is the seventh entry in our list primes, you simply type
gap> primes[7];
17
and you will get the value of the seventh prime. This value can be handled like any other
value, for example multiplied by 2 or assigned to a variable. On the other hand this mechanism allows to assign a value to a position in a list. So the next prime 43 may be inserted
in the list directly after the last occupied position of primes. This last occupied position is
returned by the function Length.
gap>
13
gap>
43
gap>
[ 2,
Length(primes);
primes[14]:= 43;
primes;
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43 ]
84
CHAPTER 1. ABOUT GAP
Note that this operation again has changed the object primes. Not only the next position
of a list is capable of taking a new value. If you know that 71 is the 20th prime, you can as
well enter it right now in the 20th position of primes. This will result in a list with holes
which is however still a list and has length 20 now.
gap>
71
gap>
[ 2,
gap>
20
primes[20]:= 71;
primes;
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,,,,,, 71 ]
Length(primes);
The list itself however must exist before a value can be assigned to a position of the list.
This list may be the empty list [ ].
gap> lll[1]:= 2;
Error, Variable: ’lll’ must have a value
gap> lll:= [];
[ ]
gap> lll[1]:= 2;
2
Of course existing entries of a list can be changed by this mechanism, too. We will not do
it here because primes then may no longer be a list of primes. Try for yourself to change
the 17 in the list into a 9.
To get the position of 17 in the list primes use the function Position which takes the list
as its first argument and the element as its second argument and returns the position of
the first occurrence of the element 17 in the list primes. Position will return false if the
element is not contained in the list.
gap> Position(primes, 17);
7
gap> Position(primes, 20);
false
In all of the above changes to the list primes, the list has been automatically resized. There
is no need for you to tell GAP3 how big you want a list to be. This is all done dynamically.
It is not necessary for the objects collected in a list to be of the same type.
gap> lll:= [true, "This is a String",,, 3];
[ true, "This is a String",,, 3 ]
In the same way a list may be part of another list. A list may even be part of itself.
gap> lll[3]:=
[ true, "This
gap> lll[4]:=
[ true, "This
[4,5,6];; lll;
is a String", [ 4, 5, 6 ],, 3 ]
lll;
is a String", [ 4, 5, 6 ], ~, 3 ]
Now the tilde ~ in the fourth position of lll denotes the object that is currently printed.
Note that the result of the last operation is the actual value of the object lll on the right
hand side of the assignment. But in fact it is identical to the value of the whole list lll on
the left hand side of the assignment.
1.10. ABOUT IDENTICAL LISTS
85
A string is a very special type of list, which is printed in a different way. A string is simply
a dense list of characters. Strings are used mainly in filenames and error messages. A string
literal can either be entered simply as the list of characters or by writing the characters
between doublequotes ". GAP will always output strings in the latter format.
gap> s1 := [’H’,’a’,’l’,’l’,’o’,’ ’,’w’,’o’,’r’,’l’,’d’,’.’];
"Hallo world."
gap> s2 := "Hallo world.";
"Hallo world."
gap> s1 := [’H’,’a’,’l’,’l’,’o’,’ ’,’w’,’o’,’r’,’l’,’d’,’.’];
"Hallo world."
gap> s1 = s2;
true
gap> s2[7];
’w’
Sublists of lists can easily be extracted and assigned using the operator { }.
gap> sl := lll{ [ 1, 2, 3 ] };
[ true, "This is a String", [ 4, 5, 6 ] ]
gap> sl{ [ 2, 3 ] } := [ "New String", false ];
[ "New String", false ]
gap> sl;
[ true, "New String", false ]
This way you get a new list that contains at position i that element whose position is the
i th entry of the argument of { }.
In this long section you have encountered the fundamental concept of a list. You have
seen how to construct lists, how to extend them and how to refer to single elements of a
list. Moreover you have seen that lists may contain elements of different types, even holes
(unbound entries). But this is still not all we have to tell you about lists.
You will find a discussion about identity and equality of lists in the next section. Moreover
you will see special kinds of lists like sets (in 1.11), vectors and matrices (in 1.12) and ranges
(in 1.14). Strings are described in chapter 30.
1.10
About Identical Lists
This second section about lists is dedicated to the subtle difference between equality and
identity of lists. It is really important to understand this difference in order to understand
how complex data structures are realized in GAP3. This section applies to all GAP3 objects
that have subobjects, i. e., to lists and to records. After reading the section about records
(1.13) you should return to this section and translate it into the record context.
Two lists are equal if all their entries are equal. This means that the equality operator =
returns true for the comparison of two lists if and only if these two lists are of the same
length and for each position the values in the respective lists are equal.
gap> numbers:= primes;
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,,,,,, 71 ]
gap> numbers = primes;
true
86
CHAPTER 1. ABOUT GAP
We assigned the list primes to the variable numbers and, of course they are equal as they
have both the same length and the same entries. Now we will change the third number to
4 and compare the result again with primes.
gap> numbers[3]:= 4;
4
gap> numbers = primes;
true
You see that numbers and primes are still equal, check this by printing the value of primes.
The list primes is no longer a list of primes! What has happened? The truth is that the lists
primes and numbers are not only equal but they are identical. primes and numbers are two
variables pointing to the same list. If you change the value of the subobject numbers[3] of
numbers this will also change primes. Variables do not point to a certain block of storage
memory but they do point to an object that occupies storage memory. So the assignment
numbers:= primes did not create a new list in a different place of memory but only created
the new name numbers for the same old list of primes.
The same object can have several names.
If you want to change a list with the contents of primes independently from primes you will
have to make a copy of primes by the function Copy which takes an object as its argument
and returns a copy of the argument. (We will first restore the old value of primes.)
gap> primes[3]:= 5;
5
gap> primes;
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,,,,,, 71 ]
gap> numbers:= Copy(primes);
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,,,,,, 71 ]
gap> numbers = primes;
true
gap> numbers[3]:= 4;
4
gap> numbers = primes;
false
Now numbers is no longer equal to primes and primes still is a list of primes. Check this
by printing the values of numbers and primes.
The only objects that can be changed this way are records and lists, because only GAP3
objects of these types have subobjects. To clarify this statement consider the following
example.
gap> i:= 1;; j:= i;; i:= i+1;;
By adding 1 to i the value of i has changed. What happens to j? After the second
statement j points to the same object as i, namely to the integer 1. The addition does
not change the object 1 but creates a new object according to the instruction i+1. It is
actually the assignment that changes the value of i. Therefore j still points to the object
1. Integers (like permutations and booleans) have no subobjects. Objects of these types
cannot be changed but can only be replaced by other objects. And a replacement does not
change the values of other variables. In the above example an assignment of a new value to
the variable numbers would also not change the value of primes.
1.11. ABOUT SETS
87
Finally try the following examples and explain the results.
gap> l:= [];
[ ]
gap> l:= [l];
[ [ ] ]
gap> l[1]:= l;
[ ~ ]
Now return to the preceding section 1.9 and find out whether the functions Add and Append
change their arguments.
In this section you have seen the difference between equal lists and identical lists. Lists are
objects that have subobjects and therefore can be changed. Changing an object will change
the values of all variables that point to that object. Be careful, since one object can have
several names. The function Copy creates a copy of a list which is then a new object.
You will find more about lists in chapter 27, and more about identical lists in 27.9.
1.11
About Sets
GAP3 knows several special kinds of lists. A set in GAP3 is a special kind of list. A set
contains no holes and its elements are sorted according to the GAP3 ordering of all its
objects. Moreover a set contains no object twice.
The function IsSet tests whether an object is a set. It returns a boolean value. For any list
there exists a corresponding set. This set is constructed by the function Set which takes the
list as its argument and returns a set obtained from this list by ignoring holes and duplicates
and by sorting the elements.
The elements of the sets used in the examples of this section are strings.
gap> fruits:= ["apple", "strawberry", "cherry", "plum"];
[ "apple", "strawberry", "cherry", "plum" ]
gap> IsSet(fruits);
false
gap> fruits:= Set(fruits);
[ "apple", "cherry", "plum", "strawberry" ]
Note that the original list fruits is not changed by the function Set. We have to make a
new assignment to the variable fruits in order to make it a set.
The in operator is used to test whether an object is an element of a set. It returns a boolean
value true or false.
gap> "apple" in fruits;
true
gap> "banana" in fruits;
false
The in operator may as well be applied to ordinary lists. It is however much faster to
perform a membership test for sets since sets are always sorted and a binary search can be
used instead of a linear search.
New elements may be added to a set by the function AddSet which takes the set fruits as
its first argument and an element as its second argument and adds the element to the set if
it wasn’t already there. Note that the object fruits is changed.
88
CHAPTER 1. ABOUT GAP
gap> AddSet(fruits, "banana");
gap> fruits;
# The banana is inserted in the right place.
[ "apple", "banana", "cherry", "plum", "strawberry" ]
gap> AddSet(fruits, "apple");
gap> fruits;
# fruits has not changed.
[ "apple", "banana", "cherry", "plum", "strawberry" ]
Sets can be intersected by the function Intersection and united by the function Union
which both take two sets as their arguments and return the intersection (union) of the two
sets as a new object.
gap> breakfast:= ["tea", "apple", "egg"];
[ "tea", "apple", "egg" ]
gap> Intersection(breakfast, fruits);
[ "apple" ]
It is however not necessary for the objects collected in a set to be of the same type. You
may as well have additional integers and boolean values for breakfast.
The arguments of the functions Intersection and Union may as well be ordinary lists,
while their result is always a set. Note that in the preceding example at least one argument
of Intersection was not a set.
The functions IntersectSet and UniteSet also form the intersection resp. union of two
sets. They will however not return the result but change their first argument to be the
result. Try them carefully.
In this section you have seen that sets are a special kind of list. There are functions to
expand sets, intersect or unite sets, and there is the membership test with the in operator.
A more detailed description of strings is contained in chapter 30. Sets are described in more
detail in chapter 28.
1.12
About Vectors and Matrices
A vector is a list of elements from a common field. A matrix is a list of vectors of equal
length. Vectors and matrices are special kinds of lists without holes.
gap> v:= [3, 6, 2, 5/2];
[ 3, 6, 2, 5/2 ]
gap> IsVector(v);
true
Vectors may be multiplied by scalars from their field. Multiplication of vectors of equal
length results in their scalar product.
gap> 2 * v;
[ 6, 12, 4, 5 ]
gap> v * 1/3;
[ 1, 2, 2/3, 5/6 ]
gap> v * v;
221/4 # the scalar product of v with itself
Note that the expression v * 1/3 is actually evaluated by first multiplying v by 1 (which
yields again v) and by then dividing by 3. This is also an allowed scalar operation. The
expression v/3 would result in the same value.
1.12. ABOUT VECTORS AND MATRICES
89
A matrix is a list of vectors of equal length.
gap> m:= [[1, -1, 1],
>
[2, 0, -1],
>
[1, 1, 1]];
[ [ 1, -1, 1 ], [ 2, 0, -1 ], [ 1, 1, 1 ] ]
gap> m[2][1];
2
Syntactically a matrix is a list of lists. So the number 2 in the second row and the first
column of the matrix m is referred to as the first element of the second element of the list m
via m[2][1].
A matrix may be multiplied by scalars, vectors and other matrices. The vectors and matrices
involved in such a multiplication must however have suitable dimensions.
gap> m:= [[1, 2, 3, 4],
>
[5, 6, 7, 8],
>
[9,10,11,12]];
[ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]
gap> PrintArray(m);
[ [
1,
2,
3,
4 ],
[
5,
6,
7,
8 ],
[
9, 10, 11, 12 ] ]
gap> [1, 0, 0, 0] * m;
Error, Vector *: vectors must have the same length
gap> [1, 0, 0] * m;
[ 1, 2, 3, 4 ]
gap> m * [1, 0, 0];
Error, Vector *: vectors must have the same length
gap> m * [1, 0, 0, 0];
[ 1, 5, 9 ]
gap> m * [0, 1, 0, 0];
[ 2, 6, 10 ]
Note that multiplication of a vector with a matrix will result in a linear combination of
the rows of the matrix, while multiplication of a matrix with a vector results in a linear
combination of the columns of the matrix. In the latter case the vector is considered as a
column vector.
Submatrices can easily be extracted and assigned using the { }{ } operator.
gap> sm := m{
[ [ 3, 4 ], [
gap> sm{ [ 1,
[ [ 1 ], [ -1
gap> sm;
[ [ 3, 1 ], [
[ 1, 2 ] }{ [ 3, 4 ] };
7, 8 ] ]
2 ] }{ [2] } := [[1],[-1]];
] ]
7, -1 ] ]
The first curly brackets contain the selection of rows, the second that of columns.
In this section you have met vectors and matrices as special lists. You have seen how to
refer to elements of a matrix and how to multiply scalars, vectors, and matrices.
90
CHAPTER 1. ABOUT GAP
Fields are described in chapter 6. The known fields in GAP3 are described in chapters 12,
13, 14, 15 and 18. Vectors and matrices are described in more detail in chapters 32 and 34.
Vector spaces are described in chapter 9 and further matrix related structures are described
in chapters 36 and 37.
1.13
About Records
A record provides another way to build new data structures. Like a list a record is a
collection of other objects. In a record the elements are not indexed by numbers but by
names (i.e., identifiers). An entry in a record is called a record component (or sometimes
also record field).
gap> date:= rec(year:= 1992,
>
month:= "Jan",
>
day:= 13);
rec(
year := 1992,
month := "Jan",
day := 13 )
Initially a record is defined as a comma separated list of assignments to its record components. Then the value of a record component is accessible by the record name and the
record component name separated by one dot as the record component selector.
gap> date.year;
1992
gap> date.time:= rec(hour:= 19, minute:= 23, second:= 12);
rec(
hour := 19,
minute := 23,
second := 12 )
gap> date;
rec(
year := 1992,
month := "Jan",
day := 13,
time := rec(
hour := 19,
minute := 23,
second := 12 ) )
Assignments to new record components are possible in the same way. The record is automatically resized to hold the new component.
Most of the complex structures that are handled by GAP3 are represented as records, for
instance groups and character tables.
Records are objects that may be changed. An assignment to a record component changes
the original object. There are many functions in the library that will do such assignments to
a record component of one of their arguments. The function Size for example, will compute
the size of its argument which may be a group for instance, and then store the value in the
1.14. ABOUT RANGES
91
record component size. The next call of Size for this object will use this stored value
rather than compute it again.
Lists and records are the only types of GAP3 objects that can be changed.
Sometimes it is interesting to know which components of a certain record are bound. This
information is available from the function RecFields (yes, this function should be called
RecComponentNames), which takes a record as its argument and returns a list of all bound
components of this record as a list of strings.
gap> RecFields(date);
[ "year", "month", "day", "time" ]
Finally try the following examples and explain the results.
gap> r:= rec();
rec(
)
gap> r:= rec(r:= r);
rec(
r := rec(
) )
gap> r.r:= r;
rec(
r := ~ )
Now return to section 1.10 and find out what that section means for records.
In this section you have seen how to define and how to use records. Record objects are
changed by assignments to record fields. Lists and records are the only types of objects that
can be changed.
Records and functions for records are described in detail in chapter 46. More about identical
records is found in 46.3.
1.14
About Ranges
A range is a finite sequence of integers. This is another special kind of list. A range is
described by its minimum (the first entry), its second entry and its maximum, separated by
a comma resp. two dots and enclosed in brackets. In the usual case of an ascending list of
consecutive integers the second entry may be omitted.
gap> [1..999999];
# a range of almost a million numbers
[ 1 .. 999999 ]
gap> [1, 2..999999]; # this is equivalent
[ 1 .. 999999 ]
gap> [1, 3..999999]; # here the step is 2
[ 1, 3 .. 999999 ]
gap> Length( last );
500000
gap> [ 999999, 999997 .. 1 ];
[ 999999, 999997 .. 1 ]
This compact printed representation of a fairly long list corresponds to a compact internal
representation. The function IsRange tests whether an object is a range. If this is true for
92
CHAPTER 1. ABOUT GAP
a list but the list is not yet represented in the compact form of a range this will be done
then.
gap> a:= [-2,-1,0,1,2,3,4,5];
[ -2, -1, 0, 1, 2, 3, 4, 5 ]
gap> IsRange(a);
true
gap> a;
[ -2 .. 5 ]
gap> a[5];
2
gap> Length(a);
8
Note that this change of representation does not change the value of the list a. The list a
still behaves in any context in the same way as it would have in the long representation.
In this section you have seen that ascending lists of consecutive integers can be represented
in a compact way as ranges.
Chapter 31 contains a detailed description of ranges. A fundamental application of ranges
is introduced in the next section.
1.15
About Loops
Given a list pp of permutations we can form their product by means of a for loop instead
of writing down the product explicitly.
gap> pp:= [ (1,3,2,6,8)(4,5,9), (1,6)(2,7,8)(4,9), (1,5,7)(2,3,8,6),
>
(1,8,9)(2,3,5,6,4), (1,9,8,6,3,4,7,2) ];;
gap> prod:= ();
()
gap> for p in pp do
>
prod:= prod * p;
>
od;
gap> prod;
(1,8,4,2,3,6,5)
First a new variable prod is initialized to the identity permutation (). Then the loop variable
p takes as its value one permutation after the other from the list pp and is multiplied with
the present value of prod resulting in a new value which is then assigned to prod.
The for loop has the following syntax.
for var in list do statements od;
The effect of the for loop is to execute the statements for every element of the list. A
for loop is a statement and therefore terminated by a semicolon. The list of statements is
enclosed by the keywords do and od (reverse do). A for loop returns no value. Therefore
we had to ask explicitly for the value of prod in the preceding example.
The for loop can loop over any kind of list, even a list with holes. In many programming
languages (and in former versions of GAP3, too) the for loop has the form
for var from first to last do statements od;
1.15. ABOUT LOOPS
93
But this is merely a special case of the general for loop as defined above where the list in
the loop body is a range.
for var in [first..last] do statements od;
You can for instance loop over a range to compute the factorial 15! of the number 15 in the
following way.
gap> ff:= 1;
1
gap> for i in [1..15] do
>
ff:= ff * i;
>
od;
gap> ff;
1307674368000
The following example introduces the while loop which has the following syntax.
while condition do statements od;
The while loop loops over the statements as long as the condition evaluates to true. Like
the for loop the while loop is terminated by the keyword od followed by a semicolon.
We can use our list primes to perform a very simple factorization. We begin by initializing a
list factors to the empty list. In this list we want to collect the prime factors of the number
1333. Remember that a list has to exist before any values can be assigned to positions of
the list. Then we will loop over the list primes and test for each prime whether it divides
the number. If it does we will divide the number by that prime, add it to the list factors
and continue.
gap> n:= 1333;
1333
gap> factors:= [];
[ ]
gap> for p in primes do
>
while n mod p = 0 do
>
n:= n/p;
>
Add(factors, p);
>
od;
>
od;
gap> factors;
[ 31, 43 ]
gap> n;
1
As n now has the value 1 all prime factors of 1333 have been found and factors contains
a complete factorization of 1333. This can of course be verified by multiplying 31 and 43.
This loop may be applied to arbitrary numbers in order to find prime factors. But as primes
is not a complete list of all primes this loop may fail to find all prime factors of a number
greater than 2000, say. You can try to improve it in such a way that new primes are added
to the list primes if needed.
You have already seen that list objects may be changed. This holds of course also for the
list in a loop body. In most cases you have to be careful not to change this list, but there are
94
CHAPTER 1. ABOUT GAP
situations where this is quite useful. The following example shows a quick way to determine
the primes smaller than 1000 by a sieve method. Here we will make use of the function
Unbind to delete entries from a list.
gap> primes:= [];
[ ]
gap> numbers:= [2..1000];
[ 2 .. 1000 ]
gap> for p in numbers do
>
Add(primes, p);
>
for n in numbers do
>
if n mod p = 0 then
>
Unbind(numbers[n-1]);
>
fi;
>
od;
>
od;
The inner loop removes all entries from numbers that are divisible by the last detected
prime p. This is done by the function Unbind which deletes the binding of the list position
numbers[n-1] to the value n so that afterwards numbers[n-1] no longer has an assigned
value. The next element encountered in numbers by the outer loop necessarily is the next
prime.
In a similar way it is possible to enlarge the list which is looped over. This yields a nice and
short orbit algorithm for the action of a group, for example.
In this section you have learned how to loop over a list by the for loop and how to loop
with respect to a logical condition with the while loop. You have seen that even the list in
the loop body can be changed.
The for loop is described in 2.17. The while loop is described in 2.15.
1.16
About Further List Operations
There is however a more comfortable way to compute the product of a list of numbers or
permutations.
gap> Product([1..15]);
1307674368000
gap> Product(pp);
(1,8,4,2,3,6,5)
The function Product takes a list as its argument and computes the product of the elements
of the list. This is possible whenever a multiplication of the elements of the list is defined.
So Product is just an implementation of the loop in the example above as a function.
There are other often used loops available as functions. Guess what the function Sum does.
The function List may take a list and a function as its arguments. It will then apply the
function to each element of the list and return the corresponding list of results. A list of
cubes is produced as follows with the function cubed from 1.8.
gap> List([2..10], cubed);
[ 8, 27, 64, 125, 216, 343, 512, 729, 1000 ]
1.17. ABOUT WRITING FUNCTIONS
95
To add all these cubes we might apply the function Sum to the last list. But we may as well
give the function cubed to Sum as an additional argument.
gap> Sum(last) = Sum([2..10], cubed);
true
The primes less than 30 can be retrieved out of the list primes from section 1.9 by the
function Filtered. This function takes the list primes and a property as its arguments and
will return the list of those elements of primes which have this property. Such a property
will be represented by a function that returns a boolean value. In this example the property
of being less than 30 can be reresented by the function x-> x <30 since x <30 will evaluate
to true for values x less than 30 and to false otherwise.
gap> Filtered(primes, x-> x < 30);
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
Another useful thing is the operator { } that forms sublists. It takes a list of positions as
its argument and will return the list of elements from the original list corresponding to these
positions.
gap> primes{ [1 .. 10] };
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
In this section you have seen some functions which implement often used for loops. There
are functions like Product to form the product of the elements of a list. The function List
can apply a function to all elements of a list and the functions Filtered and Sublist create
sublists of a given list.
You will find more predefined for loops in chapter 27.
1.17
About Writing Functions
You have already seen how to use the functions of the GAP3 library, i.e., how to apply them
to arguments. This section will show you how to write your own functions.
Writing a function that prints hello, world. on the screen is a simple exercise in GAP3.
gap> sayhello:= function()
> Print("hello, world.\n");
> end;
function ( ) ... end
This function when called will only execute the Print statement in the second line. This
will print the string hello, world. on the screen followed by a newline character \n that
causes the GAP3 prompt to appear on the next line rather than immediately following the
printed characters.
The function definition has the following syntax.
function(arguments) statements end
A function definition starts with the keyword function followed by the formal parameter
list arguments enclosed in parenthesis. The formal parameter list may be empty as in
the example. Several parameters are separated by commas. Note that there must be no
semicolon behind the closing parenthesis. The function definition is terminated by the
keyword end.
96
CHAPTER 1. ABOUT GAP
A GAP3 function is an expression like integers, sums and lists. It therefore may be assigned
to a variable. The terminating semicolon in the example does not belong to the function
definition but terminates the assignment of the function to the name sayhello. Unlike in
the case of integers, sums, and lists the value of the function sayhello is echoed in the
abbreviated fashion function ( ) ... end. This shows the most interesting part of a
function: its formal parameter list (which is empty in this example). The complete value of
sayhello is returned if you use the function Print.
gap> Print(sayhello, "\n");
function ( )
Print( "hello, world.\n" );
end
Note the additional newline character "\n" in the Print statement. It is printed after the
object sayhello to start a new line.
The newly defined function sayhello is executed by calling sayhello() with an empty
argument list.
gap> sayhello();
hello, world.
This is however not a typical example as no value is returned but only a string is printed.
A more useful function is given in the following example. We define a function sign which
shall determine the sign of a number.
gap> sign:= function(n)
>
if n < 0 then
>
return -1;
>
elif n = 0 then
>
return 0;
>
else
>
return 1;
>
fi;
>
end;
function ( n ) ... end
gap> sign(0); sign(-99); sign(11);
0
-1
1
gap> sign("abc");
1
# strings are defined to be greater than 0
This example also introduces the if statement which is used to execute statements depending on a condition. The if statement has the following syntax.
if condition then statements elif condition then statements else statements fi;
There may be several elif parts. The elif part as well as the else part of the if statement
may be omitted. An if statement is no expression and can therefore not be assigned to a
variable. Furthermore an if statement does not return a value.
Fibonacci numbers are defined recursively by f (1) = f (2) = 1 and f (n) = f (n − 1) + f (n −
2). Since functions in GAP3 may call themselves, a function fib that computes Fibonacci
numbers can be implemented basically by typing the above equations.
1.17. ABOUT WRITING FUNCTIONS
97
gap> fib:= function(n)
>
if n in [1, 2] then
>
return 1;
>
else
>
return fib(n-1) + fib(n-2);
>
fi;
>
end;
function ( n ) ... end
gap> fib(15);
610
There should be additional tests for the argument n being a positive integer. This function
fib might lead to strange results if called with other arguments. Try to insert the tests in
this example.
A function gcd that computes the greatest common divisor of two integers by Euclid’s
algorithm will need a variable in addition to the formal arguments.
gap> gcd:= function(a, b)
>
local c;
>
while b <> 0 do
>
c:= b;
>
b:= a mod b;
>
a:= c;
>
od;
>
return c;
>
end;
function ( a, b ) ... end
gap> gcd(30, 63);
3
The additional variable c is declared as a local variable in the local statement of the
function definition. The local statement, if present, must be the first statement of a
function definition. When several local variables are declared in only one local statement
they are separated by commas.
The variable c is indeed a local variable, that is local to the function gcd. If you try to use
the value of c in the main loop you will see that c has no assigned value unless you have
already assigned a value to the variable c in the main loop. In this case the local nature of
c in the function gcd prevents the value of the c in the main loop from being overwritten.
We say that in a given scope an identifier identifies a unique variable. A scope is a lexical
part of a program text. There is the global scope that encloses the entire program text,
and there are local scopes that range from the function keyword, denoting the beginning
of a function definition, to the corresponding end keyword. A local scope introduces new
variables, whose identifiers are given in the formal argument list and the local declaration
of the function. The usage of an identifier in a program text refers to the variable in the
innermost scope that has this identifier as its name.
We will now write a function to determine the number of partitions of a positive integer. A
partition of a positive integer is a descending list of numbers whose sum is the given integer.
For example [4, 2, 1, 1] is a partition of 8. The complete set of all partitions of an integer n
98
CHAPTER 1. ABOUT GAP
may be divided into subsets with respect to the largest element. The number of partitions
of n therefore equals the sum of the numbers of partitions of n − i with elements less than
i for all possible i. More generally the number of partitions of n with elements less than m
is the sum of the numbers of partitions of n − i with elements less than i for i less than m
and n. This description yields the following function.
gap> nrparts:= function(n)
>
local np;
>
np:= function(n, m)
>
local i, res;
>
if n = 0 then
>
return 1;
>
fi;
>
res:= 0;
>
for i in [1..Minimum(n,m)] do
>
res:= res + np(n-i, i);
>
od;
>
return res;
>
end;
>
return np(n,n);
> end;
function ( n ) ... end
We wanted to write a function that takes one argument. We solved the problem of determining the number of partitions in terms of a recursive procedure with two arguments. So we
had to write in fact two functions. The function nrparts that can be used to compute the
number of partitions takes indeed only one argument. The function np takes two arguments
and solves the problem in the indicated way. The only task of the function nrparts is to
call np with two equal arguments.
We made np local to nrparts. This illustrates the possibility of having local functions in
GAP3. It is however not necessary to put it there. np could as well be defined on the main
level. But then the identifier np would be bound and could not be used for other purposes.
And if it were used the essential function np would no longer be available for nrparts.
Now have a look at the function np. It has two local variables res and i. The variable res
is used to collect the sum and i is a loop variable. In the loop the function np calls itself
again with other arguments. It would be very disturbing if this call of np would use the
same i and res as the calling np. Since the new call of np creates a new scope with new
variables this is fortunately not the case.
The formal parameters n and m are treated like local variables.
It is however cheaper (in terms of computing time) to avoid such a recursive solution if this
is possible (and it is possible in this case), because a function call is not very cheap.
In this section you have seen how to write functions in the GAP3 language. You have also
seen how to use the if statement. Functions may have local variables which are declared in
an initial local statement in the function definition. Functions may call themselves.
The function syntax is described in 2.18. The if statement is described in more detail in
2.14. More about Fibonacci numbers is found in 47.22 and more about partitions in 47.13.
1.18. ABOUT GROUPS
1.18
99
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
4, 7), 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 20). 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 GAP3 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, GAP3 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 GAP3 structures, it is represented as a record
(see 7.118).
gap> RecFields( a8 );
[ "isDomain", "isGroup", "parent", "identity", "generators",
"operations", "isPermGroup", "1", "2", "3", "4", "5", "6",
100
CHAPTER 1. ABOUT GAP
"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 7, especially 7.45):
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 GAP3 to store the group at the end of a list of length 65521, so there are
special situations where it is possible to bring GAP3 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) ] ),
1.18. ABOUT GROUPS
Subgroup( s8, [ ( 1, 6, 3)( 2, 4, 5), ( 1, 8,
( 1, 7)( 2, 3)( 4, 6)( 5, 8), ( 1, 5)( 2,
Subgroup( s8, [ ( 1, 3)( 2, 7)( 4, 5)( 6, 8),
( 1, 6)( 2, 5)( 3, 8)( 4, 7), ( 1, 5)( 3,
, Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7,
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,7)(4,8), (2,3)(4,6), (1,2)(5,6) ] ),
Subgroup( s8, [ ( 1, 6, 3)( 2, 4, 5), ( 1, 8,
( 1, 7)( 2, 3)( 4, 6)( 5, 8), ( 1, 5)( 2,
101
3)( 4, 5, 7),
6) ] ),
4), ( 1, 5)( 7, 8) ] )
8) ] ),
(3,4)(7,8),
3)( 4, 5, 7),
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 GAP3 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
7.6).
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) ] )
102
CHAPTER 1. ABOUT GAP
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 23 : L3 (2) in a8. One idea is to look for an
appropriate 23 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 GAP3 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,
Error, must be a
AsSubgroup( a8, elab
main loop
brk> quit;
gap> IsSubgroup( a8,
true
AsSubgroup( a8, elab ) );
parent group in
) called from
AsSubgroup( s8, elab ) );
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
1.18. ABOUT GROUPS
103
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 4.7).
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 GAP3 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 7, for homomorphisms see chapters 8 and
43).
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) )
104
CHAPTER 1. ABOUT GAP
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 L3 (2). A more elaborate discussion of operations of groups can be found in
section 1.19 and chapter 8.
gap>
gap>
true
gap>
168
gap>
true
op:= Operation( f, Elements( f ), OnRight );;
IsPermGroup( op );
Maximum( List( op.generators, LargestMovedPointPerm ) );
IsSimple( op );
norm acts on the seven nontrivial elements of its normal subgroup elab by conjugation,
yielding a representation of L3 (2) on seven points. We embed this permutation group in
norm and deduce that norm is a split extension of an elementary abelian group 23 with L3 (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 );
1.18. ABOUT GROUPS
105
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 49 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 ],
106
CHAPTER 1. ABOUT GAP
[ 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 49 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,
1.19. ABOUT OPERATIONS OF GROUPS
107
[ (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 ]
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 ∈ D and g ∈ G to another element dg ∈ D, which we call the image of d under g,
such that didentity = d and (dg )h = dgh for each d ∈ D and g, h ∈ 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 GAP3 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 20.2). 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 34.1). 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);
108
CHAPTER 1. ABOUT GAP
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 8.16 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 47.9) we first generate a list of all pairs.
gap> pairs :=
[ [ 1, 1 ], [
[ 1, 7 ], [
[ 2, 5 ], [
[ 3, 3 ], [
[ 4, 1 ], [
[ 4, 7 ], [
[ 5, 5 ], [
[ 6, 3 ], [
[ 7, 1 ], [
[ 7, 7 ], [
[ 8, 5 ], [
Tuples(
1, 2 ],
1, 8 ],
2, 6 ],
3, 4 ],
4, 2 ],
4, 8 ],
5, 6 ],
6, 4 ],
7, 2 ],
7, 8 ],
8, 6 ],
[1..8], 2
[ 1, 3 ],
[ 2, 1 ],
[ 2, 7 ],
[ 3, 5 ],
[ 4, 3 ],
[ 5, 1 ],
[ 5, 7 ],
[ 6, 5 ],
[ 7, 3 ],
[ 8, 1 ],
[ 8, 7 ],
);
[ 1,
[ 2,
[ 2,
[ 3,
[ 4,
[ 5,
[ 5,
[ 6,
[ 7,
[ 8,
[ 8,
4
2
8
6
4
2
8
6
4
2
8
], [
], [
], [
], [
], [
], [
], [
], [
], [
], [
] ]
1,
2,
3,
3,
4,
5,
6,
6,
7,
8,
5
3
1
7
5
3
1
7
5
3
],
],
],
],
],
],
],
],
],
],
[
[
[
[
[
[
[
[
[
[
1,
2,
3,
3,
4,
5,
6,
6,
7,
8,
6
4
2
8
6
4
2
8
6
4
],
],
],
],
],
],
],
],
],
],
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 8.1 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
1.19. ABOUT OPERATIONS OF GROUPS
109
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(
[ [ [ 1, 1 ], [ 2, 2
[ 7, 7 ], [ 8,
[ [ 1, 2 ], [ 2, 3
[ 1, 4 ], [ 4,
[ 4, 2 ], [ 5,
[ 1, 6 ], [ 5,
[ 4, 6 ], [ 3,
[ 6, 2 ], [ 7,
[ 3, 7 ], [ 2,
[ 7, 2 ], [ 8,
[ 4, 8 ], [ 3,
[ 8, 3 ], [ 8,
a8, pairs, OnPairs );
], [ 3, 3 ], [ 4, 4 ], [
8 ] ],
], [ 1, 3 ], [ 3, 1 ], [
1 ], [ 4, 5 ], [ 3, 2 ],
1 ], [ 5, 6 ], [ 4, 3 ],
3 ], [ 5, 2 ], [ 6, 1 ],
6 ], [ 2, 6 ], [ 1, 7 ],
1 ], [ 7, 8 ], [ 6, 5 ],
7 ], [ 1, 8 ], [ 7, 5 ],
1 ], [ 8, 2 ], [ 7, 6 ],
8 ], [ 2, 8 ], [ 8, 6 ],
7 ] ] ]
5, 5 ], [ 6, 6 ],
3, 4
[ 2,
[ 3,
[ 6,
[ 6,
[ 5,
[ 7,
[ 6,
[ 8,
], [
4 ],
5 ],
7 ],
4 ],
7 ],
4 ],
8 ],
5 ],
2, 1
[ 1,
[ 2,
[ 5,
[ 6,
[ 4,
[ 7,
[ 5,
[ 8,
],
5 ],
5 ],
4 ],
3 ],
7 ],
3 ],
8 ],
4 ],
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] );
110
CHAPTER 1. ABOUT GAP
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
1.19. ABOUT OPERATIONS OF GROUPS
111
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
112
CHAPTER 1. ABOUT GAP
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: 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 ],
1.19. ABOUT OPERATIONS OF GROUPS
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
113
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 );
114
CHAPTER 1. ABOUT GAP
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.20. ABOUT FINITELY PRESENTED GROUPS AND PRESENTATIONS
115
>
(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 7.54).
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
Permutation. All functions are described in the chapter 8.
1.20
About Finitely Presented Groups and Presentations
In this section we will show you the investigation of a Coxeter group that is given by its
presentation. You will see that finitely presented groups and presentations are different
kinds of objects in GAP3. While finitely presented groups can never be changed after they
have been created as factor groups of free groups, presentations allow manipulations of
the generators and relators by Tietze transformations. The investigation of the example
will involve methods and algorithms like Todd-Coxeter, Reidemeister-Schreier, Nilpotent
Quotient, and Tietze transformations.
We start by defining a Coxeter group c on five generators as a factor group of the free group
of rank 5, whose generators we already call c.1, ..., c.5.
gap> c := FreeGroup( 5, "c" );;
116
CHAPTER 1. ABOUT GAP
gap> r := List( c.generators, x -> x^2 );;
gap> Append( r, [ (c.1*c.2)^3, (c.1*c.3)^2, (c.1*c.4)^3,
> (c.1*c.5)^3, (c.2*c.3)^3, (c.2*c.4)^2, (c.2*c.5)^3,
> (c.3*c.4)^3, (c.3*c.5)^3, (c.4*c.5)^3,
> (c.1*c.2*c.5*c.2)^2, (c.3*c.4*c.5*c.4)^2 ] );
gap> c := c / r;
Group( c.1, c.2, c.3, c.4, c.5 )
If we call the function Size for this group GAP3 will invoke the Todd-Coxeter method,
which however will fail to get a result going up to the default limit of defining 64000 cosets:
gap> Size(c);
Error, the coset enumeration has defined more than 64000 cosets:
type ’return;’ if you want to continue with a new limit of
128000 cosets,
type ’quit;’ if you want to quit the coset enumeration,
type ’maxlimit := 0; return;’ in order to continue without a limit,
in
AugmentedCosetTableMtc( G, H, -1, "_x" ) called from
D.operations.Size( D ) called from
Size( c ) called from
main loop
brk> quit;
In fact, as we shall see later, our finitely presented group is infinite and hence we would get
the same answer also with larger limits. So we next look for subgroups of small index, in
our case limiting the index to four.
gap> lis := LowIndexSubgroupsFpGroup( c, TrivialSubgroup(c), 4 );;
gap> Length(lis);
10
The LowIndexSubgroupsFpGroup function in fact determines generators for the subgroups,
written in terms of the generators of the given group. We can find the index of these
subgroups by the function Index, and the permutation representation on the cosets of these
subgroups by the function OperationCosetsFpGroup, which use a Todd-Coxeter method.
The size of the image of this permutation representation is found using Size which in this
case uses a Schreier-Sims method for permutation groups.
gap> List(lis, x -> [Index(c,x),Size(OperationCosetsFpGroup(c,x))]);
[ [ 1, 1 ], [ 4, 24 ], [ 4, 24 ], [ 4, 24 ], [ 4, 24 ], [ 4, 24 ],
[ 4, 24 ], [ 4, 24 ], [ 3, 6 ], [ 2, 2 ] ]
We next determine the commutator factor groups of the kernels of these permutation
representations. Note that here the difference of finitely presented groups and presentations has to be observed: We first determine the kernel of the permutation representation by the function Core as a subgroup of c, then a presentation of this subgroup using
PresentationSubgroup, which has to be converted into a finitely presented group of its
own right using FpGroupPresentation, before its commutator factor group and the abelian
invariants can be found using integer matrix diagonalisation of the relators matrix by an
elementary divisor algorithm. The conversion is necessary because Core computes a subgroup given by words in the generators of c but CommutatorFactorGroup needs a parent
group given by generators and relators.
1.20. ABOUT FINITELY PRESENTED GROUPS AND PRESENTATIONS
117
gap> List( lis, x -> AbelianInvariants( CommutatorFactorGroup(
>
FpGroupPresentation( PresentationSubgroup( c, Core(c,x) ) ) ) ) );
[ [ 2 ], [ 2, 2, 2, 2, 2, 2, 2, 2 ], [ 2, 2, 2, 2, 2, 2, 2, 2 ],
[ 2, 2, 2, 2, 2, 2, 2, 2 ], [ 2, 2, 2, 2, 2, 2, 2, 2 ],
[ 2, 2, 2, 2, 2, 2, 2, 2 ], [ 2, 2, 2, 2, 2, 2, 2, 2 ],
[ 0, 0, 0, 0, 0, 0 ], [ 2, 2, 2, 2, 2, 2 ], [ 3 ] ]
More clearly arranged, this is
[ [
[
[
[
[
[
[
[
[
[
2 ],
2, 2,
2, 2,
2, 2,
2, 2,
2, 2,
2, 2,
0, 0,
2, 2,
3 ] ]
2,
2,
2,
2,
2,
2,
0,
2,
2,
2,
2,
2,
2,
2,
0,
2,
2,
2,
2,
2,
2,
2,
0,
2,
2, 2,
2, 2,
2, 2,
2, 2,
2, 2,
2, 2,
0 ],
2 ],
2
2
2
2
2
2
],
],
],
],
],
],
Note that there is another function AbelianInvariantsSubgroupFpGroup which we could
have used to obtain this list which will do an abelianized Reduced Reidemeister-Schreier.
This function is much faster because it does not compute a complete presentation for the
core.
The output obtained shows that the third last of the kernels has a free abelian commutator
factor group of rank 6. We turn our attention to this kernel which we call n, while we call
the associated presentation pr.
gap> lis[8];
Subgroup( Group( c.1, c.2, c.3, c.4, c.5 ),
[ c.1, c.2, c.3*c.2*c.5^-1, c.3*c.4*c.3^-1, c.4*c.1*c.5^-1 ] )
gap> pr := PresentationSubgroup( c, Core( c, lis[8] ) );
<< presentation with 22 gens and 41 rels of total length 156 >>
gap> n := FpGroupPresentation(pr);;
We first determine p-factor groups for primes 2, 3, 5, and 7.
gap> InfoPQ1:= Ignore;;
gap> List( [2,3,5,7], p -> PrimeQuotient(n,p,5).dimensions );
[ [ 6, 10, 18, 30, 54 ], [ 6, 10, 18, 30, 54 ], [ 6, 10, 18, 30, 54 ],
[ 6, 10, 18, 30, 54 ] ]
Observing that the ranks of the lower exponent-p central series are the same for these primes
we suspect that the lower central series may have free abelian factors. To investigate this
we have to call the package ”nq”.
gap> RequirePackage("nq");
gap> NilpotentQuotient( n, 5 );
[ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0 ] ]
gap> List( last, Length );
118
CHAPTER 1. ABOUT GAP
[ 6, 4, 8, 12, 24 ]
The ranks of the factors except the first are divisible by four, and we compare them with
the corresponding ranks of a free group on two generators.
gap> f2 := FreeGroup(2);
Group( f.1, f.2 )
gap> PrimeQuotient( f2, 2, 5 ).dimensions;
[ 2, 3, 5, 8, 14 ]
gap> NilpotentQuotient( f2, 5 );
[ [ 0, 0 ], [ 0 ], [ 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ]
gap> List( last, Length );
[ 2, 1, 2, 3, 6 ]
The result suggests a close relation of our group to the direct product of four free groups of
rank two. In order to study this we want a simple presentation for our kernel n and obtain
this by repeated use of Tietze transformations, using first the default simplification function
TzGoGo and later specific introduction of new generators that are obtained as product of two
of the existing ones using the function TzSubstitute. (Of course, this latter sequence of
Tietze transformations that we display here has only been found after some trial and error.)
gap> pr := PresentationSubgroup( c, Core( c, lis[8] ) );
<< presentation with 22 gens and 41 rels of total length 156 >>
gap> TzGoGo(pr);
#I there are 6 generators and 14 relators of total length 74
gap> TzGoGo(pr);
#I there are 6 generators and 13 relators of total length 66
gap> TzGoGo(pr);
gap> TzPrintPairs(pr);
#I 1. 3 occurrences of _x6 * _x11^-1
#I 2. 3 occurrences of _x3 * _x15
#I 3. 2 occurrences of _x11^-1 * _x15^-1
#I 4. 2 occurrences of _x6 * _x15
#I 5. 2 occurrences of _x6^-1 * _x15^-1
#I 6. 2 occurrences of _x4 * _x15
#I 7. 2 occurrences of _x4^-1 * _x15^-1
#I 8. 2 occurrences of _x4^-1 * _x11
#I 9. 2 occurrences of _x4 * _x6
#I 10. 2 occurrences of _x3^-1 * _x11
gap> TzSubstitute(pr,10,2);
#I substituting new generator _x26 defined by _x3^-1*_x11
#I eliminating _x11 = _x3*_x26
#I there are 6 generators and 13 relators of total length 70
gap> TzGoGo(pr);
#I there are 6 generators and 12 relators of total length 62
#I there are 6 generators and 12 relators of total length 60
gap> TzGoGo(pr);
gap> TzSubstitute(pr,9,2);
#I substituting new generator _x27 defined by _x1^-1*_x15
#I eliminating _x15 = _x27*_x1
#I there are 6 generators and 12 relators of total length 64
1.20. ABOUT FINITELY PRESENTED GROUPS AND PRESENTATIONS
gap> TzGoGo(pr);
#I there are 6 generators and 11 relators of total length 56
gap> TzGoGo(pr);
gap> p2 := Copy(pr);
<< presentation with 6 gens and 11 rels of total length 56 >>
gap> TzPrint(p2);
#I generators: [ _x1, _x3, _x4, _x6, _x26, _x27 ]
#I relators:
#I 1. 4 [ -6, -1, 6, 1 ]
#I 2. 4 [ 4, 6, -4, -6 ]
#I 3. 4 [ 5, 4, -5, -4 ]
#I 4. 4 [ 4, -2, -4, 2 ]
#I 5. 4 [ -3, 2, 3, -2 ]
#I 6. 4 [ -3, -1, 3, 1 ]
#I 7. 6 [ -4, 3, 4, 6, -3, -6 ]
#I 8. 6 [ -1, -6, -2, 6, 1, 2 ]
#I 9. 6 [ -6, -2, -5, 6, 2, 5 ]
#I 10. 6 [ 2, 5, 1, -5, -2, -1 ]
#I 11. 8 [ -1, -6, -5, 3, 6, 1, 5, -3 ]
gap> TzPrintPairs(p2);
#I 1. 5 occurrences of _x1^-1 * _x27^-1
#I 2. 3 occurrences of _x6 * _x27
#I 3. 3 occurrences of _x3 * _x26
#I 4. 2 occurrences of _x3 * _x27
#I 5. 2 occurrences of _x1 * _x4
#I 6. 2 occurrences of _x1 * _x3
#I 7. 1 occurrence of _x26 * _x27
#I 8. 1 occurrence of _x26 * _x27^-1
#I 9. 1 occurrence of _x26^-1 * _x27
#I 10. 1 occurrence of _x6 * _x27^-1
gap> TzSubstitute(p2,1,2);
#I substituting new generator _x28 defined by _x1^-1*_x27^-1
#I eliminating _x27 = _x1^-1*_x28^-1
#I there are 6 generators and 11 relators of total length 58
gap> TzGoGo(p2);
#I there are 6 generators and 11 relators of total length 54
gap> TzGoGo(p2);
gap> p3 := Copy(p2);
<< presentation with 6 gens and 11 rels of total length 54 >>
gap> TzSubstitute(p3,3,2);
#I substituting new generator _x29 defined by _x3*_x26
#I eliminating _x26 = _x3^-1*_x29
gap> TzGoGo(p3);
#I there are 6 generators and 11 relators of total length 52
gap> TzGoGo(p3);
gap> TzPrint(p3);
#I generators: [ _x1, _x3, _x4, _x6, _x28, _x29 ]
#I relators:
119
120
CHAPTER 1. ABOUT GAP
#I
#I
#I
#I
#I
#I
#I
#I
#I
#I
#I
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
4
4
4
4
4
4
4
6
6
[
[
[
[
[
[
[
[
[
6
6
6, 4, -6, -4 ]
1, -6, -1, 6 ]
-5, -1, 5, 1 ]
-2, -5, 2, 5 ]
4, -2, -4, 2 ]
-3, 2, 3, -2 ]
-3, -1, 3, 1 ]
-2, 5, -6, 2, -5, 6 ]
4, -1, -5, -4, 5, 1 ]
[ -6, 3, -5, 6, -3, 5 ]
[ 3, -5, 4, -3, -4, 5 ]
The resulting presentation could further be simplified by Tietze transformations using
TzSubstitute and TzGoGo until one reaches finally a presentation on 6 generators with
11 relators, 9 of which are commutators of the generators. Working by hand from these,
the kernel can be identified as a particular subgroup of the direct product of four copies of
the free group on two generators.
1.21
About Fields
In this section we will show you some basic computations with fields. GAP3 supports at
present the following fields. The rationals, cyclotomic extensions of rationals and their
subfields (which we will refer to as number fields in the following), and finite fields.
Let us first take a look at the infinite fields mentioned above. While the set of rational
numbers is a predefined domain in GAP3 to which you may refer by its identifier Rationals,
cyclotomic fields are constructed by using the function CyclotomicField, which may be
abbreviated as CF.
gap> IsField( Rationals );
true
gap> Size( Rationals );
"infinity"
gap> f := CyclotomicField( 8 );
CF(8)
gap> IsSubset( f, Rationals );
true
The integer argument n of the function call to CF specifies that the cyclotomic field containing
all n-th roots of unity should be returned.
Cyclotomic fields are constructed as extensions of the Rationals by primitive roots of unity.
Thus a primitive n-th root of unity is always an element of CF(n), where n is a natural
number. In GAP3, one may construct a primitive n-th root of unity by calling E(n).
gap> (E(8) + E(8)^3)^2;
-2
gap> E(8) in f;
true
For every field extension you can compute the Galois group, i.e., the group of automorphisms
that leave the subfield fixed. For an example, cyclotomic fields are an extension of the
rationals, so you can compute their Galois group over the rationals.
1.21. ABOUT FIELDS
121
gap> Galf := GaloisGroup( f );
Group( NFAutomorphism( CF(8) , 7 ), NFAutomorphism( CF(8) , 5 ) )
gap> Size( Galf );
4
The above cyclotomic field is a small example where the Galois group is not cyclic.
gap> IsCyclic( Galf );
false
gap> IsAbelian( Galf );
true
gap> AbelianInvariants( Galf );
[ 2, 2 ]
This shows us that the 8th cyclotomic field has a Galois group which is isomorphic to group
V4 .
The elements of the Galois group are GAP3 automorphisms, so they may be applied to the
elements of the field in the same way as all mappings are usually applied to objects in GAP3.
gap> g := Galf.generators[1];
NFAutomorphism( CF(8) , 7 )
gap> E(8) ^ g;
-E(8)^3
There are two functions, Norm and Trace, which compute the norm and the trace of elements
of the field, respectively. The norm and the trace of an element a are defined to be the
product and the sum of the images of a under the Galois group. You should usually specify
the field as a first argument. This argument is however optional. If you omit a default field
will be used. For a cyclotomic a this is the smallest cyclotomic field that contains a (note
that this is not the smallest field that contains a, which may be a number field that is not
a cyclotomic field).
gap> orb := List( Elements( Galf ), x -> E(8) ^ x );
[ E(8), E(8)^3, -E(8), -E(8)^3 ]
gap> Sum( orb ) = Trace( f, E(8) );
true
gap> Product( orb ) = Norm( f, E(8) );
true
gap> Trace( f, 1 );
4
The basic way to construct a finite field is to use the function GaloisField which may be
abbreviated, as usual in algebra, as GF. Thus
gap> k := GF( 3, 4 );
GF(3^4)
or
gap> k := GaloisField( 81 );
GF(3^4)
will assign the finite field of order 34 to the variable k.
In fact, what GF does is to set up a record which contains all necessary information, telling
that it represents a finite field of degree 4 over its prime field with 3 elements. Of course, all
122
CHAPTER 1. ABOUT GAP
arguments to GF others than those which represent a prime power are rejected – for obvious
reasons.
Some of the more important entries of the field record are zero, one and root, which hold
the corresponding elements of the field. All elements of a finite field are represented as a
certain power of an appropriate primitive root, which is written as Z(q). As can be seen
below the smallest possible primitive root is used.
gap> k.one + k.root + k.root^10 - k.zero;
Z(3^4)^52
gap> k.root;
Z(3^4)
gap> k.root ^ 20;
Z(3^2)^2
gap> k.one;
Z(3)^0
Note that of course elements from fields of different characteristic cannot be combined in
operations.
gap> Z(3^2) * k.root + k.zero + Z(3^8);
Z(3^8)^6534
gap> Z(2) * k.one;
Error, Finite field *: operands must have the same characteristic
In this example we tried to multiply a primitive root of the field with two elements with the
identity element of the field k. As the characteristic of k equals 3, there is no way to perform
the multiplication. The first statement of the example shows, that if all the elements of the
expression belong to fields of the same characteristic, the result will be computed.
As soon as a primitive root is demanded, GAP3 internally sets up all relevant data structures that are necessary to compute in the corresponding finite field. Each finite field is
constructed as a splitting field of a Conway polynomial. These polynomials, as a set, have
special properties that make it easy to embed smaller fields in larger ones and to convert
the representation of the elements when doing so. All Conway polynomials for fields up to
an order of 65536 have been computed and installed in the GAP3 kernel.
But now look at the following example.
gap> Z(3^3) * Z(3^4);
Error, Finite field *: smallest common superfield to large
Although both factors are elements of fields of characteristic 3, the product can not be
evaluated by GAP3. The reason for this is very easy to explain:In order to compute the
product, GAP3 has to find a field in which both of the factors lie. Here in our example the
smallest field containing Z(33 ) and Z(34 ) is GF (312 ), the field with 531441 elements. As we
have mentioned above that the size of finite fields in GAP3 is limited at present by 65536
we now see that there is no chance to set up the internal data structures for the common
field to perform the computation.
As before with cyclotomic fields, the Galois group of a finite field and the norm and trace
of its elements may be computed. The calling conventions are the same as for cyclotomic
fields.
gap> Galk := GaloisGroup( k );
1.21. ABOUT FIELDS
123
Group( FrobeniusAutomorphism( GF(3^4) ) )
gap> Size( Galk );
4
gap> IsCyclic( Galk );
true
gap> Norm( k, k.root ^ 20 );
Z(3)^0
gap> Trace( k, k.root ^ 20 );
0*Z(3)
So far, in our examples, we were always interested in the Galois group of a field extension k
over its prime field. In fact it often will occur that, given a subfield l of k the Galois group
of k over l is desired. In GAP3 it is possible to change the structure of a field by using the
/ operator. So typing
gap> l := GF(3^2);
GF(3^2)
gap> IsSubset( k, l );
true
gap> k / l;
GF(3^4)/GF(3^2)
changes the representation of k from a field extension of degree 4 over GF (3) to a field given
as an extension of degree 2 over GF (32 ). The actual elements of the fields are still the same,
only the structure of the field has changed.
gap> k = k / l;
true
gap> Galkl := GaloisGroup( k / l );
Group( FrobeniusAutomorphism( GF(3^4)/GF(3^2) )^2 )
gap> Size( Galkl );
2
Of course, all the relevant functions behave in a different way when they refer to k / l
instead of k
gap> Norm( k / l, k.root ^ 20 );
Z(3)
gap> Trace( k / l, k.root ^ 20 );
Z(3^2)^6
This feature, to change the structure of the field without changing the underlying set of
elements, is also available for cyclotomic fields, which we have seen at the beginning of this
chapter.
gap> g := CyclotomicField( 4 );
GaussianRationals
gap> IsSubset( f, g );
true
gap> f / g;
CF(8)/GaussianRationals
gap> Galfg := GaloisGroup( f / g );
Group( NFAutomorphism( CF(8)/GaussianRationals , 5 ) )
124
CHAPTER 1. ABOUT GAP
gap> Size( Galfg );
2
The examples should have shown that, although the structure of finite fields and cyclotomic
fields is rather different, there is a similar interface to them in GAP3, which makes it easy
to write programs that deal with both types of fields in the same way.
1.22
About Matrix Groups
This section intends to show you the things you could do with matrix groups in GAP3.
In principle all the set theoretic functions mentioned in chapter 4 and all group functions
mentioned in chapter 7 can be applied to matrix groups. However, you should note that at
present only very few functions can work efficiently with matrix groups. Especially infinite
matrix groups (over the rationals or cyclotomic fields) can not be dealt with at all.
Matrix groups are created in the same way as the other types of groups, by using the function
Group. Of course, in this case the arguments have to be invertable matrices over a field.
gap> m1 := [ [ Z(3)^0, Z(3)^0, Z(3) ],
>
[ Z(3), 0*Z(3), Z(3) ],
>
[ 0*Z(3), Z(3), 0*Z(3) ] ];;
gap> m2 := [ [ Z(3), Z(3), Z(3)^0 ],
>
[ Z(3), 0*Z(3), Z(3) ],
>
[ Z(3)^0, 0*Z(3), Z(3) ] ];;
gap> m := Group( m1, m2 );
Group( [ [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3), 0*Z(3), Z(3) ],
[ 0*Z(3), Z(3), 0*Z(3) ] ],
[ [ Z(3), Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ],
[ Z(3)^0, 0*Z(3), Z(3) ] ] )
As usual for groups, the matrix group that we have constructed is represented by a record
with several entries. For matrix groups, there is one additional entry which holds the field
over which the matrix group is written.
gap> m.field;
GF(3)
Note that you do not specify the field when you construct the group. Group automatically
takes the smallest field over which all its arguments can be written.
At this point there is the question what special functions are available for matrix groups.
The size of our group, for example, may be computed using the function Size.
gap> Size( m );
864
If we now compute the size of the corresponding general linear group
gap> (3^3 - 3^0) * (3^3 - 3^1) * (3^3 - 3^2);
11232
we see that we have constructed a proper subgroup of index 13 of GL(3, 3).
Let us now set up a subgroup of m, which is generated by the matrix m2.
gap> n := Subgroup( m, [ m2 ] );
1.23. ABOUT DOMAINS AND CATEGORIES
125
Subgroup( Group( [ [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3), 0*Z(3), Z(3) ],
[ 0*Z(3), Z(3), 0*Z(3) ] ],
[ [ Z(3), Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ],
[ Z(3)^0, 0*Z(3), Z(3) ] ] ),
[ [ [ Z(3), Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ],
[ Z(3)^0, 0*Z(3), Z(3) ] ] ] )
gap> Size( n );
6
And to round up this example we now compute the centralizer of this subgroup in m.
gap> c := Centralizer( m, n );
Subgroup( Group( [ [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3), 0*Z(3), Z(3) ],
[ 0*Z(3), Z(3), 0*Z(3) ] ],
[ [ Z(3), Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ],
[ Z(3)^0, 0*Z(3), Z(3) ] ] ),
[ [ [ Z(3), Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ],
[ Z(3)^0, 0*Z(3), Z(3) ] ],
[ [ Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3) ],
[ 0*Z(3), 0*Z(3), Z(3) ] ] ] )
gap> Size( c );
12
In this section you have seen that matrix groups are constructed in the same way that all
groups are constructed. You have also been warned that only very few functions can work
efficiently with matrix groups. See chapter 37 to read more about matrix groups.
1.23
About Domains and Categories
Domain is GAP3’s name for structured sets. We already saw examples of domains in
the previous sections. For example, the groups s8 and a8 in sections 1.18 and 1.19 are
domains. Likewise the fields in section 1.21 are domains. Categories are sets of domains.
For example, the set of all groups forms a category, as does the set of all fields.
In those sections we treated the domains as black boxes. They were constructed by special
functions such as Group and GaloisField, and they could be passed as arguments to other
functions such as Size and Orbits.
In this section we will also treat domains as black boxes. We will describe how domains are
created in general and what functions are applicable to all domains. Next we will show how
domains with the same structure are grouped into categories and will give an overview of
the categories that are available. Then we will discuss how the organization of the GAP3
library around the concept of domains and categories is reflected in this manual. In a later
section we will open the black boxes and give an overview of the mechanism that makes all
this work (see 1.27).
The first thing you must know is how you can obtain domains. You have basically three
possibilities. You can use the domains that are predefined in the library, you can create new
domains with domain constructors, and you can use the domains returned by many library
functions. We will now discuss those three possibilities in turn.
The GAP3 library predefines some domains. That means that there is a global variable
whose value is this domain. The following example shows some of the more important
predefined domains.
126
CHAPTER 1. ABOUT GAP
gap> Integers;
Integers
# the ring of all integers
gap> Size( Integers );
"infinity"
gap> GaussianRationals;
GaussianRationals
# the field of all Gaussian
gap> (1/2+E(4)) in GaussianRationals;
true
# E(4) is GAP3’s name for the complex root of -1
gap> Permutations;
Permutations
# the domain of all permutations
Note that GAP3 prints those domains using the name of the global variable.
You can create new domains using domain constructors such as Group, Field, etc. A
domain constructor is a function that takes a certain number of arguments and returns the
domain described by those arguments. For example, Group takes an arbitrary number of
group elements (of the same type) and returns the group generated by those elements.
gap> gf16 := GaloisField( 16 );
GF(2^4)
# the finite field with 16 elements
gap> Intersection( gf16, GaloisField( 64 ) );
GF(2^2)
gap> a5 := Group( (1,2,3), (3,4,5) );
Group( (1,2,3), (3,4,5) )
# the alternating group on 5 points
gap> Size( a5 );
60
Again GAP3 prints those domains using more or less the expression that you entered to
obtain the domain.
As with groups (see 1.18) a name can be assigned to an arbitrary domain D with the
assignment D.name := string;, and GAP3 will use this name from then on in the output.
Many functions in the GAP3 library return domains. In the last example you already saw
that Intersection returned a finite field domain. Below are more examples.
gap> GaloisGroup( gf16 );
Group( FrobeniusAutomorphism( GF(2^4) ) )
gap> SylowSubgroup( a5, 2 );
Subgroup( Group( (1,2,3), (3,4,5) ), [ (2,4)(3,5), (2,3)(4,5) ] )
The distinction between domain constructors and functions that return domains is a little
bit arbitrary. It is also not important for the understanding of what follows. If you are
nevertheless interested, here are the principal differences. A constructor performs no computation, while a function performs a more or less complicated computation. A constructor
creates the representation of the domain, while a function relies on a constructor to create
the domain. A constructor knows the dirty details of the domain’s representation, while a
function may be independent of the domain’s representation. A constructor may appear as
printed representation of a domain, while a function usually does not.
After showing how domains are created, we will now discuss what you can do with domains.
You can assign a domain to a variable, put a domain into a list or into a record, pass a
domain as argument to a function, and return a domain as result of a function. In this
regard there is no difference between an integer value such as 17 and a domain such as
1.23. ABOUT DOMAINS AND CATEGORIES
127
Group( (1,2,3), (3,4,5) ). Of course many functions will signal an error when you
call them with domains as arguments. For example, Gcd does not accept two groups as
arguments, because they lie in no Euclidean ring.
There are some functions that accept domains of any type as their arguments. Those
functions are called the set theoretic functions. The full list of set theoretic functions is
given in chapter 4.
Above we already used one of those functions, namely Size. If you look back you will see
that we applied Size to the domain Integers, which is a ring, and the domain a5, which
is a group. Remember that a domain was a structured set. The size of the domain is the
number of elements in the set. Size returns this number or the string "infinity" if the
domain is infinite. Below are more examples.
gap> Size( GaussianRationals );
"infinity"
# this string is returned for infinite domains
gap> Size( SylowSubgroup( a5, 2 ) );
4
IsFinite( D ) returns true if the domain D is finite and false otherwise. You could also
test if a domain is finite using Size( D ) < "infinity" (GAP3 evaluates n < "infinity"
to true for any number n). IsFinite is more efficient. For example, if D is a permutation
group, IsFinite( D ) can immediately return true, while Size( D ) may take quite a
while to compute the size of D.
The other function that you already saw is Intersection. Above we computed the intersection of the field with 16 elements and the field with 64 elements. The following example
is similar.
gap> Intersection( a5, Group( (1,2), (1,2,3,4) ) );
Group( (2,3,4), (1,2)(3,4) )
# alternating group on 4 points
In general Intersection tries to return a domain. In general this is not possible however.
Remember that a domain is a structured set. If the two domain arguments have different
structure the intersection may not have any structure at all. In this case Intersection returns the result as a proper set, i.e., as a sorted list without holes and duplicates. The following example shows such a case. ConjugacyClass returns the conjugacy class of (1,2,3,4,5)
in the alternating group on 6 points as a domain. If we intersect this class with the symmetric group on 5 points we obtain a proper set of 12 permutations, which is only one half
of the conjugacy class of 5 cycles in s5.
gap> a6 := Group( (1,2,3), (2,3,4,5,6) );
Group( (1,2,3), (2,3,4,5,6) )
gap> class := ConjugacyClass( a6, (1,2,3,4,5) );
ConjugacyClass( Group( (1,2,3), (2,3,4,5,6) ), (1,2,3,4,5) )
gap> Size( class );
72
gap> s5 := Group( (1,2), (2,3,4,5) );
Group( (1,2), (2,3,4,5) )
gap> Intersection( class, s5 );
[ (1,2,3,4,5), (1,2,4,5,3), (1,2,5,3,4), (1,3,5,4,2), (1,3,2,5,4),
(1,3,4,2,5), (1,4,3,5,2), (1,4,5,2,3), (1,4,2,3,5), (1,5,4,3,2),
(1,5,2,4,3), (1,5,3,2,4) ]
128
CHAPTER 1. ABOUT GAP
You can intersect arbitrary domains as the following example shows.
gap> Intersection( Integers, a5 );
[ ]
# the empty set
Note that we optimized Intersection for typical cases, e.g., computing the intersection of
two permutation groups, etc. The above computation is done with a very simple–minded
method, all elements of a5 are listed (with Elements, described below), and for each element
Intersection tests whether it lies in Integers (with in, described below). So the same
computation with the alternating group on 10 points instead of a5 will probably exhaust
your patience.
Just as Intersection returns a proper set occasionally, it also accepts proper sets as arguments. Intersection also takes an arbitrary number of arguments. And finally it also
accepts a list of domains or sets to intersect as single argument.
gap> Intersection( a5, [ (1,2), (1,2,3), (1,2,3,4), (1,2,3,4,5) ] );
[ (1,2,3), (1,2,3,4,5) ]
gap> Intersection( [2,4,6,8,10], [3,6,9,12,15], [5,10,15,20,25] );
[ ]
gap> Intersection( [ [1,2,4], [2,3,4], [1,3,4] ] );
[ 4 ]
The function Union is the obvious counterpart of Intersection. Note that Union usually
does not return a domain. This is because the union of two domains, even of the same
type, is usually not again a domain of that type. For example, the union of two subgroups
is a subgroup if and only if one of the subgroups is a subset of the other. Of course this is
exactly the reason why Union is less important than Intersection in algebra.
Because domains are structured sets there ought to be a membership test that tests whether
an object lies in this domain or not. This is not implemented by a function, instead the
operator in is used. elm in D returns true if the element elm lies in the domain D and
false otherwise. We already used the in operator above when we tested whether 1/2 +
E(4) lies in the domain of Gaussian integers.
gap> (1,2,3) in a5;
true
gap> (1,2) in a5;
false
gap> (1,2,3,4,5,6,7) in a5;
false
gap> 17 in a5;
false
# of course an integer does not lie in a permutation group
gap> a5 in a5;
false
As you can see in the last example, in only implements the membership test. It does not
allow you to test whether a domain is a subset of another domain. For such tests the
function IsSubset is available.
gap> IsSubset( a5, a5 );
true
gap> IsSubset( a5, Group( (1,2,3) ) );
true
1.23. ABOUT DOMAINS AND CATEGORIES
129
gap> IsSubset( Group( (1,2,3) ), a5 );
false
In the above example you can see that IsSubset tests whether the second argument is
a subset of the first argument. As a general rule GAP3 library functions take as first
arguments those arguments that are in some sense larger or more structured.
Suppose that you want to loop over all elements of a domain. For example, suppose that you
want to compute the set of element orders of elements in the group a5. To use the for loop
you need a list of elements in the domain D, because for var in D do statements od will
not work. The function Elements does exactly that. It takes a domain D and returns the
proper set of elements of D.
gap> Elements( Group( (1,2,3), (2,3,4) ) );
[ (), (2,3,4), (2,4,3), (1,2)(3,4), (1,2,3), (1,2,4), (1,3,2),
(1,3,4), (1,3)(2,4), (1,4,2), (1,4,3), (1,4)(2,3) ]
gap> ords := [];;
gap> for elm in Elements( a5 ) do
>
Add( ords, Order( a5, elm ) );
>
od;
gap> Set( ords );
[ 1, 2, 3, 5 ]
gap> Set( List( Elements( a5 ), elm -> Order( a5, elm ) ) );
[ 1, 2, 3, 5 ]
# an easier way to compute the set of orders
Of course, if you apply Elements to an infinite domain, Elements will signal an error. It is
also not a good idea to apply Elements to very large domains because the list of elements
will take much space and computing this large list will probably exhaust your patience.
gap> Elements( GaussianIntegers );
Error, the ring must be finite to compute its elements in
D.operations.Elements( D ) called from
Elements( GaussianIntegers ) called from
main loop
brk> quit;
There are a few more set theoretic functions. See chapter 4 for a complete list.
All the set theoretic functions treat the domains as if they had no structure. Now a domain
is a structured set (excuse us for repeating this again and again, but it is really important
to get this across). If the functions ignore the structure than they are effectively viewing a
domain only as the set of elements.
In fact all set theoretic functions also accept proper sets, i.e., sorted lists without holes and
duplicates as arguments (we already mentioned this for Intersection). Also set theoretic
functions may occasionally return proper sets instead of domains as result.
This equivalence of a domain and its set of elements is particularly important for the definition of equality of domains. Two domains D and E are equal (in the sense that D = E
evaluates to true) if and only if the set of elements of D is equal to the set of elements of
E (as returned by Elements( D ) and Elements( E )). As a special case either of the
operands of = may also be a proper set, and the value is true if this set is equal to the set
of elements of the domain.
gap> a4 := Group( (1,2,3), (2,3,4) );
130
CHAPTER 1. ABOUT GAP
Group( (1,2,3), (2,3,4) )
gap> elms := Elements( a4 );
[ (), (2,3,4), (2,4,3), (1,2)(3,4), (1,2,3), (1,2,4), (1,3,2),
(1,3,4), (1,3)(2,4), (1,4,2), (1,4,3), (1,4)(2,3) ]
gap> elms = a4;
true
However the following example shows that this does not imply that all functions return the
same answer for two domains (or a domain and a proper set) that are equal. This is because
those function may take the structure into account.
gap> IsGroup( a4 );
true
gap> IsGroup( elms );
false
gap> Intersection( a4, Group( (1,2), (1,2,3) ) );
Group( (1,2,3) )
gap> Intersection( elms, Group( (1,2), (1,2,3) ) );
[ (), (1,2,3), (1,3,2) ]
# this is not a group
gap> last = last2;
true
# but it is equal to the above result
gap> Centre( a4 );
Subgroup( Group( (1,2,3), (2,3,4) ), [ ] )
gap> Centre( elms );
Error, must be a record in
Centre( elms ) called from
main loop
brk> quit;
Generally three things may happen if you have two domains D and E that are equal but
have different structure (or a domain D and a set E that are equal). First a function that
tests whether a domain has a certain structure may return true for D and false for E .
Second a function may return a domain for D and a proper set for E . Third a function may
work for D and fail for E , because it requires the structure.
A slightly more complex example for the second case is the following.
gap> v4 := Subgroup( a4, [ (1,2)(3,4), (1,3)(2,4) ] );
Subgroup( Group( (1,2,3), (2,3,4) ), [ (1,2)(3,4), (1,3)(2,4) ] )
gap> v4.name := "v4";;
gap> rc := v4 * (1,2,3);
(v4*(2,4,3))
gap> lc := (1,2,3) * v4;
((1,2,3)*v4)
gap> rc = lc;
true
gap> rc * (1,3,2);
(v4*())
gap> lc * (1,3,2);
[ (1,3)(2,4), (), (1,2)(3,4), (1,4)(2,3) ]
gap> last = last2;
1.23. ABOUT DOMAINS AND CATEGORIES
131
false
The two domains rc and lc (yes, cosets are domains too) are equal, because they have the
same set of elements. However if we multiply both with (1,3,2) we obtain the trivial right
coset for rc and a list for lc. The result for lc is not a proper set, because it is not sorted,
therefore = evaluates to false. (For the curious. The multiplication of a left coset with an
element from the right will generally not yield another coset, i.e., nothing that can easily be
represented as a domain. Thus to multiply lc with (1,3,2) GAP3 first converts lc to the
set of its elements with Elements. But the definition of multiplication requires that a list l
multiplied by an element e yields a new list n such that each element n[i ] in the new list
is the product of the element l [i ] at the same position of the operand list l with e.)
Note that the above definition only defines what the result of the equality comparison of
two domains D and E should be. It does not prescribe that this comparison is actually
performed by listing all elements of D and E . For example, if D and E are groups, it is
sufficient to check that all generators of D lie in E and that all generators of E lie in D.
If GAP3 would really compute the whole set of elements, the following test could not be
performed on any computer.
gap> Group( (1,2), (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18) )
> = Group( (17,18), (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18) );
true
If we could only apply the set theoretic functions to domains, domains would be of little
use. Luckily this is not so. We already saw that we could apply GaloisGroup to the finite
field with 16 elements, and SylowSubgroup to the group a5. But those functions are not
applicable to all domains. The argument of GaloisGroup must be a field, and the argument
of SylowSubgroup must be a group.
A category is a set of domains. So we say that the argument of GaloisGroup must
be an element of the category of fields, and the argument of SylowSubgroup must be an
element of the category of groups. The most important categories are rings, fields, groups,
and vector spaces. Which category a domain belongs to determines which functions are
applicable to this domain and its elements. We want to emphasize the each domain belongs
to one and only one category. This is necessary because domains in different categories
have, sometimes incompatible, representations.
Note that the categories only exist conceptually. That means that there is no GAP3 object
for the categories, e.g., there is no object Groups. For each category there exists a function
that tests whether a domain is an element of this category.
gap> IsRing( gf16 );
false
gap> IsField( gf16 );
true
gap> IsGroup( gf16 );
false
gap> IsVectorSpace( gf16 );
false
Note that of course mathematically the field gf16 is also a ring and a vector space. However
in GAP3 a domain can only belong to one category. So a domain is conceptually a set of
elements with one structure, e.g., a field structure. That the same set of elements may also
132
CHAPTER 1. ABOUT GAP
support a different structure, e.g., a ring or vector space structure, can not be represented
by this domain. So you need a different domain to represent this different structure. (We
are planning to add functions that changes the structure of a domain, e.g. AsRing( field )
should return a new domain with the same elements as field but with a ring structure.)
Domains may have certain properties. For example a ring may be commutative and a group
may be nilpotent. Whether a domain has a certain property Property can be tested with
the function IsProperty.
gap> IsCommutativeRing( GaussianIntegers );
true
gap> IsNilpotent( a5 );
false
There are also similar functions that test whether a domain (especially a group) is represented in a certain way. For example IsPermGroup tests whether a group is represented as
a permutation group.
gap> IsPermGroup( a5 );
true
gap> IsPermGroup( a4 / v4 );
false
# a4 / v4 is represented as a generic factor group
There is a slight difference between a function such as IsNilpotent and a function such
as IsPermGroup. The former tests properties of an abstract group and its outcome is
independent of the representation of that group. The latter tests whether a group is given
in a certain representation.
This (rather philosophical) issue is further complicated by the fact that sometimes representations and properties are not independent. This is especially subtle with IsSolvable
(see 7.61) and IsAgGroup (see 25.26). IsSolvable tests whether a group G is solvable.
IsAgGroup tests whether a group G is represented as a finite polycyclic group, i.e., by a
finite presentation that allows to efficiently compute canonical normal forms of elements
(see 25). Of course every finite polycyclic group is solvable, so IsAgGroup( G ) implies
IsSolvable( G ). On the other hand IsSolvable( G ) does not imply IsAgGroup( G
), because, even though each solvable group can be represented as a finite polycyclic group,
it need not, e.g., it could also be represented as a permutation group.
The organization of the manual follows the structure of domains and categories.
After the description of the programming language and the environment chapter 4 describes
the domains and the functions applicable to all domains.
Next come the chapters that describe the categories rings, fields, groups, and vector spaces.
The remaining chapters describe GAP3’s data–types and the domains one can make with
those elements of those data-types. The order of those chapters roughly follows the order of
the categories. The data–types whose elements form rings and fields come first (e.g., integers
and finite fields), followed by those whose elements form groups (e.g., permutations), and so
on. The data–types whose elements support little or no algebraic structure come last (e.g.,
booleans). In some cases there may be two chapters for one data–type, one describing the
elements and the other describing the domains made with those elements (e.g., permutations
and permutation groups).
1.24. ABOUT MAPPINGS AND HOMOMORPHISMS
133
The GAP3 manual not only describes what you can do, it also gives some hints how GAP3
performs its computations. However, it can be tricky to find those hints. The index of this
manual can help you.
Suppose that you want to intersect two permutation groups. If you read the section that
describes the function Intersection (see 4.12) you will see that the last paragraph describes
the default method used by Intersection. Such a last paragraph that describes the default
method is rather typical. In this case it says that Intersection computes the proper set
of elements of both domains and intersect them. It also says that this method is often
overlaid with a more efficient one. You wonder whether this is the case for permutation
groups. How can you find out? Well you look in the index under Intersection. There you
will find a reference Intersection, for permutation groups to section Set Functions
for Permutation Groups (see 21.20). This section tells you that Intersection uses a
backtrack for permutation groups (and cites a book where you can find a description of the
backtrack).
Let us now suppose that you intersect two factor groups. There is no reference in the
index for Intersection, for factor groups. But there is a reference for Intersection, for
groups to the section Set Functions for Groups (see 7.114). Since this is the next best
thing, look there. This section further directs you to the section Intersection for Groups
(see 7.116). This section finally tells you that Intersection computes the intersection of
two groups G and H as the stabilizer in G of the trivial coset of H under the operation of
G on the right cosets of H .
In this section we introduced domains and categories. You have learned that a domain is
a structured set, and that domains are either predefined, created by domain constructors,
or returned by library functions. You have seen most functions that are applicable to all
domains. Those functions generally ignore the structure and treat a domain as the set of
its elements. You have learned that categories are sets of domains, and that the category a
domain belongs to determines which functions are applicable to this domain.
More information about domains can be found in chapter 4. Chapters 5, 6, 7, and 9 define
the categories known to GAP3. The section 1.27 opens that black boxes and shows how all
this works.
1.24
About Mappings and Homomorphisms
A mapping is an object which maps each element of its source to a value in its range.
Source and range can be arbitrary sets of elements. But in most applications the source
and range are structured sets and the mapping, in such applications called homomorphism,
is compatible with this structure.
In the last sections you have already encountered examples of homomorphisms, namely
natural homomorphisms of groups onto their factor groups and operation homomorphisms
of groups into symmetric groups.
Finite fields also bear a structure and homomorphisms between fields are always bijections.
The Galois group of a finite field is generated by the Frobenius automorphism. It is very
easy to construct.
gap> f := FrobeniusAutomorphism( GF(81) );
FrobeniusAutomorphism( GF(3^4) )
134
CHAPTER 1. ABOUT GAP
gap> Image( f, Z(3^4) );
Z(3^4)^3
gap> A := Group( f );
Group( FrobeniusAutomorphism( GF(3^4) ) )
gap> Size( A );
4
gap> IsCyclic( A );
true
gap> Order( Mappings, f );
4
gap> Kernel( f );
[ 0*Z(3) ]
For finite fields and cyclotomic fields the function GaloisGroup is an easy way to construct
the Galois group.
gap> GaloisGroup( GF(81) );
Group( FrobeniusAutomorphism( GF(3^4) ) )
gap> Size( last );
4
gap> GaloisGroup( CyclotomicField( 18 ) );
Group( NFAutomorphism( CF(9) , 2 ) )
gap> Size( last );
6
Not all group homomorphisms are bijections of course, natural homomorphisms do have a
kernel in most cases and operation homomorphisms need neither be surjective nor injective.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> s4.name := "s4";;
gap> v4 := Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4) ] );
Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4) ] )
gap> v4.name := "v4";;
gap> s3 := s4 / v4;
(s4 / v4)
gap> f := NaturalHomomorphism( s4, s3 );
NaturalHomomorphism( s4, (s4 / v4) )
gap> IsHomomorphism( f );
true
gap> IsEpimorphism( f );
true
gap> Image( f );
(s4 / v4)
gap> IsMonomorphism( f );
false
gap> Kernel( f );
v4
The image of a group homomorphism is always one element of the range but the preimage
can be a coset. In order to get one representative of this coset you can use the function
PreImagesRepresentative.
1.24. ABOUT MAPPINGS AND HOMOMORPHISMS
135
gap> Image( f, (1,2,3,4) );
FactorGroupElement( v4, (2,4) )
gap> PreImages( f, s3.generators[1] );
(v4*(2,4))
gap> PreImagesRepresentative( f, s3.generators[1] );
(2,4)
But even if the homomorphism is a monomorphism but not surjective you can use the
function PreImagesRepresentative in order to get the preimage of an element of the range.
gap> A := Z(3) * [ [ 0, 1 ], [ 1, 0 ] ];;
gap> B := Z(3) * [ [ 0, 1 ], [ -1, 0 ] ];;
gap> G := Group( A, B );
Group( [ [ 0*Z(3), Z(3) ], [ Z(3), 0*Z(3) ] ],
[ [ 0*Z(3), Z(3) ], [ Z(3)^0, 0*Z(3) ] ] )
gap> Size( G );
8
gap> G.name := "G";;
gap> d8 := Operation( G, Orbit( G, Z(3)*[1,0] ) );
Group( (1,2)(3,4), (1,2,3,4) )
gap> e := OperationHomomorphism( Subgroup( G, [B] ), d8 );
OperationHomomorphism( Subgroup( G,
[ [ [ 0*Z(3), Z(3) ], [ Z(3)^0, 0*Z(3) ] ] ] ), Group( (1,2)(3,4),
(1,2,3,4) ) )
gap> Kernel( e );
Subgroup( G, [ ] )
gap> IsSurjective( e );
false
gap> PreImages( e, (1,3)(2,4) );
(Subgroup( G, [ ] )*[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ])
gap> PreImage( e, (1,3)(2,4) );
Error, must be a bijection, not an arbitrary mapping in
bij.operations.PreImageElm( bij, img ) called from
PreImage( e, (1,3)(2,4) ) called from
main loop
brk> quit;
gap> PreImagesRepresentative( e, (1,3)(2,4) );
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ]
Only bijections allow PreImage in order to get the preimage of an element of the range.
gap> Operation( G, Orbit( G, Z(3)*[1,0] ) );
Group( (1,2)(3,4), (1,2,3,4) )
gap> d := OperationHomomorphism( G, last );
OperationHomomorphism( G, Group( (1,2)(3,4), (1,2,3,4) ) )
gap> PreImage( d, (1,3)(2,4) );
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ]
Both PreImage and PreImages can also be applied to sets. They return the complete
preimage.
gap> PreImages( d, Group( (1,2)(3,4), (1,3)(2,4) ) );
136
CHAPTER 1. ABOUT GAP
Subgroup( G, [ [ [ 0*Z(3), Z(3) ], [ Z(3), 0*Z(3) ] ],
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ] ] )
gap> Size( last );
4
gap> f := NaturalHomomorphism( s4, s3 );
NaturalHomomorphism( s4, (s4 / v4) )
gap> PreImages( f, s3 );
Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4), (2,4), (3,4) ] )
gap> Size( last );
24
Another way to construct a group automorphism is to use elements in the normalizer of a
subgroup and construct the induced automorphism. A special case is the inner automorphism induced by an element of a group, a more general case is a surjective homomorphism
induced by arbitrary elements of the parent group.
gap> d12 := Group((1,2,3,4,5,6),(2,6)(3,5));; d12.name := "d12";;
gap> i1 := InnerAutomorphism( d12, (1,2,3,4,5,6) );
InnerAutomorphism( d12, (1,2,3,4,5,6) )
gap> Image( i1, (2,6)(3,5) );
(1,3)(4,6)
gap> IsAutomorphism( i1 );
true
Mappings can also be multiplied, provided that the range of the first mapping is a subgroup
of the source of the second mapping. The multiplication is of course defined as the composition. Note that, in line with the fact that mappings operate from the right, Image(
map1 * map2 , elm ) is defined as Image( map2 , Image( map1 , elm ) ).
gap> i2 := InnerAutomorphism( d12, (2,6)(3,5) );
InnerAutomorphism( d12, (2,6)(3,5) )
gap> i1 * i2;
InnerAutomorphism( d12, (1,6)(2,5)(3,4) )
gap> Image( last, (2,6)(3,5) );
(1,5)(2,4)
Mappings can also be inverted, provided that they are bijections.
gap> i1 ^ -1;
InnerAutomorphism( d12, (1,6,5,4,3,2) )
gap> Image( last, (2,6)(3,5) );
(1,5)(2,4)
Whenever you have a set of bijective mappings on a finite set (or domain) you can construct
the group generated by those mappings. So in the following example we create the group
of inner automorphisms of d12.
gap> autd12 := Group( i1, i2 );
Group( InnerAutomorphism( d12,
(1,2,3,4,5,6) ), InnerAutomorphism( d12, (2,6)(3,5) ) )
gap> Size( autd12 );
6
gap> Index( d12, Centre( d12 ) );
1.24. ABOUT MAPPINGS AND HOMOMORPHISMS
137
6
Note that the computation with such automorphism groups in their present implementation
is not very efficient. For example to compute the size of such an automorphism group all
elements are computed. Thus work with such automorphism groups should be restricted to
very small examples.
The function ConjugationGroupHomomorphism is a generalization of InnerAutomorphism.
It accepts a source and a range and an element that conjugates the source into the range.
Source and range must lie in a common parent group, and the conjugating element must
also lie in this parent group.
gap> c2 := Subgroup( d12, [ (2,6)(3,5) ] );
Subgroup( d12, [ (2,6)(3,5) ] )
gap> v4 := Subgroup( d12, [ (1,2)(3,6)(4,5), (1,4)(2,5)(3,6) ] );
Subgroup( d12, [ (1,2)(3,6)(4,5), (1,4)(2,5)(3,6) ] )
gap> x := ConjugationGroupHomomorphism( c2, v4, (1,3,5)(2,4,6) );
ConjugationGroupHomomorphism( Subgroup( d12,
[ (2,6)(3,5) ] ), Subgroup( d12, [ (1,2)(3,6)(4,5), (1,4)(2,5)(3,6)
] ), (1,3,5)(2,4,6) )
gap> IsSurjective( x );
false
gap> Image( x );
Subgroup( d12, [ (1,5)(2,4) ] )
But how can we construct homomorphisms which are not induced by elements of the parent
group? The most general way to construct a group homomorphism is to define the source,
range and the images of the generators under the homomorphism in mind.
gap> c := GroupHomomorphismByImages( G, s4, [A,B], [(1,2),(3,4)] );
GroupHomomorphismByImages( G, s4,
[ [ [ 0*Z(3), Z(3) ], [ Z(3), 0*Z(3) ] ],
[ [ 0*Z(3), Z(3) ], [ Z(3)^0, 0*Z(3) ] ] ], [ (1,2), (3,4) ] )
gap> Kernel( c );
Subgroup( G, [ [ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ] ] )
gap> Image( c );
Subgroup( s4, [ (1,2), (3,4) ] )
gap> IsHomomorphism( c );
true
gap> Image( c, A );
(1,2)
gap> PreImages( c, (1,2) );
(Subgroup( G, [ [ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ] ] )*
[ [ 0*Z(3), Z(3) ], [ Z(3), 0*Z(3) ] ])
Note that it is possible to construct a general mapping this way that is not a homomorphism,
because GroupHomomorphismByImages does not check if the given images fulfill the relations
of the generators.
gap> b := GroupHomomorphismByImages( G, s4, [A,B], [(1,2,3),(3,4)] );
GroupHomomorphismByImages( G, s4,
[ [ [ 0*Z(3), Z(3) ], [ Z(3), 0*Z(3) ] ],
138
CHAPTER 1. ABOUT GAP
[ [ 0*Z(3), Z(3) ], [ Z(3)^0, 0*Z(3) ] ] ], [ (1,2,3), (3,4) ] )
gap> IsHomomorphism( b );
false
gap> Images( b, A );
(Subgroup( s4, [ (1,3,2), (2,3,4), (1,3,4), (1,4)(2,3), (1,4,2)
] )*())
The result is a multi valued mapping, i.e., one that maps each element of its source to a
set of elements in its range. The set of images of A under b is defined as follows. Take all
the words of two letters w(x, y) such that w(A, B) = A, e.g., x and xyxyx. Then the set of
images is the set of elements that you get by inserting the images of A and B in those words,
i.e., w((1, 2, 3), (3, 4)), e.g., (1, 2, 3) and (1, 4, 2). One can show that the set of images of the
identity under a multi valued mapping such as b is a subgroup and that the set of images
of other elements are cosets of this subgroup.
1.25
About Character Tables
This section contains some examples of the use of GAP3 in character theory. First a few
very simple commands for handling character tables are introduced, and afterwards we will
construct the character tables of (A5 × 3) : 2 and of A6 .22 .
GAP3 has a large library of character tables, so let us look at one of these tables, e.g., the
table of the Mathieu group M11 :
gap> m11:= CharTable( "M11" );
CharTable( "M11" )
Character tables contain a lot of information. This is not printed in full length since the
internal structure is not easy to read. The next statement shows a more comfortable output
format.
gap> DisplayCharTable( m11 );
M11
X.1
X.2
X.3
X.4
X.5
X.6
2
3
5
11
4
2
1
1
4
1
.
.
1
2
.
.
3
.
.
.
.
.
1
.
1
1
.
.
3
.
.
.
3
.
.
.
.
.
.
1
.
.
.
1
2P
3P
5P
11P
1a
1a
1a
1a
1a
2a
1a
2a
2a
2a
3a
3a
1a
3a
3a
4a
2a
4a
4a
4a
5a
5a
5a
1a
5a
6a
3a
2a
6a
6a
8a
4a
8a
8b
8a
8b
4a
8b
8a
8b
11a
11b
11a
11a
1a
11b
11a
11b
11b
1a
1 1 1 1
. -1 . .
. 1 A -A
. 1 -A A
1 . -1 -1
1 . . .
1
-1
-1
-1
.
B
1
-1
-1
-1
.
/B
1 1 1 1
10 2 1 2
10 -2 1 .
10 -2 1 .
11 3 2 -1
16 . -2 .
1.25. ABOUT CHARACTER TABLES
X.7
X.8
X.9
X.10
A =
=
B =
=
16 . -2 . 1 . . .
44 4 -1 . -1 1 . .
45 -3 . 1 . . -1 -1
55 -1 1 -1 . -1 1 1
139
/B
.
1
.
B
.
1
.
E(8)+E(8)^3
ER(-2) = i2
E(11)+E(11)^3+E(11)^4+E(11)^5+E(11)^9
(-1+ER(-11))/2 = b11
We are not too much interested in the internal structure of this character table (see 49.2);
but of course we can access all information about the centralizer orders (first four lines),
element orders (next line), power maps for the prime divisors of the group order (next four
lines), irreducible characters (lines parametrized by X.1 . . . X.10) and irrational character
values (last four lines), see 49.37 for a detailed description of the format of the displayed
table. E.g., the irreducible characters are a list with name m11.irreducibles, and each
character is a list of cyclotomic integers (see chapter 13). There are various ways to describe
the irrationalities; e.g., the square root of −2 can be entered as E(8) + E(8)^3 or ER(-2),
the famous ATLAS of Finite Groups [CCN+ 85] denotes it as i2.
gap> m11.irreducibles[3];
[ 10, -2, 1, 0, 0, 1, E(8)+E(8)^3, -E(8)-E(8)^3, -1, -1 ]
We can for instance form tensor products of this character with all irreducibles, and compute
the decomposition into irreducibles.
gap> tens:= Tensored( [ last ], m11.irreducibles );;
gap> MatScalarProducts( m11, m11.irreducibles, tens );
[ [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0,
[ 0, 0, 0, 0, 1, 0, 0, 1, 1, 0 ], [ 1, 0, 0, 0, 0, 0,
[ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1 ], [ 0, 0, 0, 0, 0, 0,
[ 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 ], [ 0, 0, 1, 1, 0, 1,
[ 0, 1, 0, 1, 1, 1, 1, 3, 2, 3 ], [ 0, 1, 1, 0, 1, 1,
0,
0,
1,
1,
1,
0,
1,
1,
2,
3,
1,
0,
1,
3,
3,
1
1
1
3
4
],
],
],
],
] ]
The decomposition means for example that the third character in the list tens is the sum
of the irreducible characters at positions 5, 8 and 9.
gap> tens[3];
[ 100, 4, 1, 0, 0, 1, -2, -2, 1, 1 ]
gap> tens[3] = Sum( Sublist( m11.irreducibles, [ 5, 8, 9 ] ) );
true
Or we can compute symmetrizations, e.g., the characters χ2+ , defined by χ2+ (g) = 21 (χ2 (g)+
χ(g 2 )), for all irreducibles.
gap> sym:= SymmetricParts( m11, m11.irreducibles, 2 );;
gap> MatScalarProducts( m11, m11.irreducibles, sym );
[ [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 1, 1, 0, 0, 0, 0,
[ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0,
[ 1, 1, 0, 0, 1, 0, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 1, 0,
[ 0, 1, 0, 0, 1, 1, 0, 1, 0, 1 ], [ 1, 3, 0, 0, 3, 2,
[ 1, 2, 0, 0, 3, 2, 2, 8, 4, 7 ],
[ 1, 3, 1, 1, 4, 3, 3, 11, 7, 10 ] ]
0,
0,
1,
2,
1,
1,
1,
8,
0,
0,
0,
4,
0
0
1
6
],
],
],
],
140
CHAPTER 1. ABOUT GAP
gap> sym[2];
[ 55, 7, 1, 3, 0, 1, 1, 1, 0, 0 ]
gap> sym[2] = Sum( Sublist( m11.irreducibles, [ 1, 2, 8 ] ) );
true
If the subgroup fusion into a supergroup is known, characters can be induced to this group,
e.g., to obtain the permutation character of the action of M12 on the cosets of M11 .
gap> m12:= CharTable( "M12" );;
gap> permchar:= Induced( m11, m12, [ m11.irreducibles[1] ] );
[ [ 12, 0, 4, 3, 0, 0, 4, 2, 0, 1, 0, 2, 0, 1, 1 ] ]
gap> MatScalarProducts( m12, m12.irreducibles, last );
[ [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ]
gap> DisplayCharTable( m12, rec( chars:= permchar ) );
M12
2
3
5
11
6
3
1
1
4
1
1
.
6
1
.
.
1
3
.
.
2
2
.
.
5
.
.
.
5
.
.
.
1
.
1
.
2
1
.
.
1
1
.
.
3
.
.
.
2P
3P
5P
11P
1a
1a
1a
1a
1a
2a
1a
2a
2a
2a
2b
1a
2b
2b
2b
3a
3a
1a
3a
3a
3b
3b
1a
3b
3b
4a
2b
4a
4a
4a
4b
2b
4b
4b
4b
5a
5a
5a
1a
5a
6a
3b
2a
6a
6a
6b
3a
2b
6b
6b
8a
4a
8a
8a
8a
12
.
4
3
.
.
4
2
.
1
.
Y.1
3
.
.
.
1
.
1
.
.
.
.
1
.
.
.
1
8b 10a 11a 11b
4b 5a 11b 11a
8b 10a 11a 11b
8b 2a 11a 11b
8b 10a 1a 1a
2
.
1
1
It should be emphasized that the heart of character theory is dealing with lists. Characters
are lists, and also the maps which occur are represented as lists. Note that the multiplication
of group elements is not available, so we neither have homomorphisms. All we can talk of
are class functions, and the lists are regarded as such functions, being the lists of images
with respect to a fixed order of conjugacy classes. Therefore we do not write chi( cl )
or cl^chi for the value of the character chi on the class cl, but chi[i] where i is the
position of the class cl.
Since the data structures are so basic, most calculations involve compositions of maps; for
example, the embedding of a subgroup in a group is described by the so–called subgroup
fusion which is a class function that maps each class c of the subgroup to that class of the
group that contains c. Consider the symmetric group S5 ∼
= A5 .2 as subgroup of M11 . (Do
not worry about the names that are used to get library tables, see 49.12 for an overview.)
gap> s5:= CharTable( "A5.2" );;
gap> map:= GetFusionMap( s5, m11 );
[ 1, 2, 3, 5, 2, 4, 6 ]
The subgroup fusion is already stored on the table. We see that class 1 of s5 is mapped to
class 1 of m11 (which means that the identity of S5 maps to the identity of M11 ), classes 2
and 5 of s5 both map to class 2 of m11 (which means that all involutions of S5 are conjugate
in M11 ), and so on.
1.25. ABOUT CHARACTER TABLES
141
The restriction of a character of m11 to s5 is just the composition of this character with
the subgroup fusion map. Viewing this map as list one would call this composition an
indirection.
gap> chi:= m11.irreducibles[3];
[ 10, -2, 1, 0, 0, 1, E(8)+E(8)^3, -E(8)-E(8)^3, -1, -1 ]
gap> rest:= List( map, x -> chi[x] );
[ 10, -2, 1, 0, -2, 0, 1 ]
This looks very easy, and many GAP3 functions in character theory do such simple calculations. But note that it is not always obvious that a list is regarded as a map, where
preimages and/or images refer to positions of certain conjugacy classes.
gap> alt:= s5.irreducibles[2];
[ 1, 1, 1, 1, -1, -1, -1 ]
gap> kernel:= KernelChar( last );
[ 1, 2, 3, 4 ]
The kernel of a character is represented as the list of (positions of) classes lying in the kernel.
We know that the kernel of the alternating character alt of s5 is the alternating group A5 .
The order of the kernel can be computed as sum of the lengths of the contained classes from
the character table, using that the classlengths are stored in the classes component of the
table.
gap> s5.classes;
[ 1, 15, 20, 24, 10, 30, 20 ]
gap> last{ kernel };
[ 1, 15, 20, 24 ]
gap> Sum( last );
60
We chose those classlengths of s5 that belong to the S5 –classes contained in the alternating
group. The same thing is done in the following command, reflecting the view of the kernel
as map.
gap> List( kernel, x -> s5.classes[x] );
[ 1, 15, 20, 24 ]
gap> Sum( kernel, x -> s5.classes[x] );
60
This small example shows how the functions List and Sum can be used. These functions
as well as Filtered were introduced in 1.16, and we will make heavy use of them; in many
cases such a command might look very strange, but it is just the translation of a (hardly
less complicated) mathematical formula to character theory.
And now let us construct some small character tables!
The group G = (A5 × 3) : 2 is a maximal subS5 ×b S3
group of the alternating group A8 ; G extends
@
@b A × S
S5 × 3 b bG
to S5 × S3 in S8 . We want to construct the
5
3
@
@b @
character table of G.
@
@
First the tables of the subgroup A5 × 3 and
S5 b
@ @bS3
@
the supergroup S5 × S3 are constructed; the
@
b
@b 3
A5
@
tables of the factors of each direct product are
@
again got from the table library using admis@b
sible names, see 49.12 for this.
142
CHAPTER 1. ABOUT GAP
gap> a5:= CharTable( "A5" );;
gap> c3:= CharTable( "Cyclic", 3 );;
gap> a5xc3:= CharTableDirectProduct( a5, c3 );;
gap> s5:= CharTable( "A5.2" );;
gap> s3:= CharTable( "Symmetric", 3 );;
gap> s3.irreducibles;
[ [ 1, -1, 1 ], [ 2, 0, -1 ], [ 1, 1, 1 ] ]
# The trivial character shall be the first one.
gap> SortCharactersCharTable( s3 ); # returns the applied permutation
(1,2,3)
gap> s5xs3:= CharTableDirectProduct( s5, s3 );;
G is the normal subgroup of index 2 in S5 × S3 which contains neither S5 nor the normal
S3 . We want to find the classes of s5xs3 whose union is G. For that, we compute the
set of kernels of irreducibles –remember that they are given simply by lists of numbers of
contained classes– and then choose those kernels belonging to normal subgroups of index 2.
gap> kernels:= Set( List( s5xs3.irreducibles, KernelChar ) );
[ [ 1 ], [ 1, 2, 3 ], [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ],
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21 ], [ 1, 3 ],
[ 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21 ],
[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ], [ 1, 4, 7, 10 ],
[ 1, 4, 7, 10, 13, 16, 19 ] ]
gap> sizes:= List( kernels, x -> Sum( Sublist( s5xs3.classes, x ) ) );
[ 1, 6, 360, 720, 3, 360, 360, 60, 120 ]
gap> s5xs3.size;
720
gap> index2:= Sublist( kernels, [ 3, 6, 7 ] );
[ [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ],
[ 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21 ],
[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ] ]
In order to decide which kernel describes G, we consider the embeddings of s5 and s3 in
s5xs3, given by the subgroup fusions.
gap> s5ins5xs3:= GetFusionMap( s5, s5xs3 );
[ 1, 4, 7, 10, 13, 16, 19 ]
gap> s3ins5xs3:= GetFusionMap( s3, s5xs3 );
[ 1, 2, 3 ]
gap> Filtered( index2, x->Intersection(x,s5ins5xs3)<>s5ins5xs3 and
>
Intersection(x,s3ins5xs3)<>s3ins5xs3
);
[ [ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ] ]
gap> nsg:= last[1];
[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ]
We now construct a first approximation of the character table of this normal subgroup,
namely the restriction of s5xs3 to the classes given by nsg.
gap> sub:= CharTableNormalSubgroup( s5xs3, nsg );;
#I CharTableNormalSubgroup: classes in [ 8 ] necessarily split
gap> PrintCharTable( sub );
1.25. ABOUT CHARACTER TABLES
143
rec( identifier := "Rest(A5.2xS3,[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 2\
0 ])", size :=
360, name := "Rest(A5.2xS3,[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ])",\
order := 360, centralizers := [ 360, 180, 24, 12, 18, 9, 15, 15/2,
12, 4, 6 ], orders := [ 1, 3, 2, 6, 3, 3, 5, 15, 2, 4, 6
], powermap := [ , [ 1, 2, 1, 2, 5, 6, 7, 8, 1, 3, 5 ],
[ 1, 1, 3, 3, 1, 1, 7, 7, 9, 10, 9 ],,
[ 1, 2, 3, 4, 5, 6, 1, 2, 9, 10, 11 ] ], classes :=
[ 1, 2, 15, 30, 20, 40, 24, 48, 30, 90, 60
], operations := CharTableOps, irreducibles :=
[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1 ],
[ 2, -1, 2, -1, 2, -1, 2, -1, 0, 0, 0 ],
[ 6, 6, -2, -2, 0, 0, 1, 1, 0, 0, 0 ],
[ 4, 4, 0, 0, 1, 1, -1, -1, 2, 0, -1 ],
[ 4, 4, 0, 0, 1, 1, -1, -1, -2, 0, 1 ],
[ 8, -4, 0, 0, 2, -1, -2, 1, 0, 0, 0 ],
[ 5, 5, 1, 1, -1, -1, 0, 0, 1, -1, 1 ],
[ 5, 5, 1, 1, -1, -1, 0, 0, -1, 1, -1 ],
[ 10, -5, 2, -1, -2, 1, 0, 0, 0, 0, 0 ] ], fusions := [ rec(
name := [ ’A’, ’5’, ’.’, ’2’, ’x’, ’S’, ’3’ ],
map := [ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ] ) ] )
Not all restrictions of irreducible characters of s5xs3 to sub remain irreducible. We compute
those restrictions with norm larger than 1.
gap> red:= Filtered( Restricted( s5xs3, sub, s5xs3.irreducibles ),
>
x -> ScalarProduct( sub, x, x ) > 1 );
[ [ 12, -6, -4, 2, 0, 0, 2, -1, 0, 0, 0 ] ]
gap> Filtered( [ 1 .. Length( nsg ) ],
>
x -> not IsInt( sub.centralizers[x] ) );
[ 8 ]
Note that sub is not actually a character table in the sense of mathematics but only a
record with components like a character table. GAP3 does not know about this subtleties
and treats it as a character table.
As the list centralizers of centralizer orders shows, at least class 8 splits into two conjugacy
classes in G, since this is the only possibility to achieve integral centralizer orders.
Since 10 restrictions of irreducible characters remain irreducible for G (sub contains 10
irreducibles), only one of the 11 irreducibles of S5 × S3 splits into two irreducibles of G, in
other words, class 8 is the only splitting class.
Thus we create a new approximation of the desired character table (which we call split)
where this class is split; 8th and 9th column of the known irreducibles are of course equal,
and due to the splitting the second powermap for these columns is ambiguous.
gap>
gap>
gap>
rec(
splitting:= [ 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11 ];;
split:= CharTableSplitClasses( sub, splitting );;
PrintCharTable( split );
identifier := "Split(Rest(A5.2xS3,[ 1, 3, 4, 6, 7, 9, 10, 12, 14,\
144
CHAPTER 1. ABOUT GAP
17, 20 ]),[ 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11 ])", size :=
360, order :=
360, name := "Split(Rest(A5.2xS3,[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 2\
0 ]),[ 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11 ])", centralizers :=
[ 360, 180, 24, 12, 18, 9, 15, 15, 15, 12, 4, 6 ], classes :=
[ 1, 2, 15, 30, 20, 40, 24, 24, 24, 30, 90, 60 ], orders :=
[ 1, 3, 2, 6, 3, 3, 5, 15, 15, 2, 4, 6 ], powermap :=
[ , [ 1, 2, 1, 2, 5, 6, 7, [ 8, 9 ], [ 8, 9 ], 1, 3, 5 ],
[ 1, 1, 3, 3, 1, 1, 7, 7, 7, 10, 11, 10 ],,
[ 1, 2, 3, 4, 5, 6, 1, 2, 2, 10, 11, 12 ] ], irreducibles :=
[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1 ],
[ 2, -1, 2, -1, 2, -1, 2, -1, -1, 0, 0, 0 ],
[ 6, 6, -2, -2, 0, 0, 1, 1, 1, 0, 0, 0 ],
[ 4, 4, 0, 0, 1, 1, -1, -1, -1, 2, 0, -1 ],
[ 4, 4, 0, 0, 1, 1, -1, -1, -1, -2, 0, 1 ],
[ 8, -4, 0, 0, 2, -1, -2, 1, 1, 0, 0, 0 ],
[ 5, 5, 1, 1, -1, -1, 0, 0, 0, 1, -1, 1 ],
[ 5, 5, 1, 1, -1, -1, 0, 0, 0, -1, 1, -1 ],
[ 10, -5, 2, -1, -2, 1, 0, 0, 0, 0, 0, 0 ] ], fusions := [ rec(
name := "Rest(A5.2xS3,[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ])"
,
map := [ 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11 ] )
], operations := CharTableOps )
gap> Restricted( sub, split, red );
[ [ 12, -6, -4, 2, 0, 0, 2, -1, -1, 0, 0, 0 ] ]
To complete the table means to find the missing two irreducibles and to complete the
powermaps. For this, there are different possibilities. First, one can try to embed G in A8 .
gap> a8:= CharTable( "A8" );;
gap> fus:= SubgroupFusions( split, a8 );
[ [ 1, 4, 3, 9, 4, 5, 8, 13, 14, 3, 7, 9 ],
[ 1, 4, 3, 9, 4, 5, 8, 14, 13, 3, 7, 9 ] ]
gap> fus:= RepresentativesFusions( split, fus, a8 );
#I RepresentativesFusions: no subtable automorphisms stored
[ [ 1, 4, 3, 9, 4, 5, 8, 13, 14, 3, 7, 9 ] ]
gap> StoreFusion( split, a8, fus[1] );
The subgroup fusion is unique up to table automorphisms. Now we restrict the irreducibles
of A8 to G and reduce.
gap> rest:= Restricted( a8, split, a8.irreducibles );;
gap> red:= Reduced( split, split.irreducibles, rest );
rec(
remainders := [ ],
irreducibles :=
[ [ 6, -3, -2, 1, 0, 0, 1, -E(15)-E(15)^2-E(15)^4-E(15)^8,
-E(15)^7-E(15)^11-E(15)^13-E(15)^14, 0, 0, 0 ],
[ 6, -3, -2, 1, 0, 0, 1, -E(15)^7-E(15)^11-E(15)^13-E(15)^14,
-E(15)-E(15)^2-E(15)^4-E(15)^8, 0, 0, 0 ] ] )
1.25. ABOUT CHARACTER TABLES
145
gap> Append( split.irreducibles, red.irreducibles );
The list of irreducibles is now complete, but the powermaps are not yet adjusted. To
complete the 2nd powermap, we transfer that of A8 to G using the subgroup fusion.
gap> split.powermap;
[ , [ 1, 2, 1, 2, 5, 6, 7, [ 8, 9 ], [ 8, 9 ], 1, 3, 5 ],
[ 1, 1, 3, 3, 1, 1, 7, 7, 7, 10, 11, 10 ],,
[ 1, 2, 3, 4, 5, 6, 1, 2, 2, 10, 11, 12 ] ]
gap> TransferDiagram( split.powermap[2], fus[1], a8.powermap[2] );;
And this is the complete table.
gap> split.identifier:= "(A5x3):2";;
gap> DisplayCharTable( split );
Split(Rest(A5.2xS3,[ 1, 3, 4, 6, 7, 9, 10, 12, 14, 17, 20 ]),[ 1, 2, 3\
, 4, 5, 6, 7, 8, 8, 9, 10, 11 ])
2
3
5
X.1
X.2
X.3
X.4
X.5
X.6
X.7
X.8
X.9
X.10
X.11
X.12
3
2
1
3
1
.
2
1
.
1
2
.
.
2
.
1a 3a 2a
2P 1a 3a 1a
3P 1a 1a 2a
5P 1a 3a 2a
6a
3a
2a
6a
3b
3b
1a
3b
3c
3c
1a
3c
1
1
2
6
4
4
8
5
5
10
6
6
2
2
1
.
1
1
2
.
.
1
1
.
5a 15a 15b 2b 4a
5a 15a 15b 1a 2a
5a 5a 5a 2b 4a
1a 3a 3a 2b 4a
6b
3b
2b
6b
1 1 1 1 1 1
1 1 1 1 1 1
-1 2 -1 2 -1 2
6 -2 -2 . . 1
4 . . 1 1 -1
4 . . 1 1 -1
-4 . . 2 -1 -2
5 1 1 -1 -1 .
5 1 1 -1 -1 .
-5 2 -1 -2 1 .
-3 -2 1 . . 1
-3 -2 1 . . 1
.
1
1
1
1
-1
1
-1
-1
1
.
.
.
A
/A
.
1
1
2
1
.
1 1 1 1
1 -1 -1 -1
-1 . . .
1 . . .
-1 2 . -1
-1 -2 . 1
1 . . .
. 1 -1 1
. -1 1 -1
. . . .
/A . . .
A . . .
A = -E(15)-E(15)^2-E(15)^4-E(15)^8
= (-1-ER(-15))/2 = -1-b15
There are many ways around the block, so two further methods to complete the table split
shall be demonstrated; but we will not go into details.
Without use of GAP3 one could work as follows:
The irrationalities –and there must be irrational entries in the character table of G, since
the outer 2 can conjugate at most two of the four Galois conjugate classes of elements of
order 15– could also have been found from the structure of G and the restriction of the
irreducible S5 × S3 character of degree 12.
146
CHAPTER 1. ABOUT GAP
On the classes that did not split the values of this character must just be divided by 2. Let
x be one of the irrationalities. The second orthogonality relation tells us that x · x = 4 (at
class 15a) and x + x∗ = −1 (at classes 1a and 15a); here x∗ denotes the nontrivial Galois
x, otherwise it leads to the quadratic equation
conjugate of x. This has no solution for x = √
x2 + x + 4 = 0 with solutions b15 = 21 (−1 + −15) and −1 − b15.
The third possibility to complete the table is to embed A5 × 3:
gap> split.irreducibles := split.irreducibles{ [ 1 .. 10 ] };;
gap> SubgroupFusions( a5xc3, split );
[ [ 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, [ 8, 9 ], [ 8, 9 ], 7, [ 8, 9 ],
[ 8, 9 ] ] ]
The images of the four classes of element order 15 are not determined, the returned list
parametrizes the 24 possibilities.
gap>
gap>
16
gap>
[ 1,
fus:= ContainedMaps( last[1] );;
Length( fus );
fus[1];
2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 7, 8, 8 ]
Most of these 16 possibilities are excluded using scalar products of induced characters. We
take a suitable character chi of a5xc3 and compute the norm of the induced character with
respect to each possible map.
gap> chi:= a5xc3.irreducibles[5];
[ 3, 3*E(3), 3*E(3)^2, -1, -E(3), -E(3)^2, 0, 0, 0, -E(5)-E(5)^4,
-E(15)^2-E(15)^8, -E(15)^7-E(15)^13, -E(5)^2-E(5)^3,
-E(15)^11-E(15)^14, -E(15)-E(15)^4 ]
gap> List( fus, x -> List( Induced( a5xc3, split, [ chi ], x ),
>
y -> ScalarProduct( split, y, y ) )[1] );
[ 8/15, -2/3*E(5)-11/15*E(5)^2-11/15*E(5)^3-2/3*E(5)^4,
-2/3*E(5)-11/15*E(5)^2-11/15*E(5)^3-2/3*E(5)^4, 2/3,
-11/15*E(5)-2/3*E(5)^2-2/3*E(5)^3-11/15*E(5)^4, 3/5, 1,
-11/15*E(5)-2/3*E(5)^2-2/3*E(5)^3-11/15*E(5)^4,
-11/15*E(5)-2/3*E(5)^2-2/3*E(5)^3-11/15*E(5)^4, 1, 3/5,
-11/15*E(5)-2/3*E(5)^2-2/3*E(5)^3-11/15*E(5)^4, 2/3,
-2/3*E(5)-11/15*E(5)^2-11/15*E(5)^3-2/3*E(5)^4,
-2/3*E(5)-11/15*E(5)^2-11/15*E(5)^3-2/3*E(5)^4, 8/15 ]
gap> Filtered( [ 1 .. Length( fus ) ], x -> IsInt( last[x] ) );
[ 7, 10 ]
So only fusions 7 and 10 may be possible. They are equivalent (with respect to table
automorphisms), and the list of induced characters contains the missing irreducibles of G:
gap> Sublist( fus, last );
[ [ 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 9, 7, 9, 8 ],
[ 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 9, 8, 7, 8, 9 ] ]
gap> ind:= Induced( a5xc3, split, a5xc3.irreducibles, last[1] );;
gap> Reduced( split, split.irreducibles, ind );
rec(
remainders := [ ],
1.25. ABOUT CHARACTER TABLES
147
irreducibles :=
[ [ 6, -3, -2, 1, 0, 0, 1, -E(15)-E(15)^2-E(15)^4-E(15)^8,
-E(15)^7-E(15)^11-E(15)^13-E(15)^14, 0, 0, 0 ],
[ 6, -3, -2, 1, 0, 0, 1, -E(15)^7-E(15)^11-E(15)^13-E(15)^14,
-E(15)-E(15)^2-E(15)^4-E(15)^8, 0, 0, 0 ] ] )
The following example is thought mainly for experts. It shall demonstrate how one can work
together with GAP3 and the ATLAS [CCN+ 85], so better leave out the rest of this section
if you are not familiar with the ATLAS.
We shall construct the character table of the group G =
A6 .22 ∼
= Aut(A6 ) from the tables of the normal subgroups
A6 .21 ∼
= S6 , A6 .22 ∼
= P GL(2, 9) and A6 .23 ∼
= M10 .
We regard G as a downward extension of the Klein fourgroup 22 with A6 . The set of classes of all preimages of
cyclic subgroups of 22 covers the classes of G, but it may
happen that some representatives are conjugate in G, i.e.,
the classes fuse.
The ATLAS denotes the character tables of G, G.21 , G.22
and G.23 as follows:
;
@
@
@
@
@
@
360
p power
p' part
ind 1A
8
A
A
2A
9
A
A
3A
9
A
A
3B
4
A
A
4A
5
A
A
5A
@
;
G
@
@
A6 .21 A6 .23 A6 .22
@
@
A6
b
;
@
@
@
@
@
5
A
A
B* fus ind
24
A
A
2B
24
A
A
2C
4
A
A
4B
3
AB
AB
6A
3
BC
BC
6B
χ1
+
1
1
1
1
1
1
1
:
++
1
1
1
1
1
χ2
+
5
1
2
-1
-1
0
0
:
++
3
-1
1
0
-1
χ3
+
5
1
-1
2
-1
0
0
:
++
-1
3
1
-1
0
χ4
+
8
0
-1
-1
0 -b5
*
.
+
0
0
0
0
0
χ5
+
8
0
-1
-1
0
* -b5
.
χ6
+
9
1
0
0
1
-1
-1
:
++
3
3
-1
0
0
χ7
+
10
-2
1
1
0
0
0
:
++
2
-2
0
-1
1
148
CHAPTER 1. ABOUT GAP
;
;
@
@
10
A
A
fus ind 2D
4
A
A
8A
@
@
4
5
A BD
A AD
B* 10A
@
;
;
@
5
2
AD
A
BD
A
B* fus ind 4C
@
@
4
4
A
A
A
A
8C D**
:
++
1
1
1
1
1
:
++
1
1
1
χ1
.
+
0
0
0
0
0
.
+
0
0
0
χ2
.
χ3
.
:
++
2
0
0
b5
*
.
:
++
2
0
0
*
b5
.
:
++ -1
1
1
-1
-1
:
+
0
0
0
χ4
χ5
++
1
-1
-1
χ6
: ++ 0 r2 -r2
0
0
: oo 0 i2 -i2
χ7
First we construct a table whose classes are those of the three subgroups. Note that the
exponent of A6 is 60, so the representative orders could become at most 60 times the value
in 22 .
gap> s1:= CharTable( "A6.2_1" );;
gap> s2:= CharTable( "A6.2_2" );;
gap> s3:= CharTable( "A6.2_3" );;
gap> c2:= CharTable( "Cyclic", 2 );;
gap> v4:= CharTableDirectProduct( c2, c2 );;
#I CharTableDirectProduct: existing subgroup fusion on replaced
#I
by actual one
gap> for tbl in [ s1, s2, s3 ] do
>
Print( tbl.irreducibles[2], "\n" );
>
od;
[ 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 ]
[ 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 ]
[ 1, 1, 1, 1, 1, -1, -1, -1 ]
gap> split:= CharTableSplitClasses( v4,
>
[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4], 60 );;
gap> PrintCharTable( split );
rec( identifier := "Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, \
3, 3, 3, 4, 4, 4 ])", size := 4, order :=
4, name := "Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,\
4, 4, 4 ])", centralizers := [ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4 ], classes := [ 1/5, 1/5, 1/5, 1/5, 1/5, 1/5, 1/5,
1/5, 1/5, 1/5, 1/5, 1/5, 1/5, 1/5, 1/5, 1/3, 1/3, 1/3 ], orders :=
[ 1, [ 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 ],
[ 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 ],
1.25. ABOUT CHARACTER TABLES
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[
[ ,
[ [
[
[
[
],
149
2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 ],
2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ],
2, 4, 6, 8, 10, 12, 20, 24, 30, 40, 60, 120 ] ], powermap :=
[ 1, [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ],
[ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ],
[ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ],
[ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ],
[ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ],
[ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ] ] ], irreducibles :=
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1 ],
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1 ]
fusions := [ rec(
name := [ ’C’, ’2’, ’x’, ’C’, ’2’ ],
map := [ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4 ]
) ], operations := CharTableOps )
Now we embed the subgroups and adjust the classlengths, order, centralizers, powermaps
and thus the representative orders.
gap> StoreFusion( s1, split, [1,2,3,3,4,5,6,7,8,9,10]);
gap> StoreFusion( s2, split, [1,2,3,4,5,5,11,12,13,14,15]);
gap> StoreFusion( s3, split, [1,2,3,4,5,16,17,18]);
gap> for tbl in [ s1, s2, s3 ] do
>
fus:= GetFusionMap( tbl, split );
>
for class in Difference( [ 1 .. Length( tbl.classes ) ],
>
KernelChar(tbl.irreducibles[2]) ) do
>
split.classes[ fus[ class ] ]:= tbl.classes[ class ];
>
od;
>
od;
gap> for class in [ 1 .. 5 ] do
>
split.classes[ class ]:= s3.classes[ class ];
>
od;
gap> split.classes;
[ 1, 45, 80, 90, 144, 15, 15, 90, 120, 120, 36, 90, 90, 72, 72, 180,
90, 90 ]
150
CHAPTER 1. ABOUT GAP
gap> split.size:= Sum( last );
1440
gap> split.order:= last;
gap> split.centralizers:= List( split.classes, x -> split.order / x );
[ 1440, 32, 18, 16, 10, 96, 96, 16, 12, 12, 40, 16, 16, 20, 20, 8,
16, 16 ]
gap> split.powermap[3]:= InitPowermap( split, 3 );;
gap> split.powermap[5]:= InitPowermap( split, 5 );;
gap> for tbl in [ s1, s2, s3 ] do
>
fus:= GetFusionMap( tbl, split );
>
for p in [ 2, 3, 5 ] do
>
TransferDiagram( tbl.powermap[p], fus, split.powermap[p] );
>
od;
>
od;
gap> split.powermap;
[ , [ 1, 1, 3, 2, 5, 1, 1, 2, 3, 3, 1, 4, 4, 5, 5, 2, 4, 4 ],
[ 1, 2, 1, 4, 5, 6, 7, 8, 6, 7, 11, 13, 12, 15, 14, 16, 17, 18 ],,
[ 1, 2, 3, 4, 1, 6, 7, 8, 9, 10, 11, 13, 12, 11, 11, 16, 18, 17 ] ]
gap> split.orders:= ElementOrdersPowermap( split.powermap );
[ 1, 2, 3, 4, 5, 2, 2, 4, 6, 6, 2, 8, 8, 10, 10, 4, 8, 8 ]
In order to decide which classes fuse in G, we look at the norms of suitable induced characters, first the + extension of χ2 to A6 .21 .
gap> ind:= Induced( s1, split, [ s1.irreducibles[3] ] )[1];
[ 10, 2, 1, -2, 0, 6, -2, 2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> ScalarProduct( split, ind, ind );
3/2
The inertia group of this character is A6 .21 , thus the norm of the induced character must
be 1. If the classes 2B and 2C fuse, the contribution of these classes is changed from
15 · 62 + 15 · (−2)2 to 30 · 22 , the difference is 480. But we have to subtract 720 which is half
the group order, so also 6A and 6B fuse. This is not surprising, since it reflects the action of
the famous outer automorphism of S6 . Next we examine the + extension of χ4 to A6 .22 .
gap> ind:= Induced( s2, split, [ s2.irreducibles[4] ] )[1];
[ 16, 0, -2, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 2*E(5)+2*E(5)^4,
2*E(5)^2+2*E(5)^3, 0, 0, 0 ]
gap> ScalarProduct( split, ind, ind );
3/2
Again, the norm must be 1, 10A and 10B fuse.
gap> collaps:= CharTableCollapsedClasses( split,
>
[1,2,3,4,5,6,6,7,8,8,9,10,11,12,12,13,14,15] );;
gap> PrintCharTable( collaps );
rec( identifier := "Collapsed(Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2,\
2, 3, 3, 3, 3, 3, 4, 4, 4 ]),[ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 1\
1, 12, 12, 13, 14, 15 ])", size := 1440, order :=
1440, name := "Collapsed(Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3\
, 3, 3, 3, 3, 4, 4, 4 ]),[ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12\
, 12, 13, 14, 15 ])", centralizers := [ 1440, 32, 18, 16, 10, 48, 16,
1.25. ABOUT CHARACTER TABLES
151
6, 40, 16, 16, 10, 8, 16, 16 ], orders :=
[ 1, 2, 3, 4, 5, 2, 4, 6, 2, 8, 8, 10, 4, 8, 8 ], powermap :=
[ , [ 1, 1, 3, 2, 5, 1, 2, 3, 1, 4, 4, 5, 2, 4, 4 ],
[ 1, 2, 1, 4, 5, 6, 7, 6, 9, 11, 10, 12, 13, 14, 15 ],,
[ 1, 2, 3, 4, 1, 6, 7, 8, 9, 11, 10, 9, 13, 15, 14 ]
], fusionsource :=
[ "Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4 \
])" ], irreducibles :=
[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1 ],
[ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1 ]
], classes := [ 1, 45, 80, 90, 144, 30, 90, 240, 36, 90, 90, 144,
180, 90, 90 ], operations := CharTableOps )
gap> split.fusions;
[ rec(
name := [ ’C’, ’2’, ’x’, ’C’, ’2’ ],
map := [ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4 ]
), rec(
name :=
"Collapsed(Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3,\
3, 3, 4, 4, 4 ]),[ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 12, 1\
3, 14, 15 ])",
map := [ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13,
14, 15 ] ) ]
gap> for tbl in [ s1, s2, s3 ] do
>
StoreFusion( tbl, collaps,
>
CompositionMaps( GetFusionMap( split, collaps ),
>
GetFusionMap( tbl, split ) ) );
>
od;
gap> ind:= Induced( s1, collaps, [ s1.irreducibles[10] ] )[1];
[ 20, -4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> ScalarProduct( collaps, ind, ind );
1
This character must be equal to any induced character of an irreducible character of degree
10 of A6 .22 and A6 .23 . That means, 8A fuses with 8B, and 8C with 8D.
gap> a6v4:= CharTableCollapsedClasses( collaps,
>
[1,2,3,4,5,6,7,8,9,10,10,11,12,13,13] );;
gap> PrintCharTable( a6v4 );
rec( identifier := "Collapsed(Collapsed(Split(C2xC2,[ 1, 1, 1, 1, 1, 2\
, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4 ]),[ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8\
, 9, 10, 11, 12, 12, 13, 14, 15 ]),[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10\
, 11, 12, 13, 13 ])", size := 1440, order :=
1440, name := "Collapsed(Collapsed(Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, \
2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4 ]),[ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, \
10, 11, 12, 12, 13, 14, 15 ]),[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11,\
12, 13, 13 ])", centralizers := [ 1440, 32, 18, 16, 10, 48, 16, 6,
152
CHAPTER 1. ABOUT GAP
40, 8, 10, 8, 8 ], orders := [ 1, 2, 3, 4, 5, 2, 4, 6, 2, 8, 10, 4,
8 ], powermap := [ , [ 1, 1, 3, 2, 5, 1, 2, 3, 1, 4, 5, 2, 4 ],
[ 1, 2, 1, 4, 5, 6, 7, 6, 9, 10, 11, 12, 13 ],,
[ 1, 2, 3, 4, 1, 6, 7, 8, 9, 10, 9, 12, 13 ] ], fusionsource :=
[ "Collapsed(Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3\
, 4, 4, 4 ]),[ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13, 14\
, 15 ])" ], irreducibles :=
[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 ],
[ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1 ] ], classes :=
[ 1, 45, 80, 90, 144, 30, 90, 240, 36, 180, 144, 180, 180
], operations := CharTableOps )
gap> for tbl in [ s1, s2, s3 ] do
>
StoreFusion( tbl, a6v4,
>
CompositionMaps( GetFusionMap( collaps, a6v4 ),
>
GetFusionMap( tbl, collaps ) ) );
>
od;
Now the classes of G are known, the only remaining work is to compute the irreducibles.
gap> a6v4.irreducibles;
[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 ],
[ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1 ] ]
gap> for tbl in [ s1, s2, s3 ] do
>
ind:= Set( Induced( tbl, a6v4, tbl.irreducibles ) );
>
Append( a6v4.irreducibles,
>
Filtered( ind, x -> ScalarProduct( a6v4,x,x ) = 1 ) );
>
od;
gap> a6v4.irreducibles:= Set( a6v4.irreducibles );
[ [ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1 ],
[ 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 10, 2, 1, -2, 0, -2, -2, 1, 0, 0, 0, 0, 0 ],
[ 10, 2, 1, -2, 0, 2, 2, -1, 0, 0, 0, 0, 0 ],
[ 16, 0, -2, 0, 1, 0, 0, 0, -4, 0, 1, 0, 0 ],
[ 16, 0, -2, 0, 1, 0, 0, 0, 4, 0, -1, 0, 0 ],
[ 20, -4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ]
gap> sym:= Symmetrizations( a6v4, [ a6v4.irreducibles[5] ], 2 );
[ [ 45, -3, 0, 1, 0, -3, 1, 0, -5, 1, 0, -1, 1 ],
[ 55, 7, 1, 3, 0, 7, 3, 1, 5, -1, 0, 1, -1 ] ]
gap> Reduced( a6v4, a6v4.irreducibles, sym );
rec(
remainders := [ [ 27, 3, 0, 3, -3, 3, -1, 0, 1, -1, 1, 1, -1 ] ],
irreducibles := [ [ 9, 1, 0, 1, -1, -3, 1, 0, -1, 1, -1, -1, 1 ] ] )
gap> Append( a6v4.irreducibles,
1.26. ABOUT GROUP LIBRARIES
153
>
Tensored( last.irreducibles,
>
Sublist( a6v4.irreducibles, [ 1 .. 4 ] ) ) );
gap> SortCharactersCharTable( a6v4,
>
(1,4)(2,3)(5,6)(7,8)(9,13,10,11,12) );;
gap> a6v4.identifier:= "A6.2^2";;
gap> DisplayCharTable( a6v4 );
Collapsed(Collapsed(Split(C2xC2,[ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, \
3, 3, 3, 4, 4, 4 ]),[ 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 12,\
13, 14, 15 ]),[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 13 ])
2
3
5
X.1
X.2
X.3
X.4
X.5
X.6
X.7
X.8
X.9
X.10
X.11
X.12
X.13
1.26
5
2
1
5
.
.
1
2
.
4
.
.
1
.
1
4
1
.
4
.
.
1
1
.
3
.
1
1a 2a 3a
2P 1a 1a 3a
3P 1a 2a 1a
5P 1a 2a 3a
4a
2a
4a
4a
5a
5a
5a
1a
2b
1a
2b
2b
4b
2a
4b
4b
6a
3a
2b
6a
2c
1a
2c
2c
3
.
.
1
.
1
3
.
.
3
.
.
8a 10a 4c 8b
4a 5a 2a 4a
8a 10a 4c 8b
8a 2c 4c 8b
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 -1 -1
1 1 1 1 1 -1 -1 -1 1 1
1 1 1 1 1 -1 -1 -1 -1 -1
10 2 1 -2 . 2 2 -1 . .
10 2 1 -2 . -2 -2 1 . .
16 . -2 . 1 . . . 4 .
16 . -2 . 1 . . . -4 .
9 1 . 1 -1 -3 1 . 1 -1
9 1 . 1 -1 -3 1 . -1 1
9 1 . 1 -1 3 -1 . 1 -1
9 1 . 1 -1 3 -1 . -1 1
20 -4 2 . . . . . . .
1
-1
1
-1
.
.
-1
1
1
-1
1
-1
.
1
-1
-1
1
.
.
.
.
1
-1
-1
1
.
1
-1
-1
1
.
.
.
.
-1
1
1
-1
.
About Group Libraries
When you start GAP3 it already knows several groups. For example, some basic groups
such as cyclic groups or symmetric groups, all primitive permutation groups of degree at
most 50, and all 2-groups of size at most 256.
Each of the sets above is called a group library. The set of all groups that GAP3 knows
initially is called the collection of group libraries.
In this section we show you how you can access the groups in those libraries and how you
can extract groups with certain properties from those libraries.
Let us start with the basic groups, because they are not accessed in the same way as the
groups in the other libraries.
To access such a basic group you just call a function with an appropriate name, such as
CyclicGroup or SymmetricGroup.
154
CHAPTER 1. ABOUT GAP
gap> c13 := CyclicGroup( 13 );
Group( ( 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13) )
gap> Size( c13 );
13
gap> s8 := SymmetricGroup( 8 );
Group( (1,8), (2,8), (3,8), (4,8), (5,8), (6,8), (7,8) )
gap> Size( s8 );
40320
The functions above also accept an optional first argument that describes the type of group.
For example you can pass AgWords to CyclicGroup to get a cyclic group as a finite polycyclic
group (see 25).
gap> c13 := CyclicGroup( AgWords, 13 );
Group( c13 )
Of course you cannot pass AgWords to SymmetricGroup, because symmetric groups are in
general not polycyclic.
The default is to construct the groups as permutation groups, but you can also explicitly pass
Permutations. Other possible arguments are AgWords for finite polycyclic groups, Words
for finitely presented groups, and Matrices for matrix groups (however only Permutations
and AgWords currently work).
Let us now turn to the other libraries. They are all accessed in a uniform way. For a first
example we will use the group library of primitive permutation groups.
To extract a group from a group library you generally use the extraction function. In
our example this function is called PrimitiveGroup. It takes two arguments. The first is
the degree of the primitive permutation group that you want and the second is an integer
that specifies which of the primitive permutation groups of that degree you want.
gap> g := PrimitiveGroup( 12, 3 );
M(11)
gap> g.generators;
[ ( 2, 6)( 3, 5)( 4, 7)( 9,10), ( 1, 5, 7)( 2, 9, 4)( 3, 8,10),
( 1,11)( 2, 7)( 3, 5)( 4, 6), ( 2, 5)( 3, 6)( 4, 7)(11,12) ]
gap> Size( g );
7920
gap> IsSimple( g );
true
gap> h := PrimitiveGroup( 16, 19 );
2^4.A(7)
gap> Size( h );
40320
The reason for the extraction function is as follows. A group library is usually not stored as
a list of groups. Instead a more compact representation for the groups is used. For example
the groups in the library of 2-groups are represented by 4 integers. The extraction function
hides this representation from you, and allows you to access the group library as if it was a
table of groups (two dimensional in the above example).
What arguments the extraction function accepts, and how they are interpreted is described
in the sections that describe the individual group libraries in chapter 38. Those functions
will of course signal an error when you pass illegal arguments.
1.26. ABOUT GROUP LIBRARIES
155
Suppose that you want to get a list of all primitive permutation groups that have a degree
10 and are simple but not cyclic. It would be very difficult to use the extraction function to
extract all groups in the group library, and test each of those. It is much simpler to use the
selection function. The name of the selection function always begins with All and ends
with Groups, in our example it is thus called AllPrimitiveGroups.
gap> AllPrimitiveGroups( DegreeOperation,
>
IsSimple,
>
IsCyclic,
[ A(5), PSL(2,9), A(10) ]
10,
true,
false );
AllPrimitiveGroups takes a variable number of argument pairs consisting of a function
(e.g. DegreeOperation) and a value (e.g. 10). To understand what AllPrimitiveGroups
does, imagine that the group library was stored as a long list of permutation groups.
AllPrimitiveGroups takes all those groups in turn. To each group it applies each function argument and compares the result with the corresponding value argument. It selects
a group if and only if all the function results are equal to the corresponding value. So in
our example AllPrimitiveGroups selects those groups g for which DegreeOperation(g) =
10 and IsSimple(g) = true and IsCyclic(g) = false. Finally AllPrimitiveGroups
returns the list of the selected groups.
Next suppose that you want all the primitive permutation groups that have degree at
most 10, are simple but are not cyclic. You could obtain such a list with 10 calls to
AllPrimitiveGroups (i.e., one call for the degree 1 groups, another for the degree 2 groups
and so on), but there is a simple way. Instead of specifying a single value that a function
must return you can simply specify a list of such values.
gap> AllPrimitiveGroups( DegreeOperation,
[1..10],
>
IsSimple,
true,
>
IsCyclic,
false );
[ A(5), PSL(2,5), A(6), PSL(3,2), A(7), PSL(2,7), A(8), PSL(2,8),
A(9), A(5), PSL(2,9), A(10) ]
Note that the list that you get contains A(5) twice, first in its primitive presentation on 5
points and second in its primitive presentation on 10 points.
Thus giving several argument pairs to the selection function allows you to express the logical
and of properties that a group must have to be selected, and giving a list of values allows
you to express a (restricted) logical or of properties that a group must have to be selected.
There is no restriction on the functions that you can use. It is even possible to use functions
that you have written yourself. Of course, the functions must be unary, i.e., accept only one
argument, and must be able to deal with the groups.
gap> NumberConjugacyClasses := function ( g )
>
return Length( ConjugacyClasses( g ) );
> end;
function ( g ) ... end
gap> AllPrimitiveGroups( DegreeOperation,
>
IsSimple,
>
IsCyclic,
>
NumberConjugacyClasses,
[ A(7), PSL(2,8) ]
[1..10],
true,
false,
9 );
156
CHAPTER 1. ABOUT GAP
Note that in some cases a selection function will issue a warning. For example if you call
AllPrimitiveGroups without specifying the degree, it will issue such a warning.
gap> AllPrimitiveGroups( Size,
[100..400],
>
IsSimple, true,
>
IsCyclic, false );
#W AllPrimitiveGroups: degree automatically restricted to [1..50]
[ A(6), PSL(3,2), PSL(2,7), PSL(2,9), A(6) ]
If selection functions would really run over the list of all groups in a group library and apply
the function arguments to each of those, they would be very inefficient. For example the
2-groups library contains 58760 groups. Simply creating all those groups would take a very
long time.
Instead selection functions recognize certain functions and handle them more efficiently. For
example AllPrimitiveGroups recognizes DegreeOperation. If you pass DegreeOperation
to AllPrimitiveGroups it does not create a group to apply DegreeOperation to it. Instead it simply consults an index and quickly eliminates all groups that have a different
degree. Other functions recognized by AllPrimitiveGroups are IsSimple, Size, and
Transitivity.
So in our examples AllPrimitiveGroups, recognizing DegreeOperation and IsSimple,
eliminates all but 16 groups. Then it creates those 16 groups and applies IsCyclic to
them. This eliminates 4 more groups (C(2), C(3), C(5), and C(7)). Then in our last
example it applies NumberConjugacyClasses to the remaining 12 groups and eliminates all
but A(7) and PSL(2,8).
The catch is that the selection functions will take a large amount of time if they cannot recognize any special functions. For example the following selection will take a large amount of
time, because only IsSimple is recognized, and there are 116 simple groups in the primitive
groups library.
AllPrimitiveGroups( IsSimple, true, NumberConjugacyClasses, 9 );
So you should specify a sufficiently large set of recognizable functions when you call a
selection function. It is also advisable to put those functions first (though in some group
libraries the selection function will automatically rearrange the argument pairs so that the
recognized functions come first). The sections describing the individual group libraries in
chapter 38 tell you which functions are recognized by the selection function of that group
library.
There is another function, called the example function that behaves similar to the selection
function. Instead of returning a list of all groups with a certain set of properties it only
returns one such group. The name of the example function is obtained by replacing All by
One and stripping the s at the end of the name of the selection function.
gap> OnePrimitiveGroup( DegreeOperation,
>
IsSimple,
>
IsCyclic,
>
NumberConjugacyClasses,
A(7)
[1..10],
true,
false,
9 );
The example function works just like the selection function. That means that all the above
comments about the special functions that are recognized also apply to the example function.
1.26. ABOUT GROUP LIBRARIES
157
Let us now look at the 2-groups library. It is accessed in the same way as the primitive groups
library. There is an extraction function TwoGroup, a selection function AllTwoGroups, and
an example function OneTwoGroup.
gap> g := TwoGroup( 128, 5 );
Group( a1, a2, a3, a4, a5, a6, a7 )
gap> Size( g );
128
gap> NumberConjugacyClasses( g );
80
The groups are all displayed as Group( a1, a2, ..., an ), where 2n is the size of the
group.
gap> AllTwoGroups( Size,
256,
>
Rank,
3,
>
pClass, 2 );
[ Group( a1, a2, a3, a4, a5, a6, a7,
Group( a1, a2, a3, a4, a5, a6, a7,
Group( a1, a2, a3, a4, a5, a6, a7,
Group( a1, a2, a3, a4, a5, a6, a7,
gap> l := AllTwoGroups( Size,
>
Rank,
>
pClass,
>
g -> Length(
gap> Length( l );
28
a8
a8
a8
a8
),
),
),
) ]
256,
3,
5,
DerivedSeries( g ) ), 4 );;
The selection and example function of the 2-groups library recognize Size, Rank, and
pClass. Note that Rank and pClass are functions that can in fact only be used in this
context, i.e., they can not be applied to arbitrary groups.
The following discussion is a bit technical and you can ignore it safely.
For very big group libraries, such as the 2-groups library, the groups (or their compact
representations) are not stored on a single file. This is because this file would be very large
and loading it would take a long time and a lot of main memory.
Instead the groups are stored on a small number of files (27 in the case of the 2-groups).
The selection and example functions are careful to load only those files that may actually
contain groups with the specified properties. For example in the above example the files
containing the groups of size less than 256 are never loaded. In fact in the above example
only one very small file is loaded.
When a file is loaded the selection and example functions also unload the previously loaded
file. That means that they forget all the groups in this file again (except those selected of
course). Thus even if the selection or example functions have to search through the whole
group library, only a small part of the library is held in main memory at any time. In
principle it should be possible to search the whole 2-groups library with as little as 2 MByte
of main memory.
If you have sufficient main memory available you can explicitly load files from the 2-groups
library with ReadTwo( filename ), e.g., Read( "twogp64") to load the file with the groups
of size 64. Those files will then not be unloaded again. This will take up more main memory,
158
CHAPTER 1. ABOUT GAP
but the selection and example function will work faster, because they do not have to load
those files again each time they are needed.
In this section you have seen the basic groups library and the group libraries of primitive
groups and 2-groups. You have seen how you can extract a single group from such a
library with the extraction function. You have seen how you can select groups with certain
properties with the selection and example function. Chapter 38 tells you which other group
libraries are available.
1.27. ABOUT THE IMPLEMENTATION OF DOMAINS
1.27
159
About the Implementation of Domains
In this section we will open the black boxes and describe how all this works. This is complex
and you do not need to understand it if you are content to use domains only as black boxes.
So you may want to skip this section (and the remainder of this chapter).
Domains are represented by records, which we will call domain records in the following.
Which components have to be present, which may, and what those components hold, differs
from category to category, and, to a smaller extent, from domain to domain. It is possible,
though, to generally distinguish four types of components.
The first type of components are called the category components. They determine to
which category a domain belongs. A domain D in a category Cat has a component isCat
with the value true. For example, each group has the component isGroup. Also each
domain has the component isDomain (again with the value true). Finally a domain may
also have components that describe the representation of this domain. For example, each
permutation group has a component isPermGroup (again with the value true). Functions
such as IsPermGroup test whether such a component is present, and whether it has the
value true.
The second type of components are called the identification components. They distinguish the domain from other domains in the same category. The identification components
uniquely identify the domain. For example, for groups the identification components are
generators, which holds a list of generators of the group, and identity, which holds the
identity of the group (needed for the trivial group, for which the list of generators is empty).
The third type of components are called knowledge components. They hold all the
knowledge GAP3 has about the domain. For example the size of the domain D is stored
in the knowledge component D.size, the commutator subgroup of a group is stored in
the knowledge component D.commutatorSubgroup, etc. Of course, the knowledge about
a certain domain will usually increase as you work with a domain. For example, a group
record may initially hold only the knowledge that the group is finite, but may later hold all
kinds of knowledge, for example the derived series, the Sylow subgroups, etc.
Finally each domain record contains an operations record. The operations record is
discussed below.
We want to emphasize that really all information that GAP3 has about a domain is stored
in the knowledge components. That means that you can access all this information, at least
if you know where to look and how to interpret what you see. The chapters describing
categories and domains will tell you what knowledge components a domain may have, and
how the knowledge is represented in those components.
For an example let us return to the permutation group a5 from section 1.23. If we print the
record using the function PrintRec we see all the information. GAP3 stores the stabilizer
chain of a5 in the components orbit, transversal, and stabilizer. It is not important
that you understand what a stabilizer chain is (this is discussed in chapter 21), the important
point here is that it is the vital information that GAP3 needs to work efficiently with a5 and
that you can access it.
gap> a5 := Group( (1,2,3), (3,4,5) );
Group( (1,2,3), (3,4,5) )
gap> Size( a5 );
160
CHAPTER 1. ABOUT GAP
60
gap> PrintRec( a5 );
rec(
isDomain
:= true,
isGroup
:= true,
identity
:= (),
generators
:= [ (1,2,3), (3,4,5) ],
operations
:= ...,
isPermGroup
:= true,
isFinite
:= true,
1
:= (1,2,3),
2
:= (3,4,5),
orbit
:= [ 1, 3, 2, 5, 4 ],
transversal
:= [ (), (1,2,3), (1,2,3), (3,4,5), (3,4,5) ],
stabilizer
:= rec(
identity
:= (),
generators := [ (3,4,5), (2,5,3) ],
orbit
:= [ 2, 3, 5, 4 ],
transversal := [ , (), (2,5,3), (3,4,5), (3,4,5) ],
stabilizer := rec(
identity
:= (),
generators := [ (3,4,5) ],
orbit
:= [ 3, 5, 4 ],
transversal := [ ,, (), (3,4,5), (3,4,5) ],
stabilizer := rec(
identity
:= (),
generators := [ ],
operations := ... ),
operations := ... ),
operations := ... ),
isParent
:= true,
stabChainOptions := rec(
random
:= 1000,
operations := ... ),
stabChain
:= rec(
generators := [ (1,2,3), (3,4,5) ],
identity
:= (),
orbit
:= [ 1, 3, 2, 5, 4 ],
transversal := [ (), (1,2,3), (1,2,3), (3,4,5), (3,4,5) ],
stabilizer := rec(
identity
:= (),
generators := [ (3,4,5), (2,5,3) ],
orbit
:= [ 2, 3, 5, 4 ],
transversal := [ , (), (2,5,3), (3,4,5), (3,4,5) ],
stabilizer := rec(
identity
:= (),
generators := [ (3,4,5) ],
orbit
:= [ 3, 5, 4 ],
1.27. ABOUT THE IMPLEMENTATION OF DOMAINS
161
transversal := [ ,, (), (3,4,5), (3,4,5) ],
stabilizer := rec(
identity
:= (),
generators := [ ],
operations := ... ),
operations := ... ),
operations := ... ),
operations := ... ),
size
:= 60 )
Note that you can not only read this information, you can also modify it. However, unless
you truly understand what you are doing, we discourage you from playing around. All GAP3
functions assume that the information in the domain record is in a consistent state, and
everything will go wrong if it is not.
gap> a5.size := 120;
120
gap> Size( ConjugacyClass( a5, (1,2,3,4,5) ) );
24
# this is of course wrong
As was mentioned above, each domain record has an operations record. We have already
seen that functions such as Size can be applied to various types of domains. It is clear that
there is no general method that will compute the size of all domains efficiently. So Size
must somehow decide which method to apply to a given domain. The operations record
makes this possible.
The operations record of a domain D is the component with the name D.operations, its
value is a record. For each function that you can apply to D this record contains a function
that will compute the required information (hopefully in an efficient way).
To understand this let us take a look at what happens when we compute Size( a5 ). Not
much happens. Size simply calls a5.operations.Size( a5 ). a5.operations.Size is a
function written especially for permutation groups. It computes the size of a5 and returns
it. Then Size returns this value.
Actually Size does a little bit more than that. It first tests whether a5 has the knowledge
component a5.size. If this is the case, Size simply returns that value. Otherwise it
calls a5.operations.Size( a5 ) to compute the size. Size remembers the result in the
knowledge component a5.size so that it is readily available the next time Size( a5 ) is
called. The complete definition of Size is as follows.
gap> Size := function ( D )
>
local size;
>
if IsSet( D ) then
>
size := Length( D );
>
elif IsRec( D ) and IsBound( D.size ) then
>
size := D.size;
>
elif IsDomain( D ) then
>
D.size := D.operations.Size( D );
>
size := D.size;
>
else
>
Error( " must be a domain or a set" );
162
CHAPTER 1. ABOUT GAP
>
fi;
>
return size;
> end;;
Because functions such as Size only dispatch to the functions in the operations record, they
are called dispatcher functions. Almost all functions that you call directly are dispatcher
functions, and almost all functions that do the hard work are components in an operations
record.
Which function is called by a dispatcher obviously depends on the domain and its operations record (that is the whole point of having an operations record). In principle each
domain could have its own Size function. In practice however, this would require too many
functions. So different domains share the functions in their operations records, usually all
domains with the same representation share all their operations record functions. For example all permutation groups share the same Size function. Because this shared Size function
must be able to access the information in the domain record to compute the correct result,
the Size dispatcher function (and all other dispatchers as well) pass the domain as first
argument
In fact the domains not only have the same functions in their operations record, they share
the operations record. So for example all permutation groups share a common operations
record, which is called PermGroupOps. This means that changing a function in the operations
record for a domain D in the following way D.operations.function := new-function;
will also change this function for all domains of the same type, even those that do not
yet exist at the moment of the assignment and will only be constructed later. This is
usually not desirable, since supposedly new-function uses some special properties of the
domain D to work more efficiently. We suggest therefore that you first make a copy of the
operations record with D.operations := Copy( D.operations ); and only afterwards
do D.operations.function := new-function;.
If a programmer that implements a new domain D, a new type of groups say, would have
to write all functions applicable to D, this would require a lot of effort. For example, there
are about 120 functions applicable to groups. Luckily many of those functions are independent of the particular type of groups. For example the following function will compute
the commutator subgroup of any group, assuming that TrivialSubgroup, Closure, and
NormalClosure work. We say that this function is generic.
gap> GroupOps.CommutatorSubgroup := function ( U, V )
>
local
C, u, v, c;
>
C := TrivialSubgroup( U );
>
for u in U.generators do
>
for v in V.generators do
>
c := Comm( u, v );
>
if not c in C then
>
C := Closure( C, c );
>
fi;
>
od;
>
od;
>
return NormalClosure( Closure( U, V ), C );
> end;;
So it should be possible to use this function for the new type of groups. The mechanism to do
1.27. ABOUT THE IMPLEMENTATION OF DOMAINS
163
this is called inheritance. How it works is described in 1.28, but basically the programmer
just copies the generic functions from the generic group operations record into the operations
record for his new type of groups.
The generic functions are also called default functions, because they are used by default,
unless the programmer overlaid them for the new type of groups.
There is another mechanism through which work can be simplified. It is called delegation.
Suppose that a generic function works for the new type of groups, but that some special
cases can be handled more efficiently for the new type of groups. Then it is possible to
handle only those cases and delegate the general cases back to the generic function. An
example of this is the function that computes the orbit of a point under a permutation
group. If the point is an integer then the generic algorithm can be improved by keeping a
second list that remembers which points have already been seen. The other cases (remember
that Orbit can also be used for other operations, e.g., the operation of a permutation group
on pairs of points or the operations on subgroups by conjugation) are delegated back to the
generic function. How this is done can be seen in the following definition.
gap> PermGroupOps.Orbit := function ( G, d, opr )
>
local
orb,
# orbit of d under G, result
>
max,
# largest point moved by the group G
>
new,
# boolean list indicating if a point is new
>
gen,
# one generator of the group G
>
pnt,
# one point in the orbit orb
>
img;
# image of pnt under gen
>
>
# standard operation
>
if
opr = OnPoints and IsInt(d) then
>
>
# get the largest point max moved by the group G
>
max := 0;
>
for gen in G.generators do
>
if max < LargestMovedPointPerm(gen) then
>
max := LargestMovedPointPerm(gen);
>
fi;
>
od;
>
>
# handle fixpoints
>
if not d in [1..max] then
>
return [ d ];
>
fi;
>
>
# start with the singleton orbit
>
orb := [ d ];
>
new := BlistList( [1..max], [1..max] );
>
new[d] := false;
>
>
# loop over all points found
>
for pnt in orb do
>
for gen in G.generators do
164
CHAPTER 1. ABOUT GAP
>
img := pnt ^ gen;
>
if new[img] then
>
Add( orb, img );
>
new[img] := false;
>
fi;
>
od;
>
od;
>
>
# other operation, delegate back on default function
>
else
>
orb := GroupOps.Orbit( G, d, opr );
>
fi;
>
>
# return the orbit orb
>
return orb;
> end;;
Inheritance and delegation allow the programmer to implement a new type of groups by
merely specifying how those groups differ from generic groups. This is far less work than
having to implement all possible functions (apart from the problem that in this case it is
very likely that the programmer would forget some of the more exotic functions).
To make all this clearer let us look at an extended example to show you how a computation
in a domain may use default and special functions to achieve its goal. Suppose you defined
g, x, and y as follows.
gap> g := SymmetricGroup( 8 );;
gap> x := [ (2,7,4)(3,5), (1,2,6)(4,8) ];;
gap> y := [ (2,5,7)(4,6), (1,5)(3,8,7) ];;
Now you ask for an element of g that conjugates x to y, i.e., a permutation on 8 points that
takes (2,7,4)(3,5) to (2,5,7)(4,6) and (1,2,6)(4,8) to (1,5)(3,8,7). This is done
as follows (see 8.25 and 8.1).
gap> RepresentativeOperation( g, x, y, OnTuples );
(1,8)(2,7)(3,4,5,6)
Now lets look at what happens step for step. First RepresentativeOperation is called. After checking the arguments it calls the function g.operations.RepresentativeOperation,
which is the function SymmetricGroupOps.RepresentativeOperation, passing the arguments g, x, y, and OnTuples.
SymmetricGroupOps.RepresentativeOperation handles a lot of cases special, but the operation on tuples of permutations is not among them. Therefore it delegates this problem
to the function that it overlays, which is PermGroupOps.RepresentativeOperation.
PermGroupOps.RepresentativeOperation also does not handle this special case, and delegates the problem to the function that it overlays, which is the default function called
GroupOps.RepresentativeOperation.
GroupOps.RepresentativeOperation views this problem as a general tuples problem, i.e.,
it does not care whether the points in the tuples are integers or permutations, and decides
to solve it one step at a time. So first it looks for an element taking (2,7,4)(3,5) to
1.27. ABOUT THE IMPLEMENTATION OF DOMAINS
165
(2,5,7)(4,6) by calling RepresentativeOperation( g, (2,7,4)(3,5), (2,5,7)(4,6)
).
RepresentativeOperation calls g.operations.RepresentativeOperation next, which is
the function SymmetricGroupOps.RepresentativeOperation, passing the arguments g,
(2,7,4)(3,5), and (2,5,7)(4,6).
SymmetricGroupOps.RepresentativeOperation can handle this case. It knows that g
contains every permutation on 8 points, so it contains (3,4,7,5,6), which obviously does
what we want, namely it takes x[1] to y[1]. We will call this element t.
Now GroupOps.RepresentativeOperation (see above) looks for an s in the stabilizer of
x[1] taking x[2] to y[2]^(t^-1), since then for r=s*t we have x[1]^r = (x[1]^s)^t
= x[1]^t = y[1] and also x[2]^r = (x[2]^s)^t = (y[2]^(t^-1))^t = y[2]. So the
next step is to compute the stabilizer of x[1] in g. To do this it calls Stabilizer( g,
(2,7,4)(3,5) ).
Stabilizer calls g.operations.Stabilizer, which is SymmetricGroupOps.Stabilizer,
passing the arguments g and (2,7,4)(3,5). SymmetricGroupOps.Stabilizer detects that
the second argument is a permutation, i.e., an element of the group, and calls Centralizer(
g, (2,7,4)(3,5) ). Centralizer calls the function g.operations.Centralizer, which
is SymmetricGroupOps.Centralizer, again passing the arguments g, (2,7,4)(3,5).
SymmetricGroupOps.Centralizer again knows how centralizer in symmetric groups look,
and after looking at the permutation (2,7,4)(3,5) sharply for a short while returns the
centralizer as Subgroup( g, [ (1,6), (6,8), (2,7,4), (3,5) ] ), which we will call c.
Note that c is of course not a symmetric group, therefore SymmetricGroupOps.Subgroup
gives it PermGroupOps as operations record and not SymmetricGroupOps.
As explained above GroupOps.RepresentativeOperation needs an element of c taking
x[2] ((1,2,6)(4,8)) to y[2]^(t^-1) ((1,7)(4,6,8)). So RepresentativeOperation(
c, (1,2,6)(4,8), (1,7)(4,6,8) ) is called. RepresentativeOperation in turn calls
the function c.operations.RepresentativeOperation, which is, since c is a permutation
group, the function PermGroupOps.RepresentativeOperation, passing the arguments c,
(1,2,6)(4,8), and (1,7)(4,6,8).
PermGroupOps.RepresentativeOperation detects that the points are permutations and
and performs a backtrack search through c. It finds and returns (1,8)(2,4,7)(3,5),
which we call s.
Then GroupOps.RepresentativeOperation returns r = s*t = (1,8)(2,7)(3,6)(4,5),
and we are done.
In this example you have seen how functions use the structure of their domain to solve
a problem most efficiently, for example SymmetricGroupOps.RepresentativeOperation
but also the backtrack search in PermGroupOps.RepresentativeOperation, how they use
other functions, for example SymmetricGroupOps.Stabilizer called Centralizer, and
how they delegate cases which they can not handle more efficiently back to the function they overlaid, for example SymmetricGroupOps.RepresentativeOperation delegated
to PermGroupOps.RepresentativeOperation, which in turn delegated to to the function
GroupOps.RepresentativeOperation.
If you think this whole mechanism using dispatcher functions and the operations record is
overly complex let us look at some of the alternatives. This is even more technical than the
previous part of this section so you may want to skip the remainder of this section.
166
CHAPTER 1. ABOUT GAP
One alternative would be to let the dispatcher know about the various types of domains,
test which category a domain lies in, and dispatch to an appropriate function. Then we
would not need an operations record. The dispatcher function CommutatorSubgroup would
then look as follows. Note this is not how CommutatorSubgroup is implemented in GAP3.
CommutatorSubgroup := function ( G )
local
C;
if IsAgGroup( G ) then
C := CommutatorSubgroupAgGroup( G );
elif IsMatGroup( G ) then
C := CommutatorSubgroupMatGroup( G );
elif IsPermGroup( G ) then
C := CommutatorSubgroupPermGroup( G );
elif IsFpGroup( G ) then
C := CommutatorSubgroupFpGroup( G );
elif IsFactorGroup( G ) then
C := CommutatorSubgroupFactorGroup( G );
elif IsDirectProduct( G ) then
C := CommutatorSubgroupDirectProduct( G );
elif IsDirectProductAgGroup( G ) then
C := CommutatorSubgroupDirectProductAgGroup( G );
elif IsSubdirectProduct( G ) then
C := CommutatorSubgroupSubdirectProduct( G );
elif IsSemidirectProduct( G ) then
C := CommutatorSubgroupSemidirectProduct( G );
elif IsWreathProduct( G ) then
C := CommutatorSubgroupWreathProduct( G );
elif IsGroup( G ) then
C := CommutatorSubgroupGroup( G );
else
Error(" must be a group");
fi;
return C;
end;
You already see one problem with this approach. The number of cases that the dispatcher
functions would have to test is simply to large. It is even worse for set theoretic functions,
because they would have to handle all different types of domains (currently about 30).
The other problem arises when a programmer implements a new domain. Then he would
have to rewrite all dispatchers and add a new case to each. Also the probability that the
programmer forgets one dispatcher is very high.
Another problem is that inheritance becomes more difficult. Instead of just copying one
operations record the programmer would have to copy each function that should be inherited.
Again the probability that he forgets one is very high.
Another alternative would be to do completely without dispatchers. In this case there would
be the functions CommutatorSugroupAgGroup, CommutatorSubgroupPermGroup, etc., and it
would be your responsibility to call the right function. For example to compute the size of
a permutation group you would call SizePermGroup and to compute the size of a coset you
would call SizeCoset (or maybe even SizeCosetPermGroup).
1.27. ABOUT THE IMPLEMENTATION OF DOMAINS
167
The most obvious problem with this approach is that it is much more cumbersome. You
would always have to know what kind of domain you are working with and which function
you would have to call.
Another problem is that writing generic functions would be impossible. For example the
above generic implementation of CommutatorSubgroup could not work, because for a concrete group it would have to call ClosurePermGroup or ClosureAgGroup etc.
If generic functions are impossible, inheritance and delegation can not be used. Thus for
each type of domain all functions must be implemented. This is clearly a lot of work, more
work than we are willing to do.
So we argue that our mechanism is the easiest possible that serves the following two goals.
It is reasonably convenient for you to use. It allows us to implement a large (and ever
increasing) number of different types of domains.
This may all sound a lot like object oriented programming to you. This is not surprising
because we want to solve the same problems that object oriented programming tries to solve.
Let us briefly discuss the similarities and differences to object oriented programming, taking
C++ as an example (because it is probably the widest known object oriented programming
language nowadays). This discussion is very technical and again you may want to skip the
remainder of this section.
Let us first recall the problems that the GAP3 mechanism wants to handle.
1
How can we represent domains in such a way that we can handle domains of different
type in a common way?
2
How can we make it possible to allow functions that take domains of different type
and perform the same operation for those domains (but using different methods)?
3
How can we make it possible that the implementation of a new type of domains
only requires that one implements what distinguishes this new type of domains from
domains of an old type (without the need to change any old code)?
For object oriented programming the problems are the same, though the names used are
different. We talk about domains, object oriented programming talks about objects, and
we talk about categories, object oriented programming talks about classes.
1
How can we represent objects in such a way that we can handle objects of different
classes in a common way (e.g., declare variables that can hold objects of different
classes)?
2
How can we make it possible to allow functions that take objects of different classes
(with a common base class) and perform the same operation for those objects (but
using different methods)?
3
How can we make it possible that the implementation of a new class of objects only
requires that one implements what distinguishes the objects of this new class from
the objects of an old (base) class (without the need to change any old code)?
In GAP3 the first problem is solved by representing all domains using records. Actually
because GAP3 does not perform strong static type checking each variable can hold objects
of arbitrary type, so it would even be possible to represent some domains using lists or
something else. But then, where would we put the operations record?
168
CHAPTER 1. ABOUT GAP
C++ does something similar. Objects are represented by struct-s or pointers to structures.
C++ then allows that a pointer to an object of a base class actually holds a pointer to an
object of a derived class.
In GAP3 the second problem is solved by the dispatchers and the operations record. The
operations record of a given domain holds the methods that should be applied to that
domain, and the dispatcher does nothing but call this method.
In C++ it is again very similar. The difference is that the dispatcher only exists conceptually. If the compiler can already decide which method will be executed by a given call to the
dispatcher it directly calls this function. Otherwise (for virtual functions that may be overlaid in derived classes) it basically inlines the dispatcher. This inlined code then dispatches
through the so–called virtual method table (vmt). Note that this virtual method table
is the same as the operations record, except that it is a table and not a record.
In GAP3 the third problem is solved by inheritance and delegation. To inherit functions you
simply copy them from the operations record of domains of the old category to the operations
record of domains of the new category. Delegation to a method of a larger category is done
by calling super-category-operations-record .function
C++ also supports inheritance and delegation. If you derive a class from a base class,
you copy the methods from the base class to the derived class. Again this copying is
only done conceptually in C++. Delegation is done by calling a qualified function baseclass::function.
Now that we have seen the similarities, let us discuss the differences.
The first differences is that GAP3 is not an object oriented programming language. We only
programmed the library in an object oriented way using very few features of the language
(basically all we need is that GAP3 has no strong static type checking, that records can
hold functions, and that records can grow dynamically). Following Stroustrup’s convention
we say that the GAP3 language only enables object oriented programming, but does not
support it.
The second difference is that C++ adds a mechanism to support data hiding. That means
that fields of a struct can be private. Those fields can only be accessed by the functions
belonging to this class (and friend functions). This is not possible in GAP3. Every field of
every domain is accessible. This means that you can also modify those fields, with probably
catastrophic results.
The final difference has to do with the relation between categories and their domains and
classes and their objects. In GAP3 a category is a set of domains, thus we say that a
domain is an element of a category. In C++ (and most other object oriented programming
languages) a class is a prototype for its objects, thus we say that an object is an instance
of the class. We believe that GAP3’s relation better resembles the mathematical model.
In this section you have seen that domains are represented by domain records, and that you
can therefore access all information that GAP3 has about a certain domain. The following
sections in this chapter discuss how new domains can be created (see 1.28, and 1.29) and
how you can even define a new type of elements (see 1.30).
1.28
About Defining New Domains
In this section we will show how one can add a new domain to GAP3. All domains are
1.28. ABOUT DEFINING NEW DOMAINS
169
implemented in the library in this way. We will use the ring of Gaussian integers as our
example.
Note that everything defined here is already in the library file LIBNAME/"gaussian.g", so
there is no need for you to type it in. You may however like to make a copy of this file and
modify it.
The elements of this domain are already available, because Gaussian integers are just a
special case of cyclotomic numbers. As is described in chapter 13 E(4) is GAP3’s name for
the complex root of -1. So all Gaussian integers can be represented as a + b*E(4), where
a and b are ordinary integers.
As was already mentioned each domain is represented by a record. So we create a record to
represent the Gaussian integers, which we call GaussianIntegers.
gap> GaussianIntegers := rec();;
The first components that this record must have are those that identify this record as a
record denoting a ring domain. Those components are called the category components.
gap> GaussianIntegers.isDomain := true;;
gap> GaussianIntegers.isRing := true;;
The next components are those that uniquely identify this ring. For rings this must be
generators, zero, and one. Those components are called the identification components
of the domain record. We also assign a name component. This name will be printed when
the domain is printed.
gap>
gap>
gap>
gap>
GaussianIntegers.generators := [ 1, E(4) ];;
GaussianIntegers.zero := 0;;
GaussianIntegers.one := 1;;
GaussianIntegers.name := "GaussianIntegers";;
Next we enter some components that represent knowledge that we have about this domain.
Those components are called the knowledge components. In our example we know that
the Gaussian integers form a infinite, commutative, integral, Euclidean ring, which has an
unique factorization property, with the four units 1, -1, E(4), and -E(4).
gap>
gap>
gap>
gap>
gap>
gap>
gap>
GaussianIntegers.size
GaussianIntegers.isFinite
GaussianIntegers.isCommutativeRing
GaussianIntegers.isIntegralRing
GaussianIntegers.isUniqueFactorizationRing
GaussianIntegers.isEuclideanRing
GaussianIntegers.units
:=
:=
:=
:=
:=
:=
:=
"infinity";;
false;;
true;;
true;;
true;;
true;;
[1,-1,E(4),-E(4)];;
This was the easy part of this example. Now we have to add an operations record to
the domain record. This operations record (GaussianIntegers.operations) shall contain functions that implement all the functions mentioned in chapter 5, e.g., DefaultRing,
IsCommutativeRing, Gcd, or QuotientRemainder.
Luckily we do not have to implement all this functions. The first class of functions that we
need not implement are those that can simply get the result from the knowledge components.
E.g., IsCommutativeRing looks for the knowledge component isCommutativeRing, finds it
and returns this value. So GaussianIntegers.operations.IsCommutativeRing is never
called.
170
CHAPTER 1. ABOUT GAP
gap> IsCommutativeRing( GaussianIntegers );
true
gap> Units( GaussianIntegers );
[ 1, -1, E(4), -E(4) ]
The second class of functions that we need not implement are those for which there is a general algorithm that can be applied for all rings. For example once we can do a division with
remainder (which we will have to implement) we can use the general Euclidean algorithm
to compute the greatest common divisor of elements.
So the question is, how do we get those general functions into our operations record. This is
very simple, we just initialize the operations record as a copy of the record RingOps, which
contains all those general functions. We say that GaussianIntegers.operations inherits
the general functions from RingOps.
gap> GaussianIntegersOps := OperationsRecord(
>
"GaussianIntegersOps", RingOps );;
gap> GaussianIntegers.operations := GaussianIntegersOps;;
So now we have to add those functions whose result can not (easily) be derived from the
knowledge components and that we can not inherit from RingOps.
The first such function is the membership test. This function must test whether an object is
an element of the domain GaussianIntegers. IsCycInt(x ) tests whether x is a cyclotomic
integer and NofCyc(x ) returns the smallest n such that the cyclotomic x can be written
as a linear combination of powers of the primitive n-th root of unity E(n). If NofCyc(x )
returns 1, x is an ordinary rational number.
gap> GaussianIntegersOps.\in := function ( x, GaussInt )
>
return IsCycInt( x ) and (NofCyc( x ) = 1 or NofCyc( x ) = 4);
> end;;
Note that the second argument GaussInt is not used in the function. Whenever this function
is called, the second argument must be GaussianIntegers, because GaussianIntegers
is the only domain that has this particular function in its operations record. This also
happens for most other functions that we will write. This argument can not be dropped
though, because there are other domains that share a common in function, for example all
permutation groups have the same in function. If the operator in would not pass the second
argument, this function could not know for which permutation group it should perform the
membership test.
So now we can test whether a certain object is a Gaussian integer or not.
gap> E(4) in GaussianIntegers;
true
gap> 1/2 in GaussianIntegers;
false
gap> GaussianIntegers in GaussianIntegers;
false
Another function that is just as easy is the function Random that should return a random
Gaussian integer.
gap> GaussianIntegersOps.Random := function ( GaussInt )
>
return Random( Integers ) + Random( Integers ) * E( 4 );
1.28. ABOUT DEFINING NEW DOMAINS
171
> end;;
Note that actually a Random function was inherited from RingOps. But this function can
not be used. It tries to construct the sorted list of all elements of the domain and then
picks a random element from that list. Therefor this function is only applicable for finite
domains, and can not be used for GaussianIntegers. So we overlay this default function
by simply putting another function in the operations record.
Now we can already test whether a Gaussian integer is a unit or not. This is because the
default function inherited from RingOps tests whether the knowledge component units is
present, and it returns true if the element is in that list and false otherwise.
gap> IsUnit( GaussianIntegers, E(4) );
true
gap> IsUnit( GaussianIntegers, 1 + E(4) );
false
Now we finally come to more interesting stuff. The function Quotient should return the
quotient of its two arguments x and y. If the quotient does not exist in the ring (i.e., if it is
a proper Gaussian rational), it must return false. (Without this last requirement we could
do without the Quotient function and always simply use the / operator.)
gap> GaussianIntegersOps.Quotient := function ( GaussInt, x, y )
>
local
q;
>
q := x / y;
>
if not IsCycInt( q ) then
>
q := false;
>
fi;
>
return q;
> end;;
The next function is used to test if two elements are associate in the ring of Gaussian
integers. In fact we need not implement this because the function that we inherit from
RingOps will do fine. The following function is a little bit faster though that the inherited
one.
gap> GaussianIntegersOps.IsAssociated := function ( GaussInt, x, y )
>
return x = y or x = -y or x = E(4)*y or x = -E(4)*y;
> end;;
We must however implement the function StandardAssociate. It should return an associate
that is in some way standard. That means, whenever we apply StandardAssociate to two
associated elements we must obtain the same value. For Gaussian integers we return that
associate that lies in the first quadrant of the complex plane. That is, the result is that
associated element that has positive real part and nonnegative imaginary part. 0 is its
own standard associate of course. Note that this is a generalization of the absolute value
function, which is StandardAssociate for the integers. The reason that we must implement
StandardAssociate is of course that there is no general way to compute a standard associate
for an arbitrary ring, there is not even a standard way to define this!
gap> GaussianIntegersOps.StandardAssociate := function ( GaussInt, x )
>
if
IsRat(x) and 0 <= x then
>
return x;
>
elif IsRat(x) then
172
CHAPTER 1. ABOUT GAP
>
return -x;
>
elif 0 < COEFFSCYC(x)[1]
and 0 <= COEFFSCYC(x)[2]
then
>
return x;
>
elif
COEFFSCYC(x)[1] <= 0 and 0 < COEFFSCYC(x)[2]
then
>
return - E(4) * x;
>
elif
COEFFSCYC(x)[1] < 0 and
COEFFSCYC(x)[2] <= 0 then
>
return - x;
>
else
>
return E(4) * x;
>
fi;
> end;;
Note that COEFFSCYC is an internal function that returns the coefficients of a Gaussian
integer (actually of an arbitrary cyclotomic) as a list.
Now we have implemented all functions that are necessary to view the Gaussian integers
plainly as a ring. Of course there is not much we can do with such a plain ring, we can
compute with its elements and can do a few things that are related to the group of units.
gap> Quotient( GaussianIntegers, 2, 1+E(4) );
1-E(4)
gap> Quotient( GaussianIntegers, 3, 1+E(4) );
false
gap> IsAssociated( GaussianIntegers, 1+E(4), 1-E(4) );
true
gap> StandardAssociate( GaussianIntegers, 3 - E(4) );
1+3*E(4)
The remaining functions are related to the fact that the Gaussian integers are an Euclidean
ring (and thus also a unique factorization ring).
The first such function is EuclideanDegree. In our example the Euclidean degree of a
Gaussian integer is of course simply its norm. Just as with StandardAssociate we must
implement this function because there is no general way to compute the Euclidean degree
for an arbitrary Euclidean ring. The function itself is again very simple. The Euclidean
degree of a Gaussian integer x is the product of x with its complex conjugate, which is
denoted in GAP3 by GaloisCyc( x , -1 ).
gap> GaussianIntegersOps.EuclideanDegree := function ( GaussInt, x )
>
return x * GaloisCyc( x, -1 );
> end;;
Once we have defined the Euclidean degree we want to implement the QuotientRemainder
function that gives us the Euclidean quotient and remainder of a division.
gap> GaussianIntegersOps.QuotientRemainder := function ( GaussInt, x, y )
>
return [ RoundCyc( x/y ), x - RoundCyc( x/y ) * y ];
> end;;
Note that in the definition of QuotientRemainder we must use the function RoundCyc, which
views the Gaussian rational x /y as a point in the complex plane and returns the point of
the lattice spanned by 1 and E(4) closest to the point x /y. If we would truncate towards
the origin instead (this is done by the function IntCyc) we could not guarantee that the
1.28. ABOUT DEFINING NEW DOMAINS
173
result of EuclideanRemainder always has Euclidean degree less than the Euclidean degree
of y as the following example shows.
gap> x := 2 - E(4);; EuclideanDegree( GaussianIntegers, x );
5
gap> y := 2 + E(4);; EuclideanDegree( GaussianIntegers, y );
5
gap> q := x / y; q := IntCyc( q );
3/5-4/5*E(4)
0
gap> EuclideanDegree( GaussianIntegers, x - q * y );
5
Now that we have implemented the QuotientRemainder function we can compute greatest
common divisors in the ring of Gaussian integers. This is because we have inherited from
RingOps the general function Gcd that computes the greatest common divisor using Euclid’s
algorithm, which only uses QuotientRemainder (and StandardAssociate to return the
result in a normal form). Of course we can now also compute least common multiples,
because that only uses Gcd.
gap> Gcd( GaussianIntegers, 2, 5 - E(4) );
1+E(4)
gap> Lcm( GaussianIntegers, 2, 5 - E(4) );
6+4*E(4)
Since the Gaussian integers are a Euclidean ring they are also a unique factorization ring.
The next two functions implement the necessary operations. The first is the test for primality. A rational integer is a prime in the ring of Gaussian integers if and only if it is
congruent to 3 modulo 4 (the other rational integer primes split into two irreducibles), and
a Gaussian integer that is not a rational integer is a prime if its norm is a rational integer
prime.
gap> GaussianIntegersOps.IsPrime := function ( GaussInt, x )
>
if IsInt( x ) then
>
return x mod 4 = 3 and IsPrimeInt( x );
>
else
>
return IsPrimeInt( x * GaloisCyc( x, -1 ) );
>
fi;
> end;;
The factorization is based on the same observation. We compute the Euclidean degree of
the number that we want to factor, and factor this rational integer. Then for every rational
integer prime that is congruent to 3 modulo 4 we get one factor, and we split the other
rational integer primes using the function TwoSquares and test which irreducible divides.
gap> GaussianIntegersOps.Factors := function ( GaussInt, x )
>
local
facs,
# factors (result)
>
prm,
# prime factors of the norm
>
tsq;
# representation of prm as x^2 + y^2
>
>
# handle trivial cases
>
if x in [ 0, 1, -1, E(4), -E(4) ] then
174
CHAPTER 1. ABOUT GAP
>
return [ x ];
>
fi;
>
>
# loop over all factors of the norm of x
>
facs := [];
>
for prm in Set( FactorsInt( EuclideanDegree( x ) ) ) do
>
>
# p = 2 and primes p = 1 mod 4 split according to p = x^2+y^2
>
if prm = 2 or prm mod 4 = 1 then
>
tsq := TwoSquares( prm );
>
while IsCycInt( x / (tsq[1]+tsq[2]*E(4)) ) do
>
Add( facs, (tsq[1]+tsq[2]*E(4)) );
>
x := x / (tsq[1]+tsq[2]*E(4));
>
od;
>
while IsCycInt( x / (tsq[2]+tsq[1]*E(4)) ) do
>
Add( facs, (tsq[2]+tsq[1]*E(4)) );
>
x := x / (tsq[2]+tsq[1]*E(4));
>
od;
>
>
# primes p = 3 mod 4 stay prime
>
else
>
while IsCycInt( x / prm ) do
>
Add( facs, prm );
>
x := x / prm;
>
od;
>
fi;
>
>
od;
>
>
# the first factor takes the unit
>
facs[1] := x * facs[1];
>
>
# return the result
>
return facs;
> end;;
So now we can factorize numbers in the ring of Gaussian integers.
gap> Factors( GaussianIntegers, 10 );
[ -1-E(4), 1+E(4), 1+2*E(4), 2+E(4) ]
gap> Factors( GaussianIntegers, 103 );
[ 103 ]
Now we have written all the functions for the operations record that implement the operations. We would like one more thing however. Namely that we can simply write Gcd(
2, 5 - E(4) ) without having to specify GaussianIntegers as first argument. Gcd and
the other functions should be clever enough to find out that the arguments are Gaussian
integers and call GaussianIntegers.operations.Gcd automatically.
To do this we must first understand what happens when Gcd is called without a ring as
first argument. For an example suppose that we have called Gcd( 66, 123 ) (and want to
1.28. ABOUT DEFINING NEW DOMAINS
175
compute the gcd over the integers).
First Gcd calls DefaultRing( [ 66, 123 ] ), to obtain a ring that contains 66 and 123.
DefaultRing then calls Domain( [ 66, 123 ] ) to obtain a domain, which need not be
a ring, that contains 66 and 123. Domain is the only function in the whole GAP3 library
that knows about the various types of elements. So it looks at its argument and decides
to return the domain Integers (which is in fact already a ring, but it could in principle also return Rationals). DefaultRing now calls Integers.operations.DefaultRing(
[ 66, 123 ] ) and expects a ring in which the requested gcd computation can be performed. Integers.operations.DefaultRing( [ 66, 123 ] ) also returns Integers. So
DefaultRing returns Integers to Gcd and Gcd finally calls Integers.operations.Gcd(
Integers, 66, 123 ).
So the first thing we must do is to tell Domain about Gaussian integers. We do this by
extending Domain with the two lines
elif ForAll( elms, IsGaussInt )
return GaussianIntegers;
then
so that it now looks as follows.
gap> Domain := function ( elms )
>
local
elm;
>
if
ForAll( elms, IsInt ) then
>
return Integers;
>
elif ForAll( elms, IsRat ) then
>
return Rationals;
>
elif ForAll( elms, IsFFE ) then
>
return FiniteFieldElements;
>
elif ForAll( elms, IsPerm ) then
>
return Permutations;
>
elif ForAll( elms, IsMat ) then
>
return Matrices;
>
elif ForAll( elms, IsWord ) then
>
return Words;
>
elif ForAll( elms, IsAgWord ) then
>
return AgWords;
>
elif ForAll( elms, IsGaussInt ) then
>
return GaussianIntegers;
>
elif ForAll( elms, IsCyc ) then
>
return Cyclotomics;
>
else
>
for elm in elms do
>
if
IsRec(elm) and IsBound(elm.domain)
>
and ForAll( elms, l -> l in elm.domain )
>
then
>
return elm.domain;
>
fi;
>
od;
>
Error("sorry, the elements lie in no common domain");
>
fi;
176
CHAPTER 1. ABOUT GAP
> end;;
Of course we must define a function IsGaussInt, otherwise this could not possibly work.
This function is similar to the membership test we already defined above.
gap> IsGaussInt := function ( x )
>
return IsCycInt( x ) and (NofCyc( x ) = 1 or NofCyc( x ) = 4);
> end;;
Then we must define a function DefaultRing for the Gaussian integers that does nothing
but return GaussianIntegers.
gap> GaussianIntegersOps.DefaultRing := function ( elms )
>
return GaussianIntegers;
> end;;
Now we can call Gcd with two Gaussian integers without having to pass GaussianIntegers
as first argument.
gap> Gcd( 2, 5 - E(4) );
1+E(4)
Of course GAP3 can not read your mind. In the following example it assumes that you
want to factor 10 over the ring of integers, not over the ring of Gaussian integers (because
Integers is the default ring containing 10). So if you want to factor a rational integer over
the ring of Gaussian integers you must pass GaussianIntegers as first argument.
gap> Factors( 10 );
[ 2, 5 ]
gap> Factors( GaussianIntegers, 10 );
[ -1-E(4), 1+E(4), 1+2*E(4), 2+E(4) ]
This concludes our example. In the file LIBNAME/"gaussian.g" you will also find the definition of the field of Gaussian rationals. It is so similar to the above definition that there is no
point in discussing it here. The next section shows you what further considerations are necessary when implementing a type of parametrized domains (demonstrated by implementing
full symmetric permutation groups). For further details see chapter 14 for a description of
the Gaussian integers and rationals and chapter 5 for a list of all functions applicable to
rings.
1.29
About Defining New Parametrized Domains
In this section we will show you an example that is slightly more complex than the example
in the previous section. Namely we will demonstrate how one can implement parametrized
domains. As an example we will implement symmetric permutation groups. This works
similar to the implementation of a single domain. Therefore we can be very brief. Of course
you should have read the previous section.
Note that everything defined here is already in the file GRPNAME/"permgrp.grp", so there is
no need for you to type it in. You may however like to make a copy of this file and modify
it.
In the example of the previous section we simply had a variable (GaussianIntegers), whose
value was the domain. This can not work in this example, because there is not one symmetric permutation group. The solution is obvious. We simply define a function that takes
the degree and returns the symmetric permutation group of this degree (as a domain).
1.29. ABOUT DEFINING NEW PARAMETRIZED DOMAINS
177
gap> SymmetricPermGroup := function ( n )
>
local
G;
# symmetric group on points, result
>
>
# make the group generated by (1,n), (2,n), .., (n-1,n)
>
G := Group( List( [1..n-1], i -> (i,n) ), () );
>
G.degree := n;
>
>
# give it the correct operations record
>
G.operations := SymmetricPermGroupOps;
>
>
# return the symmetric group
>
return G;
> end;;
The key is of course to give the domains returned by SymmetricPermGroup a new operations
record. This operations record will hold functions that are written especially for symmetric
permutation groups. Note that all symmetric groups created by SymmetricPermGroup share
one operations record.
Just as we inherited in the example in the previous section from the operations record
RingOps, here we can inherit from the operations record PermGroupOps (after all, each
symmetric permutation group is also a permutation group).
gap> SymmetricPermGroupOps := Copy( PermGroupOps );
We will now overlay some of the functions in this operations record with new functions
that make use of the fact that the domain is a full symmetric permutation group. The first
function that does this is the membership test function.
gap> SymmetricPermGroupOps.\in := function ( g, G )
>
return
IsPerm( g )
>
and (
g = ()
>
or LargestMovedPointPerm( g ) <= G.degree);
> end;;
The most important knowledge for a permutation group is a base and a strong generating
set with respect to that base. It is not important that you understand at this point what
this is mathematically. The important point here is that such a strong generating set with
respect to an appropriate base is used by many generic permutation group functions, most
of which we inherit for symmetric permutation groups. Therefore it is important that we
are able to compute a strong generating set as fast as possible. Luckily it is possible to
simply write down such a strong generating set for a full symmetric group. This is done by
the following function.
gap> SymmetricPermGroupOps.MakeStabChain := function ( G, base )
>
local
sgs,
# strong generating system of G wrt. base
>
last;
# last point of the base
>
>
# remove all unwanted points from the base
>
base := Filtered( base, i -> i <= G.degree );
>
>
# extend the base with those points not already in the base
178
CHAPTER 1. ABOUT GAP
>
base := Concatenation( base, Difference( [1..G.degree], base ) );
>
>
# take the last point
>
last := base[ Length(base) ];
>
>
# make the strong generating set
>
sgs := List( [1..Length(base)-1], i -> ( base[i], last ) );
>
>
# make the stabilizer chain
>
MakeStabChainStrongGenerators( G, base, sgs );
> end;;
One of the things that are very easy for symmetric groups is the computation of centralizers
of elements. The next function does this. Again it is not important that you understand
this mathematically. The centralizer of an element g in the symmetric group is generated
by the cycles c of g and an element x for each pair of cycles of g of the same length that
maps one cycle to the other.
gap> SymmetricPermGroupOps.Centralizer := function ( G, g )
>
local
C,
# centralizer of g in G, result
>
sgs,
# strong generating set of C
>
gen,
# one generator in sgs
>
cycles, # cycles of g
>
cycle, # one cycle from cycles
>
lasts, # lasts[l] is the last cycle of length l
>
last,
# one cycle from lasts
>
i;
# loop variable
>
>
# handle special case
>
if IsPerm( g ) and g in G then
>
>
# start with the empty strong generating system
>
sgs := [];
>
>
# compute the cycles and find for each length the last one
>
cycles := Cycles( g, [1..G.degree] );
>
lasts := [];
>
for cycle in cycles do
>
lasts[Length(cycle)] := cycle;
>
od;
>
>
# loop over the cycles
>
for cycle in cycles do
>
>
# add that cycle itself to the strong generators
>
if Length( cycle ) <> 1 then
>
gen := [1..G.degree];
>
for i in [1..Length(cycle)-1] do
>
gen[cycle[i]] := cycle[i+1];
1.29. ABOUT DEFINING NEW PARAMETRIZED DOMAINS
179
>
od;
>
gen[cycle[Length(cycle)]] := cycle[1];
>
gen := PermList( gen );
>
Add( sgs, gen );
>
fi;
>
>
# and it can be mapped to the last cycle of this length
>
if cycle <> lasts[ Length(cycle) ] then
>
last := lasts[ Length(cycle) ];
>
gen := [1..G.degree];
>
for i in [1..Length(cycle)] do
>
gen[cycle[i]] := last[i];
>
gen[last[i]] := cycle[i];
>
od;
>
gen := PermList( gen );
>
Add( sgs, gen );
>
fi;
>
>
od;
>
>
# make the centralizer
>
C := Subgroup( G, sgs );
>
>
# make the stabilizer chain
>
MakeStabChainStrongGenerators( C, [1..G.degree], sgs );
>
>
# delegate general case
>
else
>
C := PermGroupOps.Centralizer( G, g );
>
fi;
>
>
# return the centralizer
>
return C;
> end;;
Note that the definition C := Subgroup( G, sgs ); defines a subgroup of a symmetric
permutation group. But this subgroup is usually not a full symmetric permutation group
itself. Thus C must not have the operations record SymmetricPermGroupOps, instead it
should have the operations record PermGroupOps. And indeed C will have this operations
record. This is because Subgroup calls G.operations.Subgroup, and we inherited this
function from PermGroupOps.
Note also that we only handle one special case in the function above. Namely the computation of a centralizer of a single element. This function can also be called to compute the
centralizer of a whole subgroup. In this case SymmetricPermGroupOps.Centralizer simply
delegates the problem by calling PermGroupOps.Centralizer.
The next function computes the conjugacy classes of elements in a symmetric group. This
is very easy, because two elements are conjugated in a symmetric group when they have the
same cycle structure. Thus we can simply compute the partitions of the degree, and for
180
CHAPTER 1. ABOUT GAP
each degree we get one conjugacy class.
gap> SymmetricPermGroupOps.ConjugacyClasses := function ( G )
>
local
classes,
# conjugacy classes of G, result
>
prt,
# partition of G
>
sum,
# partial sum of the entries in prt
>
rep,
# representative of a conjugacy class of G
>
i;
# loop variable
>
>
# loop over the partitions
>
classes := [];
>
for prt in Partitions( G.degree ) do
>
>
# compute the representative of the conjugacy class
>
rep := [2..G.degree];
>
sum := 1;
>
for i in prt do
>
rep[sum+i-1] := sum;
>
sum := sum + i;
>
od;
>
rep := PermList( rep );
>
>
# add the new class to the list of classes
>
Add( classes, ConjugacyClass( G, rep ) );
>
>
od;
>
>
# return the classes
>
return classes;
> end;;
This concludes this example. You have seen that the implementation of a parametrized
domain is not much more difficult than the implementation of a single domain. You have
also seen how functions that overlay generic functions may delegate problems back to the
generic function. The library file for symmetric permutation groups contain some more
functions for symmetric permutation groups.
1.30
About Defining New Group Elements
In this section we will show how one can add a new type of group elements to GAP3. A lot
of group elements in GAP3 are implemented this way, for example elements of generic factor
groups, or elements of generic direct products.
We will use prime residue classes modulo an integer as our example. They have the advantage that the arithmetic is very simple, so that we can concentrate on the implementation
without being carried away by mathematical details.
Note that everything we define is already in the library in the file LIBNAME/"numtheor.g",
so there is no need for you to type it in. You may however like to make a copy of this file
and modify it.
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
181
We will represent residue classes by records. This is absolutely typical, all group elements
not built into the GAP3 kernel are realized by records.
To distinguish records representing residue classes from other records we require that residue
class records have a component with the name isResidueClass and the value true. We
also require that they have a component with the name isGroupElement and again the
value true. Those two components are called the tag components.
Next each residue class record must of course have components that tell us which residue
class this record represents. The component with the name representative contains the
smallest nonnegative element of the residue class. The component with the name modulus
contains the modulus. Those two components are called the identifying components.
Finally each residue class record must have a component with the name operations that
contains an appropriate operations record (see below). In this way we can make use of the
possibility to define operations for records (see 46.4 and 46.5).
Below is an example of a residue class record.
r13mod43 := rec(
isGroupElement
isResidueClass
representative
modulus
domain
operations
:=
:=
:=
:=
:=
:=
true,
true,
13,
43,
GroupElements,
ResidueClassOps );
The first function that we have to write is very simple. Its only task is to test whether an
object is a residue class. It does this by testing for the tag component isResidueClass.
gap> IsResidueClass := function ( obj )
>
return IsRec( obj )
>
and IsBound( obj.isResidueClass )
>
and obj.isResidueClass;
> end;;
Our next function takes a representative and a modulus and constructs a new residue class.
Again this is not very difficult.
gap> ResidueClass := function ( representative, modulus )
>
local res;
>
res := rec();
>
res.isGroupElement := true;
>
res.isResidueClass := true;
>
res.representative := representative mod modulus;
>
res.modulus
:= modulus;
>
res.domain
:= GroupElements;
>
res.operations
:= ResidueClassOps;
>
return res;
> end;;
Now we have to define the operations record for residue classes. Remember that this record
contains a function for each binary operation, which is called to evaluate such a binary
operation (see 46.4 and 46.5). The operations =, <, *, /, mod, ^, Comm, and Order are the
182
CHAPTER 1. ABOUT GAP
ones that are applicable to all group elements. The meaning of those operations for group
elements is described in 7.2 and 7.3.
Luckily we do not have to define everything. Instead we can inherit a lot of those functions
from generic group elements. For example, for all group elements g/h should be equivalent
to g*h^-1. So the function for / could simply be function(g,h) return g*h^-1; end.
Note that this function can be applied to all group elements, independently of their type,
because all the dependencies are in * and ^.
The operations record GroupElementOps contains such functions that can be used by all
types of group elements. Note that there is no element that has GroupElementsOps as its
operations record. This is impossible, because there is for example no generic method to
multiply or invert group elements. Thus GroupElementsOps is only used to inherit general
methods as is done below.
gap> ResidueClassOps := Copy( GroupElementOps );;
Note that the copy is necessary, otherwise the following assignments would not only change
ResidueClassOps but also GroupElementOps.
The first function we are implementing is the equality comparison. The required operation
is described simply enough. = should evaluate to true if the operands are equal and false
otherwise. Two residue classes are of course equal if they have the same representative and
the same modulus. One complication is that when this function is called either operand
may not be a residue class. Of course at least one must be a residue class otherwise this
function would not have been called at all.
gap> ResidueClassOps.\= := function ( l, r )
>
local
isEql;
>
if IsResidueClass( l ) then
>
if IsResidueClass( r ) then
>
isEql :=
l.representative = r.representative
>
and l.modulus
= r.modulus;
>
else
>
isEql := false;
>
fi;
>
else
>
if IsResidueClass( r ) then
>
isEql := false;
>
else
>
Error("panic, neither nor is a residue class");
>
fi;
>
fi;
>
return isEql;
> end;;
Note that the quotes around the equal sign = are necessary, otherwise it would not be taken
as a record component name, as required, but as the symbol for equality, which must not
appear at this place.
Note that we do not have to implement a function for the inequality operator <>, because
it is in the GAP3 kernel implemented by the equivalence l <> r is not l = r .
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
183
The next operation is the comparison. We define that one residue class is smaller than
another residue class if either it has a smaller modulus or, if the moduli are equal, it has a
smaller representative. We must also implement comparisons with other objects.
gap> ResidueClassOps.\< := function ( l, r )
>
local
isLess;
>
if IsResidueClass( l ) then
>
if IsResidueClass( r ) then
>
isLess :=
l.representative < r.representative
>
or (l.representative = r.representative
>
and l.modulus
< r.modulus);
>
else
>
isLess := not IsInt( r ) and not IsRat( r )
>
and not IsCyc( r ) and not IsPerm( r )
>
and not IsWord( r ) and not IsAgWord( r );
>
fi;
>
else
>
if IsResidueClass( r ) then
>
isLess := IsInt( l ) or IsRat( l )
>
or IsCyc( l ) or IsPerm( l )
>
or IsWord( l ) or IsAgWord( l );
>
else
>
Error("panic, neither nor is a residue class");
>
fi;
>
fi;
>
return isLess;
> end;;
The next operation that we must implement is the multiplication *. This function is quite
complex because it must handle several different tasks. To make its implementation easier
to understand we will start with a very simple–minded one, which only multiplies residue
classes, and extend it in the following paragraphs.
gap> ResidueClassOps.\* := function ( l, r )
>
local
prd;
# product of l and r, result
>
if IsResidueClass( l ) then
>
if IsResidueClass( r ) then
>
if l.modulus <> r.modulus then
>
Error(" and must have the same modulus");
>
fi;
>
prd := ResidueClass(
>
l.representative * r.representative,
>
l.modulus );
>
else
>
Error("product of and must be defined");
>
fi;
>
else
>
if IsResidueClass( r ) then
>
Error("product of and must be defined");
>
else
184
CHAPTER 1. ABOUT GAP
>
Error("panic, neither nor is a residue class");
>
fi;
>
fi;
>
return prd;
> end;;
This function correctly multiplies residue classes, but there are other products that must
be implemented. First every group element can be multiplied with a list of group elements,
and the result shall be the list of products (see 7.3 and 27.13). In such a case the above
function would only signal an error, which is not acceptable. Therefore we must extend this
definition.
gap> ResidueClassOps.\* := function ( l, r )
>
local
prd;
# product of l and r, result
>
if IsResidueClass( l ) then
>
if IsResidueClass( r ) then
>
if l.modulus <> r.modulus then
>
Error( " and must have the same modulus" );
>
fi;
>
prd := ResidueClass(
>
l.representative * r.representative,
>
l.modulus );
>
elif IsList( r ) then
>
prd := List( r, x -> l * x );
>
else
>
Error("product of and must be defined");
>
fi;
>
elif IsList( l ) then
>
if IsResidueClass( r ) then
>
prd := List( l, x -> x * r );
>
else
>
Error("panic: neither nor is a residue class");
>
fi;
>
else
>
if IsResidueClass( r ) then
>
Error( "product of and must be defined" );
>
else
>
Error("panic, neither nor is a residue class");
>
fi;
>
fi;
>
return prd;
> end;;
This function is almost complete. However it is also allowed to multiply a group element
with a subgroup and the result shall be a coset (see 7.86). The operations record of subgroups, which are of course also represented by records (see 7.118), contains a function that
constructs such a coset. The problem is that in an expression like subgroup * residue-class,
this function is not called. This is because the multiplication function in the operations
record of the right operand is called if both operands have such a function (see 46.5). Now
in the above case both operands have such a function. The left operand subgroup has the
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
185
operations record GroupOps (or some refinement thereof), the right operand residue-class
has the operations record ResidueClassOps. Thus ResidueClassOps.* is called. But it
does not and also should not know how to construct a coset. The solution is simple. The
multiplication function for residue classes detects this special case and simply calls the
multiplication function of the left operand.
gap> ResidueClassOps.\* := function ( l, r )
>
local
prd;
# product of l and r, result
>
if IsResidueClass( l ) then
>
if IsResidueClass( r ) then
>
if l.modulus <> r.modulus then
>
Error( " and must have the same modulus" );
>
fi;
>
prd := ResidueClass(
>
l.representative * r.representative,
>
l.modulus );
>
elif IsList( r ) then
>
prd := List( r, x -> l * x );
>
else
>
Error("product of and must be defined");
>
fi;
>
elif IsList( l ) then
>
if IsResidueClass( r ) then
>
prd := List( l, x -> x * r );
>
else
>
Error("panic: neither nor is a residue class");
>
fi;
>
else
>
if IsResidueClass( r ) then
>
if IsRec( l ) and IsBound( l.operations )
>
and IsBound( l.operations.\* )
>
and l.operations.\* <> ResidueClassOps.\*
>
then
>
prd := l.operations.\*( l, r );
>
else
>
Error("product of and must be defined");
>
fi;
>
else
>
Error("panic, neither nor is a residue class");
>
fi;
>
fi;
>
return prd;
> end;;
Now we are done with the multiplication.
Next is the powering operation ^. It is not very complicated. The PowerMod function (see
5.25) does most of what we need, especially the inversion of elements with the Euclidean
algorithm when the exponent is negative. Note however, that the definition of operations
(see 7.3) requires that the conjugation is available as power of a residue class by another
186
CHAPTER 1. ABOUT GAP
residue class. This is of course very easy since residue classes form an abelian group.
gap> ResidueClassOps.\^ := function ( l, r )
>
local
pow;
>
if IsResidueClass( l ) then
>
if IsResidueClass( r ) then
>
if l.modulus <> r.modulus then
>
Error(" and must have the same modulus");
>
fi;
>
if GcdInt( r.representative, r.modulus ) <> 1 then
>
Error(" must be invertable");
>
fi;
>
pow := l;
>
elif IsInt( r ) then
>
pow := ResidueClass(
>
PowerMod( l.representative, r, l.modulus ),
>
l.modulus );
>
else
>
Error("power of and must be defined");
>
fi;
>
else
>
if IsResidueClass( r ) then
>
Error("power of and must be defined");
>
else
>
Error("panic, neither nor is a residue class");
>
fi;
>
fi;
>
return pow;
> end;;
The last function that we have to write is the printing function. This is called to print
a residue class. It prints the residue class in the form ResidueClass( representative,
modulus ). It is fairly typical to print objects in such a form. This form has the advantage
that it can be read back, resulting in exactly the same element, yet it is very concise.
gap> ResidueClassOps.Print := function ( r )
>
Print("ResidueClass( ",r.representative,", ",r.modulus," )");
> end;;
Now we are done with the definition of residue classes as group elements. Try them. We
can at this point actually create groups of such elements, and compute in them.
However, we are not yet satisfied. There are two problems with the code we have implemented so far. Different people have different opinions about which of those problems is the
graver one, but hopefully all agree that we should try to attack those problems.
The first problem is that it is still possible to define objects via Group (see 7.9) that are not
actually groups.
gap> G := Group( ResidueClass(13,43), ResidueClass(13,41) );
Group( ResidueClass( 13, 43 ), ResidueClass( 13, 41 ) )
The other problem is that groups of residue classes constructed with the code we have
implemented so far are not handled very efficiently. This is because the generic group
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
187
algorithms are used, since we have not implemented anything else. For example to test
whether a residue class lies in a residue class group, all elements of the residue class group
are computed by a Dimino algorithm, and then it is tested whether the residue class is an
element of this proper set.
To solve the first problem we must first understand what happens with the above code if we
create a group with Group( res1 , res2 ... ). Group tries to find a domain that contains
all the elements res1 , res2 , etc. It first calls Domain( [ res1 , res2 ... ] ) (see 4.5).
Domain looks at the residue classes and sees that they all are records and that they all
have a component with the name domain. This is understood to be a domain in which the
elements lie. And in fact res1 in GroupElements is true, because GroupElements accepts
all records with tag isGroupElement. So Domain returns GroupElements. Group then calls
GroupElements.operations.Group(GroupElements,[res1 ,res2 ...],id ), where id is the
identity residue class, obtained by res1 ^ 0, and returns the result.
GroupElementsOps.Group is the function that actually creates the group. It does this by
simply creating a record with its second argument as generators list, its third argument
as identity, and the generic GroupOps as operations record. It ignores the first argument,
which is passed only because convention dictates that a dispatcher passes the domain as
first argument.
So to solve the first problem we must achieve that another function instead of the generic
function GroupElementsOps.Group is called. This can be done by persuading Domain to
return a different domain. And this will happen if the residue classes hold this other domain
in their domain component.
The obvious choice for such a domain is the (yet to be written) domain ResidueClasses.
So ResidueClass must be slightly changed.
gap> ResidueClass := function ( representative, modulus )
>
local res;
>
res := rec();
>
res.isGroupElement := true;
>
res.isResidueClass := true;
>
res.representative := representative mod modulus;
>
res.modulus
:= modulus;
>
res.domain
:= ResidueClasses;
>
res.operations
:= ResidueClassOps;
>
return res;
> end;;
The main purpose of the domain ResidueClasses is to construct groups, so there is very
little we have to do. And in fact most of that can be inherited from GroupElements.
gap>
gap>
gap>
gap>
ResidueClasses := Copy( GroupElements );;
ResidueClasses.name := "ResidueClasses";;
ResidueClassesOps := Copy( GroupElementsOps );;
ResidueClasses.operations := ResidueClassesOps;;
So now we must implement ResidueClassesOps.Group, which should check whether the
passed elements do in fact form a group. After checking it simply delegates to the generic
function GroupElementsOps.Group to create the group as before.
gap> ResidueClassesOps.Group := function ( ResidueClasses, gens, id )
188
CHAPTER 1. ABOUT GAP
>
local
g;
# one generator from gens
>
for g in gens do
>
if g.modulus <> id.modulus then
>
Error("the generators must all have the same modulus");
>
fi;
>
if GcdInt( g.representative, g.modulus ) <> 1 then
>
Error("the generators must all be prime residue classes");
>
fi;
>
od;
>
return GroupElementOps.Group( ResidueClasses, gens, id );
> end;;
This solves the first problem. To solve the second problem, i.e., to make operations with
residue class groups more efficient, we must extend the function ResidueClassesOps.Group.
It now enters a new operations record into the group. It also puts the modulus into the
group record, so that it is easier to access.
gap> ResidueClassesOps.Group := function ( ResidueClasses, gens, id )
>
local
G,
# group G, result
>
gen;
# one generator from gens
>
for gen in gens do
>
if gen.modulus <> id.modulus then
>
Error("the generators must all have the same modulus");
>
fi;
>
if GcdInt( gen.representative, gen.modulus ) <> 1 then
>
Error("the generators must all be prime residue classes");
>
fi;
>
od;
>
G := GroupElementsOps.Group( ResidueClasses, gens, id );
>
G.modulus
:= id.modulus;
>
G.operations := ResidueClassGroupOps;
>
return G;
> end;;
Of course now we must build such an operations record. Luckily we do not have to implement
all functions, because we can inherit a lot of functions from GroupOps. This is done by
copying GroupOps as we have done before for ResidueClassOps and ResidueClassesOps.
gap> ResidueClassGroupOps := Copy( GroupOps );;
Now the first function that we must write is the Subgroup function to ensure that not only
groups constructed by Group have the correct operations record, but also subgroups of those
groups created by Subgroup. As in Group we only check the arguments and then leave the
work to GroupOps.Subgroup.
gap> ResidueClassGroupOps.Subgroup := function ( G, gens )
>
local
S,
# subgroup of G, result
>
gen;
# one generator from gens
>
for gen in gens do
>
if gen.modulus <> G.modulus then
>
Error("the generators must all have the same modulus");
>
fi;
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
189
>
if GcdInt( gen.representative, gen.modulus ) <> 1 then
>
Error("the generators must all be prime residue classes");
>
fi;
>
od;
>
S := GroupOps.Subgroup( G, gens );
>
S.modulus
:= G.modulus;
>
S.operations := ResidueClassGroupOps;
>
return S;
> end;;
The first function that we write especially for residue class groups is SylowSubgroup. Since
residue class groups are abelian we can compute a Sylow subgroup of such a group by simply
taking appropriate powers of the generators.
gap> ResidueClassGroupOps.SylowSubgroup := function ( G, p )
>
local
S,
# Sylow subgroup of G, result
>
gen,
# one generator of G
>
ord,
# order of gen
>
gens;
# generators of S
>
gens := [];
>
for gen in G.generators do
>
ord := OrderMod( gen.representative, G.modulus );
>
while ord mod p = 0 do ord := ord / p; od;
>
Add( gens, gen ^ ord );
>
od;
>
S := Subgroup( Parent( G ), gens );
>
return S;
> end;;
To allow the other functions that are applicable to residue class groups to work efficiently
we now want to make use of the fact that residue class groups are direct products of cyclic
groups and that we know what those factors are and how we can project onto those factors.
To do this we write ResidueClassGroupOps.MakeFactors that adds the components facts,
roots, sizes, and sgs to the group record G. This information, detailed below, will enable
other functions to work efficiently with such groups. Creating such information is a fairly
typical thing, for example for permutation groups the corresponding information is the
stabilizer chain computed by MakeStabChain.
G.facts will be the list of prime power factors of G.modulus. Actually this is a little bit
more complicated, because the residue class group modulo the largest power q of 2 that
divides G.modulus need not be cyclic. So if q is a multiple of 4, G.facts[1] will be 4,
corresponding to the projection of G into (Z/4Z)∗ (of size 2), furthermore if q is a multiple of
8, G.facts[2] will be q, corresponding to the projection of G into the subgroup generated
by 5 in (Z/qZ)∗ (of size q/4).
G.roots will be a list of primitive roots, i.e., of generators of the corresponding factors in
G.facts. G.sizes will be a list of the sizes of the corresponding factors in G.facts, i.e.,
G.sizes[i ] = Phi( G.facts[i ] ). (If G.modulus is a multiple of 8, G.roots[2] will
be 5, and G.sizes[2] will be q/4.)
Now we can represent each element g of the group G by a list e, called the exponent
vector, of the length of G.facts, where e[i ] is the logarithm of g.representative mod
190
CHAPTER 1. ABOUT GAP
G.facts[i ] with respect to G.roots[i ]. The multiplication of elements of G corresponds
to the componentwise addition of their exponent vectors, where we add modulo G.sizes[i ]
in the i -th component. (Again special consideration are necessary if G.modulus is divisible
by 8.)
Next we compute the exponent vectors of all generators of G, and represent this information
as a matrix. Then we bring this matrix into upper triangular form, with an algorithm that
is very much like the ordinary Gaussian elimination, modified to account for the different
sizes of the components. This upper triangular matrix of exponent vectors is the component
G.sgs. This new matrix obviously still contains the exponent vectors of a generating system
of G, but a much nicer one, which allows us to tackle problems one component at a time. (It
is not necessary that you fully check this, the important thing here is not the mathematical
side.)
gap> ResidueClassGroupOps.MakeFactors := function ( G )
>
local
p, q,
# prime factor of modulus and largest power
>
r, s,
# two rows of the standard generating system
>
g,
# extended gcd of leading entries in r, s
>
x, y,
# two entries in r and s
>
i, k, l;
# loop variables
>
>
# find the factors of the direct product
>
G.facts := [];
>
G.roots := [];
>
G.sizes := [];
>
for p in Set( Factors( G.modulus ) ) do
>
q := p;
>
while G.modulus mod (p*q) = 0 do q := p*q; od;
>
if q mod 4 = 0 then
>
Add( G.facts, 4 );
>
Add( G.roots, 3 );
>
Add( G.sizes, 2 );
>
fi;
>
if q mod 8 = 0 then
>
Add( G.facts, q );
>
Add( G.roots, 5 );
>
Add( G.sizes, q/4 );
>
fi;
>
if p <> 2 then
>
Add( G.facts, q );
>
Add( G.roots, PrimitiveRootMod( q ) );
>
Add( G.sizes, (p-1)*q/p );
>
fi;
>
od;
>
>
# represent each generator in this factorization
>
G.sgs := [];
>
for k in [ 1 .. Length( G.generators ) ] do
>
G.sgs[k] := [];
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
191
>
for i in [ 1 .. Length( G.facts ) ] do
>
if G.facts[i] mod 8 = 0 then
>
if G.generators[k].representative mod 4 = 1 then
>
G.sgs[k][i] := LogMod(
>
G.generators[k].representative,
>
G.roots[i], G.facts[i] );
>
else
>
G.sgs[k][i] := LogMod(
>
-G.generators[k].representative,
>
G.roots[i], G.facts[i] );
>
fi;
>
else
>
G.sgs[k][i] := LogMod(
>
G.generators[k].representative,
>
G.roots[i], G.facts[i] );
>
fi;
>
od;
>
od;
>
for i in [ Length( G.sgs ) + 1 .. Length( G.facts ) ] do
>
G.sgs[i] := 0 * G.facts;
>
od;
>
>
# bring this matrix to diagonal form
>
for i in [ 1 .. Length( G.facts ) ] do
>
r := G.sgs[i];
>
for k in [ i+1 .. Length( G.sgs ) ] do
>
s := G.sgs[k];
>
g := Gcdex( r[i], s[i] );
>
for l in [ i .. Length( r ) ] do
>
x := r[l]; y := s[l];
>
r[l] := (g.coeff1 * x + g.coeff2 * y) mod G.sizes[l];
>
s[l] := (g.coeff3 * x + g.coeff4 * y) mod G.sizes[l];
>
od;
>
od;
>
s := [];
>
x := G.sizes[i] / GcdInt( G.sizes[i], r[i] );
>
for l in [ 1 .. Length( r ) ] do
>
s[l] := (x * r[l]) mod G.sizes[l];
>
od;
>
Add( G.sgs, s );
>
od;
>
> end;;
With the information computed by MakeFactors it is now of course very easy to compute
the size of a residue class group. We just look at the G.sgs, and multiply the orders of the
leading exponents of the nonzero exponent vectors.
gap> ResidueClassGroupOps.Size := function ( G )
192
CHAPTER 1. ABOUT GAP
>
local
s,
# size of G, result
>
i;
# loop variable
>
if not IsBound( G.facts ) then
>
G.operations.MakeFactors( G );
>
fi;
>
s := 1;
>
for i in [ 1 .. Length( G.facts ) ] do
>
s := s * G.sizes[i] / GcdInt( G.sizes[i], G.sgs[i][i] );
>
od;
>
return s;
> end;;
The membership test is a little bit more complicated. First we test that the first argument
is really a residue class with the correct modulus. Then we compute the exponent vector of
this residue class and reduce this exponent vector using the upper triangular matrix G.sgs.
gap> ResidueClassGroupOps.\in := function ( res, G )
>
local
s,
# exponent vector of res
>
g,
# extended gcd
>
x, y,
# two entries in s and G.sgs[i]
>
i, l;
# loop variables
>
if not IsResidueClass( res )
>
or res.modulus <> G.modulus
>
or GcdInt( res.representative, res.modulus ) <> 1
>
then
>
return false;
>
fi;
>
if not IsBound( G.facts ) then
>
G.operations.MakeFactors( G );
>
fi;
>
s := [];
>
for i in [ 1 .. Length( G.facts ) ] do
>
if G.facts[i] mod 8 = 0 then
>
if res.representative mod 4 = 1 then
>
s[i] := LogMod( res.representative,
>
G.roots[i], G.facts[i] );
>
else
>
s[i] := LogMod( -res.representative,
>
G.roots[i], G.facts[i] );
>
fi;
>
else
>
s[i] := LogMod( res.representative,
>
G.roots[i], G.facts[i] );
>
fi;
>
od;
>
for i in [ 1 .. Length( G.facts ) ] do
>
if s[i] mod GcdInt( G.sizes[i], G.sgs[i][i] ) <> 0
>
return false;
>
fi;
then
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
193
>
g := Gcdex( s[i], G.sgs[i][i] );
>
for l in [ i .. Length( G.facts ) ] do
>
x := s[l]; y := G.sgs[i][l];
>
s[l] := (g.coeff3 * x + g.coeff4 * y) mod G.sizes[l];
>
od;
>
od;
>
return true;
> end;;
We also add a function Random that works by creating a random exponent as a random
linear combination of the exponent vectors in G.sgs, and converts this exponent vector to
a residue class. (The main purpose of this function is to allow you to create random test
examples for the other functions.)
gap> ResidueClassGroupOps.Random := function ( G )
>
local
s,
# exponent vector of random element
>
r,
# vector of remainders in each factor
>
i, k, l;
# loop variables
>
if not IsBound( G.facts ) then
>
G.operations.MakeFactors( G );
>
fi;
>
s := 0 * G.facts;
>
for i in [ 1 .. Length( G.facts ) ] do
>
l := G.sizes[i] / GcdInt( G.sizes[i], G.sgs[i][i] );
>
k := Random( [ 0 .. l-1 ] );
>
for l in [ i .. Length( s ) ] do
>
s[l] := (s[l] + k * G.sgs[i][l]) mod G.sizes[l];
>
od;
>
od;
>
r := [];
>
for l in [ 1 .. Length( s ) ] do
>
r[l] := PowerModInt( G.roots[l], s[l], G.facts[l] );
>
if G.facts[l] mod 8 = 0 and r[1] = 3 then
>
r[l] := G.facts[l] - r[l];
>
fi;
>
od;
>
return ResidueClass( ChineseRem( G.facts, r ), G.modulus );
> end;;
There are a lot more functions that would benefit from being implemented especially for
residue class groups. We do not show them here, because the above functions already
displayed how such functions can be written.
To round things up, we finally add a function that constructs the full residue class group
given a modulus m. This function is totally independent of the implementation of residue
classes and residue class groups. It only has to find a (minimal) system of generators of the
full prime residue classes group, and to call Group to construct this group. It also adds the
information entry size to the group record, of course with the value φ(n).
gap> PrimeResidueClassGroup := function ( m )
>
local
G,
# group Z/mZ, result
194
CHAPTER 1. ABOUT GAP
>
gens,
# generators of G
>
p, q,
# prime and prime power dividing m
>
r,
# primitive root modulo q
>
g;
# is = r mod q and = 1 mod m/q
>
>
# add generators for each prime power factor q of m
>
gens := [];
>
for p in Set( Factors( m ) ) do
>
q := p;
>
while m mod (q * p) = 0 do q := q * p; od;
>
>
# (Z/4Z)^* = < 3 >
>
if
q = 4 then
>
r := 3;
>
g := r + q * (((1/q mod (m/q)) * (1 - r)) mod (m/q));
>
Add( gens, ResidueClass( g, m ) );
>
>
# (Z/8nZ)^* = < 5, -1 > is not cyclic
>
elif q mod 8 = 0 then
>
r := q-1;
>
g := r + q * (((1/q mod (m/q)) * (1 - r)) mod (m/q));
>
Add( gens, ResidueClass( g, m ) );
>
r := 5;
>
g := r + q * (((1/q mod (m/q)) * (1 - r)) mod (m/q));
>
Add( gens, ResidueClass( g, m ) );
>
>
# for odd q, (Z/qZ)^* is cyclic
>
elif q <> 2 then
>
r := PrimitiveRootMod( q );
>
g := r + q * (((1/q mod (m/q)) * (1 - r)) mod (m/q));
>
Add( gens, ResidueClass( g, m ) );
>
fi;
>
>
od;
>
>
# return the group generated by gens
>
G := Group( gens, ResidueClass( 1, m ) );
>
G.size := Phi( n );
>
return G;
> end;;
There is one more thing that we can learn from this example. Mathematically a residue
class is not only a group element, but a set as well. We can reflect this in GAP3 by turning
residue classes into domains (see 4). Section 1.28 gives an example of how to implement a
new domain, so we will here only show the code with few comments.
First we must change the function that constructs a residue class, so that it enters the
necessary fields to tag this record as a domain. It also adds the information that residue
classes are infinite.
1.30. ABOUT DEFINING NEW GROUP ELEMENTS
195
gap> ResidueClass := function ( representative, modulus )
>
local res;
>
res := rec();
>
res.isGroupElement := true;
>
res.isDomain
:= true;
>
res.isResidueClass := true;
>
res.representative := representative mod modulus;
>
res.modulus
:= modulus;
>
res.isFinite
:= false;
>
res.size
:= "infinity";
>
res.domain
:= ResidueClasses;
>
res.operations
:= ResidueClassOps;
>
return res;
> end;;
The initialization of the ResidueClassOps record must be changed too, because now we
want to inherit both from GroupElementsOps and DomainOps. This is done by the function MergedRecord, which takes two records and returns a new record that contains all
components from either record.
Note that the record returned by MergedRecord does not have those components that appear
in both arguments. This forces us to explicitly write down from which record we want to
inherit those functions, or to define them anew. In our example the components common to
GroupElementOps and DomainOps are only the equality and ordering functions, which we
have to define anyhow. (This solution for the problem of which definition to choose in the
case of multiple inheritance is also taken by C++.)
With this function definition we can now initialize ResidueClassOps.
gap> ResidueClassOps := MergedRecord( GroupElementOps, DomainOps );;
Now we add all functions to this record as described above.
Next we add a function to the operations record that tests whether a certain object is in a
residue class.
gap> ResidueClassOps.\in := function ( element, class )
>
if IsInt( element ) then
>
return (element mod class.modulus = class.representative);
>
else
>
return false;
>
fi;
> end;;
Finally we add a function to compute the intersection of two residue classes.
gap> ResidueClassOps.Intersection := function ( R, S )
>
local
I,
# intersection of R and S, result
>
gcd;
# gcd of the moduli
>
if IsResidueClass( R ) then
>
if IsResidueClass( S ) then
>
gcd := GcdInt( R.modulus, S.modulus );
>
if
R.representative mod gcd
>
<> S.representative mod gcd
196
CHAPTER 1. ABOUT GAP
>
then
>
I := [];
>
else
>
I := ResidueClass(
>
ChineseRem(
>
[ R.modulus,
S.modulus ] ,
>
[ R.representative, S.representative ]),
>
Lcm( R.modulus,
S.modulus ) );
>
fi;
>
else
>
I := DomainOps.Intersection( R, S );
>
fi;
>
else
>
I := DomainOps.Intersection( R, S );
>
fi;
>
return I;
> end;;
There is one further thing that we have to do. When Group is called with a single argument
that is a domain, it assumes that you want to create a new group such that there is a
bijection between the original domain and the new group. This is not what we want here.
We want that in this case we get the cyclic group that is generated by the single residue
class. (This overloading of Group is probably a mistake, but so is the overloading of residue
classes, which are both group elements and domains.) The following definition solves this
problem.
gap> ResidueClassOps.Group := function ( R )
>
return ResidueClassesOps.Group( ResidueClasses, [R], R^0 );
> end;;
This concludes our example. There are however several further things that you could do.
One is to add functions for the quotient, the modulus, etc. Another is to fix the functions
so that they do not hang if asked for the residue class group mod 1. Also you might try
to implement residue class rings analogous to residue class groups. Finally it might be
worthwhile to improve the speed of the multiplication of prime residue classes. This can be
done by doing some precomputation in ResidueClass and adding some information to the
residue class record for prime residue classes ([Mon85]).
Chapter 2
The Programming Language
This chapter describes the GAP3 programming language. It should allow you in principle to
predict the result of each and every input. In order to know what we are talking about, we
first have to look more closely at the process of interpretation and the various representations
of data involved.
First we have the input to GAP3, given as a string of characters. How those characters enter
GAP3 is operating system dependent, e.g., they might be entered at a terminal, pasted
with a mouse into a window, or read from a file. The mechanism does not matter. This
representation of expressions by characters is called the external representation of the
expression. Every expression has at least one external representation that can be entered
to get exactly this expression.
The input, i.e., the external representation, is transformed in a process called reading to
an internal representation. At this point the input is analyzed and inputs that are not legal
external representations, according to the rules given below, are rejected as errors. Those
rules are usually called the syntax of a programming language.
The internal representation created by reading is called either an expression or a statement. Later we will distinguish between those two terms, however now we will use them
interchangeably. The exact form of the internal representation does not matter. It could be
a string of characters equal to the external representation, in which case the reading would
only need to check for errors. It could be a series of machine instructions for the processor
on which GAP3 is running, in which case the reading would more appropriately be called
compilation. It is in fact a tree–like structure.
After the input has been read it is again transformed in a process called evaluation or
execution. Later we will distinguish between those two terms too, but for the moment
we will use them interchangeably. The name hints at the nature of this process, it replaces
an expression with the value of the expression. This works recursively, i.e., to evaluate an
expression first the subexpressions are evaluated and then the value of the expression is
computed according to rules given below from those values. Those rules are usually called
the semantics of a programming language.
The result of the evaluation is, not surprisingly, called a value. The set of values is of course
a much smaller set than the set of expressions; for every value there are several expressions
197
198
CHAPTER 2. THE PROGRAMMING LANGUAGE
that will evaluate to this value. Again the form in which such a value is represented internally
does not matter. It is in fact a tree–like structure again.
The last process is called printing. It takes the value produced by the evaluation and
creates an external representation, i.e., a string of characters again. What you do with this
external representation is up to you. You can look at it, paste it with the mouse into another
window, or write it to a file.
Lets look at an example to make this more clear. Suppose you type in the following string
of 8 characters
1 + 2 * 3;
GAP3 takes this external representation and creates a tree like internal representation, which
we can picture as follows
+
/ \
1
*
/ \
2
3
This expression is then evaluated. To do this GAP3 first evaluates the right subexpression
2*3. Again to do this GAP3 first evaluates its subexpressions 2 and 3. However they are
so simple that they are their own value, we say that they are self–evaluating. After this
has been done, the rule for * tells us that the value is the product of the values of the two
subexpressions, which in this case is clearly 6. Combining this with the value of the left
operand of the +, which is self–evaluating too gives us the value of the whole expression 7.
This is then printed, i.e., converted into the external representation consisting of the single
character 7.
In this fashion we can predict the result of every input when we know the syntactic rules that
govern the process of reading and the semantic rules that tell us for every expression how
its value is computed in terms of the values of the subexpressions. The syntactic rules are
given in sections 2.1, 2.2, 2.3, 2.4, 2.5, and 2.20, the semantic rules are given in sections 2.6,
2.7, 2.8, 2.9, 2.10, 2.11, 2.12, 2.13, 2.14, 2.15, 2.16, 2.17, 2.18, and the chapters describing
the individual data types.
2.1
Lexical Structure
The input of GAP3 consists of sequences of the following characters.
Digits, uppercase and lowercase letters, space, tab, newline, and the special characters
"
.
[
’
/
\
(
:
]
)
;
^
*
<
_
+
=
{
,
>
}
_
~
#
Other characters will be signalled as illegal. Inside strings and comments the full character
set supported by the computer is allowed.
2.2
Language Symbols
The process of reading, i.e., of assembling the input into expressions, has a subprocess,
called scanning, that assembles the characters into symbols. A symbol is a sequence of
2.3. WHITESPACES
199
characters that form a lexical unit. The set of symbols consists of keywords, identifiers,
strings, integers, and operator and delimiter symbols.
A keyword is a reserved word consisting entirely of lowercase letters (see 2.4). An identifier
is a sequence of letters and digits that contains at least one letter and is not a keyword
(see 2.5). An integer is a sequence of digits (see 10). A string is a sequence of arbitrary
characters enclosed in double quotes (see 30).
Operator and delimiter symbols are
+
=
:=
[
<>
.
]
*
<
..
{
/
<=
->
}
^
>
,
(
~
>=
;
)
Note that during the process of scanning also all whitespace is removed (see 2.3).
2.3
Whitespaces
The characters space, tab, newline, and return are called whitespace characters. Whitespace is used as necessary to separate lexical symbols, such as integers, identifiers, or keywords. For example Thorondor is a single identifier, while Th or ondor is the keyword or
between the two identifiers Th and ondor. Whitespace may occur between any two symbols, but not within a symbol. Two or more adjacent whitespaces are equivalent to a single
whitespace. Apart from the role as separator of symbols, whitespaces are otherwise insignificant. Whitespaces may also occur inside a string, where they are significant. Whitespaces
should also be used freely for improved readability.
A comment starts with the character #, which is sometimes called sharp or hatch, and
continues to the end of the line on which the comment character appears. The whole
comment, including # and the newline character is treated as a single whitespace. Inside a
string, the comment character # looses its role and is just an ordinary character.
For example, the following statement
if i<0 then a:=-i;else a:=i;fi;
is equivalent to
if i < 0 then
a := -i;
else
a := i;
fi;
# if i is negative
#
take its inverse
# otherwise
#
take itself
(which by the way shows that it is possible to write superfluous comments). However the
first statement is not equivalent to
ifi<0thena:=-i;elsea:=i;fi;
since the keyword if must be separated from the identifier i by a whitespace, and similarly
then and a, and else and a must be separated.
200
2.4
CHAPTER 2. THE PROGRAMMING LANGUAGE
Keywords
Keywords are reserved words that are used to denote special operations or are part of
statements. They must not be used as identifiers. The keywords are
and
for
not
until
do
function
od
while
elif
if
or
quit
else
in
repeat
end
local
return
fi
mod
then
Note that all keywords are written in lowercase. For example only else is a keyword; Else,
eLsE, ELSE and so forth are ordinary identifiers. Keywords must not contain whitespace,
for example el if is not the same as elif.
2.5
Identifiers
An identifier is used to refer to a variable (see 2.7). An identifier consists of letters, digits,
and underscores , and must contain at least one letter or underscore. An identifier is
terminated by the first character not in this class. Examples of valid identifiers are
a
foo
aLongIdentifier
hello
Hello
HELLO
x100
100x
_100
some_people_prefer_underscores_to_separate_words
WePreferMixedCaseToSeparateWords
Note that case is significant, so the three identifiers in the second line are distinguished.
The backslash \ can be used to include other characters in identifiers; a backslash followed
by a character is equivalent to the character, except that this escape sequence is considered
to be an ordinary letter. For example G\(2\,5\) is an identifier, not a call to a function G.
An identifier that starts with a backslash is never a keyword, so for example \* and \mod
are identifier.
The length of identifiers is not limited, however only the first 1023 characters are significant.
The escape sequence \newline is ignored, making it possible to split long identifiers over
multiple lines.
2.6
Expressions
An expression is a construct that evaluates to a value. Syntactic constructs that are
executed to produce a side effect and return no value are called statements (see 2.11).
Expressions appear as right hand sides of assignments (see 2.12), as actual arguments in
function calls (see 2.8), and in statements.
Note that an expression is not the same as a value. For example 1 + 11 is an expression,
whose value is the integer 12. The external representation of this integer is the character
sequence 12, i.e., this sequence is output if the integer is printed. This sequence is another
expression whose value is the integer 12. The process of finding the value of an expression
is done by the interpreter and is called the evaluation of the expression.
Variables, function calls, and integer, permutation, string, function, list, and record literals
(see 2.7, 2.8, 10, 20, 30, 2.18, 27, 46), are the simplest cases of expressions.
2.7. VARIABLES
201
Expressions, for example the simple expressions mentioned above, can be combined with
the operators to form more complex expressions. Of course those expressions can then be
combined further with the operators to form even more complex expressions. The operators
fall into three classes. The comparisons are =, <>, <=, >, >=, and in (see 2.9 and 27.14).
The arithmetic operators are +, -, *, /, mod, and ^ (see 2.10). The logical operators
are not, and, and or (see 45.2).
gap> 2 * 2;
# a very simple expression with value
4
gap> 2 * 2 + 9 = Fibonacci(7) and Fibonacci(13) in Primes;
true
# a more complex expression
2.7
Variables
A variable is a location in a GAP3 program that points to a value. We say the variable is
bound to this value. If a variable is evaluated it evaluates to this value.
Initially an ordinary variable is not bound to any value. The variable can be bound to a
value by assigning this value to the variable (see 2.12). Because of this we sometimes say
that a variable that is not bound to any value has no assigned value. Assignment is in fact
the only way by which a variable, which is not an argument of a function, can be bound to
a value. After a variable has been bound to a value an assignment can also be used to bind
the variable to another value.
A special class of variables are arguments of functions. They behave similarly to other
variables, except they are bound to the value of the actual arguments upon a function call
(see 2.8).
Each variable has a name that is also called its identifier. This is because in a given scope
an identifier identifies a unique variable (see 2.5). A scope is a lexical part of a program text.
There is the global scope that encloses the entire program text, and there are local scopes
that range from the function keyword, denoting the beginning of a function definition, to
the corresponding end keyword. A local scope introduces new variables, whose identifiers
are given in the formal argument list and the local declaration of the function (see 2.18).
Usage of an identifier in a program text refers to the variable in the innermost scope that
has this identifier as its name. Because this mapping from identifiers to variables is done
when the program is read, not when it is executed, GAP3 is said to have lexical scoping. The
following example shows how one identifier refers to different variables at different points in
the program text.
g := 0;
# global variable g
x := function ( a, b, c )
local
y;
g := c;
# c refers to argument c of function x
y := function ( y )
local d, e, f;
d := y;
# y refers to argument y of function y
e := b;
# b refers to argument b of function x
f := g;
# g refers to global variable g
return d + e + f;
end;
202
CHAPTER 2. THE PROGRAMMING LANGUAGE
return y( a );
# y refers to local y of function x
end;
It is important to note that the concept of a variable in GAP3 is quite different from the
concept of a variable in programming languages like PASCAL. In those languages a variable
denotes a block of memory. The value of the variable is stored in this block. So in those
languages two variables can have the same value, but they can never have identical values,
because they denote different blocks of memory. (Note that PASCAL has the concept of
a reference argument. It seems as if such an argument and the variable used in the actual
function call have the same value, since changing the argument’s value also changes the value
of the variable used in the actual function call. But this is not so; the reference argument is
actually a pointer to the variable used in the actual function call, and it is the compiler that
inserts enough magic to make the pointer invisible.) In order for this to work the compiler
needs enough information to compute the amount of memory needed for each variable in a
program, which is readily available in the declarations PASCAL requires for every variable.
In GAP3 on the other hand each variable justs points to a value.
2.8
Function Calls
function-var ()
function-var ( arg-expr {, arg-expr } )
The function call has the effect of calling the function function-var . The precise semantics
are as follows.
First GAP3 evaluates the function-var . Usually function-var is a variable, and GAP3 does
nothing more than taking the value of this variable. It is allowed though that function-var
is a more complex expression, namely it can for example be a selection of a list element
list-var [int-expr ], or a selection of a record component record-var .ident. In any case GAP3
tests whether the value is a function. If it is not, GAP3 signals an error.
Next GAP3 checks that the number of actual arguments arg-expr s agrees with the number
of formal arguments as given in the function definition. If they do not agree GAP3 signals
an error. An exception is the case when there is exactly one formal argument with the name
arg, in which case any number of actual arguments is allowed.
Now GAP3 allocates for each formal argument and for each formal local a new variable.
Remember that a variable is a location in a GAP3 program that points to a value. Thus for
each formal argument and for each formal local such a location is allocated.
Next the arguments arg-expr s are evaluated, and the values are assigned to the newly created
variables corresponding to the formal arguments. Of course the first value is assigned to
the new variable corresponding to the first formal argument, the second value is assigned to
the new variable corresponding to the second formal argument, and so on. However, GAP3
does not make any guarantee about the order in which the arguments are evaluated. They
might be evaluated left to right, right to left, or in any other order, but each argument is
evaluated once. An exception again occurs if the function has only one formal argument
with the name arg. In this case the values of all the actual arguments are stored in a list
and this list is assigned to the new variable corresponding to the formal argument arg.
The new variables corresponding to the formal locals are initially not bound to any value.
So trying to evaluate those variables before something has been assigned to them will signal
an error.
2.9. COMPARISONS
203
Now the body of the function, which is a statement, is executed. If the identifier of one of
the formal arguments or formal locals appears in the body of the function it refers to the
new variable that was allocated for this formal argument or formal local, and evaluates to
the value of this variable.
If during the execution of the body of the function a return statement with an expression
(see 2.19) is executed, execution of the body is terminated and the value of the function call
is the value of the expression of the return. If during the execution of the body a return
statement without an expression is executed, execution of the body is terminated and the
function call does not produce a value, in which case we call this call a procedure call (see
2.13). If the execution of the body completes without execution of a return statement, the
function call again produces no value, and again we talk about a procedure call.
gap> Fibonacci( 11 );
# a call to the function Fibonacci with actual argument 11
89
gap> G.operations.RightCosets( G, Intersection( U, V ) );;
# a call to the function in G.operations.RightCosets
# where the second actual argument is another function call
2.9
Comparisons
left-expr = right-expr
left-expr <> right-expr
The operator = tests for equality of its two operands and evaluates to true if they are equal
and to false otherwise. Likewise <> tests for inequality of its two operands. Note that
any two objects can be compared, i.e., = and <> will never signal an error. For each type
of objects the definition of equality is given in the respective chapter. Objects of different
types are never equal, i.e., = evaluates in this case to false, and <> evaluates to true.
left-expr
left-expr
left-expr
left-expr
< right-expr
> right-expr
<= right-expr
>= right-expr
< denotes less than, <= less than or equal, > greater than, and >= greater than or equal
of its two operands. For each type of objects the definition of the ordering is given in the
respective chapter. The ordering of objects of different types is as follows. Rationals are
smallest, next are cyclotomics, followed by finite field elements, permutations, words, words
in solvable groups, boolean values, functions, lists, and records are largest.
Comparison operators, which includes the operator in (see 27.14) are not associative, i.e.,
it is not allowed to write a = b <> c = d , you must use (a = b) <> (c = d ) instead.
The comparison operators have higher precedence than the logical operators (see 45.2), but
lower precedence than the arithmetic operators (see 2.10). Thus, for example, a * b = c
and d is interpreted, ((a * b) = c) and d ).
gap> 2 * 2 + 9 = Fibonacci(7);
true
# a comparison where the left
# operand is an expression
204
CHAPTER 2. THE PROGRAMMING LANGUAGE
2.10
Operations
+ right-expr
- right-expr
left-expr + right-expr
left-expr - right-expr
left-expr * right-expr
left-expr / right-expr
left-expr mod right-expr
left-expr ^ right-expr
The arithmetic operators are +, -, *, /, mod, and ^. The meanings (semantic) of those
operators generally depend on the types of the operands involved, and they are defined in
the various chapters describing the types. However basically the meanings are as follows.
+ denotes the addition, and - the subtraction of ring and field elements. * is the multiplication of group elements, / is the multiplication of the left operand with the inverse of
the right operand. mod is only defined for integers and rationals and denotes the modulo
operation. + and - can also be used as unary operations. The unary + is ignored and unary
- is equivalent to multiplication by -1. ^ denotes powering of a group element if the right
operand is an integer, and is also used to denote operation if the right operand is a group
element.
The precedence of those operators is as follows. The powering operator ^ has the highest
precedence, followed by the unary operators + and -, which are followed by the multiplicative operators *, /, and mod, and the additive binary operators + and - have the lowest
precedence. That means that the expression -2 ^ -2 * 3 + 1 is interpreted as (-(2 ^
(-2)) * 3) + 1. If in doubt use parentheses to clarify your intention.
The associativity of the arithmetic operators is as follows.^ is not associative, i.e., it is
illegal to write 2^3^4, use parentheses to clarify whether you mean (2^3) ^ 4 or 2 ^ (3^4).
The unary operators + and - are right associative, because they are written to the left of
their operands. *, /, mod, +, and - are all left associative, i.e., 1-2-3 is interpreted as
(1-2)-3 not as 1-(2-3). Again, if in doubt use parentheses to clarify your intentions.
The arithmetic operators have higher precedence than the comparison operators (see 2.9
and 27.14) and the logical operators (see 45.2). Thus, for example, a * b = c and d is
interpreted, ((a * b) = c) and d .
gap> 2 * 2 + 9;
13
2.11
# a very simple arithmetic expression
Statements
Assignments (see 2.12), Procedure calls (see 2.13), if statements (see 2.14), while (see
2.15), repeat (see 2.16) and for loops (see 2.17), and the return statement (see 2.19) are
called statements. They can be entered interactively or be part of a function definition.
Every statement must be terminated by a semicolon.
Statements, unlike expressions, have no value. They are executed only to produce an effect.
For example an assignment has the effect of assigning a value to a variable, a for loop has
the effect of executing a statement sequence for all elements in a list and so on. We will
2.12. ASSIGNMENTS
205
talk about evaluation of expressions but about execution of statements to emphasize this
difference.
It is possible to use expressions as statements. However this does cause a warning.
gap> if i <> 0 then k = 16/i; fi;
Syntax error: warning, this statement has no effect
if i <> 0 then k = 16/i; fi;
^
As you can see from the example this is useful for those users who are used to languages
where = instead of := denotes assignment.
A sequence of one or more statements is a statement sequence, and may occur everywhere
instead of a single statement. There is nothing like PASCAL’s BEGIN-END, instead each
construct is terminated by a keyword. The most simple statement sequence is a single
semicolon, which can be used as an empty statement sequence.
2.12
Assignments
var := expr ;
The assignment has the effect of assigning the value of the expressions expr to the variable
var .
The variable var may be an ordinary variable (see 2.7), a list element selection list-var [intexpr ] (see 27.6) or a record component selection record-var .ident (see 46.2). Since a list
element or a record component may itself be a list or a record the left hand side of an
assignment may be arbitrarily complex.
Note that variables do not have a type. Thus any value may be assigned to any variable.
For example a variable with an integer value may be assigned a permutation or a list or
anything else.
If the expression expr is a function call then this function must return a value. If the
function does not return a value an error is signalled and you enter a break loop (see 3.2).
As usual you can leave the break loop with quit;. If you enter return return-expr ; the
value of the expression return-expr is assigned to the variable, and execution continues after
the assignment.
gap> S6 := rec( size := 720 );; S6;
rec(
size := 720 )
gap> S6.generators := [ (1,2), (1,2,3,4,5) ];; S6;
rec(
size := 720,
generators := [ (1,2), (1,2,3,4,5) ] )
gap> S6.generators[2] := (1,2,3,4,5,6);; S6;
rec(
size := 720,
generators := [ (1,2), (1,2,3,4,5,6) ] )
206
CHAPTER 2. THE PROGRAMMING LANGUAGE
2.13
Procedure Calls
procedure-var ();
procedure-var ( arg-expr {, arg-expr } );
The procedure call has the effect of calling the procedure procedure-var . A procedure call is
done exactly like a function call (see 2.8). The distinction between functions and procedures
is only for the sake of the discussion, GAP3 does not distinguish between them.
A function does return a value but does not produce a side effect. As a convention the name
of a function is a noun, denoting what the function returns, e.g., Length, Concatenation
and Order.
A procedure is a function that does not return a value but produces some effect. Procedures
are called only for this effect. As a convention the name of a procedure is a verb, denoting
what the procedure does, e.g., Print, Append and Sort.
gap> Read( "myfile.g" );
gap> l := [ 1, 2 ];;
gap> Append( l, [3,4,5] );
2.14
# a call to the procedure Read
# a call to the procedure Append
If
if bool-expr1 then statements1
{ elif bool-expr2 then statements2 }
[ else statements3 ]
fi;
The if statement allows one to execute statements depending on the value of some boolean
expression. The execution is done as follows.
First the expression bool-expr1 following the if is evaluated. If it evaluates to true the
statement sequence statements1 after the first then is executed, and the execution of the
if statement is complete.
Otherwise the expressions bool-expr2 following the elif are evaluated in turn. There may
be any number of elif parts, possibly none at all. As soon as an expression evaluates to
true the corresponding statement sequence statements2 is executed and execution of the
if statement is complete.
If the if expression and all, if any, elif expressions evaluate to false and there is an else
part, which is optional, its statement sequence statements3 is executed and the execution of
the if statement is complete. If there is no else part the if statement is complete without
executing any statement sequence.
Since the if statement is terminated by the fi keyword there is no question where an else
part belongs, i.e., GAP3 has no dangling else.
In if expr1 then if expr2 then stats1 else stats2 fi; fi;
the else part belongs to the second if statement, whereas in
if expr1 then if expr2 then stats1 fi; else stats2 fi;
the else part belongs to the first if statement.
Since an if statement is not an expression it is not possible to write
abs := if x
> 0
then
x;
else
-x;
fi;
2.15. WHILE
207
which would, even if legal syntax, be meaningless, since the if statement does not produce
a value that could be assigned to abs.
If one expression evaluates neither to true nor to false an error is signalled and a break
loop (see 3.2) is entered. As usual you can leave the break loop with quit;. If you enter
return true;, execution of the if statement continues as if the expression whose evaluation
failed had evaluated to true. Likewise, if you enter return false;, execution of the if
statement continues as if the expression whose evaluation failed had evaluated to false.
gap>
gap>
>
>
>
>
>
>
gap>
1
2.15
i := 10;;
if 0 < i then
s := 1;
elif i < 0 then
s := -1;
else
s := 0;
fi;
s;
# the sign of i
While
while bool-expr do statements od;
The while loop executes the statement sequence statements while the condition bool-expr
evaluates to true.
First bool-expr is evaluated. If it evaluates to false execution of the while loop terminates
and the statement immediately following the while loop is executed next. Otherwise if it
evaluates to true the statements are executed and the whole process begins again.
The difference between the while loop and the repeat until loop (see 2.16) is that the
statements in the repeat until loop are executed at least once, while the statements in
the while loop are not executed at all if bool-expr is false at the first iteration.
If bool-expr does not evaluate to true or false an error is signalled and a break loop (see 3.2)
is entered. As usual you can leave the break loop with quit;. If you enter return false;,
execution continues with the next statement immediately following the while loop. If you
enter return true;, execution continues at statements, after which the next evaluation of
bool-expr may cause another error.
gap>
gap>
>
>
gap>
204
2.16
i := 0;; s := 0;;
while s <= 200 do
i := i + 1; s := s + i^2;
od;
s;
# first sum of the first i squares larger than 200
Repeat
repeat statements until bool-expr ;
The repeat loop executes the statement sequence statements until the condition bool-expr
evaluates to true.
208
CHAPTER 2. THE PROGRAMMING LANGUAGE
First statements are executed. Then bool-expr is evaluated. If it evaluates to true the
repeat loop terminates and the statement immediately following the repeat loop is executed
next. Otherwise if it evaluates to false the whole process begins again with the execution
of the statements.
The difference between the while loop (see 2.15) and the repeat until loop is that the
statements in the repeat until loop are executed at least once, while the statements in
the while loop are not executed at all if bool-expr is false at the first iteration.
If bool-expr does not evaluate to true or false a error is signalled and a break loop (see 3.2)
is entered. As usual you can leave the break loop with quit;. If you enter return true;,
execution continues with the next statement immediately following the repeat loop. If you
enter return false;, execution continues at statements, after which the next evaluation of
bool-expr may cause another error.
gap>
gap>
>
>
gap>
204
2.17
i := 0;; s := 0;;
repeat
i := i + 1; s := s + i^2;
until s > 200;
s;
# first sum of the first i squares larger than 200
For
for simple-var in list-expr do statements od;
The for loop executes the statement sequence statements for every element of the list listexpr .
The statement sequence statements is first executed with simple-var bound to the first
element of the list list, then with simple-var bound to the second element of list and so on.
simple-var must be a simple variable, it must not be a list element selection list-var [intexpr ] or a record component selection record-var .ident.
The execution of the for loop is exactly equivalent to the while loop
loop-list := list;
loop-index := 1;
while loop-index <= Length(loop-list) do
variable := loop-list[loop-index ];
statements
loop-index := loop-index + 1;
od;
with the exception that loop-list and loop-index are different variables for each for loop
that do not interfere with each other.
The list list is very often a range.
for variable in [from..to] do statements od;
corresponds to the more common
for variable from from to to do statements od;
in other programming languages.
gap> s := 0;;
2.18. FUNCTIONS
gap> for i in [1..100]
>
s := s + i;
> od;
gap> s;
5050
209
do
Note in the following example how the modification of the list in the loop body causes the
loop body also to be executed for the new values
gap> l := [ 1, 2, 3, 4, 5, 6 ];;
gap> for i in l do
>
Print( i, " " );
>
if i mod 2 = 0 then Add( l, 3 * i / 2 );
> od; Print( "\n" );
1 2 3 4 5 6 3 6 9 9
gap> l;
[ 1, 2, 3, 4, 5, 6, 3, 6, 9, 9 ]
fi;
Note in the following example that the modification of the variable that holds the list has
no influence on the loop
gap> l := [ 1, 2, 3, 4, 5, 6 ];;
gap> for i in l do
>
Print( i, " " );
>
l := [];
> od; Print( "\n" );
1 2 3 4 5 6
gap> l;
[ ]
2.18
Functions
function ( [ arg-ident {, arg-ident} ] )
[ local
loc-ident {, loc-ident} ; ]
statements
end
A function is in fact a literal and not a statement. Such a function literal can be assigned
to a variable or to a list element or a record component. Later this function can be called
as described in 2.8.
The following is an example of a function definition. It is a function to compute values of
the Fibonacci sequence (see 47.22)
gap> fib := function ( n )
>
local f1, f2, f3,
>
f1 := 1; f2 := 1;
>
for i in [3..n] do
>
f3 := f1 + f2;
>
f1 := f2;
>
f2 := f3;
>
od;
i;
210
CHAPTER 2. THE PROGRAMMING LANGUAGE
>
return f2;
>
end;;
gap> List( [1..10], fib );
[ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
Because for each of the formal arguments arg-ident and for each of the formal locals locident a new variable is allocated when the function is called (see 2.8), it is possible that a
function calls itself. This is usually called recursion. The following is a recursive function
that computes values of the Fibonacci sequence
gap> fib := function ( n )
>
if n < 3 then
>
return 1;
>
else
>
return fib(n-1) + fib(n-2);
>
fi;
>
end;;
gap> List( [1..10], fib );
[ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
Note that the recursive version needs 2 * fib(n)-1 steps to compute fib(n), while the
iterative version of fib needs only n-2 steps. Both are not optimal however, the library
function Fibonacci only needs on the order of Log(n) steps.
arg-ident -> expr
This is a shorthand for
function ( arg-ident ) return expr ; end.
arg-ident must be a single identifier, i.e., it is not possible to write functions of several
arguments this way. Also arg is not treated specially, so it is also impossible to write
functions that take a variable number of arguments this way.
The following is an example of a typical use of such a function
gap> Sum( List( [1..100], x -> x^2 ) );
338350
When a function fun1 definition is evaluated inside another function fun2 , GAP3 binds
all the identifiers inside the function fun1 that are identifiers of an argument or a local of
fun2 to the corresponding variable. This set of bindings is called the environment of the
function fun1 . When fun1 is called, its body is executed in this environment. The following
implementation of a simple stack uses this. Values can be pushed onto the stack and then
later be popped off again. The interesting thing here is that the functions push and pop in
the record returned by Stack access the local variable stack of Stack. When Stack is called
a new variable for the identifier stack is created. When the function definitions of push and
pop are then evaluated (as part of the return statement) each reference to stack is bound
to this new variable. Note also that the two stacks A and B do not interfere, because each
call of Stack creates a new variable for stack.
gap> Stack := function ()
>
local
stack;
>
stack := [];
>
return rec(
>
push := function ( value )
2.19. RETURN
>
>
>
>
>
>
>
>
>
>
gap>
gap>
gap>
gap>
gap>
3
2
1
gap>
6
5
4
211
Add( stack, value );
end,
pop := function ()
local
value;
value := stack[Length(stack)];
Unbind( stack[Length(stack)] );
return value;
end
);
end;;
A := Stack();;
B := Stack();;
A.push( 1 ); A.push( 2 ); A.push( 3 );
B.push( 4 ); B.push( 5 ); B.push( 6 );
A.pop(); A.pop(); A.pop();
B.pop();
B.pop();
B.pop();
This feature should be used rarely, since its implementation in GAP3 is not very efficient.
2.19
Return
return;
In this form return terminates the call of the innermost function that is currently executing,
and control returns to the calling function. An error is signalled if no function is currently
executing. No value is returned by the function.
return expr ;
In this form return terminates the call of the innermost function that is currently executing,
and returns the value of the expression expr . Control returns to the calling function. An
error is signalled if no function is currently executing.
Both statements can also be used in break loops (see 3.2). return; has the effect that the
computation continues where it was interrupted by an error or the user hitting ctr C. return
expr ; can be used to continue execution after an error. What happens with the value expr
depends on the particular error.
2.20
The Syntax in BNF
This section contains the definition of the GAP3 syntax in Backus-Naur form.
A BNF is a set of rules, whose left side is the name of a syntactical construct. Those names
are enclosed in angle brackets and written in italics. The right side of each rule contains
a possible form for that syntactic construct. Each right side may contain names of other
212
CHAPTER 2. THE PROGRAMMING LANGUAGE
syntactic constructs, again enclosed in angle brackets and written in italics, or character
sequences that must occur literally; they are written in typewriter style.
Furthermore each righthand side can contain the following metasymbols written in boldface. If the right hand side contains forms separated by a pipe symbol (|) this means that
one of the possible forms can occur. If a part of a form is enclosed in square brackets ([ ])
this means that this part is optional, i.e. might be present or missing. If part of the form
is enclosed in curly braces ({ }) this means that the part may occur arbitrarily often, or
possibly be missing.
2.20. THE SYNTAX IN BNF
Ident
Var
:=
:=
|
|
|
|
|
List
:=
|
Record
:=
Permutation :=
Function
:=
Char
String
Int
Atom
Factor
Term
Arith
Rel
And
Log
Expr
Statement
Statements
:=
:=
:=
:=
|
|
|
|
|
|
|
|
:=
:=
:=
:=
:=
:=
:=
|
:=
|
|
|
|
|
|
|
:=
|
a|...|z|A|...|Z| {a|...|z|A|...|Z|0|...|9| }
Ident
Var . Ident
Var . ( Expr )
Var [ Expr ]
Var { Expr }
Var ( [ Expr { , Expr } ] )
[ [ Expr ] {, [ Expr ] } ]
[ Expr [, Expr ] .. Expr ]
rec( [ Ident := Expr {, Ident := Expr } ] )
( Expr {, Expr } ) { ( Expr {, Expr } ) }
function ( [ Ident {, Ident } ] )
[ local Ident {, Ident } ; ]
Statements
end
’ any character ’
" { any character } "
0|1|...|9 { 0|1|...|9 }
Int
Var
( Expr )
Permutation
Char
String
Function
List
Record
{+|-} Atom [ ^ {+|-} Atom ]
Factor { *|/|mod Factor }
Term { +|- Term }
{ not } Arith { =|<>|<|>|<=|>=|in Arith }
Rel { and Rel }
And { or And }
Log
Var [ -> Log ]
Expr
Var := Expr
if Expr then Statements
{ elif Expr then Statements }
[ else
Statements ] fi
for Var in Expr do Statements od
while Expr do Statements od
repeat Statements until Expr
return [ Expr ]
quit
{ Statement ; }
;
213
214
CHAPTER 2. THE PROGRAMMING LANGUAGE
Chapter 3
Environment
This chapter describes the interactive environment in which you use GAP3.
The first sections describe the main read eval print loop and the break loop (see 3.1, 3.2,
and 3.3).
The next section describes the commands you can use to edit the current input line (see
3.4).
The next sections describe the GAP3 help system (see 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11).
The next sections describe the input and output functions (see 3.12, 3.13, 3.14, 3.15, 3.16,
3.17, 3.18, and 3.19).
The next sections describe the functions that allow you to collect statistics about a computation (see 3.20, 3.21).
The last sections describe the functions that allow you to execute other programs as subprocesses from within GAP3 (see 3.22 and 3.23).
3.1
Main Loop
The normal interaction with GAP3 happens in the so–called read eval print loop. This
means that you type an input, GAP3 first reads it, evaluates it, and prints the result. The
exact sequence is as follows.
To show you that it is ready to accept your input, GAP3 displays the prompt gap> . When
you see this, you know that GAP3 is waiting for your input.
Note that every statement must be terminated by a semicolon. You must also enter return
before GAP3 starts to read and evaluate your input. Because GAP3 does not do anything
until you enter return, you can edit your input to fix typos and only when everything is
correct enter return and have GAP3 take a look at it (see 3.4). It is also possible to enter
several statements as input on a single line. Of course each statement must be terminated
by a semicolon.
It is absolutely acceptable to enter a single statement on several lines. When you have
entered the beginning of a statement, but the statement is not yet complete, and you enter
return, GAP3 will display the partial prompt > . When you see this, you know that GAP3
215
216
CHAPTER 3. ENVIRONMENT
is waiting for the rest of the statement. This happens also when you forget the semicolon ;
that terminates every GAP3 statement.
When you enter return, GAP3 first checks your input to see if it is syntactically correct
(see chapter 2 for the definition of syntactically correct). If it is not, GAP3 prints an error
message of the following form
gap> 1 * ;
Syntax error: expression expected
1 * ;
^
The first line tells you what is wrong about the input, in this case the * operator takes two
expressions as operands, so obviously the right one is missing. If the input came from a file
(see 3.12), this line will also contain the filename and the line number. The second line is a
copy of the input. And the third line contains a caret pointing to the place in the previous
line where GAP3 realized that something is wrong. This need not be the exact place where
the error is, but it is usually quite close.
Sometimes, you will also see a partial prompt after you have entered an input that is
syntactically incorrect. This is because GAP3 is so confused by your input, that it thinks
that there is still something to follow. In this case you should enter ;return repeatedly,
ignoring further error messages, until you see the full prompt again. When you see the full
prompt, you know that GAP3 forgave you and is now ready to accept your next – hopefully
correct – input.
If your input is syntactically correct, GAP3 evaluates or executes it, i.e., performs the required computations (see chapter 2 for the definition of the evaluation).
If you do not see a prompt, you know that GAP3 is still working on your last input. Of
course, you can type ahead, i.e., already start entering new input, but it will not be
accepted by GAP3 until GAP3 has completed the ongoing computation.
When GAP3 is ready it will usually print the result of the computation, i.e., the value
computed. Note that not all statements produce a value, for example, if you enter a for
loop, nothing will be printed, because the for loop does not produce a value that could be
printed.
Also sometimes you do not want to see the result. For example if you have computed a
value and now want to assign the result to a variable, you probably do not want to see the
value again. You can terminate statements by two semicolons to suppress the printing of
the result.
If you have entered several statements on a single line GAP3 will first read, evaluate, and
print the first one, then read evaluate, and print the second one, and so on. This means
that the second statement will not even be checked for syntactical correctness until GAP3
has completed the first computation.
After the result has been printed GAP3 will display another prompt, and wait for your next
input. And the whole process starts all over again. Note that a new prompt will only be
printed after GAP3 has read, evaluated, and printed the last statement if you have entered
several statements on a single line.
In each statement that you enter the result of the previous statement that produced a value
is available in the variable last. The next to previous result is available in last2 and the
result produced before that is available in last3.
3.2. BREAK LOOPS
217
gap> 1; 2; 3;
1
2
3
gap> last3 + last2 * last;
7
Also in each statement the time spent by the last statement, whether it produced a value
or not, is available in the variable time. This is an integer that holds the number of
milliseconds.
3.2
Break Loops
When an error has occurred or when you interrupt GAP3, usually by hitting ctr -C, GAP3
enters a break loop, that is in most respects like the main read eval print loop (see 3.1).
That is, you can enter statements, GAP3 reads them, evaluates them, and prints the result
if any. However those evaluations happen within the context in which the error occurred.
So you can look at the arguments and local variables of the functions that were active when
the error happened and even change them. The prompt is changed from gap> to brk> to
indicate that you are in a break loop.
There are two ways to leave a break loop.
The first is to quit the break loop and continue in the main loop. To do this you enter quit;
or hit the eof (end of file) character, which is usually ctr -D. In this case control returns to
the main loop, and you can enter new statements.
The other way is to return from a break loop. To do this you enter return; or return
expr ;. If the break loop was entered because you interrupted GAP3, then you can continue
by entering return;. If the break loop was entered due to an error, you usually have to
return a value to continue the computation. For example, if the break loop was entered
because a variable had no assigned value, you must return the value that this variable
should have to continue the computation.
3.3
Error
Error( messages...
)
Error signals an error. First the messages messages are printed, this is done exactly as if
Print (see 3.14) were called with these arguments. Then a break loop (see 3.2) is entered,
unless the standard error output is not connected to a terminal. You can leave this break
loop with return; to continue execution with the statement following the call to Error.
3.4
Line Editing
GAP3 allows you to edit the current input line with a number of editing commands. Those
commands are accessible either as control keys or as escape keys. You enter a control
key by pressing the ctr key, and, while still holding the ctr key down, hitting another key
key. You enter an escape key by hitting esc and then hitting another key key. Below we
denote control keys by ctr -key and escape keys by esc-key. The case of key does not matter,
i.e., ctr -A and ctr -a are equivalent.
218
CHAPTER 3. ENVIRONMENT
Characters not mentioned below always insert themselves at the current cursor position.
The first few commands allow you to move the cursor on the current line.
ctr -A move the cursor to the beginning of the line.
esc-B move the cursor to the beginning of the previous word.
ctr -B move the cursor backward one character.
ctr -F move the cursor forward one character.
esc-F move the cursor to the end of the next word.
ctr -E move the cursor to the end of the line.
The next commands delete or kill text. The last killed text can be reinserted, possibly at a
different position with the yank command.
ctr -H or del delete the character left of the cursor.
ctr -D delete the character under the cursor.
ctr -K kill up to the end of the line.
esc-D kill forward to the end of the next word.
esc-del kill backward to the beginning of the last word.
ctr -X kill entire input line, and discard all pending input.
ctr -Y insert (yank) a just killed text.
The next commands allow you to change the input.
ctr -T exchange (twiddle) current and previous character.
esc-U uppercase next word.
esc-L lowercase next word.
esc-C capitalize next word.
The tab character, which is in fact the control key ctr -I, looks at the characters before the
cursor, interprets them as the beginning of an identifier and tries to complete this identifier.
If there is more than one possible completion, it completes to the longest common prefix of all
those completions. If the characters to the left of the cursor are already the longest common
prefix of all completions hitting tab a second time will display all possible completions.
tab complete the identifier before the cursor.
The next commands allow you to fetch previous lines, e.g., to correct typos, etc. This history
is limited to about 8000 characters.
ctr -L insert last input line before current character.
ctr -P redisplay the last input line, another ctr -P will redisplay the line before that, etc. If
the cursor is not in the first column only the lines starting with the string to the left of the
cursor are taken.
ctr -N Like ctr -P but goes the other way round through the history.
esc-< goes to the beginning of the history.
esc-> goes to the end of the history.
ctr -O accepts this line and perform a ctr -N.
Finally there are a few miscellaneous commands.
ctr -V enter next character literally, i.e., enter it even if it is one of the control keys.
ctr -U execute the next command 4 times.
esc-num execute the next command num times.
esc-ctr -L repaint input line.
3.5. HELP
3.5
219
Help
This section describes together with the following sections the GAP3 help system. The help
system lets you read the manual interactively.
?section
The help command ? displays the section with the name section on the screen. For example
?Help will display this section on the screen. You should not type in the single quotes, they
are only used in help sections to delimit text that you should enter into GAP3 or that GAP3
prints in response. When the whole section has been displayed the normal GAP3 prompt
gap> is shown and normal GAP3 interaction resumes.
The section 3.6 tells you what actions you can perform while you are reading a section. You
command GAP3 to display this section by entering ?Reading Sections, without quotes.
The section 3.7 describes the format of sections and the conventions used, 3.8 lists the
commands you use to flip through sections, 3.9 describes how to read a section again, 3.10
tells you how to avoid typing the long section names, and 3.11 describes the index command.
3.6
Reading Sections
If the section is longer than 24 lines GAP3 stops after 24 lines and displays
-- for more -If you press space GAP3 displays the next 24 lines of the section and then stops again.
This goes on until the whole section has been displayed, at which point GAP3 will return
immediately to the main GAP3 loop. Pressing f has the same effect as space.
You can also press b or the key labeled del which will scroll back to the previous 24 lines
of the section. If you press b or del when GAP3 is displaying the top of a section GAP3 will
ring the bell.
You can also press q to quit and return immediately back to the main GAP3 loop without
reading the rest of the section.
Actually the 24 is only a default, if you have a larger screen that can display more lines of
text you may want to tell this to GAP3 with the -y rows option when you start GAP3.
3.7
Format of Sections
This section describes the format of sections when they are displayed on the screen and the
special conventions used.
As you can see GAP3 indents sections 4 spaces and prints a header line containing the name
of the section on the left and the name of the chapter on the right.
Text enclosed in angle brackets is used for arguments in the descriptions of functions and
for other placeholders. It means that you should not actually enter this text into GAP3 but
replace it by an appropriate text depending on what you want to do. For example when
we write that you should enter ?section to see the section with the name section, section
servers as a placeholder, indicating that you can enter the name of the section that you
want to see at this place. In the printed manual such text is printed in italics.
220
CHAPTER 3. ENVIRONMENT
’text’
Text enclosed in single quotes is used for names of variables and functions and other text
that you may actually enter into your computer and see on your screen. The text enclosed
in single quotes may contain placeholders enclosed in angle brackets as described above. For
example when the help text for IsPrime says that the form of the call is ’IsPrime(
)’ this means that you should actually enter the IsPrime( and ), without the quotes, but
replace the n with the number (or expression) that you want to test. In the printed manual
this text is printed in a monospaced (all characters have the same width) typewriter font.
"text"
Text enclosed in double quotes is used for cross references to other parts of the manual. So
the text inside the double quotes is the name of another section of the manual. This is used
to direct you to other sections that describe a topic or a function used in this section. So
for example 3.10 is a cross reference to the next section. In the printed manual the text is
replaced by the number of the section.
_ and ^
In mathematical formulas the underscore and the caret are used to denote subscription and
superscription. Ordinarily they apply only to the very next character following, unless a
whole expression enclosed in parentheses follows. So for example x_1^(i+1) denotes the
variable x with subscript 1 raised to the i+1 power. In the printed manual mathematical
formulas are typeset in italics (actually mathitalics) and subscripts and superscripts are
actually lowered and raised.
Longer examples are usually paragraphs of their own that are indented 8 spaces from the
left margin, i.e. 4 spaces further than the surrounding text. Everything on the lines with
the prompts gap> and >, except the prompts themselves of course, is the input you have to
type, everything else is GAP3’s response. In the printed manual examples are also indented
4 spaces and are printed in a monospaced typewriter font.
gap> ?Format of Sections
Format of Sections ______________________________________ Environment
This section describes the format of sections when they are displayed
on the screen and the special conventions used.
...
3.8
Browsing through the Sections
The help sections are organized like a book into chapters. This should not surprise you,
since the same source is used both for the printed manual and the online help. Just as you
can flip through the pages of a book there are special commands to browse through the help
sections.
?>
?<
The two help commands ?< and ?> correspond to the flipping of pages. ?< takes you to
the section preceding the current section and displays it, and ?> takes you to the section
following the current section.
3.9. REDISPLAYING A SECTION
221
?<<
?>>
?<< is like ?<, only more so. It takes you back to the first section of the current chapter,
which gives an overview of the sections described in this chapter. If you are already in this
section ?<< takes you to the first section of the previous chapter. ?>> takes you to the first
section of the next chapter.
??+
GAP3 remembers the sections that you have read. ?- takes you to the one that you have
read before the current one, and displays it again. Further ?- takes you further back in this
history. ?+ reverses this process, i.e., it takes you back to the section that you have read
after the current one. It is important to note, that ?- and ?+ do not alter the history like
the other help commands.
3.9
Redisplaying a Section
?
The help command ? followed by no section name redisplays the last help section again. So
if you reach the bottom of a long help section and already forgot what was mentioned at
the beginning, or, for example, the examples do not seem to agree with your interpretation
of the explanations, use ? to read the whole section again from the beginning.
When ? is used before any section has been read GAP3 displays the section Welcome to
GAP.
3.10
Abbreviating Section Names
Upper and lower case in section are not distinguished, so typing either ?Abbreviating
Section Names or ?abbreviating section names will show this very section.
Each word in section may be abbreviated. So instead of typing ?abbreviating section
names you may also type ?abb sec nam, or even ?a s n. You must not omit the spaces
separating the words. For each word in the section name you must give at least the first
character. As another example you may type ?oper for int instead of ?operations for
integers, which is especially handy when you can not remember whether it was operations
or operators.
If an abbreviation matches multiple section names a list of all these section names is displayed.
3.11
Help Index
??topic
?? looks up topic in GAP3’s index and prints all the index entries that contain the substring
topic. Then you can decide which section is the one you are actually interested in and
request this one.
gap> ??help
help ______________________________________________________ Index
222
CHAPTER 3. ENVIRONMENT
Help
Reading Sections (help!scrolling)
Format of the Sections (help!format)
Browsing through the Sections (help!browsing)
Redisplaying a Section (help!redisplaying)
Abbreviating Section Names (help!abbreviating)
Help Index
gap>
The first thing on each line is the name of the section. If the name of the section matches
topic nothing more is printed. Otherwise the index entry that matched topic is printed in
parentheses following the section name. For each section only the first matching index entry
is printed. The order of the sections corresponds to their order in the GAP3 manual, so that
related sections should be adjacent.
3.12
Read
Read( filename )
Read reads the input from the file with the filename filename, which must be a string.
Read first opens the file filename. If the file does not exist, or if GAP3 can not open it, e.g.,
because of access restrictions, an error is signalled.
Then the contents of the file are read and evaluated, but the results are not printed. The
reading and printing happens exactly as described for the main loop (see 3.1).
If an input in the file contains a syntactical error, a message is printed, and the rest of this
statement is ignored, but the rest of the file is read.
If a statement in the file causes an error a break loop is entered (see 3.2). The input for this
break loop is not taken from the file, but from the input connected to the stderr output of
GAP3. If stderr is not connected to a terminal, no break loop is entered. If this break loop
is left with quit (or ctr -D) the file is closed and GAP3 does not continue to read from it.
Note that a statement may not begin in one file and end in another, i.e., eof (end of
file) is not treated as whitespace, but as a special symbol that must not appear inside any
statement.
Note that one file may very well contain a read statement causing another file to be read,
before input is again taken from the first file. There is an operating system dependent
maximum on the number of files that may be open at once, usually it is 15.
The special file name "*stdin*" denotes the standard input, i.e., the stream through which
the user enters commands to GAP3. The exact behaviour of Read( "*stdin*") is operating
system dependent, but usually the following happens. If GAP3 was started with no input
redirection, statements are read from the terminal stream until the user enters the end of file
character, which is usually ctr -D. Note that terminal streams are special, in that they may
yield ordinary input after an end of file. Thus when control returns to the main read eval
print loop the user can continue with GAP3. If GAP3 was started with an input redirection,
statements are read from the current position in the input file up to the end of the file.
When control returns to the main read eval print loop the input stream will still return
end of file, and GAP3 will terminate. The special file name "*errin*" denotes the stream
connected with the stderr output. This stream is usually connected to the terminal, even
3.13. READLIB
223
if the standard input was redirected, unless the standard error stream was also redirected,
in which case opening of "*errin*" fails, and Read will signal an error.
Read is implemented in terms of the function READ, which behaves exactly like Read, except
that READ does not signal an error when it can not open the file. Instead it returns true or
false to indicate whether opening the file was successful or not.
3.13
ReadLib
ReadLib( name )
ReadLib reads input from the library file with the name name. ReadLib prefixes name with
the value of the variable LIBNAME and appends the string ".g" and calls Read (see 3.12)
with this file name.
3.14
Print
Print( obj1 , obj2 ...
)
Print prints the objects obj1 , obj2 ... etc. to the standard output. The output looks exactly
like the printed representation of the objects printed by the main loop. The exception are
strings, which are printed without the enclosing quotes and a few other transformations (see
30). Note that no space or newline is printed between the objects. PrintTo can be used to
print to a file (see 3.15).
gap> for i in [1..5] do
>
Print( i, " ", i^2, " ", i^3, "\n" );
> od;
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
3.15
PrintTo
PrintTo( filename, obj1 , obj2 ...
)
PrintTo works like Print, except that the output is printed to the file with the name
filename instead of the standard output. This file must of course be writable by GAP3,
otherwise an error is signalled. Note that PrintTo will overwrite the previous contents of
this file if it already existed. AppendTo can be used to append to a file (see 3.16).
The special file name "*stdout*" can be used to print to the standard output. This is
equivalent to a plain Print, except that a plain Print that is executed while evaluating an
argument to a PrintTo call will also print to the output file opened by the last PrintTo call,
while PrintTo( "*stdout*", obj1 , obj2 ... ) always prints to the standard output.
The special file name "*errout*" can be used to print to the standard error output file,
which is usually connected with the terminal, even if the standard output was redirected.
There is an operating system dependent maximum to the number of output files that may
be open at once, usually this is 14.
224
3.16
CHAPTER 3. ENVIRONMENT
AppendTo
AppendTo( filename, obj1 , obj2 ...
)
AppendTo works like PrintTo (see 3.15), except that the output does not overwrite the
previous contents of the file, but is appended to the file.
3.17
LogTo
LogTo( filename )
LogTo causes the subsequent interaction to be logged to the file with the name filename,
i.e., everything you see on your terminal will also appear in this file. This file must of course
be writable by GAP3, otherwise an error is signalled. Note that LogTo will overwrite the
previous contents of this file if it already existed.
LogTo()
In this form LogTo stops logging again.
3.18
LogInputTo
LogInputTo( filename )
LogInputTo causes the subsequent input lines to be logged to the file with the name filename,
i.e., every line you type will also appear in this file. This file must of course be writable
by GAP3, otherwise an error is signalled. Note that LogInputTo will overwrite the previous
contents of this file if it already existed.
LogInputTo()
In this form LogInputTo stops logging again.
3.19
SizeScreen
SizeScreen()
In this form SizeScreen returns the size of the screen as a list with two entries. The first
is the length of each line, the second is the number of lines.
SizeScreen( [ x , y ] )
In this form SizeScreen sets the size of the screen. x is the length of each line, y is the
number of lines. Either value may be missing, to leave this value unaffected. Note that
those parameters can also be set with the command line options -x x and -y y (see 56).
3.20
Runtime
Runtime()
Runtime returns the time spent by GAP3 in milliseconds as an integer. This is usually the
cpu time, i.e., not the wall clock time. Also time spent by subprocesses of GAP3 (see 3.22)
is not counted.
3.21. PROFILE
3.21
225
Profile
Profile( true )
In this form Profile turns the profiling on. Subsequent computations will record the time
spent by each function and the number of times each function was called. Old profiling
information is cleared.
Profile( false )
In this form Profile turns the profiling off again. Recorded information is still kept, so you
can display it even after turning the profiling off.
Profile()
In this form Profile displays the collected information in the following format.
gap> Factors( 10^21+1 );;
# make sure that the library is loaded
gap> Profile( true );
gap> Factors( 10^42+1 );
[ 29, 101, 281, 9901, 226549, 121499449, 4458192223320340849 ]
gap> Profile( false );
gap> Profile();
count
time percent time/call child function
4
1811
76
452
2324 FactorsRho
18
171
7
9
237 PowerModInt
127
94
3
0
94 GcdInt
41
83
3
2
415 IsPrimeInt
91
59
2
0
59 TraceModQF
511
47
1
0
39 QuoInt
22
23
0
1
23 Jacobi
116
20
0
0
31 log
3
20
0
6
70 SmallestRootInt
1
19
0
19
2370 FactorsInt
26
15
0
0
39 LogInt
4
4
0
1
4 Concatenation
5
4
0
0
20 RootInt
7
0
0
0
0 Add
26
0
0
0
0 Length
13
0
0
0
0 NextPrimeInt
4
0
0
0
0 AddSet
4
0
0
0
0 IsList
4
0
0
0
0 Sort
8
0
0
0
0 Append
2369
100
TOTAL
The last column contains the name of the function. The first column contains the number of
times each function was called. The second column contains the time spent in this function.
The third column contains the percentage of the total time spent in this function. The fourth
column contains the time per call, i.e., the quotient of the second by the first number. The
fifth column contains the time spent in this function and all other functions called, directly
or indirectly, by this function.
226
CHAPTER 3. ENVIRONMENT
3.22
Exec
Exec( command )
Exec executes the command given by the string command in the operating system. How this
happens is operating system dependent. Under UNIX, for example, a new shell is started
and command is passed as a command to this shell.
gap> Exec( "date" );
Fri Dec 13 17:00:29 MET 1991
Edit (see 3.23) should be used to call an editor from within GAP3.
3.23
Edit
Edit( filename )
Edit starts an editor with the file whose filename is given by the string filename, and
reads the file back into GAP3 when you exit the editor again. You should set the GAP3
variable EDITOR to the name of the editor that you usually use, e.g., /usr/ucb/vi. This can
for example be done in your .gaprc file (see the sections on operating system dependent
features in chapter 56).
Chapter 4
Domains
Domain is GAP3’s name for structured sets. The ring of Gaussian integers Z[I] is an
example of a domain, the group D12 of symmetries of a regular hexahedron is another.
The GAP3 library predefines some domains. For example the ring of Gaussian integers
is predefined as GaussianIntegers (see 14) and the field of rationals is predefined as
Rationals (see 12). Most domains are constructed by functions, which are called domain constructors. For example the group D12 is constructed by the construction Group(
(1,2,3,4,5,6), (2,6)(3,5) ) (see 7.9) and the finite field with 16 elements is constructed
by GaloisField( 16 ) (see 18.10).
The first place where you need domains in GAP3 is the obvious one. Sometimes you simply
want to talk about a domain. For example if you want to compute the size of the group
D12 , you had better be able to represent this group in a way that the Size function can
understand.
The second place where you need domains in GAP3 is when you want to be able to specify
that an operation or computation takes place in a certain domain. For example suppose you
want to factor 10 in the ring of Gaussian integers. Saying Factors( 10 ) will not do, because this will return the factorization in the ring of integers [ 2, 5 ]. To allow operations
and computations to happen in a specific domain, Factors, and many other functions as
well, accept this domain as optional first argument. Thus Factors( GaussianIntegers,
10 ) yields the desired result [ 1+E(4), 1-E(4), 2+E(4), 2-E(4) ].
Each domain in GAP3 belongs to one or more categories, which are simply sets of domains.
The categories in which a domain lies determine the functions that are applicable to this
domain and its elements. Examples of domains are rings (the functions applicable to a
domain that is a ring are described in 5), fields (see 6), groups (see 7), vector spaces (see
9), and of course the category domains that contains all domains (the functions applicable
to any domain are described in this chapter).
This chapter describes how domains are represented in GAP3 (see 4.1), how functions that
can be applied to different types of domains know how to solve a problem for each of those
types (see 4.2, 4.3, and 4.4), how domains are compared (see 4.7), and the set theoretic
functions that can be applied to any domain (see 4.6, 4.8, 4.9, 4.10, 4.11, 4.12, 4.13, 4.14,
4.16).
The functions described in this chapter are implemented in the file LIBNAME/"domain.g".
227
228
4.1
CHAPTER 4. DOMAINS
Domain Records
Domains are represented by records (see 46), which are called domain records in the
following. Which components need to be present, which may, and what those components
hold, differs from category to category, and, to a smaller extent, from domain to domain.
It is generally possible though to distinguish four types of components.
Each domain record has the component isDomain, which has the value true. Furthermore,
most domains also have a component that specifies which category this domain belongs
to. For example, each group has the component isGroup, holding the value true. Those
components are called the category components of the domain record. A domain that
only has the component isDomain is a member only of the category Domains and only the
functions described in this chapter are applicable to such a domain.
Every domain record also contains enough information to identify uniquely the domain in
the so called identification components. For example, for a group the domain record,
called group record in this case, has a component called generators containing a system
of generators (and also a component identity holding the identity element of the group,
needed if the generator list is empty, as is the case for the trivial group).
Next the domain record holds all the knowledge GAP3 has about the domain, for example
the size of the domain, in the so called knowledge components. Of course, the knowledge
about a certain domain will usually increase as time goes by. For example, a group record
may initially hold only the knowledge that the group is finite, but may end holding all kinds
of knowledge, for example the derived series, the Sylow subgroups, etc.
Finally each domain record has a component, which is called its operations record (because it is the component with the name operations and it holds a record), that tells
functions like Size how to compute this information for this domain. The exact mechanism
is described later (see 4.2).
4.2
Dispatchers
In the previous section it was mentioned that domains are represented by domain records,
and that each domain record has an operations record. This operations record is used by
functions like Size to find out how to compute this information for the domain. Let us
discuss this mechanism using the example of Size. Suppose you call Size with a domain
D.
First Size tests whether D has a component called size, i.e., if D.size is bound. If it is,
Size assumes that it holds the size of the domain and returns this value.
Let us suppose that this component has no assigned value. Then Size looks at the component D.operations, which must be a record. Size takes component D.operations.Size
of this record, which must be a function. Size calls this function passing D as argument.
If a domain record has no Size function in its operations record, an error is signalled.
Finally Size stores the value returned by D.operations.Size( D ) in the component
D.size, where it is available for the next call of Size( D ).
Because functions like Size do little except dispatch to the function in the operations record
they are called dispatcher functions.
4.3. MORE ABOUT DISPATCHERS
229
Which function is called through this mechanism obviously depends on the domain and its
operations record. In principle each domain could have its own Size function. In practice
however this is not the case. For example all permutation groups share the operations record
PermGroupOps so they all use the same Size function PermGroupOps.Size.
Note that in fact domains of the same type not only share the functions, in fact they share
the operations record. So for example all permutation groups have the same operations
record. This means that changing such a function for a domain D in the following way
D.operations.function := new-function; will also change this function for all domains of
the same type, even those that do not yet exist at the moment of the assignment and will
only be constructed later. This is usually not desirable, since supposedly new-function uses
some special properties of the domain D to work efficiently. We suggest therefore, that you
use the following assignments instead:
D.operations := Copy( D.operations );
D.operations.function := new-function;.
Some domains do not provide a special Size function, either because no efficient method
is known or because the author that implemented the domain simply was too lazy to write
one. In those cases the domain inherits the default function, which is DomainOps.Size.
Such inheritance is uncommon for the Size function, but rather common for the Union
function.
4.3
More about Dispatchers
Usually you need not care about the mechanism described in the previous section. You just
call the dispatcher functions like Size. They will call the function in the operations record,
which is hopefully implementing an algorithm that is well suited for their domain, by using
the structure of this domain.
There are three reasons why you might want to avoid calling the dispatcher function and
call the dispatched to function directly.
The first reason is efficiency. The dispatcher functions don’t do very much. They only check
the types of their arguments, check if the requested information is already present, and
dispatch to the appropriate function in the operations record. But sometimes, for example
in the innermost loop of your algorithm, even this little is too much. In those cases you
can avoid the overhead introduced by the dispatcher function by calling the function in the
operations record directly. For example, you would use G.operations.Size(G) instead
of Size(G).
The second reason is flexibility. Sometimes you do not want to call the function in the
operations record, but another function that performs the same task, using a different algorithm. In that case you will call this different function. For example, if G is a permutation
group, and the orbit of p under G is very short, GroupOps.Orbit(G,p), which is the default
function to compute an orbit, may be slightly more efficient than Orbit(G,p), which calls
G.operations.Orbit(G,p), which is the same as PermGroupOps.Orbit(G,p).
The third has to do with the fact that the dispatcher functions check for knowledge components like D.size or D.elements and also store their result in such components. For
example, suppose you know that the result of a computation takes up quite some space, as is
the case with Elements(D), and that you will never need the value again. In this case you
230
CHAPTER 4. DOMAINS
would not want the dispatcher function to enter the value in the domain record, and therefore would call D.operations.Elements(D) directly. On the other hand you may not want
to use the value in the domain record, because you mistrust it. In this case you should call
the function in the operations record directly, e.g., you would use G.operations.Size(G)
instead of Size(G) (and then compare the result with G.size).
4.4
An Example of a Computation in a Domain
This section contains an extended example to show you how a computation in a domain
may use default and special functions to achieve its goal. Suppose you defined G, x, and y
as follows.
gap> G := SymmetricGroup( 8 );;
gap> x := [ (2,7,4)(3,5), (1,2,6)(4,8) ];;
gap> y := [ (2,5,7)(4,6), (1,5)(3,8,7) ];;
Now you ask for an element of G that conjugates x to y, i.e., a permutation on 8 points that
takes (2,7,4)(3,5) to (2,5,7)(4,6) and (1,2,6)(4,8) to (1,5)(3,8,7). This is done
as follows (see 8.25 and 8.1).
gap> RepresentativeOperation( G, x, y, OnTuples );
(1,8)(2,7)(3,4,5,6)
Let us look at what happens step by step. First RepresentativeOperation is called. After checking the arguments it calls the function G.operations.RepresentativeOperation,
which is the function SymmetricGroupOps.RepresentativeOperation, passing the arguments G, x, y, and OnTuples.
SymmetricGroupOps.RepresentativeOperation handles a lot of cases specially, but the
operation on tuples of permutations is not among them. Therefore it delegates this problem
to the function that it overlays, which is PermGroupOps.RepresentativeOperation.
PermGroupOps.RepresentativeOperation also does not handle this special case, and delegates the problem to the function that it overlays, which is the default function called
GroupOps.RepresentativeOperation.
GroupOps.RepresentativeOperation views this problem as a general tuples problem, i.e.,
it does not care whether the points in the tuples are integers or permutations, and decides
to solve it one step at a time. So first it looks for an element taking (2,7,4)(3,5) to
(2,5,7)(4,6) by calling RepresentativeOperation( G, (2,7,4)(3,5), (2,5,7)(4,6)
).
RepresentativeOperation calls G.operations.RepresentativeOperation next, which is
the function SymmetricGroupOps.RepresentativeOperation, passing the arguments G,
(2,7,4)(3,5), and (2,5,7)(4,6).
SymmetricGroupOps.RepresentativeOperation can handle this case. It knows that G
contains every permutation on 8 points, so it contains (3,4,7,5,6), which obviously does
what we want, namely it takes x[1] to y[1]. We will call this element t.
Now GroupOps.RepresentativeOperation (see above) looks for an s in the stabilizer of
x[1] taking x[2] to y[2]^(t^-1), since then for r=s*t we have x[1]^r = (x[1]^s)^t
= x[1]^t = y[1] and also x[2]^r = (x[2]^s)^t = (y[2]^(t^-1))^t = y[2]. So the
next step is to compute the stabilizer of x[1] in G. To do this it calls Stabilizer( G,
(2,7,4)(3,5) ).
4.5. DOMAIN
231
Stabilizer calls G.operations.Stabilizer, which is SymmetricGroupOps.Stabilizer,
passing the arguments G and (2,7,4)(3,5). SymmetricGroupOps.Stabilizer detects that
the second argument is a permutation, i.e., an element of the group, and calls Centralizer(
G, (2,7,4)(3,5) ). Centralizer calls the function G.operations.Centralizer, which
is SymmetricGroupOps.Centralizer, again passing the arguments G, (2,7,4)(3,5).
SymmetricGroupOps.Centralizer again knows how centralizers in symmetric groups look,
and after looking at the permutation (2,7,4)(3,5) sharply for a short while returns the
centralizer as Subgroup( G, [ (1,6), (1,6,8), (2,7,4), (3,5) ] ), which we will call
S. Note that S is of course not a symmetric group, therefore SymmetricGroupOps.Subgroup
gives it PermGroupOps as operations record and not SymmetricGroupOps.
As explained above GroupOps.RepresentativeOperation needs an element of S taking
x[2] ((1,2,6)(4,8)) to y[2]^(t^-1) ((1,7)(4,6,8)). So RepresentativeOperation(
S, (1,2,6)(4,8), (1,7)(4,6,8) ) is called. RepresentativeOperation in turn calls
the function S.operations.RepresentativeOperation, which is, since S is a permutation
group, the function PermGroupOps.RepresentativeOperation, passing the arguments S,
(1,2,6)(4,8), and (1,7)(4,6,8).
PermGroupOps.RepresentativeOperation detects that the points are permutations and
and performs a backtrack search through S. It finds and returns (1,8)(2,4,7)(3,5), which
we call s.
Then GroupOps.RepresentativeOperation returns r = s*t = (1,8)(2,7)(3,6)(4,5),
and we are done.
In this example you have seen how functions use the structure of their domain to solve
a problem most efficiently, for example SymmetricGroupOps.RepresentativeOperation
but also the backtrack search in PermGroupOps.RepresentativeOperation, how they use
other functions, for example SymmetricGroupOps.Stabilizer called Centralizer, and
how they delegate cases which they can not handle more efficiently back to the function they overlaid, for example SymmetricGroupOps.RepresentativeOperation delegated
to PermGroupOps.RepresentativeOperation, which in turn delegated to to the function
GroupOps.RepresentativeOperation.
4.5
Domain
Domain( list )
Domain returns a domain that contains all the elements in list and that knows how to make
the ring, field, group, or vector space that contains those elements.
Note that the domain returned by Domain need in general not be a ring, field, group, or
vector space itself. For example if passed a list of elements of finite fields Domain will return
the domain FiniteFieldElements. This domain contains all finite field elements, no matter
of which characteristic. This domain has a function FiniteFieldElementsOps.Field that
knows how to make a finite field that contains the elements in list. This function knows
that all elements must have the same characteristic for them to lie in a common field.
gap> D := Domain( [ Z(4), Z(8) ] );
FiniteFieldElements
gap> IsField( D );
false
232
CHAPTER 4. DOMAINS
gap> D.operations.Field( [ Z(4), Z(8) ] );
GF(2^6)
Domain is the only function in the whole GAP3 library that knows about the various types of
elements. For example, when Norm is confronted by a field element z , it does not know what
to do with it. So it calls F := DefaultField( [ z ] ) to get a field in which z lies, because
this field (more precisely F.operations.Norm) will know better. However, DefaultField
also does not know what to do with z . So it calls D := Domain( [ z ] ) to get a domain
in which z lies, because it (more precisely D.operations.DefaultField) will know how to
make a default field in which z lies.
4.6
Elements
Elements( D )
Elements returns the set of elements of the domain D. The set is returned as a new proper
set, i.e., as a new sorted list without holes and duplicates (see 28). D may also be a list, in
which case the set of elements of this list is returned. An error is signalled if D is an infinite
domain.
gap> Elements( GaussianIntegers );
Error, the ring must be finite to compute its elements
gap> D12 := Group( (2,6)(3,5), (1,2)(3,6)(4,5) );;
gap> Elements( D12 );
[ (), (2,6)(3,5), (1,2)(3,6)(4,5), (1,2,3,4,5,6), (1,3)(4,6),
(1,3,5)(2,4,6), (1,4)(2,3)(5,6), (1,4)(2,5)(3,6), (1,5)(2,4),
(1,5,3)(2,6,4), (1,6,5,4,3,2), (1,6)(2,5)(3,4) ]
Elements remembers the set of elements in the component D.elements and will return
a shallow copy (see 46.12) next time it is called to compute the elements of D. If you
want to avoid this, for example for a large domain, for which you know that you will
not need the list of elements in the future, either unbind (see 46.10) D.elements or call
D.operation.Elements(D) directly.
Since there is no general method to compute the elements of a domain the default function
DomainOps.Elements just signals an error. This default function is overlaid for each special
finite domain. In fact, implementors of domains, must implement this function for new
domains, since it is, together with IsFinite (see 4.9) the most basic function for domains,
used by most of the default functions in the domain package.
In general functions that return a set of elements are free, in fact encouraged, to return a
domain instead of the proper set of elements. For one thing this allows to keep the structure,
for another the representation by a domain record is usually more space efficient. Elements
must not do this, its only purpose is to create the proper set of elements.
4.7
Comparisons of Domains
D = E
D <> E
= evaluates to true if the two domains D and E are equal, to false otherwise. <> evaluates
to true if the two domains D and E are different and to false if they are equal.
4.7. COMPARISONS OF DOMAINS
233
Two domains are considered equal if and only if the sets of their elements as computed by
Elements (see 4.6) are equal. Thus, in general = behaves as if each domain operand were
replaced by its set of elements. Except that = will also sometimes, but not always, work
for infinite domains, for which it is of course difficult to compute the set of elements. Note
that this implies that domains belonging to different categories may well be equal. As a
special case of this, either operand may also be a proper set, i.e., a sorted list without holes
or duplicates (see 28.2), and the result will be true if and only if the set of elements of the
domain is, as a set, equal to the set. It is also possible to compare a domain with something
else that is not a domain or a set, but the result will of course always be false in this case.
gap> GaussianIntegers = D12;
false
# GAP3 knows that those domains cannot be equal because
# GaussianIntegers is infinite and D12 is finite
gap> GaussianIntegers = Integers;
false
# GAP3 knows how to compare those two rings
gap> GaussianIntegers = Rationals;
Error, sorry, cannot compare the infinite domains and
gap> D12 = Group( (2,6)(3,5), (1,2)(3,6)(4,5) );
true
gap> D12 = [(),(2,6)(3,5),(1,2)(3,6)(4,5),(1,2,3,4,5,6),(1,3)(4,6),
>
(1,3,5)(2,4,6),(1,4)(2,3)(5,6),(1,4)(2,5)(3,6),
>
(1,5)(2,4),(1,5,3)(2,6,4),(1,6,5,4,3,2),(1,6)(2,5)(3,4)];
true
gap> D12 = [(1,6,5,4,3,2),(1,6)(2,5)(3,4),(1,5,3)(2,6,4),(1,5)(2,4),
>
(1,4)(2,5)(3,6),(1,4)(2,3)(5,6),(1,3,5)(2,4,6),(1,3)(4,6),
>
(1,2,3,4,5,6),(1,2)(3,6)(4,5),(2,6)(3,5),()];
false
# since the left operand behaves as a set
# while the right operand is not a set
The default function DomainOps.’=’ checks whether both domains are infinite. If they are,
an error is signalled. Otherwise, if one domain is infinite, false is returned. Otherwise
the sizes (see 4.10) of the domains are compared. If they are different, false is returned.
Finally the sets of elements of both domains are computed (see 4.6) and compared. This
default function is overlaid by more special functions for other domains.
D
D
D
D
< E
<= E
> E
>= E
<, <=, >, and >= evaluate to true if the domain D is less than, less than or equal to, greater
than, and greater than or equal to the domain E and to false otherwise.
A domain D is considered less than a domain E if and only if the set of elements of D is
less than the set of elements of the domain E . Generally you may just imagine that each
domain operand is replaced by the set of its elements, and that the comparison is performed
on those sets (see 27.12). This implies that, if you compare a domain with an object that
is not a list or a domain, this other object will be less than the domain, except if it is a
record, in which case it is larger than the domain (see 2.9).
Note that < does not test whether the left domain is a subset of the right operand, even
though it resembles the mathematical subset notation.
234
CHAPTER 4. DOMAINS
gap> GaussianIntegers < Rationals;
Error, sorry, cannot compare with the infinite domain
gap> Group( (1,2), (1,2,3,4,5,6) ) < D12;
true
# since (5,6), the second element of the left operand,
# is less than (2,6)(3,5), the second element of D12.
gap> D12 < [(1,6,5,4,3,2),(1,6)(2,5)(3,4),(1,5,3)(2,6,4),(1,5)(2,4),
>
(1,4)(2,5)(3,6),(1,4)(2,3)(5,6),(1,3,5)(2,4,6),(1,3)(4,6),
>
(1,2,3,4,5,6),(1,2)(3,6)(4,5),(2,6)(3,5),()];
true
# since (), the first element of D12, is less than
# (1,6,5,4,3,2), the first element of the right operand.
gap> 17 < D12;
true
# objects that are not lists or records are smaller
# than domains, which behave as if they were a set
The default function DomainOps.’<’ checks whether either domain is infinite. If one is, an
error is signalled. Otherwise the sets of elements of both domains are computed (see 4.6)
and compared. This default function is only very seldom overlaid by more special functions
for other domains. Thus the operators <, <=, >, and >= are quite expensive and their use
should be avoided if possible.
4.8
Membership Test for Domains
elm in D
in returns true if the element elm, which may be an object of any type, lies in the domain
D, and false otherwise.
gap> 13 in GaussianIntegers;
true
gap> GaussianIntegers in GaussianIntegers;
false
gap> (1,2) in D12;
false
gap> (1,2)(3,6)(4,5) in D12;
true
The default function for domain membership tests is DomainOps.’in’, which computes the
set of elements of the domain with the function Elements (see 4.6) and tests whether elm
lies in this set. Special domains usually overlay this function with more efficient membership
tests.
4.9
IsFinite
IsFinite( D )
IsFinite returns true if the domain D is finite and false otherwise. D may also be a
proper set (see 28.2), in which case the result is of course always true.
gap> IsFinite( GaussianIntegers );
false
gap> IsFinite( D12 );
true
4.10. SIZE
235
The default function DomainOps.IsFinite just signals an error, since there is no general
method to determine whether a domain is finite or not. This default function is overlaid
for each special domain. In fact, implementors of domains must implement this function
for new domains, since it is, together with Elements (see 4.6), the most basic function for
domains, used by most of the default functions in the domain package.
4.10
Size
Size( D )
Size returns the size of the domain D. If D is infinite, Size returns the string "infinity".
D may also be a proper set (see 28.2), in which case the result is the length of this list. Size
will, however, signal an error if D is a list that is not a proper set, i.e., that is not sorted,
or has holes, or contains duplicates.
gap> Size( GaussianIntegers );
"infinity"
gap> Size( D12 );
12
The default function to compute the size of a domain is DomainOps.Size, which computes
the set of elements of the domain with the function Elements (see 4.6) and returns the
length of this set. This default function is overlaid in practically every domain.
4.11
IsSubset
IsSubset( D, E )
IsSubset returns true if the domain E is a subset of the domain D and false otherwise.
E is considered a subset of D if and only if the set of elements of E is as a set a subset of
the set of elements of D (see 4.6 and 28.9). That is IsSubset behaves as if implemented
as IsSubsetSet( Elements(D), Elements(E ) ), except that it will also sometimes, but
not always, work for infinite domains, and that it will usually work much faster than the
above definition. Either argument may also be a proper set.
gap> IsSubset( GaussianIntegers, [1,E(4)] );
true
gap> IsSubset( GaussianIntegers, Rationals );
Error, sorry, cannot compare the infinite domains and
gap> IsSubset( Group( (1,2), (1,2,3,4,5,6) ), D12 );
true
gap> IsSubset( D12, [ (), (1,2)(3,4)(5,6) ] );
false
The default function DomainOps.IsSubset checks whether both domains are infinite. If
they are it signals an error. Otherwise if the E is infinite it returns false. Otherwise if
D is infinite it tests if each element of E is in D (see 4.8). Otherwise it tests whether the
proper set of elements of E is a subset of the proper set of elements of D (see 4.6 and 28.9).
4.12
Intersection
Intersection( D1 , D2 ...
Intersection( list )
)
236
CHAPTER 4. DOMAINS
In the first form Intersection returns the intersection of the domains D1 , D2 , etc. In the
second form list must be a list of domains and Intersection returns the intersection of
those domains. Each argument D or element of list respectively may also be an arbitrary
list, in which case Intersection silently applies Set (see 28.2) to it first.
The result of Intersection is the set of elements that lie in every of the domains D1 , D2 ,
etc. Functions called by the dispatcher function Intersection however, are encouraged to
keep as much structure as possible. So if D1 and D2 are elements of a common category
and if this category is closed under taking intersections, then the result should be a domain
lying in this category too. So for example the intersection of permutation groups will again
be a permutation group.
gap> Intersection( CyclotomicField(9), CyclotomicField(12) );
CF(3)
# CF is a shorthand for CyclotomicField
# this is one of the rare cases where the intersection
# of two infinite domains works
gap> Intersection( GaussianIntegers, Rationals );
Error, sorry, cannot intersect infinite domains and
gap> Intersection( D12, Group( (1,2), (1,2,3,4,5) ) );
Group( (1,5)(2,4) )
gap> Intersection( D12, [ (1,3)(4,6), (1,2)(3,4) ] );
[ (1,3)(4,6) ]
# note that the second argument is not a set
gap> Intersection( D12, [ (), (1,2)(3,4), (1,3)(4,6), (1,4)(5,6) ] );
[ (), (1,3)(4,6) ]
# although the result is mathematically a
# group it is returned as a proper set
# because the second argument was not a group
gap> Intersection( [2,4,6,8,10], [3,6,9,12,15], [5,10,15,20,25] );
[ ]
# two or more domains or sets as arguments are legal
gap> Intersection( [ [1,2,4], [2,3,4], [1,3,4] ] );
[ 4 ]
# or a list of domains or sets
gap> Intersection( [ ] );
Error, List Element: [1] must have a value
The dispatcher function (see 4.2) Intersection is slightly different from other dispatcher
functions. It does not simply call the function in the operations record passings its arguments. Instead it loops over its arguments (or the list of domains or sets) and calls the
function in the operations record repeatedly, and passes each time only two domains. This
obviously makes writing the function for the operations record simpler.
The default function DomainOps.Intersection checks whether both domains are infinite.
If they are it signals an error. Otherwise, if one of the domains is infinite it loops over the
elements of the other domain, and tests for each element whether it lies in the infinite domain.
If both domains are finite it computes the proper sets of elements of both and intersects
them (see 4.6 and 28.9). This default method is overlaid by more special functions for most
other domains. Those functions usually are faster and keep the structure of the domains if
possible.
4.13
Union
Union( D1 , D2 ...
Union( list )
)
4.14. DIFFERENCE
237
In the first form Union returns the union of the domains D1 , D2 , etc. In the second form
list must be a list of domains and Union returns the union of those domains. Each argument
D or element of list respectively may also be an arbitrary list, in which case Union silently
applies Set (see 28.2) to it first.
The result of Union is the set of elements that lie in any the domains D1 , D2 , etc. Functions
called by the dispatcher function Union however, are encouraged to keep as much structure
as possible. However, currently GAP3 does not support any category that is closed under
taking unions except the category of all domains. So the only case that structure will be
kept is when one argument D or element of list respectively is a superset of all the other
arguments or elements of list.
gap> Union( GaussianIntegers, Rationals );
Error, sorry, cannot unite with the infinite domain
gap> Union( D12, Group( (1,2), (1,2,3) ) );
[ (), (2,3), (2,6)(3,5), (1,2), (1,2)(3,6)(4,5), (1,2,3),
(1,2,3,4,5,6), (1,3,2), (1,3), (1,3)(4,6), (1,3,5)(2,4,6),
(1,4)(2,3)(5,6), (1,4)(2,5)(3,6), (1,5)(2,4), (1,5,3)(2,6,4),
(1,6,5,4,3,2), (1,6)(2,5)(3,4) ]
gap> Union( [2,4,6,8,10], [3,6,9,12,15], [5,10,15,20,25] );
[ 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 20, 25 ]
# two or more domains or sets as arguments are legal
gap> Union( [ [1,2,4], [2,3,4], [1,3,4] ] );
[ 1, 2, 3, 4 ]
# or a list of domains or sets
gap> Union( [ ] );
[ ]
The dispatcher function (see 4.2) Union is slightly different from other dispatcher functions.
It does not simply call the function in the operations record passings its arguments. Instead
it loops over its arguments (or the list of domains or sets) and calls the function in the
operations record repeatedly, and passes each time only two domains. This obviously makes
writing the function for the operations record simpler.
The default function DomainOps.Union checks whether either domain is infinite. If one is
it signals an error. If both domains are finite it computes the proper sets of elements of
both and unites them (see 4.6 and 28.9). This default method is overlaid by more special
functions for some other domains. Those functions usually are faster.
4.14
Difference
Difference( D, E )
Difference returns the set difference of the domains D and E . Either argument may also
be an arbitrary list, in which case Difference silently applies Set (see 28.2) to it first.
The result of Difference is the set of elements that lie in D but not in E . Note that E
need not be a subset of D. The elements of E , however, that are not element of D play no
role for the result.
gap> Difference( D12, [(),(1,2,3,4,5,6),(1,3,5)(2,4,6),
>
(1,4)(2,5)(3,6),(1,6,5,4,3,2),(1,5,3)(2,6,4)] );
[ (2,6)(3,5), (1,2)(3,6)(4,5), (1,3)(4,6), (1,4)(2,3)(5,6),
238
CHAPTER 4. DOMAINS
(1,5)(2,4), (1,6)(2,5)(3,4) ]
The default function DomainOps.Difference checks whether D is infinite. If it is it signals
an error. Otherwise Difference computes the proper sets of elements of D and E and
returns the difference of those sets (see 4.6 and 28.8). This default function is currently not
overlaid for any domain.
4.15
Representative
Representative( D )
Representative returns a representative of the domain D.
The existence of a representative, and the exact definition of what a representative is,
depends on the category of D. The representative should be an element that, within a given
context, identifies the domain D. For example if D is a cyclic group, its representative would
be a generator of D, or if D is a coset, its representative would be an arbitrary element of
the coset.
Note that Representative is pretty free in choosing a representative if there are several.
It is not even guaranteed that Representative returns the same representative if it is
called several times for one domain. Thus the main difference between Representative
and Random (see 4.16) is that Representative is free to choose a value that is cheap to
compute, while Random must make an effort to randomly distribute its answers.
gap> C := Coset( Subgroup( G, [(1,4)(2,5)(3,6)] ), (1,6,5,4,3,2) );;
gap> Representative( C );
(1,3,5)(2,4,6)
Representative first tests whether the component D.representative is bound. If the
field is bound it returns its value. Otherwise it calls D.operations.Representative( D
), remembers the returned value in D.representative, and returns it.
The default function called this way is DomainOps.Representative, which simply signals
an error, since there is no default way to find a representative.
4.16
Random
Random( D )
Random returns a random element of the domain D. The distribution of elements returned
by Random depends on the domain D. For finite domains all elements are usually equally
likely. For infinite domains some reasonable distribution is used. See the chapters of the
various domains to find out which distribution is being used.
gap> Random( GaussianIntegers );
1-4*E(4)
gap> Random( GaussianIntegers );
1+2*E(4)
gap> Random( D12 );
()
gap> Random( D12 );
(1,4)(2,5)(3,6)
4.16. RANDOM
239
The default function for random selection is DomainOps.Random, which computes the set of
elements using Elements and selects a random element of this list using RandomList (see
27.48 for a description of the pseudo random number generator used). This default function
can of course only be applied to finite domains. It is overlaid by other functions for most
other domains.
All random functions called this way rely on the low level random number generator provided
by RandomList (see 27.48).
240
CHAPTER 4. DOMAINS
Chapter 5
Rings
Rings are important algebraic domains. Mathematically a ring is a set R with two operations + and * called addition and multiplication. (R, +) must be an abelian group. The
identity of this group is called 0R . (R − {0R }, ∗) must be a monoid. If this monoid has an
identity element it is called 1R .
Important examples of rings are the integers (see 10), the Gaussian integers (see 14), the
integers of a cyclotomic field (see 15), and matrices (see 34).
This chapter contains sections that describe how to test whether a domain is a ring (see
5.1), and how to find the smallest and the default ring in which a list of elements lies (see
5.2 and 5.3).
The next sections describe the operations applicable to ring elements (see 5.4, 5.5, 5.6).
The next sections describe the functions that test whether a ring has certain properties (5.7,
5.8, 5.9, and 5.10).
The next sections describe functions that are related to the units of a ring (see 5.11, 5.12,
5.13, 5.14, and 5.15).
Then come the sections that describe the functions that deal with the irreducible and prime
elements of a ring (see 5.16, 5.17, and 5.18).
Then come the sections that describe the functions that are applicable to elements of rings
(see 5.19, 5.20, 5.21, 5.22, 5.24, 5.25, 5.26, 5.27, 5.28).
The last section describes how ring records are represented internally (see 5.29).
Because rings are a category of domains all functions applicable to domains are also applicable to rings (see chapter 4) .
All functions described in this chapter are in LIBNAME/"ring.g".
5.1
IsRing
IsRing( domain )
IsRing returns true if the object domain is a ring record, representing a ring (see 5.29),
and false otherwise.
241
242
CHAPTER 5. RINGS
More precisely IsRing tests whether domain is a ring record (see 5.29). So for example a
matrix group may in fact be a ring, yet IsRing would return false.
gap> IsRing( Integers );
true
gap> IsRing( Rationals );
false
# Rationals is a field record not a ring record
gap> IsRing( rec( isDomain := true, isRing := true ) );
true
# it is possible to fool IsRing
5.2
Ring
Ring( r , s...
Ring( list )
)
In the first form Ring returns the smallest ring that contains all the elements r , s... etc. In
the second form Ring returns the smallest ring that contains all the elements in the list list.
If any element is not an element of a ring or if the elements lie in no common ring an error
is raised.
gap> Ring( 1, -1 );
Integers
gap> Ring( [10..20] );
Integers
Ring differs from DefaultRing (see 5.3) in that it returns the smallest ring in which the
elements lie, while DefaultRing may return a larger ring if that makes sense.
5.3
DefaultRing
DefaultRing( r , s...
DefaultRing( list )
)
In the first form DefaultRing returns the default ring that contains all the elements r , s...
etc. In the second form DefaultRing returns the default ring that contains all the elements
in the list list. If any element is not an element of a ring or if the elements lie in no common
ring an error is raised.
The ring returned by DefaultRing need not be the smallest ring in which the elements
lie. For example for elements from cyclotomic fields DefaultRing may return the ring of
integers of the smallest cyclotomic field in which the elements lie, which need not be the
smallest ring overall, because the elements may in fact lie in a smaller number field which
is not a cyclotomic field.
For the exact definition of the default ring of a certain type of elements read the chapter
describing this type.
DefaultRing is used by the ring functions like Quotient, IsPrime, Factors, or Gcd if no
explicit ring is given.
gap> DefaultRing( 1, -1 );
Integers
gap> DefaultRing( [10..20] );
Integers
5.4. COMPARISONS OF RING ELEMENTS
243
Ring (see 5.2) differs from DefaultRing in that it returns the smallest ring in which the
elements lie, while DefaultRing may return a larger ring if that makes sense.
5.4
Comparisons of Ring Elements
r = s
r <> s
The equality operator = evaluates to true if the two ring elements r and s are equal, and
to false otherwise. The inequality operator <> evaluates to true if the two ring elements
r and s are not equal, and to false otherwise. Note that any two ring elements can be
compared, even if they do not lie in compatible rings. In this case they can, of course, never
be equal. For each type of rings the equality of those ring elements is given in the respective
chapter.
Ring elements can also be compared with objects of other types. Of course they are never
equal.
r
r
r
r
< s
<= s
> s
>= s
The operators <, <=, >, and >= evaluate to true if the ring element r is less than, less than
or equal to, greater than, or greater than or equal to the ring element s, and to false
otherwise. For each type of rings the definition of the ordering of those ring elements is
given in the respective chapter. The ordering of ring elements is as follows. Rationals are
smallest, next are cyclotomics, followed by finite ring elements.
Ring elements can also be compared with objects of other types. They are smaller than
everything else.
5.5
Operations for Ring Elements
The following operations are always available for ring elements. Of course the operands must
lie in compatible rings, i.e., the rings must be equal, or at least have a common superring.
r + s
The operator + evaluates to the sum of the two ring elements r and s, which must lie in
compatible rings.
r - s
The operator - evaluates to the difference of the two ring elements r and s, which must lie
in compatible rings.
r * s
The operator * evaluates to the product of the two ring elements r and s, which must lie
in compatible rings.
r ^ n
The operator ^ evaluates to the n-th power of the ring element r . If n is a positive integer
then r ^n is r *r *..*r (n factors). If n is a negative integer r ^n is defined as 1/r −n . If 0
244
CHAPTER 5. RINGS
is raised to a negative power an error is signalled. Any ring element, even 0, raised to the
0-th power yields 1.
For the precedence of the operators see 2.10.
Note that the quotient operator / usually performs the division in the quotient field of the
ring. To compute a quotient in a ring use the function Quotient (see 5.6).
5.6
Quotient
Quotient( r , s )
Quotient( R, r , s )
In the first form Quotient returns the quotient of the two ring elements r and s in their
default ring (see 5.3). In the second form Quotient returns the quotient of the two ring
elements r and s in the ring R. It returns false if the quotient does not exist.
gap> Quotient( 4, 2 );
2
gap> Quotient( Integers, 3, 2 );
false
Quotient calls R.operations.Quotient( R, r , s ) and returns the value.
The default function called this way is RingOps.Quotient, which just signals an error,
because there is no generic method to compute the quotient of two ring elements. Thus
special categories of rings must overlay this default function with other functions.
5.7
IsCommutativeRing
IsCommutativeRing( R )
IsCommutativeRing returns true if the ring R is commutative and false otherwise.
A ring R is called commutative if for all elements r and s of R we have rs = sr.
gap> IsCommutativeRing( Integers );
true
IsCommutativeRing first tests whether the flag R.isCommutativeRing is bound. If the flag
is bound, it returns this value. Otherwise it calls R.operations.IsCommutativeRing( R
), remembers the returned value in R.isCommutativeRing, and returns it.
The default function called this way is RingOps.IsCommutativeRing, which tests whether
all the generators commute if the component R.generators is bound, and tests whether all
elements commute otherwise, unless R is infinite. This function is seldom overlaid, because
most rings already have the flag bound.
5.8
IsIntegralRing
IsIntegralRing( R )
IsIntegeralRing returns true if the ring R is integral and false otherwise.
A ring R is called integral if it is commutative and if for all elements r and s of R we have
rs = 0R implies that either r or s is 0R .
5.9. ISUNIQUEFACTORIZATIONRING
245
gap> IsIntegralRing( Integers );
true
IsIntegralRing first tests whether the flag R.isIntegralRing is bound. If the flag is
bound, it returns this value. Otherwise it calls R.operations.IsIntegralRing( R ),
remembers the returned value in R.isIntegralRing, and returns it.
The default function called this way is RingOps.IsIntegralRing, which tests whether the
product of each pair of nonzero elements is unequal to zero, unless R is infinite. This
function is seldom overlaid, because most rings already have the flag bound.
5.9
IsUniqueFactorizationRing
IsUniqueFactorizationRing( R )
IsUniqueFactorizationRing returns true if R is a unique factorization ring and false
otherwise.
A ring R is called a unique factorization ring if it is an integral ring, and every element
has a unique factorization into irreducible elements, i.e., a unique representation as product
of irreducibles (see 5.16). Unique in this context means unique up to permutations of the
factors and up to multiplication of the factors by units (see 5.12).
gap> IsUniqueFactorizationRing( Integers );
true
IsUniqueFactorizationRing tests whether R.isUniqueFactorizationRing is bound. If
the flag is bound, it returns this value. If this flag has no assigned value it calls the function R.operations.IsUniqueFactorizationRing( R ), remembers the returned value in
R.isUniqueFactorizationRing, and returns it.
The default function called this way is RingOps.IsUniqueFactorizationRing, which just
signals an error, since there is no generic method to test whether a ring is a unique factorization ring. Special categories of rings thus must either have the flag bound or overlay this
default function.
5.10
IsEuclideanRing
IsEuclideanRing( R )
IsEuclideanRing returns true if the ring R is a Euclidean ring and false otherwise.
A ring R is called a Euclidean ring if it is an integral ring and there exists a function δ,
called the Euclidean degree, from R − {0R } to the nonnegative integers, such that for every
pair r ∈ R and s ∈ R − {0R } there exists an element q such that either r − qs = 0R or
δ(r − qs) < δ(s). The existence of this division with remainder implies that the Euclidean
algorithm can be applied to compute a greatest common divisor of two elements, which in
turn implies that R is a unique factorization ring.
gap> IsEuclideanRing( Integers );
true
IsEuclideanRing first tests whether the flag R.isEuclideanRing is bound. If the flag is
bound, it returns this value. Otherwise it calls R.operations.IsEuclideanRing( R ),
remembers the returned value in R.isEuclideanRing, and returns it.
246
CHAPTER 5. RINGS
The default function called this way is RingOps.IsEuclideanRing, which just signals an
error, because there is no generic way to test whether a ring is a Euclidean ring. This
function is seldom overlaid because most rings already have the flag bound.
5.11
IsUnit
IsUnit( r )
IsUnit( R, r )
In the first form IsUnit returns true if the ring element r is a unit in its default ring (see
5.3). In the second form IsUnit returns true if r is a unit in the ring R.
An element r is called a unit in a ring R, if r has an inverse in R.
gap> IsUnit( Integers, 2 );
false
gap> IsUnit( Integers, -1 );
true
IsUnit calls R.operations.IsUnit( R, r ) and returns the value.
The default function called this way is RingOps.IsUnit, which tries to compute the inverse
of r with R.operations.Quotient( R, R.one, r ) and returns true if the result is not
false, and false otherwise. Special categories of rings overlay this default function with
more efficient functions.
5.12
Units
Units( R )
Units returns the group of units of the ring R. This may either be returned as a list or as
a group described by a group record (see 7).
An element r is called a unit of a ring R, if r has an inverse in R. It is easy to see that the
set of units forms a multiplicative group.
gap> Units( Integers );
[ -1, 1 ]
Units first tests whether the component R.units is bound. If the component is bound, it
returns this value. Otherwise it calls R.operations.Units( R ), remembers the returned
value in R.units, and returns it.
The default function called this way is RingOps.Units, which runs over all elements of R
and tests for each whether it is a unit, provided that R is finite. Special categories of rings
overlay this default function with more efficient functions.
5.13
IsAssociated
IsAssociated( r , s )
IsAssociated( R, r , s )
In the first form IsAssociated returns true if the two ring elements r and s are associated
in their default ring (see 5.3) and false otherwise. In the second form IsAssociated returns
true if the two ring elements r and s are associated in the ring R and false otherwise.
5.14. STANDARDASSOCIATE
247
Two elements r and s of a ring R are called associates if there is a unit u of R such that
ru = s.
gap> IsAssociated( Integers, 2, 3 );
false
gap> IsAssociated( Integers, 17, -17 );
true
IsAssociated calls R.operations.IsAssociated( R, r , s ) and returns the value.
The default function called this way is RingOps.IsAssociated, which tries to compute the
quotient of r and s and returns true if the quotient exists and is a unit. Special categories
of rings overlay this default function with more efficient functions.
5.14
StandardAssociate
StandardAssociate( r )
StandardAssociate( R, r )
In the first form StandardAssociate returns the standard associate of the ring element r
in its default ring (see 5.3). In the second form StandardAssociate returns the standard
associate of the ring element r in the ring R.
The standard associate of an ring element r of R is an associated element of r which is,
in a ring dependent way, distinguished among the set of associates of r. For example, in the
ring of integers the standard associate is the absolute value.
gap> StandardAssociate( Integers, -17 );
17
StandardAssociate calls R.operations.StandardAssociate( R, r ) and returns the
value.
The default function called this way is RingOps.StandardAssociate, which just signals an
error, because there is no generic way even to define the standard associate. Thus special
categories of rings must overlay this default function with other functions.
5.15
Associates
Associates( r )
Associates( R, r )
In the first form Associates returns the set of associates of the ring element r in its default
ring (see 5.3). In the second form Associates returns the set of associates of r in the ring
R.
Two elements r and s of a ring R are called associate if there is a unit u of R such that
ru = s.
gap> Associates( Integers, 17 );
[ -17, 17 ]
Associates calls R.operations.Associates( R, r ) and returns the value.
The default function called this way is RingOps.Associates, which multiplies the set of
units of R with the element r , and returns the set of those elements. Special categories of
rings overlay this default function with more efficient functions.
248
CHAPTER 5. RINGS
5.16
IsIrreducible
IsIrreducible( r )
IsIrreducible( R, r )
In the first form IsIrreducible returns true if the ring element r is irreducible in its default
ring (see 5.3) and false otherwise. In the second form IsIrreducible returns true if the
ring element r is irreducible in the ring R and false otherwise.
An element r of a ring R is called irreducible if there is no nontrivial factorization of r in
R, i.e., if there is no representation of r as product st such that neither s nor t is a unit (see
5.11). Each prime element (see 5.17) is irreducible.
gap> IsIrreducible( Integers, 4 );
false
gap> IsIrreducible( Integers, 3 );
true
IsIrreducible calls R.operations.IsIrreducible( R, r ) and returns the value.
The default function called this way is RingOps.IsIrreducible, which justs signals an
error, because there is no generic way to test whether an element is irreducible. Thus
special categories of rings must overlay this default function with other functions.
5.17
IsPrime
IsPrime( r )
IsPrime( R, r )
In the first form IsPrime returns true if the ring element r is a prime in its default ring
(see 5.3) and false otherwise. In the second form IsPrime returns true if the ring element
r is a prime in the ring R and false otherwise.
An element r of a ring R is called prime if for each pair s and t such that r divides st
the element r divides either s or t. Note that there are rings where not every irreducible
element (see 5.16) is a prime.
gap> IsPrime( Integers, 4 );
false
gap> IsPrime( Integers, 3 );
true
IsPrime calls R.operations.IsPrime( R, r ) and returns the value.
The default function called this way is RingOps.IsPrime, which just signals an error, because there is no generic way to test whether an element is prime. Thus special categories
of rings must overlay this default function with other functions.
5.18
Factors
Factors( r )
Factors( R, r )
In the first form Factors returns the factorization of the ring element r in its default ring
(see 5.3). In the second form Factors returns the factorization of the ring element r in
5.19. EUCLIDEANDEGREE
249
the ring R. The factorization is returned as a list of primes (see 5.17). Each element in the
list is a standard associate (see 5.14) except the first one, which is multiplied by a unit as
necessary to have Product( Factors( R, r ) ) = r . This list is usually also sorted, thus
smallest prime factors come first. If r is a unit or zero, Factors( R, r ) = [ r ].
gap> Factors( -Factorial(6) );
[ -2, 2, 2, 2, 3, 3, 5 ]
gap> Set( Factors( Factorial(13)/11 ) );
[ 2, 3, 5, 7, 13 ]
gap> Factors( 2^63 - 1 );
[ 7, 7, 73, 127, 337, 92737, 649657 ]
gap> Factors( 10^42 + 1 );
[ 29, 101, 281, 9901, 226549, 121499449, 4458192223320340849 ]
Factors calls R.operations.Factors( R, r ) and returns the value.
The default function called this way is RingOps.Factors, which just signals an error, because there is no generic way to compute the factorization of ring elements. Thus special
categories of ring elements must overlay this default function with other functions.
5.19
EuclideanDegree
EuclideanDegree( r )
EuclideanDegree( R, r )
In the first form EuclideanDegree returns the Euclidean degree of the ring element r in its
default ring. In the second form EuclideanDegree returns the Euclidean degree of the ring
element in the ring R. R must of course be an Euclidean ring (see 5.10).
A ring R is called a Euclidean ring, if it is an integral ring, and there exists a function δ,
called the Euclidean degree, from R − {0R } to the nonnegative integers, such that for every
pair r ∈ R and s ∈ R − {0R } there exists an element q such that either r − qs = 0R or
δ(r − qs) < δ(s). The existence of this division with remainder implies that the Euclidean
algorithm can be applied to compute a greatest common divisors of two elements, which in
turn implies that R is a unique factorization ring.
gap> EuclideanDegree( Integers, 17 );
17
gap> EuclideanDegree( Integers, -17 );
17
EuclideanDegree calls R.operations.EuclideanDegree( R, r ) and returns the value.
The default function called this way is RingOps.EuclideanDegree, which justs signals an
error, because there is no default way to compute the Euclidean degree of an element. Thus
Euclidean rings must overlay this default function with other functions.
5.20
EuclideanRemainder
EuclideanRemainder( r , m )
EuclideanRemainder( R, r , m )
In the first form EuclideanRemainder returns the remainder of the ring element r modulo
the ring element m in their default ring. In the second form EuclideanRemainder returns
250
CHAPTER 5. RINGS
the remainder of the ring element r modulo the ring element m in the ring R. The ring R
must be a Euclidean ring (see 5.10) otherwise an error is signalled.
A ring R is called a Euclidean ring, if it is an integral ring, and there exists a function δ,
called the Euclidean degree, from R − {0R } to the nonnegative integers, such that for every
pair r ∈ R and s ∈ R − {0R } there exists an element q such that either r − qs = 0R or
δ(r − qs) < δ(s). The existence of this division with remainder implies that the Euclidean
algorithm can be applied to compute a greatest common divisors of two elements, which
in turn implies that R is a unique factorization ring. EuclideanRemainder returns this
remainder r − qs.
gap> EuclideanRemainder( 16, 3 );
1
gap> EuclideanRemainder( Integers, 201, 11 );
3
EuclideanRemainder calls R.operations.EuclideanRemainder( R, r , m ) in order to
compute the remainder and returns the value.
The default function called this way uses QuotientRemainder in order to compute the
remainder.
5.21
EuclideanQuotient
EuclideanQuotient( r , m )
EuclideanQuotient( R, r , m )
In the first form EuclideanQuotient returns the Euclidean quotient of the ring elements r
and m in their default ring. In the second form EuclideanQuotient returns the Euclidean
quotient of the ring elements r and m in the ring R. The ring R must be a Euclidean ring
(see 5.10) otherwise an error is signalled.
A ring R is called a Euclidean ring, if it is an integral ring, and there exists a function δ,
called the Euclidean degree, from R − {0R } to the nonnegative integers, such that for every
pair r ∈ R and s ∈ R − {0R } there exists an element q such that either r − qs = 0R or
δ(r − qs) < δ(s). The existence of this division with remainder implies that the Euclidean
algorithm can be applied to compute a greatest common divisors of two elements, which in
turn implies that R is a unique factorization ring. EuclideanQuotient returns the quotient
q.
gap> EuclideanQuotient( 16, 3 );
5
gap> EuclideanQuotient( Integers, 201, 11 );
18
EuclideanQuotient calls R.operations.EuclideanQuotient( R, r , m ) and returns
the value.
The default function called this way uses QuotientRemainder in order to compute the
quotient.
5.22
QuotientRemainder
QuotientRemainder( r , m )
QuotientRemainder( R, r , m )
5.23. MOD
251
In the first form QuotientRemainder returns the Euclidean quotient and the Euclidean
remainder of the ring elements r and m in their default ring as pair of ring elements. In
the second form QuotientRemainder returns the Euclidean quotient and the Euclidean
remainder of the ring elements r and m in the ring R. The ring R must be a Euclidean ring
(see 5.10) otherwise an error is signalled.
A ring R is called a Euclidean ring, if it is an integral ring, and there exists a function δ,
called the Euclidean degree, from R − {0R } to the nonnegative integers, such that for every
pair r ∈ R and s ∈ R − {0R } there exists an element q such that either r − qs = 0R or
δ(r − qs) < δ(s). The existence of this division with remainder implies that the Euclidean
algorithm can be applied to compute a greatest common divisors of two elements, which in
turn implies that R is a unique factorization ring. QuotientRemainder returns this quotient
q and the remainder r − qs.
gap> qr := QuotientRemainder( 16, 3 );
[ 5, 1 ]
gap> 3 * qr[1] + qr[2];
16
gap> QuotientRemainder( Integers, 201, 11 );
[ 18, 3 ]
QuotientRemainder calls R.operations.QuotientRemainder( R, r , m ) and returns
the value.
The default function called this way is RingOps.QuotientRemainder, which just signals an
error, because there is no default function to compute the Euclidean quotient or remainder
of one ring element modulo another. Thus Euclidean rings must overlay this default function
with other functions.
5.23
Mod
Mod( r , m )
Mod( R, r , m )
Mod is a synonym for EuclideanRemainder and is obsolete, see 5.20.
5.24
QuotientMod
QuotientMod( r , s, m )
QuotientMod( R, r , s, m )
In the first form QuotientMod returns the quotient of the ring elements r and s modulo the
ring element m in their default ring (see 5.3). In the second form QuotientMod returns the
quotient of the ring elements r and s modulo the ring element m in the ring R. R must be
a Euclidean ring (see 5.10) so that EuclideanRemainder (see 5.20) can be applied. If the
modular quotient does not exist, false is returned.
The quotient q of r and s modulo m is an element of R such that qs = r modulo m, i.e.,
such that qs − r is divisable by m in R and that q is either 0 (if r is divisable by m) or the
Euclidean degree of q is strictly smaller than the Euclidean degree of m.
gap> QuotientMod( Integers, 13, 7, 11 );
5
252
CHAPTER 5. RINGS
gap> QuotientMod( Integers, 13, 7, 21 );
false
QuotientMod calls R.operations.QuotientMod( R, r , s, m ) and returns the value.
The default function called this way is RingOps.QuotientMod, which applies the Euclidean
gcd algorithm to compute the gcd g of s and m, together with the representation of this
gcd as linear combination in s and m, g = a * s + b * m. The modular quotient exists
if and only if r is divisible by g, in which case the quotient is a * Quotient( R, r , g ).
This default function is seldom overlaid, because there is seldom a better way to compute
the quotient.
5.25
PowerMod
PowerMod( r , e, m )
PowerMod( R, r , e, m )
In the first form PowerMod returns the e-th power of the ring element r modulo the ring
element m in their default ring (see 5.3). In the second form PowerMod returns the e-th
power of the ring element r modulo the ring element m in the ring R. e must be an integer.
R must be a Euclidean ring (see 5.10) so that EuclideanRemainder (see 5.20) can be applied
to its elements.
If e is positive the result is re modulo m. If e is negative then PowerMod first tries to find
the inverse of r modulo m, i.e., i such that ir = 1 modulo m. If the inverse does not exist
an error is signalled. If the inverse does exist PowerMod returns PowerMod( R, i , -e, m
).
PowerMod reduces the intermediate values modulo m, improving performance drastically
when e is large and m small.
gap> PowerMod( Integers, 2, 20, 100 );
76
# 220 = 1048576
gap> PowerMod( Integers, 3, 2^32, 2^32+1 );
3029026160
# which proves that 232 + 1 is not a prime
gap> PowerMod( Integers, 3, -1, 22 );
15
# 3*15 = 45 = 1 modulo 22
PowerMod calls R.operations.PowerMod( R, r , e, m ) and returns the value.
The default function called this way is RingOps.PowerMod, which uses QuotientMod (see
5.24) if necessary to invert r , and then uses a right-to-left repeated squaring, reducing the
intermediate results modulo m in each step. This function is seldom overlaid, because there
is seldom a better way of computing the power.
5.26
Gcd
Gcd( r1 , r2 ... )
Gcd( R, r1 , r2 ...
)
In the first form Gcd returns the greatest common divisor of the ring elements r1 , r2 ... etc.
in their default ring (see 5.3). In the second form Gcd returns the greatest common divisor
of the ring elements r1 , r2 ... etc. in the ring R. R must be a Euclidean ring (see 5.10) so
5.27. GCDREPRESENTATION
253
that QuotientRemainder (see 5.22) can be applied to its elements. Gcd returns the standard
associate (see 5.14) of the greatest common divisors.
A greatest common divisor of the elements r1 , r2 ... etc. of the ring R is an element of
largest Euclidean degree (see 5.19) that is a divisor of r1 , r2 ... etc. We define gcd(r, 0R ) =
gcd(0R , r) = StandardAssociate(r) and gcd(0R , 0R ) = 0R .
gap> Gcd( Integers, 123, 66 );
3
Gcd calls R.operations.Gcd repeatedly, each time passing the result of the previous call
and the next argument, and returns the value of the last call.
The default function called this way is RingOps.Gcd, which applies the Euclidean algorithm
to compute the greatest common divisor. Special categories of rings overlay this default
function with more efficient functions.
5.27
GcdRepresentation
GcdRepresentation( r1 , r2 ... )
GcdRepresentation( R, r1 , r2 ...
)
In the first form GcdRepresentation returns the representation of the greatest common
divisor of the ring elements r1 , r2 ... etc. in their default ring (see 5.3). In the second form
GcdRepresentation returns the representation of the greatest common divisor of the ring
elements r1 , r2 ... etc. in the ring R. R must be a Euclidean ring (see 5.10) so that Gcd
(see 5.26) can be applied to its elements. The representation is returned as a list of ring
elements.
The representation of the gcd g of the elements r1 , r2 ... etc. of a ring R is a list of ring
elements s1 , s2 ... etc. of R, such that g = s1 r1 + s2 r2 .... That this representation exists can
be shown using the Euclidean algorithm, which in fact can compute those coefficients.
gap> GcdRepresentation( 123, 66 );
[ 7, -13 ]
# 3 = 7*123 - 13*66
gap> Gcd( 123, 66 ) = last * [ 123, 66 ];
true
GcdRepresentation calls R.operations.GcdRepresentation repeatedly, each time passing the gcd result of the previous call and the next argument, and returns the value of the
last call.
The default function called this way is RingOps.GcdRepresentation, which applies the
Euclidean algorithm to compute the greatest common divisor and its representation. Special
categories of rings overlay this default function with more efficient functions.
5.28
Lcm
Lcm( r1 , r2 ... )
Lcm( R, r1 , r2 ...
)
In the first form Lcm returns the least common multiple of the ring elements r1 , r2 ... etc.
in their default ring (see 5.3). In the second form Lcm returns the least common multiple
of the ring elements r1 , r2 ,... etc. in the ring R. R must be a Euclidean ring (see 5.10) so
254
CHAPTER 5. RINGS
that Gcd (see 5.26) can be applied to its elements. Lcm returns the standard associate (see
5.14) of the least common multiples.
A least common multiple of the elements r1 , r2 ... etc. of the ring R is an element of smallest
Euclidean degree (see 5.19) that is a multiple of r1 , r2 ... etc. We define lcm(r, 0R ) =
lcm(0R , r) = StandardAssociate(r) and Lcm(0R , 0R ) = 0R .
Lcm uses the equality lcm(m, n) = m ∗ n/gcd(m, n) (see 5.26).
gap> Lcm( Integers, 123, 66 );
2706
Lcm calls R.operations.Lcm repeatedly, each time passing the result of the previous call
and the next argument, and returns the value of the last call.
The default function called this way is RingOps.Lcm, which simply returns the product of
r with the quotient of s and the greatest common divisor of r and s. Special categories of
rings overlay this default function with more efficient functions.
5.29
Ring Records
A ring R is represented by a record with the following entries.
isDomain
is of course always the value true.
isRing
is of course always the value true.
isCommutativeRing
is true if the multiplication is known to be commutative, false if the multiplication
is known to be noncommutative, and unbound otherwise.
isIntegralRing
is true if R is known to be a commutative domain with 1 without zero divisor, false
if R is known to lack one of these properties, and unbound otherwise.
isUniqueFactorizationRing
is true if R is known to be a domain with unique factorization into primes, false if
R is known to have a nonunique factorization, and unbound otherwise.
isEuclideanRing
is true if R is known to be a Euclidean domain, false if it is known not to be a
Euclidean domain, and unbound otherwise.
zero
is the additive neutral element.
units
is the list of units of the ring if it is known.
size
is the size of the ring if it is known. If the ring is not finite this is the string ”infinity”.
one
is the multiplicative neutral element, if the ring has one.
5.29. RING RECORDS
255
integralBase
if the ring is, as additive group, isomorphic to the direct product of a finite number
of copies of Z this contains a base.
As an example of a ring record, here is the definition of the ring record Integers.
rec(
# category components
isDomain
isRing
:= true,
:= true,
# identity components
generators
zero
one
name
:=
:=
:=
:=
[ 1 ],
0,
1,
"Integers",
# knowledge components
size
isFinite
isCommutativeRing
isIntegralRing
isUniqueFactorizationRing
isEuclideanRing
units
:=
:=
:=
:=
:=
:=
:=
"infinity",
false,
true,
true,
true,
true,
[ -1, 1 ],
# operations record
operations
:= rec(
...
IsPrime
:= function ( Integers, n )
return IsPrimeInt( n );
end,
...
’mod’
:= function ( Integers, n, m )
return n mod m;
end,
... ) )
256
CHAPTER 5. RINGS
Chapter 6
Fields
Fields are important algebraic domains. Mathematically a field is a commutative ring F
(see chapter 5), such that every element except 0 has a multiplicative inverse. Thus F has
two operations + and * called addition and multiplication. (F, +) must be an abelian group,
whose identity is called 0F . (F − {0F }, ∗) must be an abelian group, whose identity element
is called 1F .
GAP3 supports the field of rationals (see 12), subfields of cyclotomic fields (see 15), and
finite fields (see 18).
This chapter begins with sections that describe how to test whether a domain is a field (see
6.1), how to find the smallest field and the default field in which a list of elements lies (see
6.2 and 6.3), and how to view a field over a subfield (see 6.4).
The next sections describes the operation applicable to field elements (see 6.5 and 6.6).
The next sections describe the functions that are applicable to fields (see 6.7) and their
elements (see 6.12, 6.10, 6.11, 6.9, and 6.8).
The following sections describe homomorphisms of fields (see 6.13, 6.14, 6.15, 6.16).
The last section describes how fields are represented internally (see 6.17).
Fields are domains, so all functions that are applicable to all domains are also applicable to
fields (see chapter 4).
All functions for fields are in LIBNAME/"field.g".
6.1
IsField
IsField( D )
IsField returns true if the object D is a field and false otherwise.
More precisely IsField tests whether D is a field record (see 6.17). So, for example, a
matrix group may in fact be a field, yet IsField would return false.
gap> IsField( GaloisField(16) );
true
gap> IsField( CyclotomicField(9) );
257
258
CHAPTER 6. FIELDS
true
gap> IsField( rec( isDomain := true, isField := true ) );
true
# it is possible to fool IsField
gap> IsField( AsRing( Rationals ) );
false
# though this ring is, as a set, still Rationals
6.2
Field
Field( z ,..
) Field( list )
In the first form Field returns the smallest field that contains all the elements z ,.. etc. In
the second form Field returns the smallest field that contains all the elements in the list
list. If any element is not an element of a field or the elements lie in no common field an
error is raised.
gap> Field( Z(4) );
GF(2^2)
gap> Field( E(9) );
CF(9)
gap> Field( [ Z(4), Z(9) ] );
Error, CharFFE: must be a finite field element, vector, or matrix
gap> Field( [ E(4), E(9) ] );
CF(36)
Field differs from DefaultField (see 6.3) in that it returns the smallest field in which the
elements lie, while DefaultField may return a larger field if that makes sense.
6.3
DefaultField
DefaultField( z ,..
) DefaultField( list )
In the first form DefaultField returns the default field that contains all the elements z ,..
etc. In the second form DefaultField returns the default field that contains all the elements
in the list list. If any element is not an element of a field or the elements lie in no common
field an error is raised.
The field returned by DefaultField need not be the smallest field in which the elements
lie. For example for elements from cyclotomic fields DefaultField may return the smallest
cyclotomic field in which the elements lie, which need not be the smallest field overall,
because the elements may in fact lie in a smaller number field which is not a cyclotomic
field.
For the exact definition of the default field of a certain type of elements read the chapter
describing this type (see 18 and 15).
DefaultField is used by Conjugates, Norm, Trace, CharPol, and MinPol (see 6.12, 6.10,
6.11, 6.9, and 6.8) if no explicit field is given.
gap> DefaultField( Z(4) );
GF(2^2)
gap> DefaultField( E(9) );
CF(9)
gap> DefaultField( [ Z(4), Z(9) ] );
6.4. FIELDS OVER SUBFIELDS
259
Error, CharFFE: must be a finite field element, vector, or matrix
gap> DefaultField( [ E(4), E(9) ] );
CF(36)
Field (see 6.2) differs from DefaultField in that it returns the smallest field in which the
elements lie, while DefaultField may return a larger field if that makes sense.
6.4
Fields over Subfields
F / G
The quotient operator / evaluates to a new field H . This field has the same elements as F ,
i.e., is a domain equal to F . However H is viewed as a field over the field G, which must be
a subfield of F .
What subfield a field is viewed over determines its Galois group. As described in 6.7 the
Galois group is the group of field automorphisms that leave the subfield fixed. It also
influences the results of 6.10, 6.11, 6.9, and 6.8, because they are defined in terms of the
Galois group.
gap> F := GF(2^12);
GF(2^12)
gap> G := GF(2^2);
GF(2^2)
gap> Q := F / G;
GF(2^12)/GF(2^2)
gap> Norm( F, Z(2^6) );
Z(2)^0
gap> Norm( Q, Z(2^6) );
Z(2^2)^2
The operator / calls G.operations./( F , G ).
The default function called this way is FieldOps./, which simply makes a copy of F and
enters G into the record component F .field (see 6.17).
6.5
Comparisons of Field Elements
f = g
f <> g
The equality operator = evaluates to true if the two field elements f and g are equal, and
to false otherwise. The inequality operator <> evaluates to true if the two field elements
f and g are not equal, and to false otherwise. Note that any two field elements can be
compared, even if they do not lie in compatible fields. In this case they cn, of course, never
be equal. For each type of fields the equality of those field elements is given in the respective
chapter.
Note that you can compare field elements with elements of other types; of course they are
never equal.
f < g
f <= g
260
CHAPTER 6. FIELDS
f > g
f >= g
The operators <, <=, >, and >= evaluate to true if the field element f is less than, less than
or equal to, greater than, or greater than or equal to the field element g. For each type of
fields the definition of the ordering of those field elements is given in the respective chapter.
The ordering of field elements is as follows. Rationals are smallest, next are cyclotomics,
followed by finite field elements.
Note that you can compare field elements with elements of other types; they are smaller
than everything else.
6.6
Operations for Field Elements
The following operations are always available for field elements. Of course the operands must
lie in compatible fields, i.e., the fields must be equal, or at least have a common superfield.
f + g
The operator + evaluates to the sum of the two field elements f and g, which must lie in
compatible fields.
f - g
The operator - evaluates to the difference of the two field elements f and g, which must lie
in compatible fields.
f * g
The operator * evaluates to the product of the two field elements f and g, which must lie
in compatible fields.
f / g
The operator / evaluates to the quotient of the two field elements f and g, which must lie
in compatible fields. If the divisor is 0 an error is signalled.
f ^ n
The operator ^ evaluates to the n-th power of the field element f . If n is a positive integer
then f ^n is f *f *..*f (n factors). If n is a negative integer f ^n is defined as 1/f −n . If 0
is raised to a negative power an error is signalled. Any field element, even 0, raised to the
0-th power yields 1.
For the precedence of the operators see 2.10.
6.7
GaloisGroup
GaloisGroup( F )
GaloisGroup returns the Galois group of the field F as a group (see 7) of field automorphisms
(see 6.13).
The Galois group of a field F over a subfield F .field is the group of automorphisms of
F that leave the subfield F .field fixed. This group can be interpreted as a permutation
group permuting the zeroes of the characteristic polynomial of a primitive element of F .
The degree of this group is equal to the number of zeroes, i.e., to the dimension of F as
6.8. MINPOL
261
a vector space over the subfield F .field. It operates transitively on those zeroes. The
normal divisors of the Galois group correspond to the subfields between F and F .field.
gap> G := GaloisGroup( GF(4096)/GF(4) );;
gap> Size( G );
6
gap> IsCyclic( G );
true
# the Galois group of every finite field is
# generated by the Frobenius automorphism
gap> H := GaloisGroup( CF(60) );;
gap> Size( H );
16
gap> IsAbelian( H );
true
The default function FieldOps.GaloisGroup just raises an error, since there is no general
method to compute the Galois group of a field. This default function is overlaid by more
specific functions for special types of domains (see 18.13 and 15.8).
6.8
MinPol
MinPol( z )
MinPol( F , z )
In the first form MinPol returns the coefficients of the minimal polynomial of the element
z in its default field over its prime field (see 6.3). In the second form MinPol returns the
coefficients of the minimal polynomial of the element z in the field F over the subfield
F .field.
Let F/S be a field extension and L a minimal normal extension of S, containing F . The
minimal polynomial of z in F over S is the squarefree polynomial whose roots are precisely
the conjugates of z in L (see 6.12). Because the set of conjugates is fixed under the Galois
group of L over S (see 6.7), so is the polynomial. Thus all the coefficients of the minimal
polynomial lie in S.
gap> MinPol( Z(2^6) );
[ Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0 ]
gap> MinPol( GF(2^12), Z(2^6) );
[ Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0 ]
gap> MinPol( GF(2^12)/GF(2^2), Z(2^6) );
[ Z(2^2), Z(2)^0, Z(2)^0, Z(2)^0 ]
The default function FieldOps.MinPol, which works only for extensions with abelian Galois
group, multiplies the linear factors x − c with c ranging over the set of conjugates of z in
F (see 6.12). For generic algebraic extensions, it is overlayed by solving a system of linear
equations, given by the coefficients of powers of z in respect to a given base.
6.9
CharPol
CharPol( z )
CharPol( F , z )
262
CHAPTER 6. FIELDS
In the first form CharPol returns the coefficients of the characteristic polynomial of the
element z in its default field over its prime field (see 6.3). In the second form CharPol
returns the coefficients of the characteristic polynomial of the element z in the field F over
the subfield F .field. The characteristic polynomial is returned as a list of coefficients, the
i -th entry is the coefficient of xi−1 .
:S]
The characteristic polynomial of an element z in a field F over a subfield S is the [F
degµ -th
power of µ, where µ denotes the minimal polynomial of z in F over S. It is fixed under
the Galois group of the normal closure of F . Thus all the coefficients of the characteristic
polynomial lie in S. The constant term is (−1)F.degree/S.degree = (−1)[F :S] times the norm
of z (see 6.10), and the coefficient of the second highest degree term is the negative of the
trace of z (see 6.11). The roots (including their multiplicities) in F of the characteristic
polynomial of z in F are the conjugates (see 6.12) of z in F .
gap> CharPol( Z(2^6) );
[ Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0 ]
gap> CharPol( GF(2^12), Z(2^6) );
[ Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2),
Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ]
gap> CharPol( GF(2^12)/GF(2^2), Z(2^6) );
[ Z(2^2)^2, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0 ]
The default function FieldOps.CharPol multiplies the linear factors x − c with c ranging
over the conjugates of z in F (see 6.12). For nonabelian extensions, it is overlayed by a
function, which computes the appropriate power of the minimal polynomial.
6.10
Norm
Norm( z )
Norm( F , z )
In the first form Norm returns the norm of the field element z in its default field over its
prime field (see 6.3). In the second form Norm returns the norm of z in the field F over the
subfield F .field.
The norm of an element z in a field F over a subfield S is (−1)F.degree/S.degree = (−1)[F :S]
times the constant term of the characteristic polynomial of z (see 6.9). Thus the norm lies
in S. The norm is the product of all conjugates of z in the normal closure of F over S (see
6.12).
gap> Norm( Z(2^6) );
Z(2)^0
gap> Norm( GF(2^12), Z(2^6) );
Z(2)^0
gap> Norm( GF(2^12)/GF(2^2), Z(2^6) );
Z(2^2)^2
The default function FieldOps.Norm multiplies the conjugates of z in F (see 6.12). For
nonabelian extensions, it is overlayed by a function, which obtains the norm from the characteristic polynomial.
6.11. TRACE
6.11
263
Trace
Trace( z )
Trace( F , z )
In the first form Trace returns the trace of the field element z in its default field over its
prime field (see 6.3). In the second form Trace returns the trace of the element z in the
field F over the subfield F .field.
The trace of an element z in a field F over a subfield S is the negative of the coefficient
of the second highest degree term of the characteristic polynomial of z (see 6.9). Thus the
trace lies in S. The trace is the sum over all conjugates of z in the normal closure of F over
S (see 6.12).
gap> Trace( Z(2^6) );
0*Z(2)
gap> Trace( GF(2^12), Z(2^6) );
0*Z(2)
gap> Trace( GF(2^12)/GF(2^2), Z(2^6) );
0*Z(2)
The default function FieldOps.Trace adds the conjugates of z in F (see 6.12). For nonabelian extensions, this is overlayed by a function, which obtains the trace from the characteristic polynomial.
6.12
Conjugates
Conjugates( z )
Conjugates( F , z )
In the first form Conjugates returns the list of conjugates of the field element z in its
default field over its prime field (see 6.3). In the second form Conjugates returns the list
of conjugates of the field element z in the field F over the subfield F .field. In either case
the list may contain duplicates if z lies in a proper subfield of its default field, respectively
of F .
The conjugates of an element z in a field F over a subfield S are the roots in F of the
characteristic polynomial of z in F (see 6.9). If F is a normal extension of S, then the
conjugates of z are the images of z under all elements of the Galois group of F over S
(see 6.7), i.e., under those automorphisms of F that leave S fixed. The number of different
conjugates of z is given by the degree of the smallest extension of S in which z lies.
For a normal extension F , Norm (see 6.10) computes the product, Trace (see 6.11) the sum of
all conjugates. CharPol (see 6.9) computes the polynomial that has precisely the conjugates
with their corresponding multiplicities as roots, MinPol (see 6.8) the squarefree polynomial
that has precisely the conjugates as roots.
gap> Conjugates( Z(2^6) );
[ Z(2^6), Z(2^6)^2, Z(2^6)^4, Z(2^6)^8, Z(2^6)^16, Z(2^6)^32 ]
gap> Conjugates( GF(2^12), Z(2^6) );
[ Z(2^6), Z(2^6)^2, Z(2^6)^4, Z(2^6)^8, Z(2^6)^16, Z(2^6)^32, Z(2^6),
Z(2^6)^2, Z(2^6)^4, Z(2^6)^8, Z(2^6)^16, Z(2^6)^32 ]
gap> Conjugates( GF(2^12)/GF(2^2), Z(2^6) );
264
CHAPTER 6. FIELDS
[ Z(2^6), Z(2^6)^4, Z(2^6)^16, Z(2^6), Z(2^6)^4, Z(2^6)^16 ]
The default function FieldOps.Conjugates applies the automorphisms of the Galois group
of F (see 6.7) to z and returns the list of images. For nonabelian extensions, this is overlayed
by a factorization of the characteristic polynomial.
6.13
Field Homomorphisms
Field homomorphisms are an important class of homomorphisms in GAP3 (see chapter 44).
A field homomorphism φ is a mapping that maps each element of a field F , called the
source of φ, to an element of another field G, called the range of φ, such that for each pair
x, y ∈ F we have (x + y)φ = xφ + y φ and (xy)φ = xφ y φ . We also require that φ maps the
one of F to the one of G (that φ maps the zero of F to the zero of G is implied by the above
relations).
An Example of a field homomorphism is the Frobinius automorphism of a finite field (see
18.11). Look under field homomorphisms in the index for a list of all available field
homomorphisms.
Since field homomorphisms are just a special case of homomorphisms, all functions described
in chapter 44 are applicable to all field homomorphisms, e.g., the function to test if a
homomorphism is a an automorphism (see 44.6). More general, since field homomorphisms
are just a special case of mappings all functions described in chapter 43 are also applicable,
e.g., the function to compute the image of an element under a homomorphism (see 43.8).
The following sections describe the functions that test whether a mapping is a field homomorphism (see 6.14), compute the kernel of a field homomorphism (see 6.15), and how the
general mapping functions are implemented for field homomorphisms.
6.14
IsFieldHomomorphism
IsFieldHomomorphism( map )
IsFieldHomomorphism returns true if the mapping map is a field homomorphism and false
otherwise. Signals an error if map is a multi valued mapping.
A mapping map is a field homomorphism if its source F and range G are both fields and if for
each pair of elements x, y ∈ F we have (x + y)map = xmap + y map and (xy)map = xmap y map .
We also require that 1map
= 1G .
F
gap> f := GF( 16 );
GF(2^4)
gap> fun := FrobeniusAutomorphism( f );
FrobeniusAutomorphism( GF(2^4) )
gap> IsFieldHomomorphism( fun );
true
IsFieldHomomorphism first tests if the flag map.isFieldHomomorphism is bound. If the
flag is bound, IsFieldHomomorphism returns its value. Otherwise it calls
map.source.operations.IsFieldHomomorphism( map ), remembers the returned value
in map.isFieldHomomorphism, and returns it. Note that of course all functions that create
field homomorphism set the flag map.isFieldHomomorphism to true, so that no function
is called for those field homomorphisms.
6.15. KERNELFIELDHOMOMORPHISM
265
The default function called this way is MappingOps.IsFieldHomomorphism. It computes
all the elements of the source of map and for each pair of elements x, y tests whether
(x + y)map = xmap + y map and (xy)map = xmap y map . Look under IsHomomorphism in
the index to see for which mappings this function is overlaid.
6.15
KernelFieldHomomorphism
KernelFieldHomomorphism( hom )
KernelFieldHomomorphism returns the kernel of the field homomorphism hom.
Because the kernel must be a ideal in the source and it can not be the full source (because
we require that the one of the source is mapped to the one of the range), it must be the
trivial ideal. Therefor the kernel of every field homomorphism is the set containing only the
zero of the source.
6.16
Mapping Functions for Field Homomorphisms
This section describes how the mapping functions defined in chapter 43 are implemented for
field homomorphisms. Those functions not mentioned here are implemented by the default
functions described in the respective sections.
IsInjective( hom )
Always returns true (see 6.15).
IsSurjective( hom )
The field homomorphism hom is surjective if the size of the image Size( Image( hom ) )
is equal to the size of the range Size( hom.range ).
hom1 = hom2
The two field homomorphism hom1 and hom2 are are equal if the have the same source and
range and if the images of the generators of the source under hom1 and hom2 are equal.
Image( hom )
Image( hom, H )
Images( hom, H )
The image of a subfield under a field homomorphism is computed by computing the images
of a set of generators of the subfield, and the result is the subfield generated by those images.
PreImage( hom )
PreImage( hom, H )
PreImages( hom, H )
The preimages of a subfield under a field homomorphism are computed by computing the
preimages of all the generators of the subfield, and the result is the subfield generated by
those elements.
Look in the index under IsInjective, IsSurjective, Image, Images, PreImage, PreImages, and equality to see for which field homomorphisms these functions are overlaid.
266
CHAPTER 6. FIELDS
6.17
Field Records
A field is represented by a record that contains important information about this field.
The GAP3 library predefines some field records, for example Rationals (see 12). Field
constructors construct others, for example Field (see 6.2), and GaloisField (see 18.10).
Of course you may also create such a record by hand.
All field records contain the components isDomain, isField, char, degree, generators,
zero, one, field, base, and dimension. They may also contain the optional components
isFinite, size, galoisGroup. The contents of all components of a field F are described
below.
isDomain
is always true. This indicates that F is a domain.
isField
is always true. This indicates that F is a field.
char
is the characteristic of F . For finite fields this is always a prime, for infinite fields this
is 0.
degree
is the degree of F as extension of the prime field, not as extension of the subfield
S . For finite fields the order of F is given by F .char^F .degree.
generators
a list of elements that together generate F . That is F is the smallest field over the
prime field given by F .char that contains the elements of F .generators.
zero
is the additive neutral element of the finite field.
one
is the multiplicative neutral element of the finite field.
field
is the subfield S over which F was constructed. This is either a field record for S , or
the same value as F .char, denoting the prime field (see 6.4).
base
is a list of elements of F forming a base for F as vector space over the subfield S .
dimension
is the dimension of F as vector space over the subfield S .
isFinite
if present this is true if the field F is finite and false otherwise.
size
if present this is the size of the field F . If F is infinite this holds the string ”infinity”.
galoisGroup
if present this holds the Galois group of F (see 6.7).
Chapter 7
Groups
Finitely generated groups and their subgroups are important domains in GAP3. They are
represented as permutation groups, matrix groups, ag groups or even more complicated
constructs as for instance automorphism groups, direct products or semi-direct products
where the group elements are represented by records.
Groups are created using Group (see 7.9), they are represented by records that contain
important information about the groups. Subgroups are created as subgroups of a given
group using Subgroup, and are also represented by records. See 7.6 for details about the
distinction between groups and subgroups.
Because this chapter is very large it is split into several parts. Each part consists of several
sections.
Note that some functions will only work if the elements of a group are represented in an
unique way. This is not true in finitely presented groups, see 23.3 for a list of functions
applicable to finitely presented groups.
The first part describes the operations and functions that are available for group elements, e.g., Order (see 7.1). The next part tells your more about the distinction of parent groups and subgroups (see 7.6). The next parts describe the functions that compute
subgroups, e.g., SylowSubgroup (7.14), and series of subgroups, e.g., DerivedSeries (see
7.36). The next part describes the functions that compute and test properties of groups, e.g.,
AbelianInvariants and IsSimple (see 7.45), and that identify the isomorphism type. The
next parts describe conjugacy classes of elements and subgroups (see 7.67) and cosets (see
7.84). The next part describes the functions that create new groups, e.g., DirectProduct
(see 7.98). The next part describes group homomorphisms, e.g., NaturalHomomorphism (see
7.106). The last part tells you more about the implementation of groups, e.g., it describes
the format of group records (see 7.114).
The functions described in this chapter are implemented in the following library files.
LIBNAME/"grpelms.g" contains the functions for group elements, LIBNAME/"group.g" contains the dispatcher and default group functions, LIBNAME/"grpcoset.g" contains the functions for cosets and factor groups, LIBNAME/"grphomom.g" implements the group homomorphisms, and LIBNAME/"grpprods.g" implements the group constructions.
267
268
7.1
CHAPTER 7. GROUPS
Group Elements
The following sections describe the operations and functions available for group elements
(see 7.2, 7.3, 7.4, and 7.5).
Note that group elements usually exist independently of a group, e.g., you can write down
two permutations and compute their product without ever defining a group that contains
them.
7.2
Comparisons of Group Elements
g = h
g <> h
The equality operator = evaluates to true if the group elements g and h are equal and to
false otherwise. The inequality operator <> evaluates to true if the group elements g and
h are not equal and to false otherwise.
You can compare group elements with objects of other types. Of course they are never
equal. Standard group elements are permutations, ag words and matrices. For examples of
generic group elements see for instance 7.99.
g
g
g
g
< h
<= h
>= h
> h
The operators <, <=, >= and > evaluate to true if the group element g is strictly less than,
less than or equal to, greater than or equal to and strictly greater than the group element
h. There is no general ordering on group elements.
Standard group elements may be compared with objects of other types while generic group
elements may disallow such a comparison.
7.3
Operations for Group Elements
g * h
g / h
The operators * and / evaluate to the product and quotient of the two group elements g
and h. The operands must of course lie in a common parent group, otherwise an error is
signaled.
g ^ h
The operator ^ evaluates to the conjugate h −1 ∗ g ∗ h of g under h for two group elements
elements g and h. The operands must of course lie in a common parent group, otherwise
an error is signaled.
g ^ i
7.4. ISGROUPELEMENT
269
The powering operator ^ returns the i -th power of a group element g and an integer i . If i
is zero the identity of a parent group of g is returned.
list * g
g * list
In this form the operator * returns a new list where each entry is the product of g and the
corresponding entry of list. Of course multiplication must be defined between g and each
entry of list.
list / g
In this form the operator / returns a new list where each entry is the quotient of g and the
corresponding entry of list. Of course division must be defined between g and each entry of
list.
Comm( g, h )
Comm returns the commutator g −1 ∗ h −1 ∗ g ∗ h of two group elements g and h. The operands
must of course lie in a common parent group, otherwise an error is signaled.
LeftNormedComm( g1 , ..., gn )
LeftNormedComm returns the left normed commutator Comm( LeftNormedComm( g1 , ...,
gn-1 ), gn ) of group elements g1 , ..., gn. The operands must of course lie in a common
parent group, otherwise an error is signaled.
RightNormedComm( g1 , g2 , ..., gn )
RightNormedComm returns the right normed commutator Comm( g1 , RightNormedComm(
g2 , ..., gn ) ) of group elements g1 , ..., gn. The operands must of course lie in a
common parent group, otherwise an error is signaled.
LeftQuotient( g, h )
LeftQuotient returns the left quotient g −1 ∗h of two group elements g and h. The operands
must of course lie in a common parent group, otherwise an error is signaled.
7.4
IsGroupElement
IsGroupElement( obj )
IsGroupElement returns true if obj , which may be an object of arbitrary type, is a group
element, and false otherwise. The function will signal an error if obj is an unbound variable.
gap> IsGroupElement( 10 );
false
gap> IsGroupElement( (11,10) );
true
gap> IsGroupElement( IdWord );
true
270
7.5
CHAPTER 7. GROUPS
Order
Order( G, g )
Order returns the order of a group element g in the group G.
The order is the smallest positive integer i such that g i is the identity. The order of the
identity is one.
gap> Order( Group( (1,2), (1,2,3,4) ), (1,2,3) );
3
gap> Order( Group( (1,2), (1,2,3,4) ), () );
1
7.6
More about Groups and Subgroups
GAP3 distinguishs between parent groups and subgroups of parent groups. Each subgroup
belongs to a unique parent group. We say that this parent group is the parent of the
subgroup. We also say that a parent group is its own parent.
Parent groups are constructed by Group and subgroups are constructed by Subgroup. The
first argument of Subgroup must be a parent group, i.e., it must not be a subgroup of a
parent group, and this parent group will be the parent of the constructed subgroup.
Those group functions that take more than one argument require that the arguments have a
common parent. Take for instance CommutatorSubgroup. It takes two arguments, a group
G and a group H , and returns the commutator subgroup of H with G. So either G is a
parent group, and H is a subgroup of this parent group, or G and H are subgroups of a
common parent group P .
gap> s4 := Group( (1,2), (1,2,3,4) );
Group( (1,2), (1,2,3,4) )
gap> c3 := Subgroup( s4, [ (1,2,3) ] );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2,3) ] )
gap> CommutatorSubgroup( s4, c3 );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,3,2), (1,2,4) ] )
# ok, c3 is a subgroup of the parent group s4
gap> a4 := Subgroup( s4, [ (1,2,3), (2,3,4) ] );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2,3), (2,3,4) ] )
gap> CommutatorSubgroup( a4, c3 );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,4)(2,3), (1,3)(2,4) ] )
# also ok, c3 and a4 are subgroups of the parent group s4
gap> x3 := Group( (1,2,3) );
Group( (1,2,3) )
gap> CommutatorSubgroup( s4, x3 );
Error, and must have the same parent group
# not ok, s4 is its own parent and x3 is its own parent
Those functions that return new subgroups, as with CommutatorSubgroup above, return
this subgroup as a subgroup of the common parent of their arguments. Note especially that
the commutator subgroup of c3 with a4 is returned as a subgroup of their common parent
group s4, not as a subgroup of a4. It can not be a subgroup of a4, because subgroups must
7.7. ISPARENT
271
be subgroups of parent groups, and a4 is not a parent group. Of course, mathematically
the commutator subgroup is a subgroup of a4.
Note that a subgroup of a parent group need not be a proper subgroup, as can be seen in
the following example.
gap> s4 := Group( (1,2), (1,2,3,4) );
Group( (1,2), (1,2,3,4) )
gap> x4 := Subgroup( s4, [ (1,2,3,4), (3,4) ] );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2,3,4), (3,4) ] )
gap> Index( s4, x4 );
1
One exception to the rule are functions that construct new groups such as DirectProduct.
They accept groups with different parents. If you want rename the function DirectProduct
to OuterDirectProduct.
Another exception is Intersection (see 4.12), which allows groups with different parent
groups, it computes the intersection in such cases as if the groups were sets of elements.
This is because Intersection is not a group function, but a domain function, i.e., it accepts
two (or more) arbitrary domains as arguments.
Whenever you have two subgroups which have different parent groups but have a common
supergroup G you can use AsSubgroup (see 7.13) in order to construct new subgroups which
have a common parent group G.
gap> s4 := Group( (1,2), (1,2,3,4) );
Group( (1,2), (1,2,3,4) )
gap> x3 := Group( (1,2,3) );
Group( (1,2,3) )
gap> CommutatorSubgroup( s4, x3 );
Error, and must have the same parent group
# not ok, s4 is its own parent and x3 is its own parent
gap> c3 := AsSubgroup( s4, x3 );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2,3) ] )
gap> CommutatorSubgroup( s4, c3 );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,3,2), (1,2,4) ] )
The following sections describe the functions related to this concept (see 7.7, 7.8, 7.9, 7.10,
7.11, 7.12, 7.13).
7.7
IsParent
IsParent( G )
IsParent returns true if G is a parent group, and false otherwise (see 7.6).
7.8
Parent
Parent( U1 , ..., Un )
Parent returns the common parent group of its subgroups and parent group arguments.
In case more than one argument is given, all groups must have the same parent group. Otherwise an error is signaled. This can be used to ensure that a collection of given subgroups
have a common parent group.
272
7.9
CHAPTER 7. GROUPS
Group
Group( U )
Let U be a parent group or a subgroup. Group returns a new parent group G which is
isomorphic to U . The generators of G need not be the same elements as the generators of
U . The default group function uses the same generators, while the ag group function may
create new generators along with a new collector.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> s3 := Subgroup( s4, [ (1,2,3), (1,2) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2,3), (1,2) ] )
gap> Group( s3 ); # same elements
Group( (1,2,3), (1,2) )
gap> s4.1 * s3.1;
(1,3,4,2)
gap> s4 := AgGroup( s4 );
Group( g1, g2, g3, g4 )
gap> a4 := DerivedSubgroup( s4 );
Subgroup( Group( g1, g2, g3, g4 ), [ g2, g3, g4 ] )
gap> a4 := Group( a4 ); # different elements
Group( g1, g2, g3 )
gap> s4.1 * a4.1;
Error, AgWord op: agwords have different groups
Group( list, id )
Group returns a new parent group G generated by group elements g1 , ..., gn of list. id must
be the identity of this group.
Group( g1 , ..., gn )
Group returns a new parent group G generated by group elements g1 , ..., gn .
The generators of this new parent group need not be the same elements as g1 , ..., gn . The
default group function however returns a group record with generators g1 , ..., gn and identity
id , while the ag group function may create new generators along with a new collector.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> z4 := Group( s4.1 ); # same element
Group( (1,2,3,4) )
gap> s4.1 * z4.1;
(1,3)(2,4)
gap> s4 := AgGroup( s4 );
Group( g1, g2, g3, g4 )
gap> z4 := Group( s4.1 * s4.3 ); # different elements
Group( g1, g2 )
gap> s4.1 * z4.1;
Error, AgWord op: agwords have different groups
Let gi1 , ..., gim be the set of nontrivial generators in all four cases. Groups sets record
components G.1, ..., G.m to these generators.
7.10. ASGROUP
7.10
273
AsGroup
AsGroup( D )
Let D be a domain. AsGroup returns a group G such that the set of elements of D is the
same as the set of elements of G if this is possible.
If D is a list of group elements these elements must form a group. Otherwise an error is
signaled.
Note that this function returns a parent group or a subgroup of a parent group depending
on D. In order to convert a subgroup into a parent group you must use Group (see 7.9).
gap> s4 := AgGroup( Group( (1,2,3,4), (2,3) ) );
Group( g1, g2, g3, g4 )
gap> Elements( last );
[ IdAgWord, g4, g3, g3*g4, g2, g2*g4, g2*g3, g2*g3*g4, g2^2, g2^2*g4,
g2^2*g3, g2^2*g3*g4, g1, g1*g4, g1*g3, g1*g3*g4, g1*g2, g1*g2*g4,
g1*g2*g3, g1*g2*g3*g4, g1*g2^2, g1*g2^2*g4, g1*g2^2*g3,
g1*g2^2*g3*g4 ]
gap> AsGroup( last );
Group( g1, g2, g3, g4 )
The default function GroupOps.AsGroup for a group D returns a copy of D. If D is a
subgroup then a subgroup is returned. The default function GroupElementsOps.AsGroup
expects a list D of group elements forming a group and uses successively Closure in order
to compute a reduced generating set.
7.11
IsGroup
IsGroup( obj )
IsGroup returns true if obj , which can be an object of arbitrary type, is a parent group
or a subgroup and false otherwise. The function will signal an error if obj is an unbound
variable.
gap> IsGroup( Group( (1,2,3) ) );
true
gap> IsGroup( 1/2 );
false
7.12
Subgroup
Subgroup( G, L )
Let G be a parent group and L be a list of elements g1 , ..., gn of G. Subgroup returns the
subgroup U generated by g1 , ..., gn with parent group G.
Note that this function is the only group function in which the name Subgroup does not refer
to the mathematical terms subgroup and supergroup but to the implementation of groups
as subgroups and parent groups. IsSubgroup (see 7.62) is not the negation of IsParent
(see 7.7) but decides subgroup and supergroup relations.
Subgroup always binds a copy of L to U .generators, so it is safe to modify L after calling
Subgroup because this will not change the entries in U .
274
CHAPTER 7. GROUPS
Let gi1 , ..., gim be the nontrivial generators. Subgroups binds these generators to U .1, ...,
U .m.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> v4 := Subgroup( s4, [ (1,2), (1,2)(3,4) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2), (1,2)(3,4) ] )
gap> IsParent( v4 );
false
7.13
AsSubgroup
AsSubgroup( G, U )
Let G be a parent group and U be a parent group or a subgroup with a possibly different
parent group, such that the generators g1 , ..., gn of U are elements of G. AsSubgroup returns
a new subgroup S such that S has parent group G and is generated by g1 , ..., gn .
gap> d8 := Group( (1,2,3,4), (1,2)(3,4) );
Group( (1,2,3,4), (1,2)(3,4) )
gap> z := Centre( d8 );
Subgroup( Group( (1,2,3,4), (1,2)(3,4) ), [ (1,3)(2,4) ] )
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> Normalizer( s4, AsSubgroup( s4, z ) );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (2,4), (1,2,3,4), (1,3)(2,4)
] )
7.14
Subgroups
The following sections describe functions that compute certain subgroups of a given group,
e.g., SylowSubgroup computes a Sylow subgroup of a group (see 7.16, 7.17, 7.18, 7.19, 7.20,
7.21, 7.22, 7.23, 7.24, 7.25, 7.26, 7.27, 7.28, 7.29, 7.30, 7.31, 7.32).
They return group records as described in 7.118 for the computed subgroups. Some functions
may not terminate if the given group has an infinite set of elements, while other functions
may signal an error in such cases.
Here the term “subgroup” is used in a mathematical sense. But in GAP3, every group is
either a parent group or a subgroup of a unique parent group. If you compute a Sylow
subgroup S of a group U with parent group G then S is a subgroup of U but its parent
group is G (see 7.6).
Further sections describe functions that return factor groups of a given group (see 7.33 and
7.35).
7.15
Agemo
Agemo( G, p )
G must be a p-group. Agemo returns the subgroup of G generated by the p.th powers of
the elements of G.
7.16. CENTRALIZER
275
gap> d8 := Group( (1,3)(2,4), (1,2) );
Group( (1,3)(2,4), (1,2) )
gap> Agemo( d8, 2 );
Subgroup( Group( (1,3)(2,4), (1,2) ), [ (1,2)(3,4) ] )
The default function GroupOps.Agemo computes the subgroup of G generated by the p.th
powers of the generators of G if G is abelian. Otherwise the function computes the normal
closure of the p.th powers of the representatives of the conjugacy classes of G.
7.16
Centralizer
Centralizer( G, x )
Centralizer returns the centralizer of an element x in G where x must be an element of
the parent group of G.
The centralizer of an element x in G is defined as the set C of elements c of G such that
c and x commute.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> v4 := Centralizer( s4, (1,2) );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (3,4), (1,2) ] )
The default function GroupOps.Centralizer uses Stabilizer (see 8.24) in order to compute the centralizer of x in G acting by conjugation.
Centralizer( G, U )
Centralizer returns the centralizer of a group U in G as group record. Note that G and
U must have a common parent group.
The centralizer of a group U in G is defined as the set C of elements c of C such c
commutes with every element of U .
If G is the parent group of U then Centralizer will set and test the record component
U .centralizer.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> v4 := Centralizer( s4, (1,2) );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (3,4), (1,2) ] )
gap> c2 := Subgroup( s4, [ (1,3) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,3) ] )
gap> Centralizer( v4, c2 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ ] )
The default function GroupOps.Centralizer uses Stabilizer in order to compute successively the stabilizer of the generators of U .
7.17
Centre
Centre( G )
Centre returns the centre of G.
The centre of a group G is defined as the centralizer of G in G.
276
CHAPTER 7. GROUPS
Note that Centre sets and tests the record component G.centre.
gap> d8 := Group( (1,2,3,4), (1,2)(3,4) );
Group( (1,2,3,4), (1,2)(3,4) )
gap> Centre( d8 );
Subgroup( Group( (1,2,3,4), (1,2)(3,4) ), [ (1,3)(2,4) ] )
The default group function GroupOps.Centre uses Centralizer (see 7.16) in order to compute the centralizer of G in G.
7.18
Closure
Closure( U , g )
Let U be a group with parent group G and let g be an element of G. Then Closure returns
the closure C of U and g as subgroup of G. The closure C of U and g is the subgroup
generated by U and g.
gap> s4 := Group( (1,2,3,4), (1,2 ) );
Group( (1,2,3,4), (1,2) )
gap> s2 := Subgroup( s4, [ (1,2) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2) ] )
gap> Closure( s2, (3,4) );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2), (3,4) ] )
The default function GroupOps.Closure returns U if U is a parent group, or if g or its
inverse is a generator of U , or if the set of elements is known and g is in this set, or if g
is trivial. Otherwise the function constructs a new subgroup C which is generated by the
generators of U and the element g.
Note that if the set of elements of U is bound to U .elements then GroupOps.Closure
computes the set of elements for C and binds it to C.elements.
If U is known to be non-abelian or infinite so is C. If U is known to be abelian the function
checks whether g commutes with every generator of U .
Closure( U , S )
Let U and S be two group with a common parent group G. Then Closure returns the
subgroup of G generated by U and S .
gap> s4 := Group( (1,2,3,4), (1,2 ) );
Group( (1,2,3,4), (1,2) )
gap> s2 := Subgroup( s4, [ (1,2) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2) ] )
gap> z3 := Subgroup( s4, [ (1,2,3) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2,3) ] )
gap> Closure( z3, s2 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2,3), (1,2) ] )
The default function GroupOps.Closure returns the parent of U and S if U or S is a parent
group. Otherwise the function computes the closure of U under all generators of S .
Note that if the set of elements of U is bound to U .elements then GroupOps.Closure
computes the set of elements for the closure C and binds it to C.elements.
7.19. COMMUTATORSUBGROUP
7.19
277
CommutatorSubgroup
CommutatorSubgroup( G, H )
Let G and H be groups with a common parent group. CommutatorSubgroup returns the
commutator subgroup [G, H].
The commutator subgroup of G and H is the group generated by all commutators [g, h]
with g ∈ G and h ∈ H .
See also DerivedSubgroup (7.22).
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> d8 := Group( (1,2,3,4), (1,2)(3,4) );
Group( (1,2,3,4), (1,2)(3,4) )
gap> CommutatorSubgroup( s4, AsSubgroup( s4, d8 ) );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,3)(2,4), (1,3,2) ] )
Let G be generated by g1 , ..., gn and H be generated by h1 , ..., hm . The normal closure
of the subgroup S generated by Comm(gi , hj ) for 1 ≤ i ≤ n and 1 ≤ j ≤ m under
G and H is the commutator subgroup of G and H (see [Hup67]). The default function
GroupOps.CommutatorSubgroup returns the normal closure of S under the closure of G and
H.
7.20
ConjugateSubgroup
ConjugateSubgroup( U , g )
ConjugateSubgroup returns the subgroup U g conjugate to U under g, which must be an
element of the parent group of G.
If present, the flags U .isAbelian, U .isCyclic, U .isElementaryAbelian, U .isFinite,
U .isNilpotent, U .isPerfect, U .isSimple, U .isSolvable, and U .size are copied to
U g.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> c2 := Subgroup( s4, [ (1,2)(3,4) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2)(3,4) ] )
gap> ConjugateSubgroup( c2, (1,3) );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,4)(2,3) ] )
The default function GroupOps.ConjugateSubgroup returns U if the set of elements of U
is known and g is an element of this set or if g is a generator of U . Otherwise it conjugates
the generators of U with g.
If the set of elements of U is known the default function also conjugates and binds it to the
conjugate subgroup.
7.21
Core
Core( S , U )
278
CHAPTER 7. GROUPS
Let S and U be groups with a common parent group G. Then Core returns the core of U
under conjugation of S .
T
The core of a group U under a group S CoreS (U ) is the intersection s∈S U s of all groups
conjugate to U under conjugation by elements of S .
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> s4.name := "s4";;
gap> d8 := Subgroup( s4, [ (1,2,3,4), (1,2)(3,4) ] );
Subgroup( s4, [ (1,2,3,4), (1,2)(3,4) ] )
gap> Core( s4, d8 );
Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4) ] )
gap> Core( d8, s4 );
s4
The default function GroupOps.Core starts with U and replaces U with the intersection of
U and a conjugate subgroup of U under a generator of G until the subgroup is normalized
by G.
7.22
DerivedSubgroup
DerivedSubgroup( G )
DerivedSubgroup returns the derived subgroup G 0 = [G, G] of G.
The derived subgroup of G is the group generated by all commutators [g, h] with g, h ∈ G.
Note that DerivedSubgroup sets and tests G.derivedSubgroup. CommutatorSubgroup
(see 7.19) allows you to compute the commutator group of two subgroups.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> DerivedSubgroup( s4 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,3,2), (2,4,3) ] )
Let G be generated by g1 , ..., gn . Then the default function GroupOps.DerivedSubgroup
returns the normal closure of S under G where S is the subgroup of G generated by
Comm(gi , gj ) for 1 ≤ j < i ≤ n.
7.23
FittingSubgroup
FittingSubgroup( G )
FittingSubgroup returns the Fitting subgroup of G.
The Fitting subgroup of a group G is the biggest nilpotent normal subgroup of G.
gap> s4;
Group( (1,2,3,4), (1,2) )
gap> FittingSubgroup( s4 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,3)(2,4), (1,4)(2,3) ] )
gap> IsNilpotent( last );
true
Let G be a finite group. Then the default group function GroupOps.FittingSubgroup
computes the subgroup of G generated by the cores of the Sylow subgroups in G.
7.24. FRATTINISUBGROUP
7.24
279
FrattiniSubgroup
FrattiniSubgroup( G )
FrattiniSubgroup returns the Frattini subgroup of group G.
The Frattini subgroup of a group G is the intersection of all maximal subgroups of G.
gap> s4 := SymmetricGroup( AgWords, 4 );;
gap> ss4 := SpecialAgGroup( s4 );;
gap> FrattiniSubgroup( ss4 );
Subgroup( Group( g1, g2, g3, g4 ), [ ] )
The generic method computes the Frattini subgroup as intersection of the cores (see 7.21)
of the representatives of the conjugacy classes of maximal subgroups (see 7.80).
7.25
NormalClosure
NormalClosure( S , U )
Let S and U be groups with a common parent group G. Then NormalClosure returns the
normal closure of U under S as a subgroup of G.
The normal closure N of a group U under the action of a group S is the smallest subgroup
in G that contains U and is invariant under conjugation by elements of S . Note that N is
independent of G.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> s4.name := "s4";;
gap> d8 := Subgroup( s4, [ (1,2,3,4), (1,2)(3,4) ] );
Subgroup( s4, [ (1,2,3,4), (1,2)(3,4) ] )
gap> NormalClosure( s4, d8 );
Subgroup( s4, [ (1,2,3,4), (1,2)(3,4), (1,3,4,2) ] )
gap> last = s4;
true
7.26
NormalIntersection
NormalIntersection( N , U )
Let N and U be two subgroups with a common parent group. NormalIntersection returns
the intersection in case U normalizes N .
Depending on the domain this may be faster than the general intersection algorithm (see
4.12). The default function GroupOps.NormalIntersection however uses Intersection.
7.27
Normalizer
Normalizer( S , U )
Let S and U be groups with a common parent group G. Then Normalizer returns the
normalizer of U in S .
280
CHAPTER 7. GROUPS
The normalizer NS (U ) of U in S is the biggest subgroup of S which leaves U invariant
under conjugation.
If S is the parent group of U then Normalizer sets and tests U .normalizer.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> c2 := Subgroup( s4, [ (1,2) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2) ] )
gap> Normalizer( s4, c2 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (3,4), (1,2) ] )
The default function GroupOps.Normalizer uses Stabilizer (see 8.24) in order to compute
the stabilizer of U in S acting by conjugation (see 7.20).
7.28
PCore
PCore( G, p )
PCore returns the p-core of the finite group G for a prime p.
The p-core is the largest normal subgroup whose size is a power of p. This is the core of
the Sylow-p-subgroups (see 7.21 and 7.31).
Note that PCore sets and tests G.pCores[ p ].
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> PCore( s4, 2 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,4)(2,3), (1,3)(2,4) ] )
gap> PCore( s4, 3 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ ] )
The default function GroupOps.PCore computes the p-core as the core of a Sylow-p-subgroup
(see 7.21 and 7.31).
7.29
PrefrattiniSubgroup
PrefrattiniSubgroup( G )
PrefrattiniSubgroup returns a Prefrattini subgroup of the group G.
A factor M/N of G is called a Frattini factor if M/N ≤ φ(G/N ) holds. The group P is a
Prefrattini subgroup of G if P covers each Frattini chief factor of G, and if for each maximal
subgroup of G there exists a conjugate maximal subgroup, which contains P .
gap> s4 := SymmetricGroup( AgWords, 4 );;
gap> ss4 := SpecialAgGroup( s4 );;
gap> PrefrattiniSubgroup( ss4 );
Subgroup( Group( g1, g2, g3, g4 ), [ ] )
Currently PrefrattiniSubgroup can only be applied to special Ag groups (see 26).
7.30. RADICAL
7.30
281
Radical
Radical( G )
Radical returns the radical of the finite group G.
The radical is the largest normal solvable subgroup of G.
gap> g := Group( (1,5), (1,5,6,7,8)(2,3,4) );
Group( (1,5), (1,5,6,7,8)(2,3,4) )
gap> Radical( g );
Subgroup( Group( (1,5), (1,5,6,7,8)(2,3,4) ), [ ( 2, 3, 4) ] )
The default function GroupOps.Radical tests if G is solvable and signals an error if not.
7.31
SylowSubgroup
SylowSubgroup( G, p )
SylowSubgroup returns a Sylow-p-subgroup of the finite group G for a prime p.
Let p be a prime and G be a finite group of order p n m where m is relative prime to p. Then
by Sylow’s theorem there exists at least one subgroup S of G of order p n .
Note that SylowSubgroup sets and tests G.sylowSubgroups[ p ].
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> SylowSubgroup( s4, 2 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (3,4), (1,2), (1,3)(2,4) ] )
gap> SylowSubgroup( s4, 3 );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (2,3,4) ] )
The default function GroupOps.SylowSubgroup computes the set of elements of p power
order of G, starts with such an element of maximal order and computes the closure (see
7.18) with normalizing elements of p power order until a Sylow group is found.
7.32
TrivialSubgroup
TrivialSubgroup( U )
Let U be a group with parent group G. Then TrivialSubgroup returns the trivial subgroup
T of U . Note that the parent group of T is G not U (see 7.14).
The default function GroupOps.TrivialSubgroup binds the set of elements of U , namely
[U .identity], to T .elements,
7.33
FactorGroup
FactorGroup( G, N )
FactorGroup returns the factor group G/N where N must be a normal subgroup of G (see
7.58). This is the same as G / N (see 7.117).
NaturalHomomorphism returns the natural homomorphism from G (or a subgroup thereof)
onto the factor group (see 7.110).
282
CHAPTER 7. GROUPS
It is not specified how the factor group N is represented.
gap> a4 := Group( (1,2,3), (2,3,4) );; a4.name := "a4";
"a4"
gap> v4 := Subgroup(a4,[(1,2)(3,4),(1,3)(2,4)]);; v4.name := "v4";
"v4"
gap> f := FactorGroup( a4, v4 );
(a4 / v4)
gap> Size( f );
3
gap> Elements( f );
[ FactorGroupElement( v4, () ), FactorGroupElement( v4, (2,3,4) ),
FactorGroupElement( v4, (2,4,3) ) ]
If G is the parent group of N , FactorGroup first checks for the knowledge component
N .factorGroup. If this component is bound, FactorGroup returns its value. Otherwise,
FactorGroup calls G.operations.FactorGroup( G, N ), remembers the returned value
in N .factorGroup, and returns it. If G is not the parent group of N , FactorGroup calls
G.operations.FactorGroup( G, N ) and returns this value.
The default function called this way is GroupOps.FactorGroup. It returns the factor group
as a group of factor group elements (see 7.34). Look under FactorGroup in the index to
see for which groups this function is overlaid.
7.34
FactorGroupElement
FactorGroupElement( N , g )
FactorGroupElement returns the coset N * g as a group element. It is not tested whether
g normalizes N , but g must be an element of the parent group of N .
Factor group elements returned by FactorGroupElement are represented by records. Those
records contain the following components.
isGroupElement
contains true.
isFactorGroupElement
contains true.
element
contains a right coset of N (see 7.86).
domain
contains FactorGroupElements (see 4.5).
operations
contains the operations record FactorGroupElementOps.
All operations for group elements (see 7.3) are available for factor group elements, e.g., two
factor group elements can be multiplied (provided that they have the same subgroup N ).
gap> a4 := Group( (1,2,3), (2,3,4) );; a4.name := "a4";;
gap> v4 := Subgroup(a4,[(1,2)(3,4),(1,3)(2,4)]);; v4.name := "v4";;
gap> x := FactorGroupElement( v4, (1,2,3) );
FactorGroupElement( v4, (2,4,3) )
7.35. COMMUTATORFACTORGROUP
283
gap> y := FactorGroupElement( v4, (2,3,4) );
FactorGroupElement( v4, (2,3,4) )
gap> x * y;
FactorGroupElement( v4, () )
7.35
CommutatorFactorGroup
CommutatorFactorGroup( G )
CommutatorFactorGroup returns a group isomorphic to G/G 0 where G 0 is the derived subgroup of G (see 7.22).
gap> s4 := AgGroup( Group( (1,2,3,4), (1,2) ) );
Group( g1, g2, g3, g4 )
gap> CommutatorFactorGroup( s4 );
Group( g1 )
The default group function GroupOps.CommutatorFactorGroup uses DerivedSubgroup (see
7.22) and FactorGroup (see 7.33) in order to compute the commutator factor group.
7.36
Series of Subgroups
The following sections describe functions that compute and return series of subgroups of a
given group (see 7.37, 7.41, 7.43, and 7.44). The series are returned as lists of subgroups of
the group (see 7.6).
These functions print warnings if the argument is an infinite group, because they may run
forever.
7.37
DerivedSeries
DerivedSeries( G )
DerivedSeries returns the derived series of G.
The derived series is the series of iterated derived subgroups. The group G is solvable if
and only if this series reaches {1} after finitely many steps.
Note that this function does not terminate if G is an infinite group with derived series of
infinite length.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> DerivedSeries( s4 );
[ Group( (1,2,3,4), (1,2) ), Subgroup( Group( (1,2,3,4), (1,2) ),
[ (1,3,2), (1,4,3) ] ), Subgroup( Group( (1,2,3,4), (1,2) ),
[ (1,4)(2,3), (1,3)(2,4) ] ),
Subgroup( Group( (1,2,3,4), (1,2) ), [ ] ) ]
The default function GroupOps.DerivedSeries uses DerivedSubgroup (see 7.22) in order
to compute the derived series of G.
284
CHAPTER 7. GROUPS
7.38
CompositionSeries
CompositionSeries( G )
CompositionSeries returns a composition series of G as list of subgroups.
gap> s4 := SymmetricGroup( 4 );
Group( (1,4), (2,4), (3,4) )
gap> s4.name := "s4";;
gap> CompositionSeries( s4 );
[ Subgroup( s4, [ (1,2), (1,3,2), (1,3)(2,4), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,3,2), (1,3)(2,4), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,3)(2,4), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,2)(3,4) ] ), Subgroup( s4, [ ] ) ]
gap> d8 := SylowSubgroup( s4, 2 );
Subgroup( s4, [ (1,2), (3,4), (1,3)(2,4) ] )
gap> CompositionSeries( d8 );
[ Subgroup( s4, [ (1,3)(2,4), (1,2), (3,4) ] ),
Subgroup( s4, [ (1,2), (3,4) ] ), Subgroup( s4, [ (3,4) ] ),
Subgroup( s4, [ ] ) ]
Note that there is no default function. GroupOps.CompositionSeries signals an error if
called.
7.39
ElementaryAbelianSeries
ElementaryAbelianSeries( G )
Let G be a solvable group (see 7.61). Then the functions returns a normal series G =
E0 , E1 , ..., En = {1} of G such that the factor groups Ei /Ei+1 are elementary abelian
groups.
gap> s5 := SymmetricGroup( 5 );; s5.name := "s5";;
gap> s4 := Subgroup( s5, [ (2,3,4,5), (2,3) ] );
Subgroup( s5, [ (2,3,4,5), (2,3) ] )
gap> ElementaryAbelianSeries( s4 );
[ Subgroup( s5, [ (2,3), (2,4,3), (2,5)(3,4), (2,3)(4,5) ] ),
Subgroup( s5, [ (2,4,3), (2,5)(3,4), (2,3)(4,5) ] ),
Subgroup( s5, [ (2,5)(3,4), (2,3)(4,5) ] ), Subgroup( s5, [
] ) ]
The default function GroupOps.ElementaryAbelianSeries uses AgGroup (see 25.25) in
order to convert G into an isomorphic ag group and computes the elementary abelian series
in this group. (see 25.9).
7.40
JenningsSeries
JenningsSeries( G, p )
JenningsSeries returns the Jennings series of a p-group G.
The Jennings series of a p-group G is defined as follows. S1 = G and Sn = [Sn−1 , G]Si p
where i is the smallest integer equal or greater than n/p. The length l of S is the smallest
integer such that Sl = {1}.
7.41. LOWERCENTRALSERIES
285
Note that Sn = Sn+1 is possible.
gap> G := CyclicGroup( AgWords, 27 );
Group( c27_1, c27_2, c27_3 )
gap> G.name := "G";;
gap> JenningsSeries( G );
[ G, Subgroup( G, [ c27_2, c27_3 ] ),
Subgroup( G, [ c27_3 ] ), Subgroup(
Subgroup( G, [ c27_3 ] ), Subgroup(
Subgroup( G, [ c27_3 ] ), Subgroup(
Subgroup( G, [ ] ) ]
7.41
Subgroup( G,
G, [ c27_3 ]
G, [ c27_3 ]
G, [ c27_3 ]
[ c27_2, c27_3 ] ),
),
),
),
LowerCentralSeries
LowerCentralSeries( G )
LowerCentralSeries returns the lower central series of G as a list of group records.
The lower central series is the series defined by S1 = G and Si = [G, Si−1 ]. The group
G is nilpotent if this series reaches {1} after finitely many steps.
Note that this function may not terminate if G is an infinite group. LowerCentralSeries
sets and tests the record component G.lowerCentralSeries in the group record of G.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> LowerCentralSeries( s4 );
[ Group( (1,2,3,4), (1,2) ), Subgroup( Group( (1,2,3,4), (1,2) ),
[ (1,3,2), (2,4,3) ] ) ]
The default group function GroupOps.LowerCentralSeries uses CommutatorSubgroup (see
7.19) in order to compute the lower central series of G.
7.42
PCentralSeries
PCentralSeries( G, p )
PCentralSeries returns the p-central series of a group G for a prime p.
The p-central series of a group G is defined as follows. S1 = G and Si+1 is set to
[G, Si ] ∗ Sip . The length of this series is n, where n = max{i; Si > Si+1 }.
gap> s4 := Group( (1,2,3,4), (1,2) );; s4.name := "s4";;
gap> PCentralSeries( s4, 3 );
[ s4 ]
gap> PCentralSeries( s4, 2 );
[ s4, Subgroup( s4, [ (1,2,3), (1,3,4) ] ) ]
7.43
SubnormalSeries
SubnormalSeries( G, U )
Let U be a subgroup of G, then SubnormalSeries returns a subnormal series G = G1 >
... > Gn of groups such that U is contained in Gn and there exists no proper subgroup V
between Gn and U which is normal in Gn .
286
CHAPTER 7. GROUPS
Gn is equal to U if and only if U is subnormal in G.
Note that this function may not terminate if G is an infinite group.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> c2 := Subgroup( s4, [ (1,2) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2) ] )
gap> SubnormalSeries( s4, c2 );
[ Group( (1,2,3,4), (1,2) ) ]
gap> IsSubnormal( s4, c2 );
false
gap> c2 := Subgroup( s4, [ (1,2)(3,4) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2)(3,4) ] )
gap> SubnormalSeries( s4, c2 );
[ Group( (1,2,3,4), (1,2) ), Subgroup( Group( (1,2,3,4), (1,2) ),
[ (1,2)(3,4), (1,3)(2,4) ] ),
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2)(3,4) ] ) ]
gap> IsSubnormal( s4, c2 );
true
The default function GroupOps.SubnormalSeries constructs the subnormal series as follows. G1 = G and Gi+1 is set to the normal closure (see 7.25) of U under Gi . The length
of the series is n, where n = max{i; Gi > Gi+1 }.
7.44
UpperCentralSeries
UpperCentralSeries( G )
UpperCentralSeries returns the upper central series of G as a list of subgroups.
The upper central series is the series Sn , ..., S0 defined by S0 = {1} < G and Si /Si−1 =
Z(G/Si−1 ) where n = min{i; Si = Si+1 }
Note that this function may not terminate if G is an infinite group. UpperCentralSeries
sets and tests G.upperCentralSeries in the group record of G.
gap> d8 := AgGroup( Group( (1,2,3,4), (1,2)(3,4) ) );
Group( g1, g2, g3 )
gap> UpperCentralSeries( d8 );
[ Group( g1, g2, g3 ), Subgroup( Group( g1, g2, g3 ), [ g3 ] ),
Subgroup( Group( g1, g2, g3 ), [ ] ) ]
7.45
Properties and Property Tests
The following sections describe the functions that computes or test properties of groups (see
7.46, 7.47, 7.48, 7.49, 7.50, 7.51, 7.52, 7.53, 7.54, 7.55, 7.56, 7.57, 7.58, 7.59, 7.60, 7.61, 7.62,
7.63, 7.64, 7.65, 7.66).
All tests expect a parent group or subgroup and return true if the group has the property
and false otherwise. Some functions may not terminate if the given group has an infinite
set of elements. A warning may be printed in such cases.
7.46. ABELIANINVARIANTS
287
In addition the set theoretic functions Elements, Size and IsFinite, which are described
in chapter 4, can be used for groups. Size (see 4.10) returns the order of a group, this is
either a positive integer or the string “infinity”. IsFinite (see 4.9) returns true if a group
is finite and false otherwise.
7.46
AbelianInvariants
AbelianInvariants( G )
Let G be an abelian group. Then AbelianInvariants returns the abelian invariants of G
as a list of integers. If G is not abelian then the abelian invariants of the commutator factor
group of G are returned.
Let G be a finitely generated abelian group. Then there exist n nontrivial subgroups Ai of
prime power order pei i and m infinite cyclic subgroups Zj such that G = A1 × ... × An ×
Z1 ... × Zm . The invariants of G are the integers pe11 , ..., penn together with m zeros.
Note that AbelianInvariants tests and sets G.abelianInvariants.
gap> AbelianInvariants( AbelianGroup( AgWords, [2,3,4,5,6,9] ) );
[ 2, 2, 3, 3, 4, 5, 9 ]
The default function GroupOps.AbelianInvariants requires that G is finite.
Let G be a finite abelian group of order pe11 ...penn where pi are distinct primes. The default
2
function constructs for every prime pi the series G, G pi , G pi , ... and computes the abelian
invariants using the indices of these groups.
7.47
DimensionsLoewyFactors
DimensionsLoewyFactors( G )
Let G be p-group. Then DimensionsLoewyFactors returns the dimensions ci of the Loewy
factors of Fp G.
The Loewy series of Fp G is defined as follows. Let R be the Jacobson radical of the
group ring Fp G. The series R0 = Fp G > R1 > ... > Rl+1 = {1} is the Loewy series. The
dimensions ci are the dimensions of Ri /Ri+1 .
gap> f6 := FreeGroup( 6, "f6" );;
gap> g := f6 / [ f6.1^3, f6.2^3, f6.3^3, f6.4^3, f6.5^3, f6.6^3,
>
Comm(f6.3,f6.2)/f6.6^2, Comm(f6.3,f6.1)/(f6.6*f6.5),
>
Comm(f6.2,f6.1)/(f6.5*f6.4^2) ];;
gap> a := AgGroupFpGroup(g);
Group( f6.1, f6.2, f6.3, f6.4, f6.5, f6.6 )
gap> DimensionsLoewyFactors(a);
[ 1, 3, 9, 16, 30, 42, 62, 72, 87, 85, 87, 72, 62, 42, 30, 16, 9, 3,
1 ]
The default function GroupOps.DimensionsLoewyFactors computes the Jennings series of
G and uses Jennings thereom in order to calculate the dimensions of the Loewy factors.
Let G = X1 ≥ X2 ≥ ... ≥ Xl > Xl+1 = {1} be the Jennings series of G (see 7.40) and let di
be the dimensions of Xi /Xi+1 . Then the Jennings polynomial is
l
X
i=0
ci xi =
l
Y
(1 + xk + x2k + ... + x(p−1)k )dk .
k=1
288
CHAPTER 7. GROUPS
7.48
EulerianFunction
EulerianFunction( G, n )
EulerianFunction returns the number of n-tuples (g1 , g2 , . . . gn ) of elements of the group
G that generate the whole group G. The elements of a tuple need not be different.
gap> s4 := SymmetricGroup( AgWords, 4 );;
gap> ss4 := SpecialAgGroup( s4 );;
gap> EulerianFunction( ss4, 1 );
0
gap> EulerianFunction( ss4, 2 );
216
gap> EulerianFunction( ss4, 3 );
10080
Currently EulerianFunction can only be applied to special Ag groups (see 26).
7.49
Exponent
Exponent( G )
Let G be a finite group. Then Exponent returns the exponent of G.
Note that Exponent tests and sets G.exponent.
gap> Exponent( Group( (1,2,3,4), (1,2) ) );
12
The default function GroupOps.Exponent computes all elements of G and their orders.
7.50
Factorization
Factorization( G, g )
Let G be a group with generators g1 , ..., gn and let g be an element of G. Factorization
returns a representation of g as word in the generators of G.
The group record of G must have a component G.abstractGenerators which contains a
list of n abstract words h1 , ..., hn . Otherwise a list of n abstract generators is bound to
m
G.abstractGenerators. The function returns an abstract word h = hei11 ∗ ... ∗ heim
such
e1
em
that gi1 ∗ ... ∗ gim = g.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> Factorization( s4, (1,2,3) );
x1^3*x2*x1*x2
gap> (1,2,3,4)^3 * (1,2) * (1,2,3,4) * (1,2);
(1,2,3)
The default group function GroupOps.Factorization needs a finite group G. It computes
the set of elements of G using a Dimino algorithm, together with a representation of these
elements as words in the generators of G.
7.51. INDEX
7.51
289
Index
Index( G, U )
Let U be a subgroup of G. Then Index returns the index of U in G as an integer.
Note that Index sets and checks U .index if G is the parent group of U .
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> Index( s4, DerivedSubgroup( s4 ) );
2
The default function GroupOps.Index needs a finite group G. It returns the quotient of
Size( G ) and Size( U ).
7.52
IsAbelian
IsAbelian( G )
IsAbelian returns true if the group G is abelian and false otherwise.
A group G is abelian if and only if for every g, h ∈ G the equation g ∗ h = h ∗ g holds.
Note that IsAbelian sets and tests the record component G.isAbelian. If G is abelian it
also sets G.centre.
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> IsAbelian( s4 );
false
gap> IsAbelian( Subgroup( s4, [ (1,2) ] ) );
true
The default group function GroupOps.IsAbelian returns true for a group G generated by
g1 , ..., gn if gi commutes with gj for i > j.
7.53
IsCentral
IsCentral( G, U )
IsCentral returns true if the group G centralizes the group U and false otherwise.
A group G centralizes a group U if and only if for all g ∈ G and for all u ∈ U the equation
g ∗ u = u ∗ g holds. Note that U need not to be a subgroup of G but they must have a
common parent group.
Note that IsCentral sets and tests U .isCentral if G is the parent group of U .
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> d8 := Subgroup( s4, [ (1,2,3,4), (1,2)(3,4) ] );;
gap> c2 := Subgroup( s4, [ (1,3)(2,4) ] );;
gap> IsCentral( s4, c2 );
false
gap> IsCentral( d8, c2 );
true
The default function GroupOps.IsCentral tests whether G centralizes U by testing whether
the generators of G commutes with the generators of U .
290
CHAPTER 7. GROUPS
7.54
IsConjugate
IsConjugate( G, x , y )
Let x and y be elements of the parent group of G. Then IsConjugate returns true if x is
conjugate to y under an element g of G and false otherwise.
gap> s5 := Group( (1,2,3,4,5), (1,2) );
Group( (1,2,3,4,5), (1,2) )
gap> a5 := Subgroup( s5, [ (1,2,3), (2,3,4), (3,4,5) ] );
Subgroup( Group( (1,2,3,4,5), (1,2) ), [ (1,2,3), (2,3,4), (3,4,5) ] )
gap> IsConjugate( a5, (1,2,3,4,5), (1,2,3,4,5)^2 );
false
gap> IsConjugate( s5, (1,2,3,4,5), (1,2,3,4,5)^2 );
true
The default function GroupOps.IsConjugate uses Representative (see 4.15) in order to
check whether x is conjugate to y under G.
7.55
IsCyclic
IsCyclic( G )
IsCyclic returns true if G is cyclic and false otherwise.
A group G is cyclic if and only if there exists an element g ∈ G such that G is generated
by g.
Note that IsCyclic sets and tests the record component G.isCyclic.
gap>
gap>
true
gap>
gap>
true
z6 := Group( (1,2,3), (4,5) );;
IsCyclic( z6 );
z36 := AbelianGroup( AgWords, [ 9, 4 ] );;
IsCyclic( z36 );
The default function GroupOps.IsCyclic returns false if G is not an abelian group. Otherwise it computes the abelian invariants (see 7.46) if G is infinite. If G is finite of order
pe11 ...penn , where pi are distinct primes, then G is cyclic if and only if each G pi has index pi
in G.
7.56
IsElementaryAbelian
IsElementaryAbelian( G )
IsElementaryAbelian returns true if the group G is an elementary abelian p-group for a
prime p and false otherwise.
A p-group G is elementary abelian if and only if for every g, h ∈ G the equations g ∗ h =
h ∗ g and g p = 1 hold.
Note that the IsElementaryAbelian sets and tests G.isElementaryAbelian.
gap> z4 := Group( (1,2,3,4) );;
7.57. ISNILPOTENT
291
gap> IsElementaryAbelian( z4 );
false
gap> v4 := Group( (1,2)(3,4), (1,3)(2,4) );;
gap> IsElementaryAbelian( v4 );
true
The default function GroupOps.IsElementaryAbelian returns true if G is abelian and for
some prime p each generator is of order p.
7.57
IsNilpotent
IsNilpotent( G )
IsNilpotent returns true if the group G is nilpotent and false otherwise.
A group G is nilpotent if and only if the lower central series of G is of finite length and
reaches {1}.
Note that IsNilpotent sets and tests the record component G.isNilpotent.
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> IsNilpotent( s4 );
false
gap> v4 := Group( (1,2)(3,4), (1,3)(2,4) );;
gap> IsNilpotent( v4 );
true
The default group function GroupOps.IsNilpotent computes the lower central series using
LowerCentralSeries (see 7.41) in order to check whether G is nilpotent.
If G has an infinite set of elements a warning is given, as this function does not stop if G
has a lower central series of infinite length.
7.58
IsNormal
IsNormal( G, U )
IsNormal returns true if the group G normalizes the group U and false otherwise.
A group G normalizes a group U if and only if for every g ∈ G and u ∈ U the element ug
is a member of U . Note that U need not be a subgroup of G but they must have a common
parent group.
Note that IsNormal tests and sets U .isNormal if G is the parent group of U .
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> d8 := Subgroup( s4, [ (1,2,3,4), (1,2)(3,4) ] );;
gap> c2 := Subgroup( s4, [ (1,3)(2,4) ] );;
gap> IsNormal( s4, c2 );
false
gap> IsNormal( d8, c2 );
true
Let G be a finite group. Then the default function GroupOps.IsNormal checks whether the
conjugate of each generator of U under each generator of G is an element of U .
If G is an infinite group, then the default function GroupOps.IsNormal checks whether the
conjugate of each generator of U under each generator of G and its inverse is an element of
U.
292
CHAPTER 7. GROUPS
7.59
IsPerfect
IsPerfect( G )
IsPerfect returns true if G is a perfect group and false otherwise.
A group G is perfect if G is equal to its derived subgroup. See 7.22.
Note that IsPerfect sets and tests G.isPerfect.
gap> a4 := Group( (1,2,3), (2,3,4) );
Group( (1,2,3), (2,3,4) )
gap> IsPerfect( a4 );
false
gap> a5 := Group( (1,2,3), (2,3,4), (3,4,5) );
Group( (1,2,3), (2,3,4), (3,4,5) )
gap> IsPerfect( a5 );
true
The default group function GroupOps.IsPerfect checks for a finite group G the index of G 0
(see 7.22) in G. For an infinite group it computes the abelian invariants of the commutator
factor group (see 7.46 and 7.35).
7.60
IsSimple
IsSimple( G )
IsSimple returns true if G is simple and false otherwise.
A group G is simple if and only if G and the trivial subgroup are the only normal subgroups
of G.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> IsSimple( DerivedSubgroup( s4 ) );
false
gap> s5 := Group( (1,2,3,4,5), (1,2) );
Group( (1,2,3,4,5), (1,2) )
gap> IsSimple( DerivedSubgroup( s5 ) );
true
7.61
IsSolvable
IsSolvable( G )
IsSolvable returns true if the group G is solvable and false otherwise.
A group G is solvable if and only if the derived series of G is of finite length and reaches
{1}.
Note that IsSolvable sets and tests G.isSolvable.
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> IsSolvable( s4 );
true
7.62. ISSUBGROUP
293
The default function GroupOps.IsSolvable computes the derived series using the function
DerivedSeries (see 7.37) in order to see whether G is solvable.
If G has an infinite set of elements a warning is given, as this function does not stop if G
has a derived series of infinite length.
7.62
IsSubgroup
IsSubgroup( G, U )
IsSubgroup returns true if U is a subgroup of G and false otherwise.
Note that G and U must have a common parent group. This function returns true if and
only if the set of elements of U is a subset of the set of elements of G, it is not the inverse
of IsParent (see 7.7).
gap> s6 := Group( (1,2,3,4,5,6), (1,2) );;
gap> s4 := Subgroup( s6, [ (1,2,3,4), (1,2) ] );;
gap> z2 := Subgroup( s6, [ (5,6) ] );;
gap> IsSubgroup( s4, z2 );
false
gap> v4 := Subgroup( s6, [ (1,2)(3,4), (1,3)(2,4) ] );;
gap> IsSubgroup( s4, v4 );
true
If the elements of G are known, then the default function GroupOps.IsSubgroup checks
whether the set of generators of U is a subset of the set of elements of G. Otherwise the
function checks whether each generator of U is an element of G using in.
7.63
IsSubnormal
IsSubnormal( G, U )
IsSubnormal returns true if the subgroup U of G is subnormal in G and false otherwise.
A subgroup U of G is subnormal if and only if there exists a series of subgroups G = G0 >
G1 > ... > Gn = U such that Gi is normal in Gi−1 for all i ∈ {1, ..., n}.
Note that U must be a subgroup of G. The function sets and checks U .isSubnormal if G
is the parent group of G.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> c2 := Subgroup( s4, [ (1,2) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2) ] )
gap> IsSubnormal( s4, c2 );
false
gap> c2 := Subgroup( s4, [ (1,2)(3,4) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2)(3,4) ] )
gap> IsSubnormal( s4, c2 );
true
The default function GroupOps.IsSubnormal uses SubnormalSeries (see 7.43) in order to
check if U is subnormal in G.
294
CHAPTER 7. GROUPS
7.64
IsTrivial for Groups
GroupOps.IsTrivial( G )
GroupOps.IsTrivial returns true if G is the trivial group and false otherwise.
Note that G is trivial if and only if the component generators of the group record of G is
the empty list. It is faster to check this than to call IsTrivial.
7.65
GroupId
GroupId( G )
For certain small groups the function returns a record which will identify the isomorphism
type of G with respect to certain classifications. This record contains the components
described below.
The function will work for all groups of order at most 100 or whose order is a product of
at most three primes. Moreover if the ANU pq is installed and loaded (see 57.1 and 57.2)
you can also use GroupId to identify groups of order 128, 256, 243 and 729. In this case a
standard presentation for G is computed (see 58.6) and the returned record will only contain
the components size, pGroupId, and possibly abelianInvariants. For 2- or 3-groups of
order at most 100 GroupId will return the pGroupId identifier even if the ANU pq is not
installed.
catalogue
a pair [o, n] where o is the size of G and n is the catalogue number of G following the
catalogue of groups of order at most 100. See 38.7 for further details. This catalogue
uses the Neubueser list for groups of order at most 100, excluding groups of orders
64 and 96 (see [Neu67]). It uses the lists developed by [HS64] and [Lau82] for orders
64 and 96 respectively.
Note that there are minor discrepancies between n and the number in [Neu67] for
abelian groups and groups of type D(p,q)xr. However, a solvable group G is isomorphic to SolvableGroup(o, n), i.e., GroupId(SolvableGroup(o,n)).catalogue
will be [o,n].
If G is a 2- or 3-group of order at most 100, its number in the appropriate p-group
library is also returned. Note that, for such groups, the number n usually differs from
the p-group identifier returned in pGroupId (see below).
3primes
if G is non-abelian and its size is a product of at most three primes then 3primes
holds an identifier for G. The following isomorphisms are returned in 3primes:
["A",p] = A(p^3), ["B",p] = B(p^3), ["D",p,q,r] = D(p,q)xr,
["D",p,q] = D(p,q), ["G",p,q] = G(p^2,q), ["G",p,q,r,s] = G(p,q,r,s),
["H",p,q] = H(p^2,q), ["H",p,q,r] = H(p,q,r), ["K",p,q] = K(p,q^2),
["L",p,q,s] = L(p,q^2,s), ["M",p,q] = M(p,q^2), ["N",p,q] = N(p,q^2)
(see names below for a definition of A ... N).
pGroupId
if G is a 2- or 3-group, this will be the number of G in the list of 2-groups of order
at most 256, prepared by Newman and O’Brien, or 3-groups of order at most 729,
7.65. GROUPID
295
prepared by O’Brien and Rhodes. In particular, for an integer n and for o a power
of 2 at most 256, GroupId(TwoGroup(o,n)).pGroupId is always n (and similarly for
3-groups). See 38.8 and 38.9 for details about the libraries of 2- and 3-groups. Note
that if G is a 2- or 3-group of order at most 100 its pGroupId usually differs from
its GAP solvable library number returned in catalogue.
abelianInvariants
if G is abelian, this is a list of abelian invariants.
names
a list of names of G. For non-abelian groups of order 96 this name is that used in the
Laue catalogue (see [Lau82]). For the other groups the following symbols are used.
Note that this list of names is neither complete, i.e., most of the groups of order 64
do not have a name even if they are of one of the types described below, nor does it
uniquely determine the group up to isomorphism in some cases.
m is the cyclic group of order m,
Dm is the dihedral group of order m,
Qm is the quaternion group of order m,
QDm is the quasi-dihedral group of order m,
Sm is the symmetric group on m points,
Am is the alternating group on m points,
SL(d,q) is the special linear group,
GL(d,q) is the general linear group,
PSL(d,q) is the projective special linear group,
K^n is the direct power of m copies of K,
K$H is a wreath product of K and H,
K:H is a split extension of K by H,
K.H is a non-split extension of K and H,
K+H is a subdirect product with identified factor groups of K and H,
KYH is a central amalgamated product of the groups K and H,
KxH is the direct product of K and H,
A(p^3) is hA, B, C; Ap = B p = C p = [A, B] = [A, C] = 1, [B, C] = Ai,
B(p^3) is hA, B, C; B p = C p = A, Ap = [A, B] = [A, C] = 1, [B, C] = Ai,
D(p,q) is hA, B; Aq = B p = 1, AB = Ax i such that p|q − 1, x 6= 1 mod q, and xp = 1
mod q,
G(p^2,q) is hA, B, C; Ap = B q = 1, C p = A, [A, B] = [A, C] = 1, B C = B x i such that
p|q − 1, x 6= 1 mod q, and xp = 1 mod q,
s
G(p,q,r,s) is hA, B, C; Ar = B q = C p = [A, B] = 1, AC = Ax , B C = B (y ) i such
p
that p|q − 1, p|r − 1, x minimal with x 6= 1 mod r and x = 1 mod r, y minimal with
y 6= 1 mod q and y p = 1 mod q, and 0 < s < p,
2
H(p^2,q) is hA, B; Aq = B (p ) = 1, AB = Ax i such that p2 |q − 1, xp 6= 1 mod q, and
2
x(p ) = 1 mod q,
H(p,q,r) is hA, B; Ar = B pq = 1, AB = Ax i such that pq|r − 1, xp 6= 1 mod r, xq 6= 1
mod r, and xpq = 1 mod r,
K(p,q^2) is hA, B, C; Aq = B q = C p = [A, B] = 1, AC = Ax , B C = B x i such that
p|q − 1, x 6= 1 mod q, and xp = 1 mod q,
s
L(p,q^2,s) is hA, B, C; Aq = B q = C p = [A, B] = 1, AC = Ax , B C = B (x ) i such
296
CHAPTER 7. GROUPS
that p|q − 1, x 6= 1 mod q, xp = 1 mod q, and 1 < s < p, note that L(q,p^2,s) ∼
=
L(q,p^2,t) iff st = 1 mod p,
2
M(p,q^2) is hA, B; A(q ) = B p = 1, AB = Ax i such that p|q − 1, x 6= 1 mod q 2 , and
xp = 1 mod q 2 ,
q
N(p,q^2) is hA, B, C; Aq = B q = C p = [A, B] = 1, AC = A−1 B, B C = A−1 B x +x−1 i
such that 2 < p, p|q + 1, x is an element of order p mod q 2 ,
^ has the strongest, x the weakest binding.
gap> q8 := SolvableGroup( 8, 5 );;
gap> s4 := SymmetricGroup(4);;
gap> d8 := SylowSubgroup( s4, 2 );;
gap> GroupId(q8);
rec(
catalogue := [ 8, 5 ],
names := [ "Q8" ],
3primes := [ "B", 2 ],
size := 8,
pGroupId := 4 )
gap> GroupId(d8);
rec(
catalogue := [ 8, 4 ],
names := [ "D8" ],
3primes := [ "A", 2 ],
size := 8,
pGroupId := 3 )
gap> GroupId(s4);
rec(
catalogue := [ 24, 15 ],
names := [ "S4" ],
size := 24 )
gap> GroupId(DirectProduct(d8,d8));
rec(
catalogue := [ 64, 154 ],
names := [ "D8xD8" ],
size := 64,
pGroupId := 226 )
gap> GroupId(DirectProduct(q8,d8));
rec(
catalogue := [ 64, 155 ],
names := [ "D8xQ8" ],
size := 64,
pGroupId := 230 )
gap> GroupId( WreathProduct( CyclicGroup(2), CyclicGroup(4) ) );
rec(
catalogue := [ 64, 250 ],
names := [ ],
size := 64,
pGroupId := 32 )
7.66. PERMUTATIONCHARACTER
297
gap> f := FreeGroup("c","b","a");; a:=f.3;;b:=f.2;;c:=f.1;;
gap> r := [ c^5, b^31, a^31, Comm(b,c)/b^7, Comm(a,c)/a, Comm(a,b) ];;
gap> g := AgGroupFpGroup( f / r );
Group( c, b, a )
gap> GroupId(g);
rec(
3primes := [ "L", 5, 31, 2 ],
names := [ "L(5,31^2,2)" ],
size := 4805 )
gap> RequirePackage("anupq");
gap> g := TwoGroup(256,4);
Group( a1, a2, a3, a4, a5, a6, a7, a8 )
gap> GroupId(g);
rec(
size := 256,
pGroupId := 4 )
gap> g := TwoGroup(256,232);
Group( a1, a2, a3, a4, a5, a6, a7, a8 )
gap> GroupId(g);
rec(
size := 256,
pGroupId := 232 )
7.66
PermutationCharacter
PermutationCharacter( G, U )
computes the permutation character of the operation of G on the cosets of U . The permutation character is returned as list of integers such that the i.th position contains the value
of the permutation character on the i.th conjugacy class of G (see 7.68).
The value of the permutation character of U in G on a class c of G is the number of
right cosets invariant under the action of an element of c.
gap> G := SymmetricPermGroup(5);;
gap> PermutationCharacter( G, SylowSubgroup(G,2) );
[ 15, 3, 3, 0, 0, 1, 0 ]
For small groups the default function GroupOps.PermutationCharacter calculates the permutation character by inducing the trivial character of U . For large groups it counts the
fixed points by examining double cosets of U and the subgroup generated by a class element.
7.67
Conjugacy Classes
The following sections describe how one can compute conjugacy classes of elements and
subgroups in a group (see 7.68 and 7.74). Further sections describe how conjugacy classes
of elements are created (see 7.69 and 7.71), and how they are implemented (see 7.72 and
7.73). Further sections describe how classes of subgroups are created (see 7.76 and 7.77),
and how they are implemented (see 7.78 and 7.79). Another section describes the function
that returns a conjugacy class of subgroups as a list of subgroups (see 7.83).
298
CHAPTER 7. GROUPS
7.68
ConjugacyClasses
ConjugacyClasses( G )
ConjugacyClasses returns a list of the conjugacy classes of elements of the group G. The
elements in the list returned are conjugacy class domains as created by ConjugacyClass
(see 7.69). Because conjugacy classes are domains, all set theoretic functions can be applied
to them (see 4).
gap> a5 := Group( (1,2,3), (3,4,5) );; a5.name := "a5";;
gap> ConjugacyClasses( a5 );
[ ConjugacyClass( a5, () ), ConjugacyClass( a5, (3,4,5) ),
ConjugacyClass( a5, (2,3)(4,5) ), ConjugacyClass( a5, (1,2,3,4,5) ),
ConjugacyClass( a5, (1,2,3,5,4) ) ]
ConjugacyClasses first checks if G.conjugacyClasses is bound. If the component is
bound, it returns that value. Otherwise it calls G.operations.ConjugacyClasses( G ),
remembers the returned value in G.conjugacyClasses, and returns it.
The default function called this way is GroupOps.ConjugacyClasses. This function takes
random elements in G and tests whether such a random element g lies in one of the already
known classes. If it does not it adds the new class ConjugacyClass( G, g ) (see 7.69).
Also after adding a new class it tests whether any power of the representative gives rise to
a new class. It returns the list of classes when the sum of the sizes is equal to the size of G.
7.69
ConjugacyClass
ConjugacyClass( G, g )
ConjugacyClass returns the conjugacy class of the element g in the group G. Signals an
error if g is not an element in G. The conjugacy class is returned as a domain, so that all
set theoretic functions are applicable (see 4).
gap> a5 := Group( (1,2,3), (3,4,5) );; a5.name := "a5";;
gap> c := ConjugacyClass( a5, (1,2,3,4,5) );
ConjugacyClass( a5, (1,2,3,4,5) )
gap> Size( c );
12
gap> Representative( c );
(1,2,3,4,5)
gap> Elements( c );
[ (1,2,3,4,5), (1,2,4,5,3), (1,2,5,3,4), (1,3,5,4,2), (1,3,2,5,4),
(1,3,4,2,5), (1,4,3,5,2), (1,4,5,2,3), (1,4,2,3,5), (1,5,4,3,2),
(1,5,2,4,3), (1,5,3,2,4) ]
ConjugacyClass calls G.operations.ConjugacyClass( G, g ) and returns that value.
The default function called this way is GroupOps.ConjugacyClass, which creates a conjugacy class record (see 7.73) with the operations record ConjugacyClassOps (see 7.72). Look
in the index under ConjugacyClass to see for which groups this function is overlaid.
7.70. POSITIONCLASS
7.70
299
PositionClass
PositionClass( G, g )
G must be a domain for which ConjugacyClasses is defined and g must be an element of
G. This functions returns a positive integer i such that g in ConjugacyClasses( G )[i].
gap> G := Group( (1,2)(3,4), (1,2,3,4,5) );;
gap> ConjugacyClasses( G );
[ ConjugacyClass( Group( (1,2)(3,4), (1,2,3,4,5)
ConjugacyClass( Group( (1,2)(3,4), (1,2,3,4,5)
ConjugacyClass( Group( (1,2)(3,4), (1,2,3,4,5)
ConjugacyClass( Group( (1,2)(3,4), (1,2,3,4,5)
ConjugacyClass( Group( (1,2)(3,4), (1,2,3,4,5)
gap> g := Random( G );
(1,2,5,4,3)
gap> PositionClass( G, g );
5
7.71
),
),
),
),
),
() ),
(3,4,5) ),
(2,3)(4,5) ),
(1,2,3,4,5) ),
(1,2,3,5,4) ) ]
IsConjugacyClass
IsConjugacyClass( obj )
IsConjugacyClass returns true if obj is a conjugacy class as created by ConjugacyClass
(see 7.69) and false otherwise.
gap> a5 := Group( (1,2,3), (3,4,5) );; a5.name := "a5";;
gap> c := ConjugacyClass( a5, (1,2,3,4,5) );
ConjugacyClass( a5, (1,2,3,4,5) )
gap> IsConjugacyClass( c );
true
gap> IsConjugacyClass(
>
[ (1,2,3,4,5), (1,2,4,5,3), (1,2,5,3,4), (1,3,5,4,2),
>
(1,3,2,5,4), (1,3,4,2,5), (1,4,3,5,2), (1,4,5,2,3),
>
(1,4,2,3,5), (1,5,4,3,2), (1,5,2,4,3), (1,5,3,2,4) ] );
false
# even though this is as a set equal to c
7.72
Set Functions for Conjugacy Classes
As mentioned above, conjugacy classes are domains, so all domain functions are applicable
to conjugacy classes (see 4). This section describes the functions that are implemented
especially for conjugacy classes. Functions not mentioned here inherit the default functions
mentioned in the respective sections.
In the following let C be the conjugacy class of the element g in the group G.
Elements( C )
The elements of the conjugacy class C are computed as the orbit of g under G, where G
operates by conjugation.
300
CHAPTER 7. GROUPS
Size( C )
The size of the conjugacy class C is computed as the index of the centralizer of g in G.
h in C
To test whether an element h lies in C , in tests whether there is an element of G that takes
h to g. This is done by calling RepresentativeOperation(G,h,g) (see 8.25).
Random( C )
A random element of the conjugacy class C is computed by conjugating g with a random
element of G.
7.73
Conjugacy Class Records
A conjugacy class C of an element g in a group G is represented by a record with the
following components.
isDomain
always true.
isConjugacyClass
always true.
group
holds the group G.
representative
holds the representative g.
The following component is optional. It is computed and assigned when the size of a
conjugacy class is computed.
centralizer
holds the centralizer of g in G.
7.74
ConjugacyClassesSubgroups
ConjugacyClassesSubgroups( G )
ConjugacyClassesSubgroups returns a list of all conjugacy classes of subgroups of the
group G. The elements in the list returned are conjugacy class domains as created by
ConjugacyClassSubgroups (see 7.76). Because conjugacy classes are domains, all set theoretic functions can be applied to them (see 4).
In fact, ConjugacyClassesSubgroups computes much more than it returns, for it calls (indirectly via the function G.operations.ConjugacyClassesSubgroups( G )) the Lattice
command (see 7.75), constructs the whole subgroup lattice of G, stores it in the record
component G.lattice, and finally returns the list G.lattice.classes. This means, in
particular, that it will fail if G is non-solvable and its maximal perfect subgroup is not in
the built-in catalogue of perfect groups (see the description of the Lattice command 7.75
for details).
gap> # Conjugacy classes of subgroups of S4
7.75. LATTICE
301
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> s4.name := "s4";;
gap> cl := ConjugacyClassesSubgroups( s4 );
[ ConjugacyClassSubgroups( s4, Subgroup( s4, [ ] ) ),
ConjugacyClassSubgroups( s4, Subgroup( s4, [ (1,2)(3,4) ] ) ),
ConjugacyClassSubgroups( s4, Subgroup( s4, [ (3,4) ] ) ),
ConjugacyClassSubgroups( s4, Subgroup( s4, [ (2,3,4) ] ) ),
ConjugacyClassSubgroups( s4, Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4)
] ) ), ConjugacyClassSubgroups( s4, Subgroup( s4,
[ (3,4), (1,2) ] ) ), ConjugacyClassSubgroups( s4, Subgroup( s4,
[ (1,2)(3,4), (1,4,2,3) ] ) ),
ConjugacyClassSubgroups( s4, Subgroup( s4, [ (2,3,4), (3,4) ] ) ),
ConjugacyClassSubgroups( s4, Subgroup( s4,
[ (3,4), (1,2), (1,3)(2,4) ] ) ),
ConjugacyClassSubgroups( s4, Subgroup( s4,
[ (1,2)(3,4), (1,3)(2,4), (2,3,4) ] ) ),
ConjugacyClassSubgroups( s4, s4 ) ]
Each entry of the resulting list is a domain. As an example, let us take the seventh class in
the above list of conjugacy classes of S4 .
gap> # Conjugacy classes of subgroups of S4 (continued)
gap> class7 := cl[7];;
gap> # Print the class representative subgroup.
gap> rep7 := Representative( class7 );
Subgroup( s4, [ (1,2)(3,4), (1,4,2,3) ] )
gap> # Print the order of the class representative subgroup.
gap> Size( rep7 );
4
gap> # Print the number of conjugates.
gap> Size( class7 );
3
7.75
Lattice
Lattice( G )
Lattice returns the lattice of subgroups of the group G in the form of a record L, say, which
contains certain lists with some appropriate information on the subgroups of G and their
conjugacy classes. In particular, in its component L.classes, L provides the same list of all
conjugacy classes of all subgroups of G as is returned by the ConjugacyClassesSubgroups
command (see 7.74).
The construction of the subgroup lattice record L of a group G may be very time consuming.
Therefore, as soon as L has been computed for the first time, it will be saved as a component
G.lattice in the group record G to avoid any duplication of that effort.
The underlying routines are a reimplementation of the subgroup lattice routines which have
been developed since 1958 by several people in Kiel and Aachen under the supervision of
Joachim Neubüser. Their final version, written by Volkmar Felsch in 1984, has been available
since then in Cayley (see [BC92]) and has also been used in SOGOS (see [Leh89a]). The
302
CHAPTER 7. GROUPS
current implementation in GAP3 by Jürgen Mnich is described in [Mni92], a summary of
the method and references to all predecessors can be found in [FS84].
The Lattice command invokes the following procedure. In a first step, the solvable residuum P , say, of G is computed and looked up in a built-in catalogue of perfect groups which is
given in the file LIBNAME/"lattperf.g". A list of subgroups is read off from that catalogue
which contains just one representative of each conjugacy class of perfect subgroups of P
and hence at least one representative of each conjugacy class of perfect subgroups of G.
Then, starting from the identity subgroup and the conjugacy classes of perfect subgroups,
the so called cyclic extension method is used to compute the non-perfect subgroups of
G by forming for each class representative all its not yet involved cyclic extensions of prime
number index and adding their conjugacy classes to the list.
It is clear that this procedure cannot work if the catalogue of perfect groups does not contain
a group isomorphic to P . At present, it contains only all perfect groups of order less than
5000 and, in addition, the groups P SL(3, 3), M11 , and A8 . If the Lattice command is
called for a group G with a solvable residuum P not in the catalogue, it will provide an
error message. As an example we handle the group SL(2, 19) of order 6840.
gap> s := [ [4,0], [0,5] ] * Z( 19 )^0;;
gap> t := [ [4,4], [-9,-4] ] * Z(19)^0;;
gap> G := Group( s, t );;
gap> Size( G );
6840
gap> Lattice( G );
Error, sorry, can’ t identify the group’s solvable residuum
However, if you know the perfect subgroups of G, you can use the Lattice command to
compute the whole subgroup lattice of G even if the solvable residuum of G is not in the
catalogue. All you have to do in such a case is to create a list of subgroups of G which
contains at least one representative of each conjugacy class of proper perfect subgroups
of G, attach this list to the group record as a new component G.perfectSubgroups, and
then call the Lattice command. The existence of that record component will prevent GAP3
from looking up the solvable residuum of G in the catalogue. Instead, it will insert the given
subgroups into the lattice, leaving it to you to guarantee that in fact all conjugacy classes
of proper perfect subgroups are involved.
If you miss classes, the resulting lattice will be incomplete, but you will not get any warning.
As long as you are aware of this fact, you may use this possibility to compute a sublattice
of the subgroup lattice of G without getting the above mentioned error message even if the
solvable residuum of G is not in the catalogue. In particular, you will get at least the classes
of all proper solvable subgroups of G if you define G.perfectSubgroups to be an empty
list.
As an example for the computation of the complete lattice of subgroups of a group which
is not covered by the catalogue, we handle the Mathieu group M12 .
gap>
gap>
gap>
gap>
gap>
# Define the Mathieu group M12.
a := (2,3,5,7,11,9,8,12,10,6,4);;
b := (3,6)(5,8)(9,11)(10,12);;
c := (1,2)(3,4)(5,9)(6,8)(7,12)(10,11);;
M12 := Group( a, b, c );;
7.75. LATTICE
303
gap> Print( "#I M12 has order ", Size( M12 ), "\n" );
#I M12 has order 95040
gap> # Define a list of proper perfect subgroups of M_12 and attach
gap> # it to the group record M12 as component M12.perfectSubgroups.
gap> L2_11a := Subgroup( M12, [ a, b ] );;
gap> M11a
:= Subgroup( M12, [ a, b, c*a^-1*b*a*c ] );;
gap> M11b
:= Subgroup( M12, [ a, b, c*a*b*a^-1*c ] );;
gap> x
:= a*b*a^2;;
gap> y
:= a*c*a^-1*b*a*c*a^6;;
gap> A6a
:= Subgroup( M12, [ x, y ] );;
gap> A5c
:= Subgroup( M12, [ x*y, x^3*y^2*x^2*y ] );;
gap> x
:= a^2*b*a;;
gap> y
:= a^6*c*a*b*a^-1*c*a;;
gap> A6b
:= Subgroup( M12, [ x, y ] );;
gap> A5d
:= Subgroup( M12, [ x*y, x^3*y^2*x^2*y ] );;
gap> x
:= a;;
gap> y
:= b*c*b;;
gap> z
:= c;;
gap> L2_11b := Subgroup( M12, [ x, y, z ] );;
gap> A5b
:= Subgroup( M12, [ y, x*z ] );;
gap> x
:= c;;
gap> y
:= b*a^-1*c*a*b;;
gap> z
:= a^2*b*a^-1*c*a*b*a^-2;;
gap> A5a
:= Subgroup( M12, [ (x*z)^2, (y*z)^2 ] );;
gap> M12.perfectSubgroups := [
>
L2_11a, L2_11b, M11a, M11b, A6a, A6b, A5a, A5b, A5c, A5d ];;
gap> # Now compute the subgroup lattice of M12.
gap> lat := Lattice( M12 );
LatticeSubgroups( Group( ( 2, 3, 5, 7,11, 9, 8,12,10, 6, 4), ( 3, 6)
( 5, 8)( 9,11)(10,12), ( 1, 2)( 3, 4)( 5, 9)( 6, 8)( 7,12)(10,11) ) )
The Lattice command returns a record which represents a very complicated structure.
gap> # Subgroup lattice of M12 (continued)
gap> RecFields( lat );
[ "isLattice", "classes", "group", "printLevel", "operations" ]
Probably the most important component of the lattice record is the list lat.classes. Its
elements are domains. They are described in section 7.74. We can use this list, for instance,
to print the number of conjugacy classes of subgroups and the number of subgroups of M12 .
gap> # Subgroup lattice of M12 (continued)
gap> n1 := Length( lat.classes );;
gap> n2 := Sum( [ 1 .. n1 ], i -> Size( lat.classes[i] ) );;
gap> Print( "#I M12 has ", n1, " classes of altogether ", n2,
>
" subgroups\n" );
#I M12 has 147 classes of altogether 214871 subgroups
It would not make sense to get all components of a subgroup lattice record printed in full
detail whenever we ask GAP3 to print the lattice. Therefore, as you can see in the above
example, the default printout is just an expression of the form ”Lattice( group )”. However,
304
CHAPTER 7. GROUPS
you can ask GAP3 to display some additional information in any subsequent printout of the
lattice by increasing its individual print level. This print level is stored (in the form of a
list of several print flags) in the lattice record and can be changed by an appropriate call of
the SetPrintLevel command described below.
The following example demonstrates the effect of the subgroup lattice print level.
gap> # Subgroup lattice of S4
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> lat := Lattice( s4 );
LatticeSubgroups( Group( (1,2,3,4), (1,2) ) )
The default subgroup lattice print level is 0. In this case, the print command provides just
the expression mentioned above.
gap> # Subgroup lattice of S4 (continued)
gap> SetPrintLevel( lat, 1 );
gap> lat;
#I class 1, size 1, length 1
#I class 2, size 2, length 3
#I class 3, size 2, length 6
#I class 4, size 3, length 4
#I class 5, size 4, length 1
#I class 6, size 4, length 3
#I class 7, size 4, length 3
#I class 8, size 6, length 4
#I class 9, size 8, length 3
#I class 10, size 12, length 1
#I class 11, size 24, length 1
LatticeSubgroups( Group( (1,2,3,4), (1,2) ) )
If the print level is set to a value greater than 0, you get, in addition, for each class a kind of
heading line. This line contains the position number and the length of the respective class
as well as the order of the subgroups in the class.
gap> # Subgroup lattice of S4 (continued)
gap> SetPrintLevel( lat, 2 );
gap> lat;
#I class 1, size 1, length 1
#I
representative [ ]
#I
maximals
#I class 2, size 2, length 3
#I
representative [ (1,2)(3,4) ]
#I
maximals [ 1, 1 ]
#I class 3, size 2, length 6
#I
representative [ (3,4) ]
#I
maximals [ 1, 1 ]
#I class 4, size 3, length 4
#I
representative [ (2,3,4) ]
#I
maximals [ 1, 1 ]
#I class 5, size 4, length 1
#I
representative [ (1,2)(3,4), (1,3)(2,4) ]
7.75. LATTICE
305
#I
maximals [ 2, 1 ] [ 2, 2 ] [ 2, 3 ]
#I class 6, size 4, length 3
#I
representative [ (3,4), (1,2) ]
#I
maximals [ 3, 1 ] [ 3, 4 ] [ 2, 1 ]
#I class 7, size 4, length 3
#I
representative [ (1,2)(3,4), (1,4,2,3) ]
#I
maximals [ 2, 1 ]
#I class 8, size 6, length 4
#I
representative [ (2,3,4), (3,4) ]
#I
maximals [ 4, 1 ] [ 3, 1 ] [ 3, 2 ] [ 3, 3 ]
#I class 9, size 8, length 3
#I
representative [ (3,4), (1,2), (1,3)(2,4) ]
#I
maximals [ 7, 1 ] [ 6, 1 ] [ 5, 1 ]
#I class 10, size 12, length 1
#I
representative [ (1,2)(3,4), (1,3)(2,4), (2,3,4) ]
#I
maximals [ 5, 1 ] [ 4, 1 ] [ 4, 2 ] [ 4, 3 ] [ 4, 4 ]
#I class 11, size 24, length 1
#I
representative [ (1,2,3,4), (1,2) ]
#I
maximals [ 10, 1 ] [ 9, 1 ] [ 9, 2 ] [ 9, 3 ] [ 8, 1 ]
[ 8, 2 ] [ 8, 3 ] [ 8, 4 ]
LatticeSubgroups( Group( (1,2,3,4), (1,2) ) )
gap> PrintClassSubgroupLattice( lat, 8 );
#I class 8, size 6, length 4
#I
representative [ (2,3,4), (3,4) ]
#I
maximals [ 4, 1 ] [ 3, 1 ] [ 3, 2 ] [ 3, 3 ]
If the subgroup lattice print level is at least 2, GAP3 prints, in addition, for each class representative subgroup a set of generators and a list of its maximal subgroups, where each maximal subgroup is represented by a pair of integers consisting of its class number and its position number in that class. As this information blows up the output, it may be convenient to
restrict it to a particular class. We can do this by calling the PrintClassSubgroupLattice
command described below.
gap> # Subgroup lattice of S4 (continued)
gap> SetPrintLevel( lat, 3 );
gap> PrintClassSubgroupLattice( lat, 8 );
#I class 8, size 6, length 4
#I
representative [ (2,3,4), (3,4) ]
#I
maximals [ 4, 1 ] [ 3, 1 ] [ 3, 2 ] [ 3, 3 ]
#I
conjugate 2 by (1,4,3,2) is [ (1,2,3), (2,3) ]
#I
conjugate 3 by (1,2) is [ (1,3,4), (3,4) ]
#I
conjugate 4 by (1,3)(2,4) is [ (1,2,4), (1,2) ]
If the subgroup lattice print level has been set to at least 3, GAP3 displays, in addition,
for each non-representative subgroup of a class its number in the class, an element which
transforms the class representative subgroup into that subgroup, and a set of generators.
gap> # Subgroup lattice of S4 (continued)
gap> SetPrintLevel( lat, 4 );
gap> PrintClassSubgroupLattice( lat, 8 );
#I class 8, size 6, length 4
306
CHAPTER 7. GROUPS
#I
#I
#I
#I
#I
#I
#I
#I
representative [ (2,3,4), (3,4) ]
maximals [ 4, 1 ] [ 3, 1 ] [ 3, 2 ] [ 3, 3 ]
conjugate 2 by (1,4,3,2) is [ (1,2,3), (2,3) ]
maximals [ 4, 2 ] [ 3, 2 ] [ 3, 4 ] [ 3, 5 ]
conjugate 3 by (1,2) is [ (1,3,4), (3,4) ]
maximals [ 4, 3 ] [ 3, 1 ] [ 3, 5 ] [ 3, 6 ]
conjugate 4 by (1,3)(2,4) is [ (1,2,4), (1,2) ]
maximals [ 4, 4 ] [ 3, 4 ] [ 3, 6 ] [ 3, 3 ]
A subgroup lattice print level value of at least 4 causes GAP3 to list the maximal subgroups
not only for the class representatives, but also for the other subgroups.
gap> # Subgroup lattice of S4 (continued)
gap> SetPrintLevel( lat, 5 );
gap> PrintClassSubgroupLattice( lat, 8 );
#I class 8, size 6, length 4
#I
representative [ (2,3,4), (3,4) ]
#I
maximals [ 4, 1 ] [ 3, 1 ] [ 3, 2 ] [ 3, 3 ]
#I
minimals [ 11, 1 ]
#I
conjugate 2 by (1,4,3,2) is [ (1,2,3), (2,3) ]
#I
maximals [ 4, 2 ] [ 3, 2 ] [ 3, 4 ] [ 3, 5 ]
#I
minimals [ 11, 1 ]
#I
conjugate 3 by (1,2) is [ (1,3,4), (3,4) ]
#I
maximals [ 4, 3 ] [ 3, 1 ] [ 3, 5 ] [ 3, 6 ]
#I
minimals [ 11, 1 ]
#I
conjugate 4 by (1,3)(2,4) is [ (1,2,4), (1,2) ]
#I
maximals [ 4, 4 ] [ 3, 4 ] [ 3, 6 ] [ 3, 3 ]
#I
minimals [ 11, 1 ]
The maximal valid value of the subgroup lattice print level is 5. If it is set, GAP3 displays
not only the maximal subgroups, but also the minimal supergroups of each subgroup. This
is the most extensive output of a subgroup lattice record which you can get with the Print
command, but of course you can use the RecFields command (see 46.13) to list all record
components and then print them out individually in full detail.
If the computation of some subgroup lattice is very time consuming (as in the above example
of the Mathieu group M12 ), you might wish to see some intermediate printout which informs
you about the progress of the computation. In fact, you can get such messages by activating
a print mechanism which has been inserted into the subgroup lattice routines for diagnostic
purposes. All you have to do is to replace the call
lat := Lattice( M12 );
by the three calls
InfoLattice1 := Print;
lat := Lattice( M12 );
InfoLattice1 := Ignore;
Note, however, that the final numbering of the conjugacy classes of subgroups will differ
from the order in which they occur in the intermediate listing because they will be reordered
by increasing subgroup orders at the end of the construction.
7.76. CONJUGACYCLASSSUBGROUPS
307
PrintClassSubgroupLattice( lattice, n )
PrintClassSubgroupLattice prints information on the nth conjugacy class of subgroups
in the subgroup lattice lattice. The amount of this information depends on the current
value of the subgroup lattice print level of lattice. Note that the default of that print level is
zero which means that you will not get any output from the PrintClassSubgroupLattice
command without increasing it (see SetPrintLevel below). Examples are given in the
above description of the Lattice command.
SetPrintLevel( lattice, level )
SetPrintLevel changes the subgroup lattice print level of the subgroup lattice lattice to
the specified value level by an appropriate alteration of the list of print flags which is stored
in lattice.printLevel. The argument level is expected to be an integer between 0 and 5.
Examples of the effect of the subgroup lattice print level are given in the above description
of the Lattice command.
7.76
ConjugacyClassSubgroups
ConjugacyClassSubgroups( G, U )
ConjugacyClassSubgroups returns the conjugacy class of the subgroup U in the group G.
Signals an error if U is not a subgroup of G. The conjugacy class is returned as a domain,
so all set theoretic functions are applicable (see 4).
gap> s5 := Group( (1,2), (1,2,3,4,5) );; s5.name := "s5";;
gap> a5 := DerivedSubgroup( s5 );
Subgroup( s5, [ (1,2,3), (2,3,4), (3,4,5) ] )
gap> C := ConjugacyClassSubgroups( s5, a5 );
ConjugacyClassSubgroups( s5, Subgroup( s5,
[ (1,2,3), (2,3,4), (3,4,5) ] ) )
gap> Size( C );
1
Another example of such domains is given in section 7.74.
ConjugacyClassSubgroups calls
G.operations.ConjugacyClassSubgroups( G, U ) and returns this value.
The default function called is GroupOps.ConjugacyClassSubgroups, which creates a conjugacy class record (see 7.79) with the operations record ConjugacyClassSubgroupsOps (see
7.78). Look in the index under ConjugacyClassSubgroups to see for which groups this
function is overlaid.
7.77
IsConjugacyClassSubgroups
IsConjugacyClassSubgroups( obj )
IsConjugacyClassSubgroups returns true if obj is a conjugacy class of subgroups as created by ConjugacyClassSubgroups (see 7.76) and false otherwise.
gap> s5 := Group( (1,2), (1,2,3,4,5) );;
gap> a5 := DerivedSubgroup( s5 );
s5.name := "s5";;
308
CHAPTER 7. GROUPS
Subgroup( s5, [ (1,2,3), (2,3,4), (2,4)(3,5) ] )
gap> c := ConjugacyClassSubgroups( s5, a5 );
ConjugacyClassSubgroups( s5, Subgroup( s5,
[ (1,2,3), (2,3,4), (2,4)(3,5) ] ) )
gap> IsConjugacyClassSubgroups( c );
true
gap> IsConjugacyClassSubgroups( [ a5 ] );
false
# even though this is as a set equal to c
7.78
Set Functions for Subgroup Conjugacy Classes
As mentioned above, conjugacy classes of subgroups are domains, so all set theoretic functions are also are applicable to conjugacy classes (see 4). This section describes the functions
that are implemented especially for conjugacy classes. Functions not mentioned here inherit
the default functions mentioned in the respective sections.
Elements( C )
The elements of the conjugacy class C with representative U in the group G are computed
by first finding a right transversal of the normalizer of U in G and by computing the
conjugates of U with the elements in the right transversal.
V in C
Membership of a group V is tested by comparing the set of contained cyclic subgroups of
prime power order of V with those of the groups in C .
Size( C )
The size of the conjugacy class C with representative U in the group G is computed as the
index of the normalizer of U in G.
7.79
Subgroup Conjugacy Class Records
Each conjugacy class of subgroups C is represented as a record with at least the following
components.
isDomain
always true, because conjugacy classes of subgroups are domains.
isConjugacyClassSubgroups
as well, this entry is always set to true.
group
The group in which the members of this conjugacy class lie. This is not necessarily a
parent group; it may also be a subgroup.
representative
The representative of the conjugacy class of subgroups as domain.
The following components are optional and may be bound by some functions which compute
or make use of their value.
7.80. CONJUGACYCLASSESMAXIMALSUBGROUPS
309
normalizer
The normalizer of C .representative in C .group.
normalizerLattice
A special entry that is used when the conjugacy classes of subgroups are computed
by ConjugacyClassesSubgroups. It determines the normalizer of the subgroup
C .representative. It is a list of length 2. The first element is another conjugacy class D (in the same group), the second is an element g in C .group. The
normalizer of C .representative is then D.representative ^ g.
conjugands
A right transversal of the normalizer of C .representative in C .group. Thus the
elements of the class C can be computed by conjugating C .representative with
those elements.
7.80
ConjugacyClassesMaximalSubgroups
ConjugacyClassesMaximalSubgroups( G )
ConjugacyClassesMaximalSubgroups returns a list of conjugacy classes of maximal subgroups of the group G.
A subgroup H of G is maximal if H is a proper subgroup and for all subgroups I of G
with H < I ≤ G the equality I = G holds.
gap> s4 := SymmetricGroup( AgWords, 4 );;
gap> ss4 := SpecialAgGroup( s4 );;
gap> ConjugacyClassesMaximalSubgroups( ss4 );
[ ConjugacyClassSubgroups( Group( g1, g2, g3, g4 ), Subgroup( Group(
g1, g2, g3, g4 ), [ g2, g3, g4 ] ) ),
ConjugacyClassSubgroups( Group( g1, g2, g3, g4 ), Subgroup( Group(
g1, g2, g3, g4 ), [ g1, g3, g4 ] ) ),
ConjugacyClassSubgroups( Group( g1, g2, g3, g4 ), Subgroup( Group(
g1, g2, g3, g4 ), [ g1, g2 ] ) ) ]
The generic method computes the entire lattice of conjugacy classes of subgroups (see 7.75)
and returns the maximal ones.
MaximalSubgroups (see 7.81) computes the list of all maximal subgroups.
7.81
MaximalSubgroups
MaximalSubgroups( G )
MaximalSubgroups calculates all maximal subroups of the special ag group G.
gap> s4 := SymmetricGroup( AgWords, 4 );;
gap> ss4 := SpecialAgGroup( s4 );;
gap> MaximalSubgroups( ss4 );
[ Subgroup( Group( g1, g2, g3, g4 ), [ g2, g3, g4 ] ),
Subgroup( Group( g1, g2, g3, g4 ), [ g1, g3, g4 ] ),
Subgroup( Group( g1, g2, g3, g4 ), [ g1*g2^2, g3, g4 ] ),
Subgroup( Group( g1, g2, g3, g4 ), [ g1*g2, g3, g4 ] ),
Subgroup( Group( g1, g2, g3, g4 ), [ g1, g2 ] ),
310
CHAPTER 7. GROUPS
Subgroup( Group( g1, g2, g3, g4 ), [ g1, g2*g3*g4 ] ),
Subgroup( Group( g1, g2, g3, g4 ), [ g1*g4, g2*g4 ] ),
Subgroup( Group( g1, g2, g3, g4 ), [ g1*g4, g2*g3 ] ) ]
ConjugacyClassesMaximalSubgroups (see 7.80) computes the list of conjugacy classes of
maximal subgroups.
7.82
NormalSubgroups
NormalSubgroups( G )
NormalSubgroups returns a list of all normal subgroups of G. The subgroups are sorted
according to their sizes.
gap> s4 := Group( (1,2,3,4), (1,2) );; s4.name := "s4";;
gap> NormalSubgroups( s4 );
[ Subgroup( s4, [ ] ), Subgroup( s4, [ (1,2)(3,4), (1,4)(2,3) ] ),
Subgroup( s4, [ (2,3,4), (1,3,4) ] ),
Subgroup( s4, [ (3,4), (1,4), (1,2,4) ] ) ]
The default function GroupOps.NormalSubgroups uses the conjugacy classes of G and normal closures in order to compute the normal subgroups.
7.83
ConjugateSubgroups
ConjugateSubgroups( G, U )
ConjugateSubgroups returns the orbit of U under G acting by conjugation (see 7.20) as
list of subgroups. U and G must have a common parent group.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> s3 := Subgroup( s4, [ (1,2,3), (1,2) ] );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2,3), (1,2) ]
gap> ConjugateSubgroups( s4, s3 );
[ Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2,3), (1,2)
Subgroup( Group( (1,2,3,4), (1,2) ), [ (2,3,4), (2,3)
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,3,4), (3,4)
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,2,4), (1,4)
7.84
)
]
]
]
]
),
),
),
) ]
Cosets of Subgroups
The following sections describe how one can compute the right, left, and double cosets of
subgroups (see 7.85, 7.90, 7.93). Further sections describe how cosets are created (see 7.86,
7.87, 7.91, 7.92, 7.94, and 7.95), and their implementation (see 7.88, 7.89, 7.96, and 7.97).
A coset is a GAP3 domain, which is different from a group. Altough the set of elements
of a group and its trivial coset are equal, the group functions do not take trivial cosets as
arguments. A trivial coset must be convert into a group using AsGroup (see 7.10) in order
to be used as group.
7.85. RIGHTCOSETS
7.85
311
RightCosets
Cosets( G, U )
RightCosets( G, U )
Cosets and RightCosets return a list of the right cosets of the subgroup U in the group
G. The list is not sorted, i.e., the right cosets may appear in any order. The right cosets
are domains as constructed by RightCoset (see 7.86).
gap> G := Group( (1,2), (1,2,3,4) );;
gap> G.name := "G";;
gap> U := Subgroup( G, [ (1,2), (3,4) ] );;
gap> RightCosets( G, U );
[ (Subgroup( G, [ (1,2), (3,4) ] )*()),
(Subgroup( G, [ (1,2), (3,4) ] )*(2,4,3)),
(Subgroup( G, [ (1,2), (3,4) ] )*(2,3)),
(Subgroup( G, [ (1,2), (3,4) ] )*(1,2,4,3)),
(Subgroup( G, [ (1,2), (3,4) ] )*(1,2,3)),
(Subgroup( G, [ (1,2), (3,4) ] )*(1,3)(2,4)) ]
If G is the parent of U , the dispatcher RightCosets first checks whether U has a component rightCosets. If U has this component, it returns that value. Otherwise it calls
G.operations.RightCosets(G,U ), remembers the returned value in U .rightCosets
and returns it. If G is not the parent of U , RightCosets directly calls the function
G.operations.RightCosets(G,U ) and returns that value.
The default function called this way is GroupOps.RightCosets, which calls Orbit( G,
RightCoset( U ), OnRight ). Look up RightCosets in the index, to see for which groups
this function is overlaid.
7.86
RightCoset
U * u
Coset( U , u )
RightCoset( U , u )
Coset( U )
RightCoset( U )
The first three forms return the right coset of the subgroup U with the representative u. u
must lie in the parent group of U , otherwise an error is signalled. In the last two forms the
right coset of U with the identity element of the parent of U as representative is returned.
In each case the right coset is returned as a domain, so all domain functions are applicable
to right cosets (see chapter 4 and 7.88).
gap> G := Group( (1,2), (1,2,3,4) );;
gap> U := Subgroup( G, [ (1,2), (3,4) ] );;
gap> U * (1,2,3);
(Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2), (3,4) ] )*(1,2,3))
RightCosets (see 7.85) computes the set of all right cosets of a subgroup in a group.
LeftCoset (see 7.91) constructs left cosets.
RightCoset calls U .operations.RightCoset( U , u ) and returns that value.
312
CHAPTER 7. GROUPS
The default function called this way is GroupOps.RightCoset, which creates a right coset
record (see 7.89) with the operations record RightCosetGroupOps (see 7.88). Look up the
entries for RightCoset in the index to see for which groups this function is overlaid.
7.87
IsRightCoset
IsRightCoset( obj )
IsCoset( obj )
IsRightCoset and IsCoset return true if the object obj is a right coset, i.e., a record with
the component isRightCoset with value true, and false otherwise. Will signal an error
if obj is an unbound variable.
gap> C := Subgroup( Group( (1,2), (1,2,3) ), [ (1,2,3) ] ) * (1,2);;
gap> IsRightCoset( C );
true
gap> D := (1,2) * Subgroup( Group( (1,2), (1,2,3) ), [ (1,2,3) ] );;
gap> IsCoset( D );
false
# note that D is a left coset record,
gap> C = D;
true
# though as a set, it is of course also a right coset
gap> IsCoset( 17 );
false
7.88
Set Functions for Right Cosets
Right cosets are domains, thus all set theoretic functions are applicable to cosets (see chapter
4). The following describes the functions that are implemented especially for right cosets.
Functions not mentioned here inherit the default function mentioned in the respective sections.
More technically speaking, all right cosets of generic groups have the operations record
RightCosetGroupOps, which inherits its functions from DomainOps and overlays the components mentioned below with more efficient functions.
In the following let C be the coset U * u.
Elements( C )
To compute the proper set of elements of a right coset C the proper set of elements of the
subgroup U is computed, each element is multiplied by u, and the result is sorted.
IsFinite( C )
This returns the result of applying IsFinite to the subgroup U .
Size( C )
This returns the result of applying Size to the subgroup U .
C = D
7.89. RIGHT COSETS RECORDS
313
If C and D are both right cosets of the same subgroup, = returns true if the quotient of
the representatives lies in the subgroup U , otherwise the test is delegated to DomainOps.=.
h in U
If h is an element of the parent group of U , this returns true if the quotient h / u lies in
the subgroup U , otherwise the test is delegated to DomainOps.in.
Intersection( C , D )
If C and D are both right cosets of subgroups U and V with the same parent group the
result is a right coset of the intersection of U and V . The representative is found by a
random search for a common element. In other cases the computation of the intersection is
delegated to DomainOps.Intersection.
Random( C )
This takes a random element of the subgroup U and returns the product of this element by
the representative u.
Print( C )
A right coset C is printed as (U * u) (the parenthesis are used to avoid confusion about
the precedence, which could occur if the coset is part of a larger object).
C * v
If v is an element of the parent group of the subgroup U , the result is a new right coset of
U with representative u * v . Otherwise the result is obtained by multiplying the proper
set of elements of C with the element v , which may signal an error.
v * C
The result is obtained by multiplying the proper set of elements of the coset C with the
element v , which may signal an error.
7.89
Right Cosets Records
A right coset is represented by a domain record with the following tag components.
isDomain
always true.
isRightCoset
always true.
The right coset is determined by the following identity components, which every right coset
record has.
group
the subgroup U of which this right coset is a right coset.
314
CHAPTER 7. GROUPS
representative
an element of the right coset. It is unspecified which element.
In addition, a right coset record may have the following optional information components.
elements
if present the proper set of elements of the coset.
isFinite
if present this is true if the coset is finite, and false if the coset is infinite. If not
present it is not known whether the coset is finite or infinite.
size
if present the size of the coset. Is ”infinity” if the coset is infinite. If not present the
size of the coset is not known.
7.90
LeftCosets
LeftCosets( G, U )
LeftCosets returns a list of the left cosets of the subgroup U in the group G. The list is
not sorted, i.e., the left cosets may appear in any order. The left cosets are domains as
constructed by LeftCosets (see 7.90).
gap> G := Group( (1,2), (1,2,3,4) );;
gap> G.name := "G";;
gap> U := Subgroup( G, [ (1,2), (3,4) ] );;
gap> LeftCosets( G, U );
[ (()*Subgroup( G, [ (1,2), (3,4) ] )),
((2,3,4)*Subgroup( G, [ (1,2), (3,4) ] )),
((2,3)*Subgroup( G, [ (1,2), (3,4) ] )),
((1,3,4,2)*Subgroup( G, [ (1,2), (3,4) ] )),
((1,3,2)*Subgroup( G, [ (1,2), (3,4) ] )),
((1,3)(2,4)*Subgroup( G, [ (1,2), (3,4) ] )) ]
If G is the parent of U , the dispatcher LeftCosets first checks whether U has a component
leftCosets. If U has this component, it returns that value. Otherwise LeftCosets calls
G.operations.LeftCosets(G,U ), remembers the returned value in U .leftCosets and
returns it. If G is not the parent of U , LeftCosets calls G.operations.LeftCosets(G,U )
directly and returns that value.
The default function called this way is GroupOps.LeftCosets, which calls RightCosets(
G, U ) and turns each right coset U * u into the left coset u^-1 * U . Look up the
entries for LeftCosets in the index, to see for which groups this function is overlaid.
7.91
LeftCoset
u * U
LeftCoset( U , u )
LeftCoset( U )
LeftCoset is exactly like RightCoset, except that it constructs left cosets instead of right
cosets. So everything that applies to RightCoset applies also to LeftCoset, with right
replaced by left (see 7.86, 7.88, 7.89).
7.92. ISLEFTCOSET
315
gap> G := Group( (1,2), (1,2,3,4) );;
gap> U := Subgroup( G, [ (1,2), (3,4) ] );;
gap> (1,2,3) * U;
((1,2,3)*Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2), (3,4) ] ))
LeftCosets (see 7.90) computes the set of all left cosets of a subgroup in a group.
7.92
IsLeftCoset
IsLeftCoset( obj )
IsLeftCoset returns true if the object obj is a left coset, i.e., a record with the component
isLeftCoset with value true, and false otherwise. Will signal an error if obj is an unbound
variable.
gap> C := (1,2) * Subgroup( Group( (1,2), (1,2,3) ), [ (1,2,3) ] );;
gap> IsLeftCoset( C );
true
gap> D := Subgroup( Group( (1,2), (1,2,3) ), [ (1,2,3) ] ) * (1,2);;
gap> IsLeftCoset( D );
false
# note that D is a right coset record,
gap> C = D;
true
# though as a set, it is of course also a left coset
gap> IsLeftCoset( 17 );
false
IsRightCoset (see 7.87) tests if an object is a right coset.
7.93
DoubleCosets
DoubleCosets( G, U , V )
DoubleCosets returns a list of the double cosets of the subgroups U and V in the group
G. The three groups G, U and V must have a common parent. The list is not sorted, i.e.,
the double cosets may appear in any order. The double cosets are domains as constructed
by DoubleCoset (see 7.94).
gap> G := Group( (1,2), (1,2,3,4) );;
gap> U := Subgroup( G, [ (1,2), (3,4) ] );; U.name := "U";;
gap> DoubleCosets( G, U, U );
[ DoubleCoset( U, (), U ), DoubleCoset( U, (2,3), U ),
DoubleCoset( U, (1,3)(2,4), U ) ]
DoubleCosets calls G.operations.DoubleCoset( G, U , V ) and returns that value.
The default function called this way is GroupOps.DoubleCosets, which takes random elements from G, tests if this element lies in one of the already found double cosets, adds the
double coset if this is not the case, and continues this until the sum of the sizes of the found
double cosets equals the size of G. Look up DoubleCosets in the index, to see for which
groups this function is overlaid.
316
CHAPTER 7. GROUPS
7.94
DoubleCoset
DoubleCoset( U , u, V )
DoubleCoset returns the double coset with representative u and left group U and right
group V . U and V must have a common parent and u must lie in this parent, otherwise
an error is signaled. Double cosets are domains, so all domain function are applicable to
double cosets (see chapter 4 and 7.96).
gap> G := Group( (1,2), (1,2,3,4) );;
gap> U := Subgroup( G, [ (1,2), (3,4) ] );;
gap> D := DoubleCoset( U, (1,2,3), U );
DoubleCoset( Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2), (3,4) ] ),
(1,2,3), Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2), (3,4) ] ) )
gap> Size( D );
16
DoubleCosets (see 7.93) computes the set of all double cosets of two subgroups in a group.
DoubleCoset calls U .operations.DoubleCoset(U ,u,V ) and returns that value.
The default function called this way is GroupOps.DoubleCoset, which creates a double
coset record (see 7.97) with the operations record DoubleCosetGroupOps (see 7.96). Look
up DoubleCosets in the index to see for which groups this function is overlaid.
7.95
IsDoubleCoset
IsDoubleCoset( obj )
IsDoubleCoset returns true if the object obj is a double coset, i.e., a record with the
component isDoubleCoset with value true, and false otherwise. Will signal an error if
obj is an unbound variable.
gap>
gap>
gap>
gap>
true
7.96
G := Group( (1,2), (1,2,3,4) );;
U := Subgroup( G, [ (1,2), (3,4) ] );;
D := DoubleCoset( U, (1,2,3), U );;
IsDoubleCoset( D );
Set Functions for Double Cosets
Double cosets are domains, thus all set theoretic functions are applicable to double cosets
(see chapter 4). The following describes the functions that are implemented especially for
double cosets. Functions not mentioned here inherit the default functions mentioned in the
respective sections.
More technically speaking, double cosets of generic groups have the operations record
DoubleCosetGroupOps, which inherits its functions from DomainOps and overlays the components mentioned below with more efficient functions.
Most functions below use the component D.rightCosets that contains a list of right cosets
of the left group U whose union is this double coset. If this component is unbound they will
compute it by computing the orbit of the right group V on the right coset U * u, where u
is the representative of the double coset (see 7.97).
7.97. DOUBLE COSET RECORDS
317
Elements( D )
To compute the proper set of elements the union of the right cosets D.rightCosets is
computed.
IsFinite( D )
This returns the result of IsFinite( U ) and IsFinite( V ).
Size( D )
This returns the size of the left group U times the number of cosets in D.rightCosets.
C = D
If C and D are both double cosets with the same left and right groups this returns the result
of testing whether the representative of C lies in D. In other cases the test is delegated to
DomainOps.=.
g in D
If g is an element of the parent group of the left and right group of D, this returns true if
g lies in one of the right cosets in D.rightCosets. In other cases the the test is delegated
to DomainOps.in.
Intersection( C , D )
If C and D are both double cosets that are equal, this returns C . If C and D are both
double cosets with the same left and right groups that are not equal, this returns []. In all
other cases the computation is delegated to DomainsOps.Intersection.
Random( D )
This takes a random right coset from D.rightCosets and returns the result of applying
Random to this right coset.
Print( D )
This prints the double coset in the form DoubleCoset( U , u, V ).
D * g
g * D
Those returns the result of multiplying the proper set of element of D with the element g,
which may signal an error.
7.97
Double Coset Records
A double coset is represented by a domain record with the following tag components.
318
CHAPTER 7. GROUPS
isDomain
always true.
isDoubleCoset
always true.
The double coset is determined by the following identity components, which every double
coset must have.
leftGroup
the left subgroup U .
rightGroup
the right subgroup V .
representative
an element of the double coset. It is unspecified which element.
In addition, a double coset record may have the following optional information components.
rightCosets
a list of disjoint right cosets of the left subgroup U , whose union is the double coset.
elements
if present the proper set of elements of the double coset.
isFinite
if present this is true if the double coset is finite and false if the double coset is
infinite. If not present it is not known whether the double coset is finite or infinite.
size
if present the size of the double coset. Is ”infinity” if the coset is infinite. If not
present the size of the double coset is not known.
7.98
Group Constructions
The following functions construct new parent groups from given groups (see 7.99, 7.101,
7.103 and 7.104).
7.99
DirectProduct
DirectProduct( G1 , ..., Gn )
DirectProduct returns a group record of the direct product D of the groups G1 , ...., Gn
which need not to have a common parent group, it is even possible to construct the direct
product of an ag group with a permutation group.
Note that the elements of the direct product may be just represented as records. But more
complicate constructions, as for instance installing a new collector, may be used. The choice
of method strongly depends on the type of group arguments.
Embedding( U , D, i )
Let U be a subgroup of Gi . Embedding returns a homomorphism of U into D which
describes the embedding of U in D.
7.100. DIRECTPRODUCT FOR GROUPS
319
Projection( D, U , i )
Let U be a supergroup of Gi . Projection returns a homomorphism of D into U which
describes the projection of D onto Gi .
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> S4 := AgGroup( s4 );
Group( g1, g2, g3, g4 )
gap> D := DirectProduct( s4, S4 );
Group( DirectProductElement(
(1,2,3,4), IdAgWord ), DirectProductElement(
(1,2), IdAgWord ), DirectProductElement( (),
g1 ), DirectProductElement( (), g2 ), DirectProductElement( (),
g3 ), DirectProductElement( (), g4 ) )
gap> pr := Projection( D, s4, 1 );;
gap> Image( pr );
Group( (1,2,3,4), (1,2) )
7.100
DirectProduct for Groups
GroupOps.DirectProduct( L )
Let L be a list of groups G1 , ..., Gn . Then a group element g of the direct product D is
represented as record containing the following components.
element
a list g1 ∈ G1 , ..., gn ∈ Gn describing g.
domain
contains GroupElements.
isGroupElement
contains true.
isDirectProductElement
contains true.
operations
contains the operations record DirectProductElementOps (see 4.5).
7.101
SemidirectProduct
SemidirectProduct( G, a, H )
SemidirectProduct returns the semidirect product of G with H . a must be a homomorphism that from G onto a group A that operates on H via the caret (^) operator. A may
either be a subgroup of the parent group of H that normalizes H , or a subgroup of the
automorphism group of H , i.e., a group of automorphisms (see 7.106).
The semidirect product of G and H is a the group of pairs (g, h) with g ∈ G and h ∈ H,
ga
where the product of (g1 , h1 )(g2 , h2 ) is defined as (g1 g2 , h12 h2 ). Note that the elements
(1G , h) form a normal subgroup in the semidirect product.
320
CHAPTER 7. GROUPS
Embedding( U , S , 1 )
Let U be a subgroup of G. Embedding returns the homomorphism of U into the semidirect
product S where u is mapped to (u,1).
Embedding( U , S , 2 )
Let U be a subgroup of H . Embedding returns the homomorphism of U into the semidirect
product S where u is mapped to (1,u).
Projection( S , G, 1 )
Projection returns the homomorphism of S onto G, where (g,h) is mapped to g.
Projection( S , H , 2 )
Projection returns the homomorphism of S onto H , where (g,h) is mapped to h.
It is not specified how the elements of the semidirect product are represented. Thus
Embedding and Projection are the only general possibility to relate G and H with the
semidirect product.
gap> s4 := Group( (1,2), (1,2,3,4) );; s4.name := "s4";;
gap> s3 := Subgroup( s4, [ (1,2), (1,2,3) ] );; s3.name := "s3";;
gap> a4 := Subgroup( s4, [ (1,2,3), (2,3,4) ] );; a4.name := "a4";;
gap> a := IdentityMapping( s3 );;
gap> s := SemidirectProduct( s3, a, a4 );
Group( SemidirectProductElement( (1,2),
(1,2), () ), SemidirectProductElement( (1,2,3),
(1,2,3), () ), SemidirectProductElement( (), (),
(1,2,3) ), SemidirectProductElement( (), (), (2,3,4) ) )
gap> Size( s );
72
Note that the three arguments of SemidirectProductElement are the element g, its image
under a, and the element h.
SemidirectProduct calls the function G.operations.SemidirectProduct with the arguments G, a, and H , and returns the result.
The default function called this way is GroupOps.SemidirectProduct. This function constructs the semidirect product as a group of semidirect product elements (see 7.102). Look
in the index under SemidirectProduct to see for which groups this function is overlaid.
7.102
SemidirectProduct for Groups
The function GroupOps.SemidirectProduct constructs the semidirect product as a group
of semidirect product elements. In the following let G, a, and H be the arguments of
SemidirectProduct.
Each such element (g,h) is represented by a record with the following components.
element
the list [ g, h ].
automorphism
contains the image of g under a.
7.103. SUBDIRECTPRODUCT
321
isGroupElement
always true.
isSemidirectProductElement
always true.
domain
contains GroupElements.
operations
contains the operations record SemidirectProductOps.
The operations of semidirect product elements in done in the obvious way.
7.103
SubdirectProduct
SubdirectProduct( G1 , G2 , h1 , h2 )
SubdirectProduct returns the subdirect product of the groups G1 and G2 . h1 and h2
must be homomorphisms from G1 and G2 into a common group H .
The subdirect product of G1 and G2 is the subgroup of the direct product of G1 and G2 of
those elements (g1 , g2 ) with g1h1 = g2h2 . This subgroup is generated by the elements (g1 , xg1 ),
where g1 loops over the generators of G1 and xg1 ∈ G2 is an arbitrary element such that
g1h1 = xhg12 together with the element (1G , k2 ) where k2 loops over the generators of the
kernel of h2 .
Projection( S , G1 , 1 )
Projection returns the projection of S onto G1 , where (g1 ,g2 ) is mapped to g1 .
Projection( S , G2 , 2 )
Projection returns the projection of S onto G2 , where (g1 ,g2 ) is mapped to g2 .
It is not specified how the elements of the subdirect product are represented. Therefor
Projection is the only general possibility to relate G1 and G2 with the subdirect product.
gap> s3 := Group( (1,2,3), (1,2) );;
gap> c3 := Subgroup( s3, [ (1,2,3) ] );;
gap> x1 := Operation( s3, Cosets( s3, c3 ), OnRight );;
gap> h1 := OperationHomomorphism( s3, x1 );;
gap> d8 := Group( (1,2,3,4), (2,4) );;
gap> c4 := Subgroup( d8, [ (1,2,3,4) ] );;
gap> x2 := Operation( d8, Cosets( d8, c4 ), OnRight );;
gap> h2 := OperationHomomorphism( d8, x2 );;
gap> s := SubdirectProduct( s3, d8, h1, h2 );
Group( (1,2,3), (1,2)(5,7), (4,5,6,7) )
gap> Size( s );
24
SubdirectProduct calls the function G1 .operations.SubdirectProduct with the arguments G1 , G2 , h1 , and h2 .
The default function called this way is GroupOps.SubdirectProduct. This function constructs the subdirect product as a subgroup of the direct product. The generators for this
subgroup are computed as described above.
322
CHAPTER 7. GROUPS
7.104
WreathProduct
WreathProduct( G, H )
WreathProduct( G, H , α )
In the first form of WreathProduct the right regular permutation representation of H on its
elements is used as the homomorphism α. In the second form α must be a homomorphism
of H into a permutation group. Let d be the degree of the range of α. Then WreathProduct
returns the wreath product of G by H with respect to α, that is the semi-direct product of
the direct product of d copies of G which are permuted by H through application of α to
H.
gap> s3 := Group( (1,2,3), (1,2) );
Group( (1,2,3), (1,2) )
gap> z2 := CyclicGroup( AgWords, 2 );
Group( c2 )
gap> f := IdentityMapping( s3 );
IdentityMapping( Group( (1,2,3), (1,2) ) )
gap> w := WreathProduct( z2, s3, f );
Group( WreathProductElement(
c2, IdAgWord, IdAgWord, (), () ), WreathProductElement( IdAgWord,
c2, IdAgWord, (), () ), WreathProductElement( IdAgWord, IdAgWord,
c2, (), () ), WreathProductElement( IdAgWord, IdAgWord, IdAgWord,
(1,2,3),
(1,2,3) ), WreathProductElement( IdAgWord, IdAgWord, IdAgWord, (1,2),
(1,2) ) )
gap> Factors( Size( w ) );
[ 2, 2, 2, 2, 3 ]
7.105
WreathProduct for Groups
GroupOps.WreathProduct( G, H , α )
Let d be the degree of α.range. A group element of the wreath product W is represented
as a record containing the following components.
element
a list of d elements of G followed by an element h of H .
permutation
the image of h under α.
domain
contains GroupElements.
isGroupElement
contains true.
isWreathProductElement
contains true.
operations
contains the operations record WreathProductElementOps (see 4.5).
7.106. GROUP HOMOMORPHISMS
7.106
323
Group Homomorphisms
Since groups is probably the most important category of domains in GAP3 group homomorphisms are probably the most important homomorphisms (see chapter 44)
A group homomorphism φ is a mapping that maps each element of a group G, called
the source of φ, to an element of another group H, called the range of φ, such that for each
pair x, y ∈ G we have (xy)φ = xφ y φ .
Examples of group homomorphisms are the natural homomorphism of a group into a factor
group (see 7.110) and the homomorphism of a group into a symmetric group defined by an
operation (see 8.21). Look under group homomorphisms in the index for a list of all
available group homomorphisms.
Since group homomorphisms are just a special case of homomorphisms, all functions described in chapter 44 are applicable to all group homomorphisms, e.g., the function to test
if a homomorphism is an automorphism (see 44.6). More general, since group homomorphisms are just a special case of mappings all functions described in chapter 43 are also
applicable, e.g., the function to compute the image of an element under a group homomorphism (see 43.8).
The following sections describe the functions that test whether a mapping is a group homomorphism (see 7.107), compute the kernel of a group homomorphism (see 7.108), how
the general mapping functions are implemented for group homomorphisms (see 7.109), the
natural homomorphism of a group onto a factor group (see 7.110), homomorphisms by conjugation (see 7.111, 7.112), and the most general group homomorphism, which is defined by
simply specifying the images of a set of generators (see 7.113).
7.107
IsGroupHomomorphism
IsGroupHomomorphism( map )
IsGroupHomomorphism returns true if the function map is a group homomorphism and
false otherwise. Signals an error if map is a multi value mapping.
A mapping map is a group homomorphism if its source G and range H are both groups and
if for every pair of elements x, y ∈ G it holds that (xy)map = xmap y map .
gap> s4 := Group( (1,2), (1,2,3,4) );;
gap> v4 := Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4) ] );;
gap> phi := NaturalHomomorphism( s4, s4/v4 );;
gap> IsGroupHomomorphism( phi );
true
gap> IsHomomorphism( phi );
true
# since the source is a group this is equivalent to the above
gap> IsGroupHomomorphism( FrobeniusAutomorphism( GF(16) ) );
false
# it is a field automorphism
IsGroupHomomorphism first tests if the flag map.isGroupHomomorphism is bound. If the
flag is bound, IsGroupHomomorphism returns its value. Otherwise it calls
map.source.operations.IsGroupHomomorphism( map ), remembers the returned value
in map.isGroupHomomorphism, and returns it. Note that of course all functions that create
324
CHAPTER 7. GROUPS
group homomorphisms set the flag map.isGroupHomomorphism to true, so that no function
is called for those group homomorphisms.
The default function called this way is MappingOps.IsGroupHomomorphism. It computes
all the elements of the source of map and for each such element x and each generator y
tests whether (xy)map = xmap y map . Look under IsHomomorphism in the index to see
for which mappings this function is overlaid.
7.108
KernelGroupHomomorphism
KernelGroupHomomorphism( hom )
KernelGroupHomomorphism returns the kernel of the group homomorphism hom as a subgroup of the group hom.source.
The kernel of a group homomorphism hom is the subset of elements x of the source G that
are mapped to the identity of the range H, i.e., xhom = H.identity.
gap> s4 := Group( (1,2), (1,2,3,4) );;
gap> v4 := Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4) ] );;
gap> phi := NaturalHomomorphism( s4, s4/v4 );;
gap> KernelGroupHomomorphism( phi );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2)(3,4), (1,3)(2,4) ] )
gap> Kernel( phi );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2)(3,4), (1,3)(2,4) ] )
# since the source is a group this is equivalent to the above
gap> rho := GroupHomomorphismByImages( s4, Group( (1,2) ),
>
[ (1,2), (1,2,3,4) ], [ (1,2), (1,2) ] );;
gap> Kernel( rho );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (2,4,3), (1,4,3) ] )
KernelGroupHomomorphism first tests if hom.kernelGroupHomomorphism is bound. If it is
bound, KernelGroupHomomorphisms returns that value. Otherwise it calls
hom.operations.KernelGroupHomomorphism( hom ), remembers the returned value in
hom.kernelGroupHomomorphism, and returns it.
The default function for this is MappingOps.KernelGroupHomomorphism, which simply tries
random elements of the source of hom, until the subgroup generated by those that map
to the identity has the correct size, i.e., Size( hom.source ) / Size( Image( hom ) ).
Note that this implies that the image of hom and its size are computed. Look under Kernel
in the index to see for which group homomorphisms this function is overlaid.
7.109
Mapping Functions for Group Homomorphisms
This section describes how the mapping functions defined in chapter 43 are implemented
for group homomorphisms. Those functions not mentioned here are implemented by the
default functions described in the respective sections.
IsInjective( hom )
The group homomorphism hom is injective if the kernel of hom KernelGroupHomomorphism(
hom ) (see 7.108) is trivial.
7.109. MAPPING FUNCTIONS FOR GROUP HOMOMORPHISMS
325
IsSurjective( hom )
The group homomorphism hom is surjective if the size of the image Size( Image( hom )
) (see 43.8 and below) is equal to the size of the range Size( hom.range ).
hom1 = hom2
The two group homomorphisms hom1 and hom2 are equal if the have the same source and
range and if the images of the generators of the source under hom1 and hom2 are equal.
hom1 < hom2
By definition hom1 is smaller than hom2 if either the source of hom1 is smaller than the
source of hom2 , or, if the sources are equal, if the range of hom1 is smaller than the range
of hom2 , or, if sources and ranges are equal, the image of the smallest element x of the
source for that the images are not equal under hom1 is smaller than the image under hom2 .
Therefor GroupHomomorphismOps.< first compares the sources and the ranges. For group
homomorphisms with equal sources and ranges only the images of the smallest irredundant
generating system are compared. A generating system g1 , g2 , ..., gn is called irredundant if
no gi lies in the subgroup generated by g1 , ..., gi−1 . The smallest irredundant generating
system is simply the smallest such generating system with respect to the lexicographical
ordering.
Image( hom )
Image( hom, H )
Images( hom, H )
The image of a subgroup under a group homomorphism is computed by computing the
images of a set of generators of the subgroup, and the result is the subgroup generated by
those images.
PreImages( hom, elm )
The preimages of an element under a group homomorphism are computed by computing a
representative with PreImagesRepresentative( hom, elm ) and the result is the coset
of Kernel( hom ) containing this representative.
PreImage( hom )
PreImage( hom, H )
PreImages( hom, H )
The preimages of a subgroup under a group homomorphism are computed by computing
representatives of the preimages of all the generators of the subgroup, adding the generators
of the kernel of hom, and the result is the subgroup generated by those elements.
Look under IsInjective, IsSurjective, equality, ordering, Image, Images, PreImage,
and PreImages in the index to see for which group homomorphisms these functions are
overlaid.
326
CHAPTER 7. GROUPS
7.110
NaturalHomomorphism
NaturalHomomorphism( G, F )
NaturalHomomorphism returns the natural homomorphism of the group G into the factor
group F . F must be a factor group, i.e., the result of FactorGroup(H ,N ) (see 7.33) or
H /N (see 7.117), and G must be a subgroup of H .
Mathematically the factor group H/N consists of the cosets of N , and the natural homomorphism φ maps each element h of H to the coset N h. Note that in GAP3 the representation
of factor group elements is unspecified, but they are never cosets (see 7.87), because cosets
are domains and not group elements in GAP3. Thus the natural homomorphism is the only
connection between a group and one of its factorgroups.
G is the source of the natural homomorphism φ, F is its range. Note that because G may be
a proper subgroup of the group H of which F is a factor group φ need not be surjective, i.e.,
the image of φ may be a proper subgroup of F . The kernel of φ is of course the intersection
of N and G.
gap> s4 := Group( (1,2), (1,2,3,4) );;
gap> v4 := Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4) ] );;
gap> v4.name := "v4";;
gap> phi := NaturalHomomorphism( s4, s4/v4 );;
gap> (1,2,3) ^ phi;
FactorGroupElement( v4, (2,4,3) )
gap> PreImages( phi, last );
(v4*(2,4,3))
gap> (1,2,3) in last;
true
gap> rho :=
> NaturalHomomorphism( Subgroup( s4, [ (1,2), (1,2,3) ] ), s4/v4 );;
gap> Kernel( rho );
Subgroup( Group( (1,2), (1,2,3,4) ), [ ] )
gap> IsIsomorphism( rho );
true
NaturalHomomorphism calls
F .operations.NaturalHomomorphism( G, F ) and returns that value.
The default function called this way is GroupOps.NaturalHomomorphism. The homomorphism constructed this way has the operations record NaturalHomomorphismOps. It computes the image of an element g of G by calling FactorGroupElement( N , g ), the preimages of an factor group element f as Coset( Kernel(phi ), f .element.representative
), and the kernel by computing Intersection( G, N ). Look under NaturalHomomorphism in the index to see for which groups this function is overlaid.
7.111
ConjugationGroupHomomorphism
ConjugationGroupHomomorphism( G, H , x )
ConjugationGroupHomomorphism returns the homomorphism from G into H that takes
each element g in G to the element g ^ x . G and H must have a common parent group P
and x must lie in this parent group. Of course G ^ x must be a subgroup of H .
7.112. INNERAUTOMORPHISM
327
gap> d12 := Group( (1,2,3,4,5,6), (2,6)(3,5) );; d12.name := "d12";;
gap> c2 := Subgroup( d12, [ (2,6)(3,5) ] );
Subgroup( d12, [ (2,6)(3,5) ] )
gap> v4 := Subgroup( d12, [ (1,2)(3,6)(4,5), (1,4)(2,5)(3,6) ] );
Subgroup( d12, [ (1,2)(3,6)(4,5), (1,4)(2,5)(3,6) ] )
gap> x := ConjugationGroupHomomorphism( c2, v4, (1,3,5)(2,4,6) );
ConjugationGroupHomomorphism( Subgroup( d12,
[ (2,6)(3,5) ] ), Subgroup( d12, [ (1,2)(3,6)(4,5), (1,4)(2,5)(3,6)
] ), (1,3,5)(2,4,6) )
gap> IsSurjective( x );
false
gap> Image( x );
Subgroup( d12, [ (1,5)(2,4) ] )
ConjugationGroupHomomorphism calls
G.operations.ConjugationGroupHomomorphism( G, H , x ) and returns that value.
The default function called is GroupOps.ConjugationGroupHomomorphism. It just creates
a homomorphism record with range G, source H , and the component element with the
value x . It computes the image of an element g of G as g ^ x . If the sizes of the range
and the source are equal the inverse of such a homomorphism is computed as a conjugation
homomorphism from H to G by x ^-1. To multiply two such homomorphisms their elements
are multiplied. Look under ConjugationGroupHomomorphism in the index to see for
which groups this default function is overlaid.
7.112
InnerAutomorphism
InnerAutomorphism( G, g )
InnerAutomorphism returns the automorphism on the group G that takes each element h
to h ^ g. g must be an element in the parent group of G (but need not actually be in G)
that normalizes G.
gap> s5 := Group( (1,2), (1,2,3,4,5) );; s5.name := "s5";;
gap> i := InnerAutomorphism( s5, (1,2) );
InnerAutomorphism( s5, (1,2) )
gap> (1,2,3,4,5) ^ i;
(1,3,4,5,2)
InnerAutomorphism( G, g ) calls ConjugationGroupHomomorphism( G, G, g ) (see
7.111).
7.113
GroupHomomorphismByImages
GroupHomomorphismByImages( G, H , gens, imgs )
GroupHomomorphismByImages returns the group homomorphism with source G and range
H that is defined by mapping the list gens of generators of G to the list imgs of images in
H.
gap> g := Group( (1,2,3,4), (1,2) );;
gap> h := Group( (2,3), (1,2) );;
328
CHAPTER 7. GROUPS
gap> m := GroupHomomorphismByImages(g,h,g.generators,h.generators);
GroupHomomorphismByImages( Group( (1,2,3,4), (1,2) ), Group( (2,3),
(1,2) ), [ (1,2,3,4), (1,2) ], [ (2,3), (1,2) ] )
gap> Image( m, (1,3,4) );
(1,3,2)
gap> Kernel( m );
Subgroup( Group( (1,2,3,4), (1,2) ), [ (1,4)(2,3), (1,2)(3,4) ] )
Note that the result need not always be a single value mapping, even though the name
seems to imply this. Namely if the elements in imgs do not satisfy all relations that hold
for the generators gens, no element of G has a unique image under the mapping. This is
demonstrated in the following example.
gap> g := Group( (1,2,3,4,5,6,7,8,9,10) );;
gap> h := Group( (1,2,3,4,5,6) );;
gap> m := GroupHomomorphismByImages(g,h,g.generators,h.generators);
GroupHomomorphismByImages( Group( ( 1, 2, 3, 4, 5, 6, 7, 8, 9,10
) ), Group( (1,2,3,4,5,6) ), [ ( 1, 2, 3, 4, 5, 6, 7, 8, 9,10) ],
[ (1,2,3,4,5,6) ] )
gap> IsMapping( m );
false
gap> Images( m, () );
(Subgroup( Group( (1,2,3,4,5,6) ), [ ( 1, 3, 5)( 2, 4, 6) ] )*())
gap> g.1^10;
()
# the generator of g satisfies this relation
gap> h.1^10;
(1,5,3)(2,6,4)
# but its image does not
The set of images of the identity returned by Images is the set of elements h.1^n such that
g.1^n is the identity in g.
The test whether a mapping constructed by GroupHomomorphismByImages is a single valued
mapping, is usually quite expensive. Note that this test is automatically performed the
first time that you apply a function that expects a single valued mapping, e.g., Image or
Images. There are two possibilities to avoid this test. When you know that the mapping
constructed is really a single valued mapping, you can set the flag map.isMapping to true.
Then the functions assume that map is indeed a mapping and do not test it again. On
the other hand if you are not certain whether the mapping is single valued, you can use
ImagesRepresentative instead of Image (see 43.10). ImagesRepresentative returns just
one possible image, without testing whether there might actually be more than one possible
image.
GroupHomomorphismByImages calls
G.operations.GroupHomomorphismByImages( G, H , gens, imgs )
and returns this value.
The default function called this way is GroupOps.GroupHomomorphismByImages. Below we
describe how the mapping functions are implemented for such a mapping. The functions
not mentioned below are implemented by the default functions described in 7.109.
All the function below first compute the list of elements of G with an orbit algorithm, sorts
this list, and stores this list in hom.elements. In parallel they computes and sort a list of
images, and store this list in hom.images.
7.114. SET FUNCTIONS FOR GROUPS
329
IsMapping( map )
The mapping constructed by GroupHomomorphismByImages is a single valued mapping if for
each i and for each k the following equation holds
map.images[Position(map.elements,map.elements[i ]*gens[k ])]
= map.images[i ] * imgs[k ].
Image( map, elm )
If the mapping map is a single valued mapping, the image of an element elm is computed
as map.images[ Position(map.elements,elm) ].
ImagesRepresentative( map, elm )
The representative of the images of an element elm under the mapping map is computed as
map.images[ Position(map.elements,elm) ].
InverseMapping( map )
The inverse of the mapping map is constructed as GroupHomomorphismByImages( H , G,
imgs, gens ).
CompositionMapping( map1 , map2 )
If map2 is a mapping constructed by GroupHomomorphismByImages the composition is constructed by making a copy of map2 and replacing every element in map2 .images with its
image under map1 .
Look under GroupHomomorphismByImages in the index to see for which groups this
function is overlaid.
7.114
Set Functions for Groups
As already mentioned in the introduction of the chapter, groups are domains. Thus all set
theoretic functions, for example Intersection and Size can be applied to groups. This and
the following sections give further comments on the definition and implementations of those
functions for groups. All set theoretic functions not mentioned here not treated specially
for groups. The last section describes the format of the records that describe groups (see
7.118).
Elements( G )
The elements of a group G are constructed using a Dimino algorithm. See 7.115.
IsSubset( G, H )
If G and H are groups then IsSubset tests whether the generators of H are elements of G.
Otherwise DomainOps.IsSubset is used.
Intersection( G, H )
The intersection of groups G and H is computed using an orbit algorithm. See 7.116.
330
7.115
CHAPTER 7. GROUPS
Elements for Groups
GroupOps.Elements( G )
GroupOps.Elements returns the sets of elements of G (see 4.6). The function starts with the
trivial subgroup of G, for which the set of elements is known and constructs the successive
closures with the generators of G using GroupOps.Closure (see 7.18).
Note that this function neither checks nor sets the record component G.elements. It
recomputes the set of elements even it is bound to G.elements.
7.116. INTERSECTION FOR GROUPS
7.116
331
Intersection for Groups
GroupOps.Intersection( G, H )
GroupOps.Intersection returns the intersection of G and H either as set of elements or
as a group record (see 4.12).
If one argument, say G, is a set and the other a group, say H , then GroupOps.Intersection
returns the subset of elements of G which lie in H .
If G and H have different parent groups then GroupOps.Intersection uses the function
DomainOps.Intersection in order to compute the intersection.
Otherwise GroupOps.Intersection computes the stabilizer of the trivial coset of the bigger
group in the smaller group using Stabilizer and Coset.
7.117
Operations for Groups
G ^ s
The operator ^ evaluates to the subgroup conjugate to G under a group element s of the
parent group of G. See 7.20.
gap> s4 := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> s4.name := "s4";;
gap> v4 := Subgroup( s4, [ (1,2), (1,2)(3,4) ] );
Subgroup( s4, [ (1,2), (1,2)(3,4) ] )
gap> v4 ^ (2,3);
Subgroup( s4, [ (1,3), (1,3)(2,4) ] )
gap> v4 ^ (2,5);
Error, must be an element of the parent group of
s in G
The operator in evaluates to true if s is an element of G and false otherwise. s must be
an element of the parent group of G.
gap> (1,2,3,4) in v4;
false
gap> (2,4) in v4^(2,3);
true
G * s
The operator * evaluates to the right coset of G with representative s. s must be an element
of the parent group of G. See 7.86 for details about right cosets.
s * G
The operator * evaluates to the left coset of G with representative s. s must be an element
of the parent group of G. See 7.91 for details about left cosets.
332
CHAPTER 7. GROUPS
gap> v4 * (1,2,3,4);
(Subgroup( s4, [ (1,2), (1,2)(3,4) ] )*(1,2,3))
gap> (1,2,3,4) * v4;
((1,2,3,4)*Subgroup( s4, [ (1,2), (1,2)(3,4) ] ))
G / N
The operator / evaluates to the factor group G/N where N must be a normal subgroup of
G. This is the same as FactorGroup(G,N ) (see 7.33).
7.118
Group Records
As for all domains (see 4 and 4.1) groups and their subgroups are represented by records
that contain important information about groups. Most of the following functions return
such records. Of course it is possible to create a group record by hand but generally Group
(see 7.9) and Subgroup (see 7.12) should be used for such tasks.
Once a group record is created you may add record components to it but you must not alter
informations already present, especially not generators and identity.
Group records must always contain the components generators, identity, isDomain and
isGroup. Subgroups contain an additional component parent. The contents of all components of a group G are described below.
The following two components are the so-called category components used to identify
the category this domain belongs to.
isDomain
is always true as a group is a domain.
isGroup
is of course true as G is a group.
The following three components determine a group domain. These are the so-called identification components.
generators
is a list group generators. Duplicate generators are allowed but none of the generators
may be the group identity. The group G is the trivial group if and only if generators
is the empty list. Note that once created this entry must never be changed, as most
of the other entries depend on generators.
identity
is the group identity of G.
parent
if present this contains the group record of the parent group of a subgroup G, otherwise G itself is a parent group.
The following components are optional and contain knowledge about the group G.
abelianInvariants
a list of integers containing the abelian invariants of an abelian group G.
centralizer
contains the centralizer of G in its parent group.
7.118. GROUP RECORDS
333
centre
contains the centre of G. See 7.17.
commutatorFactorGroup
contains the commutator factor group of G. See 7.35 for details.
conjugacyClasses
contains a list of the conjugacy classes of G. See 7.68 for details.
core
contains the core of G under the action of its parent group. See 7.21 for details.
derivedSubgroup
contains the derived subgroup of G. See 7.22.
elements
is the set of all elements of G. See 4.6.
fittingSubgroup
contains the Fitting subgroup of G. See 7.23.
frattiniSubgroup
contains the Frattini subgroup of G. See 7.24.
index
contains the index of G in its parent group. See 7.51.
lowerCentralSeries
contains the lower central series of G as list of subgroups. See 7.41.
normalizer
contains the normalizer of G in its parent group. See 7.27 for details.
normalClosure
contains the normal closure of G in its parent group. See 7.25 for details.
upperCentralSeries
contains the upper central series of G as list of subgroups. See 7.44.
subnormalSeries
contains a subnormal series from the parent of G down to G. See 7.43 for details.
sylowSubgroups
contains a list of Sylow subgroups of G. See 7.31 for details.
size
is either an integer containing the size of a finite group or the string “infinity” if the
group is infinite. See 4.10.
perfectSubgroups
contains the a list of subgroups which includes at least one representative of each
class of conjugate proper perfect subgroups of G. See 7.75.
lattice
contains the subgroup lattice of G. See 7.75.
conjugacyClassesSubgroups
identical to the list G.lattice.classes, contains the conjugacy classes of subgroups
of G. See 7.74.
334
CHAPTER 7. GROUPS
tableOfMarks
contains the table of narks of G. See 48.4.
The following components are true if the group G has the property, false if not, and are
not present if it is unknown whether the group has the property or not.
isAbelian
is true if the group G is abelian. See 7.52.
isCentral
is true if the group G is central in its parent group. See 7.53.
isCyclic
is true if the group G is cyclic. See 7.55.
isElementaryAbelian
is true if the group G is elementary abelian. See 7.56.
isFinite
is true if the group G is finite. If you know that a group for which you want to
use the generic low level group functions is infinite, you should set this component to
false. This will avoid attempts to compute the set of elements.
isNilpotent
is true if the group G is nilpotent. See 7.57.
isNormal
is true if the group G is normal in its parent group. See 7.58.
isPerfect
is true if the group G is perfect. See 7.59.
isSimple
is true if the group G is simple. See 7.60.
isSolvable
is true if the group G is solvable. See 7.61.
isSubnormal
is true if the group G is subnormal in its parent group. See 7.63.
The component operations contains the operations record (see 4.1 and 4.2).
Chapter 8
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 d ∈ D
and each g ∈ G to another element dg ∈ D, which we call the image of d under g, such that
didentity = d and (dg )h = dgh for each d ∈ D and g, h ∈ 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.
An example of the usage of the functions in this package can be found in the introduction
to GAP3 (see 1.19).
In GAP3 group elements usually operate through the power operator, which is denoted by
the caret ^. It is possible however to specify other operations (see 8.1).
First this chapter describes the functions that take a single element of the group and compute
cycles of this group element and related information (see 8.2, 8.3, 8.4, and 8.5), and the
function that describes how a group element operates by a permutation that operates the
same way on [1..n] (see 8.8).
Next come the functions that test whether an orbit has minimal or maximal length and
related functions (see 8.9, 8.10, 8.11, 8.12, and 8.13).
Next this chapter describes the functions that take a group and compute orbits of this group
and related information (see 8.16, 8.17, 8.18, and 8.19).
Next are the functions that compute the permutation group P that operates on [ 1 ..
Length(D) ] in the same way that G operates on D, and the corresponding homomorphism
from G to P (see 8.20, 8.21).
Next is the functions that compute block systems, i.e., partitions of D such that G operates
on the sets of the partition (see 8.22), and the function that tests whether D has such a
nontrivial partitioning under the operation of G (see 8.23).
Finally come the functions that relate an orbit of G on D with the subgroup of G that fixes
the first point in the orbit (see 8.24), and the cosets of this subgroup in G (see 8.25 and
8.26).
All functions described in this chapter are in LIBNAME/"operatio.g".
335
336
8.1
CHAPTER 8. OPERATIONS OF GROUPS
Other Operations
The functions in the operation package generally compute with the operation of group
elements defined by the canonical operation that is denoted with the caret (^) in GAP3.
However they also allow you to specify other operations. Such operations are specified by
functions, which are accepted as optional argument by all the operations package functions.
This function must accept two arguments. The first argument will be the point and the
second will be the group element. The function must return the image of the point under
the group element.
As an example, the function OnPairs that specifies the operation on pairs could be defined
as follows
OnPairs := function ( pair, g )
return [ pair[1] ^ g, pair[2] ^ g ];
end;
The following operations are predefined.
OnPoints
specifies the canonical default operation. Passing this function is equivalent to specifying no operation. This function exists because there are places where the operation
in not an option.
OnPairs
specifies the componentwise operation of group elements on pairs of points, which are
represented by lists of length 2.
OnTuples
specifies the componentwise operation of group elements on tuples of points, which
are represented by lists. OnPairs is the special case of OnTuples for tuples with two
elements.
OnSets
specifies the operation of group elements on sets of points, which are represented by
sorted lists of points without duplicates (see 28).
OnRight
specifies that group elements operate by multiplication from the right.
OnLeftInverse
specifies that group elements operate by multiplication by their inverses from the left.
This is an operation, unlike OnLeftAntiOperation (see below).
OnRightCosets
specifies that group elements operate by multiplication from the right on sets of
points, which are represented by sorted lists of points without duplicates (see 28).
OnLeftCosets
specifies that group elements operate by multiplication from the left on sets of points,
which are represented by sorted lists of points without duplicates (see 28).
OnLines
specifies that group elements, which must be matrices, operate on lines, which are
represented by vectors with first nonzero coefficient one. That is, OnLines multiplies
8.2. CYCLE
337
the vector by the group element and then divides the vector by the first nonzero
coefficient.
Note that it is your responsibility to make sure that the elements of the domain D on which
you are operating are already in normal form. The reason is that all functions will compare
points using the = operation. For example, if you are operating on sets with OnSets, you
will get an error message it not all elements of the domain are sets.
gap> Cycle( (1,2), [2,1], OnSets );
Error, OnSets: must be a set
The former function OnLeft which operated by mulitplication from the left has been renamed
OnLeftAntiOperation, to emphasise the point that it does not satisify the axioms of an
operation, and may cause errors if supplied where an operation is expected.
8.2
Cycle
Cycle( g, d )
Cycle( g, d , operation )
Cycle returns the orbit of the point d , which may be an object of arbitrary type, under the
group element g as a list of points.
The points e in the cycle of d under the group element g are those for which a power g i
i
exists such that dg = e.
The first point in the list returned by Cycle is the point d itself, the ordering of the other
points is such that each point is the image of the previous point.
Cycle accepts a function operation of two arguments d and g as optional third argument,
which specifies how the element g operates (see 8.1).
gap> Cycle( (1,5,3,8)(4,6,7), 3 );
[ 3, 8, 1, 5 ]
gap> Cycle( (1,5,3,8)(4,6,7), [3,4], OnPairs );
[ [ 3, 4 ], [ 8, 6 ], [ 1, 7 ], [ 5, 4 ], [ 3, 6 ], [ 8, 7 ],
[ 1, 4 ], [ 5, 6 ], [ 3, 7 ], [ 8, 4 ], [ 1, 6 ], [ 5, 7 ] ]
Cycle calls
Domain([g]).operations.Cycle( g, d , operation )
and returns the value. Note that the third argument is not optional for the functions called
this way.
The default function called this way is GroupElementsOps.Cycle, which starts with d and
applies g to the last point repeatedly until d is reached again. Special categories of group
elements overlay this default function with more efficient functions.
8.3
CycleLength
CycleLength( g, d )
CycleLength( g, d , operation )
CycleLength returns the length of the orbit of the point d , which may be an object of
arbitrary type, under the group elements g. See 8.2 for the definition of cycles.
338
CHAPTER 8. OPERATIONS OF GROUPS
CycleLength accepts a function operation of two arguments d and g as optional third
argument, which specifies how the group element g operates (see 8.1).
gap> CycleLength( (1,5,3,8)(4,6,7), 3 );
4
gap> CycleLength( (1,5,3,8)(4,6,7), [3,4], OnPairs );
12
CycleLength calls
Domain([g]).operations.CycleLength( g, d , operation )
and returns the value. Note that the third argument is not optional for the functions called
this way.
The default function called this way is GroupElementsOps.CycleLength, which starts with
d and applies g to the last point repeatedly until d is reached again. Special categories of
group elements overlay this default function with more efficient functions.
8.4
Cycles
Cycles( g, D )
Cycles( g, D, operation )
Cycles returns the set of cycles of the group element g on the domain D, which must be a
list of points of arbitrary type, as a set of lists of points. See 8.2 for the definition of cycles.
It is allowed that D is a proper subset of a domain, i.e., that D is not invariant under the
operation of g. In this case D is silently replaced by the smallest superset of D which is
invariant.
The first point in each cycle is the smallest point of D in this cycle. The ordering of the
other points is such that each point is the image of the previous point. If D is invariant
under g, then because Cycles returns a set of cycles, i.e., a sorted list, and because cycles
are compared lexicographically, and because the first point in each cycle is the smallest point
in that cycle, the list returned by Cycles is in fact sorted with respect to the smallest point
in the cycles.
Cycles accepts a function operation of two arguments d and g as optional third argument,
which specifies how the element g operates (see 8.1).
gap> Cycles( (1,5,3,8)(4,6,7), [3,5,7] );
[ [ 3, 8, 1, 5 ], [ 7, 4, 6 ] ]
gap> Cycles( (1,5,3,8)(4,6,7), [[1,3],[4,6]], OnPairs );
[ [ [ 1, 3 ], [ 5, 8 ], [ 3, 1 ], [ 8, 5 ] ],
[ [ 4, 6 ], [ 6, 7 ], [ 7, 4 ] ] ]
Cycles calls
Domain([g]).operations.Cycles( g, D, operation )
and returns the value. Note that the third argument is not optional for the functions called
this way.
The default function called this way is GroupElementsOps.Cycles, which takes elements
from D, computes their orbit, removes all points in the orbit from D, and repeats this until
D has been emptied. Special categories of group elements overlay this default function with
more efficient functions.
8.5. CYCLELENGTHS
8.5
339
CycleLengths
CycleLengths( g, D )
CycleLengths( g, D, operation )
CycleLengths returns a list of the lengths of the cycles of the group element g on the domain
D, which must be a list of points of arbitrary type. See 8.2 for the definition of cycles.
It is allowed that D is a proper subset of a domain, i.e., that D is not invariant under the
operation of g. In this case D is silently replaced by the smallest superset of D which is
invariant.
The ordering of the lengths of cycles in the list returned by CycleLengths corresponds to
the list of cycles returned by Cycles, which is ordered with respect to the smallest point in
each cycle.
CycleLengths accepts a function operation of two arguments d and g as optional third
argument, which specifies how the element g operates (see 8.1).
gap>
[ 4,
gap>
[ 4,
CycleLengths( (1,5,3,8)(4,6,7), [3,5,7] );
3 ]
CycleLengths( (1,5,3,8)(4,6,7), [[1,3],[4,6]], OnPairs );
3 ]
CycleLengths calls
Domain([g]).operations.CycleLengths( g, D, operation )
and returns the value. Note that the third argument is not optional for the functions called
this way.
The default function called this way is GroupElementsOps.CycleLengths, which takes elements from D, computes their orbit, removes all points in the orbit from D, and repeats
this until D has been emptied. Special categories of group elements overlay this default
function with more efficient functions.
8.6
MovedPoints
MovedPoints( g )
gap> MovedPoints( (1,7)(2,3,8) );
[ 1, 2, 3, 7, 8 ]
8.7
NrMovedPoints
NrMovedPoints( p )
NrMovedPoints returns the number of points moved by the permutation g, the group element g, or the group g.
gap> NrMovedPoints( (1,7)(2,3,8) );
5
340
8.8
CHAPTER 8. OPERATIONS OF GROUPS
Permutation
Permutation( g, D )
Permutation( g, D, operation )
Permutation returns a permutation that operates on the points [1..Length(D)] in the
same way that the group element g operates on the domain D, which may be a list of
arbitrary type.
It is not allowed that D is a proper subset of a domain, i.e., D must be invariant under the
element g.
Permutation accepts a function operation of two arguments d and g as optional third
argument, which specifies how the element g operates (see 8.1).
gap> Permutation( (1,5,3,8)(4,6,7), [4,7,6] );
(1,3,2)
gap> D := [ [1,4], [1,6], [1,7], [3,4], [3,6], [3,7],
>
[4,5], [5,6], [5,7], [4,8], [6,8], [7,8] ];;
gap> Permutation( (1,5,3,8)(4,6,7), D, OnSets );
( 1, 8, 6,10, 2, 9, 4,11, 3, 7, 5,12)
Permutation calls
Domain([g]).operations.Permutation( g, D, operation )
and returns the value. Note that the third argument is not optional for the functions called
this way.
The default function called this way is GroupElementsOps.Permutation, which simply applies g to all the points of D, finds the position of the image in D, and finally applies
PermList (see 20.9) to the list of those positions. Actually this is not quite true. Because
finding the position of an image in a sorted list is so much faster than finding it in D,
GroupElementsOps.Permutation first sorts a copy of D and remembers how it had to rearrange the elements of D to achieve this. Special categories of group elements overlay this
default function with more efficient functions.
8.9
IsFixpoint
IsFixpoint( G, d )
IsFixpoint( G, d , operation )
IsFixpoint returns true if the point d is a fixpoint under the operation of the group G.
We say that d is a fixpoint under the operation of G if every element g of G maps d to
itself. This is equivalent to saying that each generator of G maps d to itself.
As a special case it is allowed that the first argument is a single group element, though this
does not make a lot of sense, since in this case IsFixpoint simply has to test d ^g = d .
IsFixpoint accepts a function operation of two arguments d and g as optional third argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> IsFixpoint( g, 1 );
false
gap> IsFixpoint( g, [6,7,8], OnSets );
8.10. ISFIXPOINTFREE
341
true
IsFixpoint is so simple that it does all the work by itself, and, unlike the other functions
described in this chapter, does not dispatch to another function.
8.10
IsFixpointFree
IsFixpointFree( G, D )
IsFixpointFree( G, D, operation )
IsFixpointFree returns true if the group G operates without a fixpoint (see 8.9) on the
domain D, which must be a list of points of arbitrary type.
We say that G operates fixpoint free on the domain D if each point of D is moved by at
least one element of G. This is equivalent to saying that each point of D is moved by at
least one generator of G. This definition also applies in the case that D is a proper subset
of a domain, i.e., that D is not invariant under the operation of G.
As a special case it is allowed that the first argument is a single group element.
IsFixpointFree accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> IsFixpointFree( g, [1..8] );
true
gap> sets := Combinations( [1..8], 3 );; Length( sets );
56
# a list of all three element subsets of [1..8]
gap> IsFixpointFree( g, sets, OnSets );
false
IsFixpointFree calls
G.operations.IsFixpointFree( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.IsFixpointFree, which simply loops over
the elements of D and applies to each all generators of G, and tests whether each is moved
by at least one generator. This function is seldom overlaid, because it is very difficult to
improve it.
8.11
DegreeOperation
DegreeOperation( G, D )
DegreeOperation( G, D, operation )
DegreeOperation returns the degree of the operation of the group G on the domain D,
which must be a list of points of arbitrary type.
The degree of the operation of G on D is defined as the number of points of D that are
properly moved by at least one element of G. This definition also applies in the case that
D is a proper subset of a domain, i.e., that D is not invariant under the operation of G.
DegreeOperation accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
342
CHAPTER 8. OPERATIONS OF GROUPS
gap>
gap>
8
gap>
56
gap>
55
g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
DegreeOperation( g, [1..10] );
sets := Combinations( [1..8], 3 );; Length( sets );
# a list of all three element subsets of [1..8]
DegreeOperation( g, sets, OnSets );
DegreeOperation calls
G.operations.DegreeOperation( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.DegreeOperation, which simply loops
over the elements of D and applies to each all generators of G, and counts those that are
moved by at least one generator. This function is seldom overlaid, because it is very difficult
to improve it.
8.12
IsTransitive
IsTransitive( G, D )
IsTransitive( G, D, operation )
IsTransitive returns true if the group G operates transitively on the domain D, which
must be a list of points of arbitrary type.
We say that a group G acts transitively on a domain D if and only if for every pair of
points d and e there is an element g of G such that dg = e. An alternative characterization
of this property is to say that D as a set is equal to the orbit of every single point.
It is allowed that D is a proper subset of a domain, i.e., that D is not invariant under the
operation of G. In this case IsTransitive checks whether for every pair of points d , e of
D there is an element g of G, such that dg = e. This can also be characterized by saying
that D is a subset of the orbit of every single point.
IsTransitive accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> IsTransitive( g, [1..8] );
false
gap> IsTransitive( g, [1,6] );
false
# note that the domain need not be invariant
gap> sets := Combinations( [1..5], 3 );; Length( sets );
10
# a list of all three element subsets of [1..5]
gap> IsTransitive( g, sets, OnSets );
true
IsTransitive calls
G.operations.IsTransitive( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
8.13. TRANSITIVITY
343
The default function called this way is GroupOps.IsTransitive, which tests whether D is
a subset of the orbit of the first point in D. This function is seldom overlaid, because it is
difficult to improve it.
8.13
Transitivity
Transitivity( G, D )
Transitivity( G, D, operation )
Transitivity returns the degree of transitivity of the group G on the domain D, which
must be a list of points of arbitrary type. If G does not operate transitively on D then
Transitivity returns 0.
The degree of transitivity of the operation of G on D is the largest k such that G
operates k -fold transitively on D. We say that G operates k -fold transitively on D if
it operates transitively on D (see 8.12) and the stabilizer of one point d of D operates
k -1-fold transitively on Difference(D,[d ]). Because the stabilizers of the points of D
are conjugate this is equivalent to saying that the stabilizer of each point d of D operates
k -1-fold transitively on Difference(D,[d ]).
It is not allowed that D is a proper subset of a domain, i.e., D must be invariant under the
operation of G.
Transitivity accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
gap>
gap>
0
gap>
3
gap>
10
gap>
1
g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
Transitivity( g, [1..8] );
Transitivity( g, [1..5] );
sets := Combinations( [1..5], 3 );; Length( sets );
# a list of all three element subsets of [1..5]
Transitivity( g, sets, OnSets );
Transitivity calls
G.operations.Transitivity( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.Transitivity, which first tests whether
G operates transitively on D. If so, it returns
Transitivity(Stabilizer(G,Difference(D,[D[1]]),operation)+1;
if not, it simply returns 0. Special categories of groups overlay this default function with
more efficient functions.
8.14
IsRegular
IsRegular( G, D ) IsRegular( G, D, operation )
IsRegular returns true if the group G operates regularly on the domain D, which must be
a list of points of arbitrary type, and false otherwise.
344
CHAPTER 8. OPERATIONS OF GROUPS
A group G operates regularly on a domain D if it operates transitively and no element
of G other than the idenity leaves a point of D fixed. An equal characterisation is that
G operates transitively on D and the stabilizer of any point of D is trivial. Yet another
characterisation is that the operation of G on D is equivalent to the operation of G on its
elements by multiplication from the right.
It is not allowed that D is a proper subset of a domain, i.e., D must be invariant under the
operation of G.
IsRegular accepts a function operation of two arguments d and g as optional third argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> IsRegular( g, [1..5] );
false
gap> IsRegular( g, Elements(g), OnRight );
true
gap> g := Group( (1,2,3), (3,4,5) );;
gap> IsRegular( g, Orbit( g, [1,2,3], OnTuples ), OnTuples );
true
IsRegular calls
G.operations.IsRegular( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.IsRegular, which tests if G operates
transitively and semiregularly on D (see 8.12 and 8.15).
8.15
IsSemiRegular
IsSemiRegular( G, D )
IsSemiRegular( G, D, operation )
IsSemiRegular returns true if the group G operates semiregularly on the domain D, which
must be a list of points of arbitrary type, and false otherwise.
A group G operates semiregularly on a domain D if no element of G other than the idenity
leaves a point of D fixed. An equal characterisation is that the stabilizer of any point of
D is trivial. Yet another characterisation is that the operation of G on D is equivalent to
multiple copies of the operation of G on its elements by multiplication from the right.
It is not allowed that D is a proper subset of a domain, i.e., D must be invariant under the
operation of G.
IsSemiRegular accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2)(3,4)(5,7)(6,8), (1,3)(2,4)(5,6)(7,8) );;
gap> IsSemiRegular( g, [1..8] );
true
gap> g := Group( (1,2)(3,4)(5,7)(6,8), (1,3)(2,4)(5,6,7,8) );;
gap> IsSemiRegular( g, [1..8] );
false
8.16. ORBIT
345
gap> IsSemiRegular( g, Orbit( g, [1,5], OnSets ), OnSets );
true
IsSemiRegular calls
G.operations.IsSemiRegular( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.IsSemiRegular, which computes a permutation group P that operates on [1..Length(D)] in the same way that G operates
on D (see 8.20) and then checks if this permutation group operations semiregularly. This
of course only works because this default function is overlaid for permutation groups (see
21.22).
8.16
Orbit
Orbit( G, d )
Orbit( G, d , operation )
Orbit returns the orbit of the point d , which may be an object of arbitrary type, under the
group G as a list of points.
The points e in the orbit of d under the group G are those points for which a group element
g of G exists such that dg = e.
Suppose G has n generators. First we order the words of the free monoid with n abstract
generators according to length and for words with equal length lexicographically. So if G has
two generators called a and b the ordering is identity, a, b, a2 , ab, ba, b2 , a3 , .... Next we order
the elements of G that can be written as a product of the generators, i.e., without inverses
of the generators, according to the first occurrence of a word representing the element in the
above ordering. Then the ordering of points in the orbit returned by Orbit is according to
the order of the first representative of each point e, i.e., the smallest g such that dg = e. Note
that because the orbit is finite there is for every point in the orbit at least one representative
that can be written as a product in the generators of G.
Orbit accepts a function operation of two arguments d and g as optional third argument,
which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> Orbit( g, 1 );
[ 1, 2, 3, 4, 5 ]
gap> Orbit( g, 2 );
[ 2, 3, 1, 4, 5 ]
gap> Orbit( g, [1,6], OnPairs );
[ [ 1, 6 ], [ 2, 7 ], [ 3, 6 ], [ 2, 8 ], [ 1, 7 ], [ 4, 6 ],
[ 3, 8 ], [ 2, 6 ], [ 1, 8 ], [ 4, 7 ], [ 5, 6 ], [ 3, 7 ],
[ 5, 8 ], [ 5, 7 ], [ 4, 8 ] ]
Orbit calls
G.operations.Orbit( G, d , operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
346
CHAPTER 8. OPERATIONS OF GROUPS
The default function called this way is GroupOps.Orbit, which performs an ordinary orbit
algorithm. Special categories of groups overlay this default function with more efficient
functions.
8.17
OrbitLength
OrbitLength( G, d )
OrbitLength( G, d , operation )
OrbitLength returns the length of the orbit of the point d , which may be an object of
arbitrary type, under the group G. See 8.16 for the definition of orbits.
OrbitLength accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
gap>
gap>
5
gap>
1
gap>
15
g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
OrbitLength( g, 1 );
OrbitLength( g, 10 );
OrbitLength( g, [1,6], OnPairs );
OrbitLength calls
G.operations.OrbitLength( G, d , operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.OrbitLength, which performs an ordinary
orbit algorithm. Special categories of groups overlay this default function with more efficient
functions.
8.18
Orbits
Orbits( G, D )
Orbits( G, D, operation )
Orbits returns the orbits of the group G on the domain D, which must be a list of points
of arbitrary type, as a set of lists of points. See 8.16 for the definition of orbits.
It is allowed that D is a proper subset of a domain, i.e., that D is not invariant under the
operation of G. In this case D is silently replaced by the smallest superset of D which is
invariant.
The first point in each orbit is the smallest point, the other points of each orbit are ordered
in the standard order defined for orbits (see 8.16). Because Orbits returns a set of orbits,
i.e., a sorted list, and because those orbits are compared lexicographically, and because the
first point in each orbit is the smallest point in that orbit, the list returned by Orbits is in
fact sorted with respect to the smallest points the orbits.
Orbits accepts a function operation of two arguments d and g as optional third argument,
which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
8.19. ORBITLENGTHS
gap> Orbits( g, [1..8] );
[ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8 ] ]
gap> Orbits( g, [1,6] );
[ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8 ] ]
# the domain is not invariant
gap> sets := Combinations( [1..8], 3 );; Length( sets );
56
# a list of all three element subsets of [1..8]
gap> Orbits( g, sets, OnSets );
[ [ [ 1, 2, 3 ], [ 1, 2, 4 ], [ 2, 3, 4 ], [ 1, 2, 5 ], [ 1, 3, 4
[ 2, 4, 5 ], [ 2, 3, 5 ], [ 1, 4, 5 ], [ 3, 4, 5 ], [ 1, 3,
],
[ [ 1, 2, 6 ], [ 2, 3, 7 ], [ 1, 3, 6 ], [ 2, 4, 8 ], [ 1, 2, 7
[ 1, 4, 6 ], [ 3, 4, 8 ], [ 2, 5, 7 ], [ 2, 3, 6 ],
[ 1, 2, 8 ], [ 2, 4, 7 ], [ 1, 5, 6 ], [ 1, 4, 8 ],
[ 4, 5, 7 ], [ 3, 5, 6 ], [ 2, 3, 8 ], [ 1, 3, 7 ],
[ 2, 4, 6 ], [ 3, 4, 6 ], [ 2, 5, 8 ], [ 1, 5, 7 ],
[ 4, 5, 6 ], [ 3, 5, 8 ], [ 1, 3, 8 ], [ 3, 4, 7 ],
[ 2, 5, 6 ], [ 1, 4, 7 ], [ 1, 5, 8 ], [ 4, 5, 8 ], [ 3, 5,
],
[ [ 1, 6, 7 ], [ 2, 6, 7 ], [ 1, 6, 8 ], [ 3, 6, 7 ], [ 2, 6, 8
[ 2, 7, 8 ], [ 4, 6, 8 ], [ 3, 7, 8 ], [ 3, 6, 8 ],
[ 4, 7, 8 ], [ 5, 6, 7 ], [ 1, 7, 8 ], [ 4, 6, 7 ],
[ 5, 7, 8 ], [ 5, 6, 8 ] ], [ [ 6, 7, 8 ] ] ]
347
],
5 ]
],
7 ]
],
Orbits calls
G.operations.Orbits( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.Orbits, which takes an element from D,
computes its orbit, removes all points in the orbit from D, and repeats this until D has
been emptied. Special categories of groups overlay this default function with more efficient
functions.
8.19
OrbitLengths
OrbitLengths( G, D )
OrbitLengths( G, D, operation )
OrbitLengths returns a list of the lengths of the orbits of the group G on the domain D,
which may be a list of points of arbitrary type. See 8.16 for the definition of orbits.
It is allowed that D is proper subset of a domain, i.e., that D is not invariant under the
operation of G. In this case D is silently replaced by the smallest superset of D which is
invariant.
The ordering of the lengths of orbits in the list returned by OrbitLengths corresponds to
the list of cycles returned by Orbits, which is ordered with respect to the smallest point in
each orbit.
OrbitLengths accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
348
CHAPTER 8. OPERATIONS OF GROUPS
gap> OrbitLengths( g, [1..8] );
[ 5, 3 ]
gap> sets := Combinations( [1..8], 3 );; Length( sets );
56
# a list of all three element subsets of [1..8]
gap> OrbitLengths( g, sets, OnSets );
[ 10, 30, 15, 1 ]
OrbitLengths calls
G.operations.OrbitLenghts( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.OrbitLengths, which takes an element
from D, computes its orbit, removes all points in the orbit from D, and repeats this until
D has been emptied. Special categories of groups overlay this default function with more
efficient functions.
8.20
Operation
Operation( G, D )
Operation( G, D, operation )
Operation returns a permutation group with the same number of generators as G, such
that each generator of the permutation group operates on the set [1..Length(D)] in the
same way that the corresponding generator of the group G operates on the domain D, which
may be a list of arbitrary type.
It is not allowed that D is a proper subset of a domain, i.e., D must be invariant under the
element g.
Operation accepts a function operation of two arguments d and g as optional third argument, which specifies how the elements of G operate (see 8.1).
The function OperationHomomorphism (see 8.21) can be used to compute the homomorphism that maps G onto the new permutation group. Of course if you are only interested in
mapping single elements of G into the new permutation group you may also use Permutation
(see 8.8).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> Operation( g, [1..5] );
Group( (1,2,3), (3,4,5) )
gap> Operation( g, Orbit( g, [1,6], OnPairs ), OnPairs );
Group( ( 1, 2, 3, 5, 8,12)( 4, 7, 9)( 6,10)(11,14), ( 2, 4)( 3, 6,11)
( 5, 9)( 7,10,13,12,15,14) )
Operation calls
G.operations.Operation( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.Operation, which simply applies each
generator of G to all the points of D, finds the position of the image in D, and finally
applies PermList (see 20.9) to the list of those positions. Actually this is not quite true.
Because finding the position on an image in a sorted list is so much faster than finding it
8.21. OPERATIONHOMOMORPHISM
349
in D, GroupElementsOps.Operation first sorts a copy of D and remembers how it had to
rearrange the elements of D to achieve this. Special categories of groups overlay this default
function with more efficient functions.
8.21
OperationHomomorphism
OperationHomomorphism( G, P )
OperationHomomorphism returns the group homomorphism (see 7.106) from the group G
to the permutation group P , which must be the result of a prior call to Operation (see
8.20) with G or a group of which G is a subgroup (see 7.62) as first argument.
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> h := Operation( g, [1..5] );
Group( (1,2,3), (3,4,5) )
gap> p := OperationHomomorphism( g, h );
OperationHomomorphism( Group( (1,2,3)(6,7), (3,4,5)(7,8) ), Group(
(1,2,3), (3,4,5) ) )
gap> (1,4,2,5,3)(6,7,8) ^ p;
(1,4,2,5,3)
gap> h := Operation( g, Orbit( g, [1,6], OnPairs ), OnPairs );
Group( ( 1, 2, 3, 5, 8,12)( 4, 7, 9)( 6,10)(11,14), ( 2, 4)( 3, 6,11)
( 5, 9)( 7,10,13,12,15,14) )
gap> p := OperationHomomorphism( g, h );;
gap> s := SylowSubgroup( g, 2 );
Subgroup( Group( (1,2,3)(6,7), (3,4,5)(7,8) ),
[ (7,8), (7,8), (2,5)(3,4), (2,3)(4,5) ] )
gap> Images( p, s );
Subgroup( Group( ( 1, 2, 3, 5, 8,12)( 4, 7, 9)( 6,10)(11,14), ( 2, 4)
( 3, 6,11)( 5, 9)( 7,10,13,12,15,14) ),
[ ( 2, 4)( 5, 9)( 7,12)(10,15)(13,14),
( 2, 4)( 5, 9)( 7,12)(10,15)(13,14),
( 2,14)( 3, 6)( 4,13)( 7,15)( 8,11)(10,12),
( 2,12)( 3, 8)( 4, 7)( 6,11)(10,14)(13,15) ] )
gap> OperationHomomorphism( g, Group( (1,2,3), (3,4,5) ) );
Error, Record: element ’operation’ must have an assigned value
OperationHomomorphism calls
P .operations.OperationHomomorphism( G, P )
and returns the value.
The default function called this way is GroupOps.OperationHomomorphism, which uses the
fields P .operationGroup, P .operationDomain, and P .operationOperation (the arguments to the Operation call that created P ) to construct a generic homomorphism h. This
homomorphism uses
Permutation(g,h.range.operationDomain,h.range.operationOperation)
to compute the image of an element g of G under h. It uses Representative to compute
the preimages of an element p of P under h. And it computes the kernel by intersecting
the cores (see 7.21) of the stabilizers (see 8.24) of representatives of the orbits of G. Look
under OperationHomomorphism in the index to see for which groups and operations
this function is overlaid.
350
CHAPTER 8. OPERATIONS OF GROUPS
8.22
Blocks
Blocks( G, D, seed )
Blocks( G, D, seed , operation )
In this form Blocks returns a block system of the domain D, which may be a list of points
of arbitrary type, under the group G, such that the points in the list seed all lie in the same
block. If no such nontrivial block system exists, Blocks returns [ D ]. G must operate
transitively on D, otherwise an error is signalled.
Blocks( G, D )
Blocks( G, D, operation )
In this form Blocks returns a minimal block system of the domain D, which may be a list
of points of arbitrary type, under the group G. If no nontrivial block system exists, Blocks
returns [ D ]. G must operate transitively on D, otherwise an error is signalled.
A block system B is a list of blocks with the following properties. Each block b of B is
a subset of D. The blocks are pairwise disjoint. The union of blocks is D. The image of
each block under each element g of G is as a set equal to some block of the block system.
Note that this implies that all blocks contain the same number of elements as G operates
transitive on D. Put differently a block system B of D is a partition of D such that G
operates with OnSets (see 8.1) on B . The block system that consists of only singleton sets
and the block system consisting only of D are called trivial. A block system B is called
minimal if there is no nontrivial block system whose blocks are all subsets of the blocks of
B and whose number of blocks is larger than the number of blocks of B .
Blocks accepts a function operation of two arguments d and g as optional third, resp.
fourth, argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> Blocks( g, [1..5] );
[ [ 1 .. 5 ] ]
gap> Blocks( g, Orbit( g, [1,2], OnPairs ), OnPairs );
[ [ [ 1, 2 ], [ 3, 2 ], [ 4, 2 ], [ 5, 2 ] ],
[ [ 1, 3 ], [ 2, 3 ], [ 4, 3 ], [ 5, 3 ] ],
[ [ 1, 4 ], [ 2, 4 ], [ 3, 4 ], [ 5, 4 ] ],
[ [ 1, 5 ], [ 2, 5 ], [ 3, 5 ], [ 4, 5 ] ],
[ [ 2, 1 ], [ 3, 1 ], [ 4, 1 ], [ 5, 1 ] ] ]
Blocks calls
G.operations.Blocks( G, D, seed , operation )
and returns the value. If no seed was given as argument to Blocks it passes the empty list.
Note that the fourth argument is not optional for functions called this way.
The default function called this way is GroupOps.Blocks, which computes a permutation
group P that operates on [1..Length(D)] in the same way that G operates on D (see
8.20) and leaves it to this permutation group to find the blocks. This of course works only
because this default function is overlaid for permutation groups (see 21.22).
8.23
IsPrimitive
IsPrimitive( G, D )
IsPrimitive( G, D, operation )
8.24. STABILIZER
351
IsPrimitive returns true if the group G operates primitively on the domain D, which may
be a list of points of arbitrary type, and false otherwise.
A group G operates primitively on a domain D if and only if D operates transitively (see
8.12) and has only the trivial block systems (see 8.22).
IsPrimitive accepts a function operation of two arguments d and g as optional third
argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> IsPrimitive( g, [1..5] );
true
gap> IsPrimitive( g, Orbit( g, [1,2], OnPairs ), OnPairs );
false
IsPrimitive calls
G.operations.IsPrimitive( G, D, operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.IsPrimitive, which simply calls Blocks(
G, D, operation ) and tests whether the returned block system is [ D ]. This function
is seldom overlaid, because all the important work is done in Blocks.
8.24
Stabilizer
Stabilizer( G, d )
Stabilizer( G, d , operation )
Stabilizer returns the stabilizer of the point d under the operation of the group G.
The stabilizer S of d in G is the subgroup of those elements g of G that fix d, i.e., for
which dg = d. The right cosets of S correspond in a canonical way to the points p in the
orbit O of d under G; namely all elements from a right coset Sg map d to the same point
dg ∈ O, and elements from different right cosets Sg and Sh map d to different points dg
and dh . Thus the index of the stabilizer S in G is equal to the length of the orbit O.
RepresentativesOperation (see 8.26) computes a system of representatives of the right
cosets of S in G.
Stabilizer accepts a function operation of two arguments d and g as optional third argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> g.name := "G";;
gap> Stabilizer( g, 1 );
Subgroup( G, [ (3,4,5)(7,8), (2,5,3)(6,7) ] )
gap> Stabilizer( g, [1,2,3], OnSets );
Subgroup( G, [ (7,8), (6,8), (2,3)(4,5)(6,7,8), (1,2)(4,5)(6,7,8) ] )
Stabilizer calls
G.operations.Stabilizer( G, d , operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
352
CHAPTER 8. OPERATIONS OF GROUPS
The default function called this way is GroupOps.Stabilizer, which computes the orbit of d
under G, remembers a representative re for each point e in the orbit, and uses Schreier’s theorem, which says that the stabilizer is generated by the elements re gre−1
g . Special categories
of groups overlay this default function with more efficient functions.
8.25
RepresentativeOperation
RepresentativeOperation( G, d , e )
RepresentativeOperation( G, d , e, operation )
RepresentativeOperation returns a representative of the point e in the orbit of the point
d under the group G. If d = e then RepresentativeOperation returns G.identity, otherwise it is not specified which group element RepresentativeOperation will return if there
are several that map d to e. If e is not in the orbit of d under G, RepresentativeOperation
returns false.
An element g of G is called a representative for the point e in the orbit of d under G if g
maps d to e, i.e., dg = e. Note that the set of such representatives that map d to e forms a
right coset of the stabilizer of d in G (see 8.24).
RepresentativeOperation accepts a function operation of two arguments d and g as optional third argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> RepresentativeOperation( g, 1, 5 );
(1,5,4,3,2)(6,8,7)
gap> RepresentativeOperation( g, 1, 6 );
false
gap> RepresentativeOperation( g, [1,2,3], [3,4,5], OnSets );
(1,3,5,2,4)
gap> RepresentativeOperation( g, [1,2,3,4], [3,4,5,2], OnTuples );
false
RepresentativeOperation calls
G.operations.RepresentativeOperation( G, d , e, operation )
and returns the value. Note that the fourth argument is not optional for functions called
this way.
The default function called this way is GroupOper.RepresentativeOperation, which starts
a normal orbit calculation to compute the orbit of d under G, and remembers for each
point how it was obtained, i.e., which generator of G took which orbit point to this new
point. When the point e appears this information can be traced back to write down the
representative of e as a word in the generators. Special categories of groups overlay this
default function with more efficient functions.
8.26
RepresentativesOperation
RepresentativesOperation( G, d )
RepresentativesOperation( G, d , operation )
RepresentativesOperation returns a list of representatives of the points in the orbit of
the point d under the group G.
8.27. ISEQUIVALENTOPERATION
353
The ordering of the representatives corresponds to the ordering of the points in the orbit
as returned by Orbit (see 8.16). Therefore List( RepresentativesOperation(G,d ),
r->d ^r ) = Orbit(G,d ).
An element g of G is called a representative for the point e in the orbit of d under G if g
maps d to e, i.e., dg = e. Note that the set of such representatives that map d to e forms a
right coset of the stabilizer of d in G (see 8.24). The set of all representatives of the orbit
of d under G thus forms a system of representatives of the right cosets of the stabilizer of d
in G.
RepresentativesOperation accepts a function operation of two arguments d and g as
optional third argument, which specifies how the elements of G operate (see 8.1).
gap> g := Group( (1,2,3)(6,7), (3,4,5)(7,8) );;
gap> RepresentativesOperation( g, 1 );
[ (), (1,2,3)(6,7), (1,3,2), (1,4,5,3,2)(7,8), (1,5,4,3,2) ]
gap> Orbit( g, [1,2], OnSets );
[ [ 1, 2 ], [ 2, 3 ], [ 1, 3 ], [ 2, 4 ], [ 1, 4 ], [ 3, 4 ],
[ 2, 5 ], [ 1, 5 ], [ 4, 5 ], [ 3, 5 ] ]
gap> RepresentativesOperation( g, [1,2], OnSets );
[ (), (1,2,3)(6,7), (1,3,2), (1,2,4,5,3)(6,8,7), (1,4,5,3,2)(7,8),
(1,3,2,4,5)(6,8), (1,2,5,4,3)(6,7), (1,5,4,3,2), (1,4,3,2,5)(6,7,8),
(1,3,2,5,4) ]
RepresentativesOperation calls
G.operations.RepresentativesOperation( G, d , operation )
and returns the value. Note that the third argument is not optional for functions called this
way.
The default function called this way is GroupOps.RepresentativesOperation, which computes the orbit of d with the normal algorithm, but remembers for each point e in the orbit
a representative re . When a generator g of G takes an old point e to a point f not yet in the
orbit, the representative rf for f is computed as re g. Special categories of groups overlay
this default function with more efficient functions.
8.27
IsEquivalentOperation
IsEquivalentOperation(
IsEquivalentOperation(
IsEquivalentOperation(
IsEquivalentOperation(
G,
G,
G,
G,
D,
D,
D,
D,
H, E )
H , E , operationH )
operationG, H , E )
operationG, H , E , operationH )
IsEquivalentOperation returns true if G operates on D in like H operates on E , and
false otherwise.
The operations of G on D and H on E are equivalent if they have the same number of
generators and there is a permutation F of the elements of E such that for every generator
g of G and the corresponding generator h of H we have P osition(D, Dig ) = P osition(F, Fih ).
Note that this assumes that the mapping defined by mapping G.generators to H.generators
is a homomorphism (actually an isomorphism of factor groups of G and H represented by
the respective operation).
354
CHAPTER 8. OPERATIONS OF GROUPS
IsEquivalentOperation accepts functions operationG and operationH of two arguments d
and g as optional third and sixth arguments, which specify how the elements of G and H
operate (see 8.1).
gap> g := Group( (1,2)(4,5), (1,2,3)(4,5,6) );;
gap> h := Group( (2,3)(4,5), (1,2,3)(4,5,6) );;
gap> IsEquivalentOperation( g, [1..6], h, [1..6] );
true
gap> h := Group( (1,2), (1,2,3) );;
gap> IsEquivalentOperation(g,[[1,4],[2,5],[3,6]],OnPairs,h,[1..3]);
true
gap> h := Group( (1,2), (1,2,3)(4,5,6) );;
gap> IsEquivalentOperation( g, [1..6], h, [1..6] );
false
gap> h := Group( (1,2,3)(4,5,6), (1,2)(4,5) );;
gap> IsEquivalentOperation( g, [1..6], h, [1..6] );
false
# the generators must correspond
IsEquivalentOperation calls
G.operations.IsEquivalentOperation(G,D,oprG,H ,E ,oprH ) and returns the value.
Note that the third and sixth argument are not optional for functions called this way.
The default function called this way is GroupOps.IsEquivalentOperation, which tries to
rearrange E so that the above condition is satisfied. This is done one orbit of G at a time,
and for each such orbit all the orbits of H of the same length are tried to see if there is
one which can be rearranged as necessary. Special categories of groups overlay this function
with more efficient ones.
Chapter 9
Vector Spaces
The material described in this chapter is subject to change.
Vector spaces form another important domain in GAP3. They may be given in any representation whenever the underlying set of elements forms a vector space in terms of linear
algebra. Thus, for example, one may construct a vector space by defining generating matrices over a field or by using the base of a field extension as generators. More complex
constructions may fake elements of a vector space by specifying records with appropriate
operations. A special type of vector space, that is implemented in the GAP3 library, handles
the case where the elements are lists over a field. This type is the so called RowSpace (see
33 for details).
General vector spaces are created using the function VectorSpace (see 9.1) and they are
represented as records that contain all necessary information to deal with the vector space.
The components listed in 9.3 are common for all vector spaces, but special types of vector
spaces, such as the row spaces, may use additional entries to store specific data.
The following sections contain descriptions of functions and operations defined for vector
spaces.
The next sections describe functions to compute a base (see 9.6) and the dimension (see
9.8) of a vector space over its field.
The next sections describe how to calculate linear combinations of the elements of a base
(see 9.9) and how to find the coefficients of an element of a vector space when expressed as
a linear combination in the current base (see 9.10).
The functions described in this chapter are implemented in the file LIBNAME/"vecspace.g".
9.1
VectorSpace
VectorSpace( generators, field )
Let generators be a list of objects generating a vector space over the field field . Then
VectorSpace returns this vector space represented as a GAP3 record.
gap> f := GF( 3^2 );
GF(3^2)
355
356
CHAPTER 9. VECTOR SPACES
gap> m := [ [ f.one, f.one ], [ f.zero, f.zero ] ];
[ [ Z(3)^0, Z(3)^0 ], [ 0*Z(3), 0*Z(3) ] ]
gap> n := [ [ f.one, f.zero ], [ f.zero, f.one ] ];
[ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]
gap> VectorSpace( [ m, n ], f );
VectorSpace( [ [ [ Z(3)^0, Z(3)^0 ], [ 0*Z(3), 0*Z(3) ] ],
[ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ] ], GF(3^2) )
VectorSpace( generators, field , zero )
VectorSpace returns the vector space generated by generators over the field field having zero
as the uniquely determined neutral element. This call of VectorSpace always is requested
if generators is the empty list.
gap> VectorSpace( [], f, [ [ f.zero, f.zero ], [ f.zero, f.zero ] ] );
VectorSpace( [ ], GF(3^2), [ [ 0*Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3) ]
] )
9.2
IsVectorSpace
IsVectorSpace( obj )
IsVectorSpace returns true if obj , which can be an object of arbitrary type, is a vector
space and false otherwise.
9.3
Vector Space Records
A vector space is represented as a GAP3 record having several entries to hold some necessary
information about the vector space.
Basically a vector space record is constructed using the function VectorSpace although one
may create such a record by hand. Furthermore vector space records may be returned by
functions described here or somewhere else in this manual.
Once a vector space record is created you are free to add components, but you should never
alter existing entries, especially generators, field and zero.
The following list mentions all components that are requested for a vector space V .
generators
a list of elements generating the vector space V .
field
the field over which the vector space V is written.
zero
the zero element of the vector space.
isDomain
always true, because vector spaces are domains.
isVectorSpace
always true, for obvious reasons.
There are as well some optional components for a vector space record.
9.4. SET FUNCTIONS FOR VECTOR SPACES
357
base
a base for V , given as a list of elements of V .
dimension
the dimension of V which is the length of a base of V .
9.4
Set Functions for Vector Spaces
As mentioned before, vector spaces are domains. So all functions that exist for domains may
also be applied to vector spaces. This and the following chapters give further information
on the implementation of these functions for vector spaces, as far as they differ in their
implementation from the general functions.
Elements( V )
The elements of a vector space V are computed by producing all linear combinations of the
generators of V .
Size( V )
The size of a vector space V is determined by calculating the dimension of V and looking
at the field over which it is written.
IsFinite( V )
A vector space in GAP3 is finite if it contains only its zero element or if the field over which
it is written is finite. This characterisation is true here, as in GAP3 all vector spaces have a
finite dimension.
Intersection( V , W )
The intersection of vector spaces is computed by finding a base for the intersection of the
sets of their elements. One may consider the algorithm for finding a base of a vector space
V as another way to write Intersection( V , V ).
9.5
IsSubspace
IsSubspace( V , W )
IsSubspace tests whether the vector space W is a subspace of V . It returns true if W lies
in V and false if it does not.
The answer to the question is obtained by testing whether all the generators of W lie in
V , so that, for the general case of vector space handling, a list of all the elements of V is
constructed.
9.6
Base
Base( V )
Base computes a base of the given vector space V . The result is returned as a list of elements
of the vector space V .
358
CHAPTER 9. VECTOR SPACES
The base of a vector space is defined to be a minimal generating set. It can be shown that
for a given vector space V each base has the same number of elements, which is called the
dimension of V (see 9.8).
Unfortunately, no better algorithm is known to compute a base in general than to browse
through the list of all elements of the vector space. So be careful when using this command
on plain vector spaces.
gap> f := GF(3);
GF(3)
gap> m1 := [[ f.one, f.one, f.zero, f.zero ]];
[ [ Z(3)^0, Z(3)^0, 0*Z(3), 0*Z(3) ] ]
gap> m2 := [[ f.one, f.one, f.one, f.zero ]];
[ [ Z(3)^0, Z(3)^0, Z(3)^0, 0*Z(3) ] ]
gap> V := VectorSpace( [ m1, m2, m1+m2 ], GF(3) );
VectorSpace( [ [ [ Z(3)^0, Z(3)^0, 0*Z(3), 0*Z(3) ] ],
[ [ Z(3)^0, Z(3)^0, Z(3)^0, 0*Z(3) ] ],
[ [ Z(3), Z(3), Z(3)^0, 0*Z(3) ] ] ], GF(3) )
gap> Base( V );
[ [ [ Z(3)^0, Z(3)^0, 0*Z(3), 0*Z(3) ] ],
[ [ Z(3)^0, Z(3)^0, Z(3)^0, 0*Z(3) ] ] ]
gap> Dimension( V );
2
9.7
AddBase
AddBase( V , base )
AddBase attaches a user-supplied base for the vector space V to the record that represents
V.
Most of the functions for vector spaces make use of a base (see 9.9, 9.10). These functions
get access to a base using the function Base, which normally computes a base for the vector
space using an appropriate algorithm. Once a base is computed it will always be reused, no
matter whether there is a more interesting base available or not.
AddBase installs a given base for V by overwriting any other base of the vector space that
has been installed before. So after AddBase has successfully been used, base will be used
whenever Base is called with V as argument.
Calling AddBase with a base which is not a base for V might produce unpredictable results
in following computations.
gap> f := GF(3);
GF(3)
gap> m1 := [[ f.one, f.one, f.zero, f.zero ]];
[ [ Z(3)^0, Z(3)^0, 0*Z(3), 0*Z(3) ] ]
gap> m2 := [[ f.one, f.one, f.one, f.zero ]];
[ [ Z(3)^0, Z(3)^0, Z(3)^0, 0*Z(3) ] ]
gap> V := VectorSpace( [ m1, m2, m1+m2 ], GF(3) );
VectorSpace( [ [ [ Z(3)^0, Z(3)^0, 0*Z(3), 0*Z(3) ] ],
[ [ Z(3)^0, Z(3)^0, Z(3)^0, 0*Z(3) ] ],
9.8. DIMENSION
[ [ Z(3), Z(3), Z(3)^0, 0*Z(3) ] ]
gap> Base( V );
[ [ [ Z(3)^0, Z(3)^0, 0*Z(3), 0*Z(3)
[ [ Z(3)^0, Z(3)^0, Z(3)^0, 0*Z(3)
gap> AddBase( V, [ m1, m1+m2 ] );
gap> Base( V );
[ [ [ Z(3)^0, Z(3)^0, 0*Z(3), 0*Z(3)
[ [ Z(3), Z(3), Z(3)^0, 0*Z(3) ] ]
9.8
359
], GF(3) )
] ],
] ] ]
] ],
]
Dimension
Dimension( V )
Dimension computes the dimension of the given vector space V over its field.
The dimension of a vector space V is defined to be the length of a minimal generating set
of V , which is called a base of V (see 9.6).
The implementation of Dimension strictly follows its above definition, so that this function
will always determine a base of V .
gap> f := GF( 3^4 );
GF(3^4)
gap> f.base;
[ Z(3)^0, Z(3^4), Z(3^4)^2, Z(3^4)^3 ]
gap> V := VectorSpace( f.base, GF( 3 ) );
VectorSpace( [ Z(3)^0, Z(3^4), Z(3^4)^2, Z(3^4)^3 ], GF(3) )
gap> Dimension( V );
4
9.9
LinearCombination
LinearCombination( V , cf )
LinearCombination computes the linear combination of the base elements of the vector
space V with coefficients cf .
cf has to be a list of elements of V .field, the field over which the vector space is written.
Its length must be equal to the dimension of V to make sure that one coefficient is specified
for each element of the base.
LinearCombination will use that base of V which is returned when applying the function
Base to V (see 9.6). To perform linear combinations of different bases use AddBase to
specify which base should be used (see 9.7).
gap> f := GF( 3^4 );
GF(3^4)
gap> f.base;
[ Z(3)^0, Z(3^4), Z(3^4)^2, Z(3^4)^3 ]
gap> V := VectorSpace( f.base, GF( 3 ) );
VectorSpace( [ Z(3)^0, Z(3^4), Z(3^4)^2, Z(3^4)^3 ], GF(3) )
gap> LinearCombination( V, [ Z(3), Z(3)^0, Z(3), 0*Z(3) ] );
Z(3^4)^16
gap> Coefficients( V, f.root ^ 16 );
[ Z(3), Z(3)^0, Z(3), 0*Z(3) ]
360
CHAPTER 9. VECTOR SPACES
9.10
Coefficients
Coefficients( V , v )
Coefficients computes the coefficients that have to be used to write v as a linear combination in the base of V .
To make sure that this function produces the correct result, v has to be an element of V .
If v does not lie in V the result is unpredictable.
The result of Coefficients is returned as a list of elements of the field over which the
vector space V is written. Of course, the length of this list equals the dimension of V .
gap> f := GF( 3^4 );
GF(3^4)
gap> f.base;
[ Z(3)^0, Z(3^4), Z(3^4)^2, Z(3^4)^3 ]
gap> V := VectorSpace( f.base, GF( 3 ) );
VectorSpace( [ Z(3)^0, Z(3^4), Z(3^4)^2, Z(3^4)^3 ], GF(3) )
gap> Dimension( V );
4
gap> Coefficients( V, f.root ^ 16 );
[ Z(3), Z(3)^0, Z(3), 0*Z(3) ]
Chapter 10
Integers
One of the most fundamental datatypes in every programming language is the integer type.
GAP3 is no exception.
GAP3 integers are entered as a sequence of digits optionally preceded by a + sign for positive
integers or a - sign for negative integers. The size of integers in GAP3 is only limited by the
amount of available memory, so you can compute with integers having thousands of digits.
gap> -1234;
-1234
gap> 123456789012345678901234567890123456789012345678901234567890;
123456789012345678901234567890123456789012345678901234567890
The first sections in this chapter describe the operations applicable to integers (see 10.1,
10.2, 10.3 and 10.4).
The next sections describe the functions that test whether an object is an integer (see 10.5)
and convert objects of various types to integers (see 10.6).
The next sections describe functions related to the ordering of integers (see 10.7, 10.8).
The next section describes the function that computes a Chinese remainder (see 10.11).
The next sections describe the functions related to the ordering of integers, logarithms, and
roots (10.12, 10.13, 10.14).
The GAP3 object Integers is the ring domain of all integers. So all set theoretic functions
are also applicable to this domain (see chapter 4 and 10.15). The only serious use of this
however seems to be the generation of random integers.
Since the integers form a Euclidean ring all the ring functions are applicable to integers (see
chapter 5, 10.16, 10.17, 10.18, 10.19, 10.20, 10.21, 10.22, 10.23, 10.24, 10.25, and 10.26).
Since the integers are naturally embedded in the field of rationals all the field functions are
applicable to integers (see chapter 6 and 12.9).
Many more functions that are mainly related to the prime residue group of integers modulo
an integer are described in chapter 11.
The external functions are in the file LIBNAME/"integer.g".
361
362
CHAPTER 10. INTEGERS
10.1
Comparisons of Integers
n1 = n2
n1 <> n2
The equality operator = evaluates to true if the integer n1 is equal to the integer n2 and
false otherwise. The inequality operator <> evaluates to true if n1 is not equal to n2 and
false otherwise.
Integers can also be compared to objects of other types; of course, they are never equal.
gap> 1 = 1;
true
gap> 1 <> 0;
true
gap> 1 = (1,2);
false
n1
n1
n1
n1
# (1,2) is a permutation
< n2
<= n2
> n2
>= n2
The operators <, <=, >, and => evaluate to true if the integer n1 is less than, less than or
equal to, greater than, or greater than or equal to the integer n2 , respectively.
Integers can also be compared to objects of other types, they are considered smaller than
any other object, except rationals, where the ordering reflects the ordering of the rationals
(see 12.6).
gap> 1
true
gap> 1
false
gap> 1
true
gap> 1
true
10.2
< 2;
< -1;
< 3/2;
< false;
Operations for Integers
n1 + n2
The operator + evaluates to the sum of the two integers n1 and n2 .
n1 - n2
The operator - evaluates to the difference of the two integers n1 and n2 .
n1 * n2
The operator * evaluates to the product of the two integers n1 and n2 .
n1 / n2
The operator / evaluates to the quotient of the two integers n1 and n2 . If the divisor does
not divide the dividend the quotient is a rational (see 12). If the divisor is 0 an error is
signalled. The integer part of the quotient can be computed with QuoInt (see 10.3).
10.3. QUOINT
363
n1 mod n2
The operator mod evaluates to the smallest positive representative of the residue class
of the left operand modulo the right, i.e., i mod k is the unique m in the range [0 ..
AbsInt(k )-1] such that k divides i - m. If the right operand is 0 an error is signalled.
The remainder of the division can be computed with RemInt (see 10.4).
n1 ^ n2
The operator ^ evaluates to the n2 -th power of the integer n1 . If n2 is a positive integer
then n1 ^n2 is n1 *n1 *..*n1 (n2 factors). If n2 is a negative integer n1 ^n2 is defined as
1/n1 −n2 . If 0 is raised to a negative power an error is signalled. Any integer, even 0, raised
to the zeroth power yields 1.
Since integers embed naturally into the field of rationals all the rational operations are
available for integers too (see 12.7).
For the precedence of the operators see 2.10.
gap> 2 * 3 + 1;
7
10.3
QuoInt
QuoInt( n1 , n2 )
QuoInt returns the integer part of the quotient of its integer operands.
If n1 and n2 are positive QuoInt( n1 , n2 ) is the largest positive integer q such that
q*n2 <= n1 . If n1 or n2 or both are negative the absolute value of the integer part of
the quotient is the quotient of the absolute values of n1 and n2 , and the sign of it is the
product of the signs of n1 and n2 .
RemInt (see 10.4) can be used to compute the remainder.
gap> QuoInt(5,2);
2
-2
-2
2
10.4
QuoInt(-5,2);
QuoInt(5,-2);
QuoInt(-5,-2);
RemInt
RemInt( n1 , n2 )
RemInt returns the remainder of its two integer operands.
If n2 is not equal to zero RemInt( n1 , n2 ) = n1 - n2 *QuoInt( n1 , n2 ). Note that
the rules given for QuoInt (see 10.3) imply that RemInt( n1 , n2 ) has the same sign as
n1 and its absolute value is strictly less than the absolute value of n2 . Dividing by 0 signals
an error.
gap> RemInt(5,2);
1
-1
1
-1
RemInt(-5,2);
RemInt(5,-2);
RemInt(-5,-2);
364
CHAPTER 10. INTEGERS
10.5
IsInt
IsInt( obj )
IsInt returns true if obj , which can be an arbitrary object, is an integer and false otherwise. IsInt will signal an error if obj is an unbound variable.
gap> IsInt( 1 );
true
gap> IsInt( IsInt );
false
# IsInt is a function, not an integer
10.6
Int
Int( obj )
Int converts an object obj to an integer. If obj is an integer Int will simply return obj .
If obj is a rational number (see 12) Int returns the unique integer that has the same sign
as obj and the largest absolute value not larger than the absolute value of obj .
If obj is an element of the prime field of a finite field F , Int returns the least positive integer
n such that n*F .one = obj (see 18.8).
If obj is not of one of the above types an error is signalled.
gap> Int( 17 );
17
gap> Int( 17 / 3 );
5
gap> Int( Z(5^3)^62 );
4 # Z(53 )62 = (Z(53 )124/4 )2 = Z(5)2 = P rimitiveRoot(5)2 = 22
10.7
AbsInt
AbsInt( n )
AbsInt returns the absolute value of the integer n, i.e., n if n is positive, -n if n is negative
and 0 if n is 0 (see 10.8).
gap> AbsInt( 33 );
33
gap> AbsInt( -214378 );
214378
gap> AbsInt( 0 );
0
10.8
SignInt
SignInt( obj )
SignInt returns the sign of the integer obj , i.e., 1 if obj is positive, -1 if obj is negative and
0 if obj is 0 (see 10.7).
gap> SignInt( 33 );
10.9. ISODDINT
365
1
gap> SignInt( -214378 );
-1
gap> SignInt( 0 );
0
10.9
IsOddInt
IsOddInt( i )
Determines whether i is odd.
gap> IsOddInt(3);IsOddInt(4);
true
false
10.10
IsEvenInt
IsEvenInt( i )
Determines whether i is even.
gap> IsEvenInt(3);IsEvenInt(4);
false
true
10.11
ChineseRem
ChineseRem( moduli , residues )
ChineseRem returns the combination of the residues modulo the moduli , i.e., the unique
integer c from [0..Lcm(moduli )-1] such that c = residues[i] modulo moduli [i] for all
i , if it exists. If no such combination exists ChineseRem signals an error.
Such a combination does exist if and only if
residues[i ]=residues[k ] mod Gcd(moduli [i ],moduli [k ]) for every pair i , k . Note that
this implies that such a combination exists if the moduli are pairwise relatively prime. This
is called the Chinese remainder theorem.
gap> ChineseRem( [ 2, 3, 5, 7 ], [ 1, 2, 3, 4 ] );
53
gap> ChineseRem( [ 6, 10, 14 ], [ 1, 3, 5 ] );
103
gap> ChineseRem( [ 6, 10, 14 ], [ 1, 2, 3 ] );
Error, the residues must be equal modulo 2
10.12
LogInt
LogInt( n, base )
LogInt returns the integer part of the logarithm of the positive integer n with respect to the
positive integer base, i.e., the largest positive integer exp such that baseexp <= n. LogInt
will signal an error if either n or base is not positive.
366
CHAPTER 10. INTEGERS
gap> LogInt( 1030, 2 );
10
# 210 = 1024
gap> LogInt( 1, 10 );
0
10.13
RootInt
RootInt( n )
RootInt( n, k )
RootInt returns the integer part of the k th root of the integer n. If the optional integer
argument k is not given it defaults to 2, i.e., RootInt returns the integer part of the square
root in this case.
If n is positive RootInt returns the largest positive integer r such that rk <= n. If n is
negative and k is odd RootInt returns -RootInt( -n, k ). If n is negative and k is even
RootInt will cause an error. RootInt will also cause an error if k is 0 or negative.
gap> RootInt( 361 );
19
gap> RootInt( 2 * 10^12 );
1414213
gap> RootInt( 17000, 5 );
7
# 75 = 16807
10.14
SmallestRootInt
SmallestRootInt( n )
SmallestRootInt returns the smallest root of the integer n.
The smallest root of an integer n is the integer r of smallest absolute value for which a
positive integer k exists such that n = rk .
gap>
2
gap>
-4
gap>
6
gap>
7
gap>
1001
SmallestRootInt( 2^30 );
SmallestRootInt( -(2^30) );
# note that (−2)30 = +(230 )
SmallestRootInt( 279936 );
LogInt( 279936, 6 );
SmallestRootInt( 1001 );
SmallestRootInt can be used to identify and decompose powers of primes as is demonstrated in the following example (see 10.19)
p := SmallestRootInt( q ); n := LogInt( q, p );
if not IsPrimeInt(p) then Error("GF: must be a primepower"); fi;
10.15. SET FUNCTIONS FOR INTEGERS
10.15
367
Set Functions for Integers
As already mentioned in the first section of this chapter, Integers is the domain of all
integers. Thus in principle all set theoretic functions, for example Intersection, Size, and
so on can be applied to this domain. This seems generally of little use.
gap> Intersection( Integers, [ 0, 1/2, 1, 3/2 ] );
[ 0, 1 ]
gap> Size( Integers );
"infinity"
Random( Integers )
This seems to be the only useful domain function that can be applied to the domain
Integers. It returns pseudo random integers between -10 and 10 distributed according
to a binomial distribution.
gap> Random( Integers );
1
gap> Random( Integers );
-4
To generate uniformly distributed integers from a range, use the construct Random( [ low
.. high ] ).
10.16
Ring Functions for Integers
As was already noted in the introduction to this chapter the integers form a Euclidean ring,
so all ring functions (see chapter 5) are applicable to the integers. This section comments
on the implementation of those functions for the integers and tells you how you can call the
corresponding functions directly, for example to save time.
IsPrime( Integers, n )
This is implemented by IsPrimeInt, which you can call directly to save a little bit of time
(see 10.18).
Factors( Integers, n )
This is implemented as by FactorsInt, which you can call directly to save a little bit of
time (see 10.22).
EuclideanDegree( Integers, n )
The Euclidean degree of an integer is of course simply the absolute value of the integer.
Calling AbsInt directly will be a little bit faster.
EuclideanRemainder( Integers, n, m )
This is implemented as RemInt( n, m ), which you can use directly to save a lot of time.
EuclideanQuotient( Integers, n, m )
This is implemented as QuoInt( n, m ), which you can use directly to save a lot of time.
QuotientRemainder( Integers, n, m )
This is implemented as [ QuoInt(n,m), RemInt(n,m) ], which you can use directly to
save a lot of time.
368
CHAPTER 10. INTEGERS
QuotientMod( Integers, n1 , n2 , m )
This is implemented as (n1 / n2 ) mod m, which you can use directly to save a lot of time.
PowerMod( Integers, n, e, m )
This is implemented by PowerModInt, which you can call directly to save a little bit of
time. Note that using n ^ e mod m will generally be slower, because it can not reduce
intermediate results like PowerMod.
Gcd( Integers, n1 , n2 ..
)
This is implemented by GcdInt, which you can call directly to save a lot of time. Note that
GcdInt takes only two arguments, not several as Gcd does.
Gcdex( n1 , n2 )
Gcdex returns a record. The component gcd is the gcd of n1 and n2 .
The components coeff1 and coeff2 are integer cofactors such that
g.gcd = g.coeff1*n1 + g.coeff2*n2 .
If n1 and n2 both are nonzero, AbsInt( g.coeff1 ) is less than or equal to AbsInt(n2 )
/ (2*g.gcd) and AbsInt( g.coeff2 ) is less than or equal to AbsInt(n1 ) / (2*g.gcd).
The components coeff3 and coeff4 are integer cofactors such that
0 = g.coeff3*n1 + g.coeff4*n2 .
If n1 or n2 or are both nonzero coeff3 is -n2 / g.gcd and coeff4 is n1 / g.gcd.
The coefficients always form a unimodular matrix, i.e., the determinant
g.coeff1*g.coeff4 - g.coeff3*g.coeff2
is 1 or -1.
gap> Gcdex( 123, 66 );
rec(
gcd := 3,
coeff1 := 7,
coeff2 := -13,
coeff3 := -22,
coeff4 := 41 )
# 3 = 7*123 - 13*66, 0 = -22*123 + 41*66
gap> Gcdex( 0, -3 );
rec(
gcd := 3,
coeff1 := 0,
coeff2 := -1,
coeff3 := 1,
coeff4 := 0 )
gap> Gcdex( 0, 0 );
rec(
gcd := 0,
coeff1 := 1,
coeff2 := 0,
coeff3 := 0,
coeff4 := 1 )
Lcm( Integers, n1 , n2 ..
)
10.17. PRIMES
369
This is implemented as LcmInt, which you can call directly to save a little bit of time. Note
that LcmInt takes only two arguments, not several as Lcm does.
10.17
Primes
Primes[ n ]
Primes is a set, i.e., a sorted list, of the 168 primes less than 1000.
Primes is used in IsPrimeInt (see 10.18) and FactorsInt (see 10.22) to cast out small
prime divisors quickly.
gap> Primes[1];
2
gap> Primes[100];
541
10.18
IsPrimeInt
IsPrimeInt( n )
IsPrimeInt returns false if it can prove that n is composite and true otherwise. By
convention IsPrimeInt(0) = IsPrimeInt(1) = false and we define IsPrimeInt( -n )
= IsPrimeInt( n ).
IsPrimeInt will return true for all prime n. IsPrimeInt will return false for all composite
n < 1013 and for all composite n that have a factor p < 1000. So for integers n < 1013 ,
IsPrimeInt is a proper primality test. It is conceivable that IsPrimeInt may return true
for some composite n > 1013 , but no such n is currently known. So for integers n > 1013 ,
IsPrimeInt is a probable-primality test. If composites that fool IsPrimeInt do exist, they
would be extremly rare, and finding one by pure chance is less likely than finding a bug in
GAP3.
IsPrimeInt is a deterministic algorithm, i.e., the computations involve no random numbers,
and repeated calls will always return the same result. IsPrimeInt first does trial divisions
by the primes less than 1000. Then it tests that n is a strong pseudoprime w.r.t. the base 2.
Finally it tests whether n is a Lucas pseudoprime w.r.t. the smallest quadratic nonresidue
of n. A better description can be found in the comment in the library file integer.g.
The time taken by IsPrimeInt is approximately proportional to the third power of the
number of digits of n. Testing numbers with several hundreds digits is quite feasible.
gap> IsPrimeInt( 2^31 - 1 );
true
gap> IsPrimeInt( 10^42 + 1 );
false
10.19
IsPrimePowerInt
IsPrimePowerInt( n )
IsPrimePowerInt returns true if the integer n is a prime power and false otherwise.
370
CHAPTER 10. INTEGERS
n is a prime power if there exists a prime p and a positive integer i such that pi = n. If
n is negative the condition is that there must exist a negative prime p and an odd positive
integer i such that pi = n. 1 and -1 are not prime powers.
Note that IsPrimePowerInt uses SmallestRootInt (see 10.14) and a probable-primality
test (see 10.18).
gap> IsPrimePowerInt( 31^5 );
true
gap> IsPrimePowerInt( 2^31-1 );
true
# 231 − 1 is actually a prime
gap> IsPrimePowerInt( 2^63-1 );
false
gap> Filtered( [-10..10], IsPrimePowerInt );
[ -8, -7, -5, -3, -2, 2, 3, 4, 5, 7, 8, 9 ]
10.20
NextPrimeInt
NextPrimeInt( n )
NextPrimeInt returns the smallest prime which is strictly larger than the integer n.
Note that NextPrimeInt uses a probable-primality test (see 10.18).
gap> NextPrimeInt( 541 );
547
gap> NextPrimeInt( -1 );
2
10.21
PrevPrimeInt
PrevPrimeInt( n )
PrevPrimeInt returns the largest prime which is strictly smaller than the integer n.
Note that PrevPrimeInt uses a probable-primality test (see 10.18).
gap> PrevPrimeInt( 541 );
523
gap> PrevPrimeInt( 1 );
-2
10.22
FactorsInt
FactorsInt( n )
FactorsInt returns a list of the prime factors of the integer n. If the i th power of a prime
divides n this prime appears i times. The list is sorted, that is the smallest prime factors
come first. The first element has the same sign as n, the others are positive. For any integer
n it holds that Product( FactorsInt( n ) ) = n.
Note that FactorsInt uses a probable-primality test (see 10.18). Thus FactorsInt might
return a list which contains composite integers.
The time taken by FactorsInt is approximately proportional to the square root of the
second largest prime factor of n, which is the last one that FactorsInt has to find, since
10.23. DIVISORSINT
371
the largest factor is simply what remains when all others have been removed. Thus the time
is roughly bounded by the fourth root of n. FactorsInt is guaranteed to find all factors
less than 106 and will find most factors less than 1010 . If n contains multiple factors larger
than that FactorsInt may not be able to factor n and will then signal an error.
gap> FactorsInt( -Factorial(6) );
[ -2, 2, 2, 2, 3, 3, 5 ]
gap> Set( FactorsInt( Factorial(13)/11 ) );
[ 2, 3, 5, 7, 13 ]
gap> FactorsInt( 2^63 - 1 );
[ 7, 7, 73, 127, 337, 92737, 649657 ]
gap> FactorsInt( 10^42 + 1 );
[ 29, 101, 281, 9901, 226549, 121499449, 4458192223320340849 ]
10.23
DivisorsInt
DivisorsInt( n )
DivisorsInt returns a list of all positive divisors of the integer n. The list is sorted, so
it starts with 1 and ends with n. We define DivisorsInt( -n ) = DivisorsInt( n ).
Since the set of divisors of 0 is infinite calling DivisorsInt( 0 ) causes an error.
DivisorsInt calls FactorsInt (see 10.22) to obtain the prime factors. Sigma (see 10.24)
computes the sum, Tau (see 10.25) the number of positive divisors.
gap> DivisorsInt(
[ 1 ]
gap> DivisorsInt(
[ 1, 2, 4, 5, 10,
gap> DivisorsInt(
[ 1, 541 ]
10.24
1 );
20 );
20 ]
541 );
Sigma
Sigma( n )
Sigma returns the sum of the positive divisors (see 10.23) of the integer n.
Sigma is a multiplicative arithmetic function, i.e., if n and m are relatively prime we have
σ(nm) = σ(n)σ(m). Together with the formula σ(pe ) = (pe+1 − 1)/(p − 1) this allows you
to compute σ(n).
Integers n for which σ(n) = 2n are called perfect. Even perfect integers are exactly of the
form 2n−1 (2n − 1) where 2n − 1 is prime. Primes of the form 2n − 1 are called Mersenne
primes, the known ones are obtained for n = 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127,
521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497,
86243, 110503, 132049, 216091, 756839, and 859433. It is not known whether odd perfect
integers exist, however [BC89] show that any such integer must have at least 300 decimal
digits.
Sigma usually spends most of its time factoring n (see 10.22).
gap> Sigma( 0 );
Error, Sigma: must not be 0
372
CHAPTER 10. INTEGERS
gap> Sigma( 1 );
1
gap> Sigma( 1009 );
1010
# thus 1009 is a prime
gap> Sigma( 8128 ) = 2*8128;
true
# thus 8128 is a perfect number
10.25
Tau
Tau( n )
Tau returns the number of the positive divisors (see 10.23) of the integer n.
Tau is a multiplicative arithmetic function, i.e., if n and m are relatively prime we have
τ (nm) = τ (n)τ (m). Together with the formula τ (pe ) = e + 1 this allows us to compute
τ (n).
Tau usually spends most of its time factoring n (see 10.22).
gap> Tau( 0 );
Error, Tau: must not be 0
gap> Tau( 1 );
1
gap> Tau( 1013 );
2
# thus 1013 is a prime
gap> Tau( 8128 );
14
gap> Tau( 36 );
9
# τ (n) is odd if and only if n is a perfect square
10.26
MoebiusMu
MoebiusMu( n )
MoebiusMu computes the value of the Moebius function for the integer n. This is 0 for
integers which are not squarefree, i.e., which are divisible by a square r2 . Otherwise it is 1
if n has an even number and -1 if n has an odd number of prime factors.
The importance of µ stems from the so called inversion
formula. Suppose fP
(n) is a function
P
defined on the positive integers and let g(n) = d|n f (d). Then f (n) = d|n µ(d)g(n/d).
P
P
As a special case we have φ(n) = d|n µ(d)n/d since n = d|n φ(d) (see 11.2).
MoebiusMu usually spends all of its time factoring n (see 10.22).
gap> MoebiusMu( 60 );
0
gap> MoebiusMu( 61 );
-1
gap> MoebiusMu( 62 );
1
Chapter 11
Number Theory
The integers relatively prime to m form a group under multiplication modulo m, called the
prime residue group. This chapter describes the functions that deal with this group.
The first section describes the function that computes the set of representatives of the group
(see 11.1).
The next sections describe the functions that compute the size and the exponent of the
group (see 11.2 and 11.3).
The next section describes the function that computes the order of an element in the group
(see 11.4).
The next section describes the functions that test whether a residue generates the group or
computes a generator of the group, provided it is cyclic (see 11.5, 11.6).
The next section describes the functions that test whether an element is a square in the
group (see 11.7 and 11.8).
The next sections describe the functions that compute general roots in the group (see 11.9
and 11.10).
All these functions are in the file LIBNAME/"numtheor.g".
11.1
PrimeResidues
PrimeResidues( m )
PrimeResidues returns the set of integers from the range 0..Abs(m) − 1 that are relatively
prime to the integer m.
Abs(m) must be less than 228 , otherwise the set would probably be too large anyhow.
The integers relatively prime to m form a group under multiplication modulo m, called the
prime residue group. φ(m) (see 11.2) is the order of this group, λ(m) (see 11.3) the
exponent. If and only if m is 2, 4, an odd prime power pe , or twice an odd prime power 2pe ,
this group is cyclic. In this case the generators of the group, i.e., elements of order φ(m),
are called primitive roots (see 11.5, 11.6).
gap> PrimeResidues( 0 );
373
374
CHAPTER 11. NUMBER THEORY
[ ]
gap> PrimeResidues( 1 );
[ 0 ]
gap> PrimeResidues( 20 );
[ 1, 3, 7, 9, 11, 13, 17, 19 ]
11.2
Phi
Phi( m )
Phi returns the value of the Euler totient function φ(m) for the integer m. φ(m) is
defined as the number of positive integers less than or equal to m that are relatively prime
to m.
Suppose that m = pe11 pe22 ...pekk . Then φ(m) is pe11 −1 (p1 − 1)p2e2 −1 (p2 − 1)...pkek −1 (pk − 1). It
follows that m is a prime if and only if φ(m) = m − 1.
The integers relatively prime to m form a group under multiplication modulo m, called the
prime residue group. It can be computed with PrimeResidues (see 11.1). φ(m) is the
order of this group, λ(m) (see 11.3) the exponent. If and only if m is 2, 4, an odd prime
power pe , or twice an odd prime power 2pe , this group is cyclic. In this case the generators
of the group, i.e., elements of order φ(m), are called primitive roots (see 11.5, 11.6).
Phi usually spends most of its time factoring m (see 10.22).
gap> Phi( 12 );
4
gap> Phi( 2^13-1 );
8190
# which proves that 213 − 1 is a prime
gap> Phi( 2^15-1 );
27000
11.3
Lambda
Lambda( m )
Lambda returns the exponent of the group of relatively prime residues modulo the integer
m.
λ(m) is the smallest positive integer l such that for every a relatively prime to m we have
al = 1 mod m. Fermat’s theorem asserts aφ(m) = 1 mod m, thus λ(m) divides φ(m) (see
11.2).
Carmichael’s theorem states that λ can be computed as follows λ(2) = 1, λ(4) = 2 and
λ(2e ) = 2e−2 if 3 <= e, λ(pe ) = (p − 1)pe−1 (= φ(pe )) if p is an odd prime, and λ(nm) =
Lcm(λ(n), λ(m)) if n, m are relatively prime.
Composites for which λ(m) divides m − 1 are called Carmichaels. If 6k + 1, 12k + 1 and
18k +1 are primes their product is such a number. It is believed but unproven that there are
infinitely many Carmichaels. There are only 1547 Carmichaels below 1010 but 455052511
primes.
The integers relatively prime to m form a group under multiplication modulo m, called the
prime residue group. It can be computed with PrimeResidues (see 11.1). φ(m) (see
11.4. ORDERMOD
375
11.2) is the order of this group, λ(m) the exponent. If and only if m is 2, 4, an odd prime
power pe , or twice an odd prime power 2pe , this group is cyclic. In this case the generators
of the group, i.e., elements of order φ(m), are called primitive roots (see 11.5, 11.6).
Lambda usually spends most of its time factoring m (see 10.22).
gap> Lambda( 10 );
4
gap> Lambda( 30 );
4
gap> Lambda( 561 );
80
# 561 is the smallest Carmichael number
11.4
OrderMod
OrderMod( n, m )
OrderMod returns the multiplicative order of the integer n modulo the positive integer m.
If n is less than 0 or larger than m it is replaced by its remainder. If n and m are not
relatively prime the order of n is not defined and OrderMod will return 0.
If n and m are relatively prime the multiplicative order of n modulo m is the smallest
positive integer i such that ni = 1 mod m. Elements of maximal order are called primitive
roots (see 11.2).
OrderMod usually spends most of its time factoring m and φ(m) (see 10.22).
gap> OrderMod( 2, 7 );
3
gap> OrderMod( 3, 7 );
6
# 3 is a primitive root modulo 7
11.5
IsPrimitiveRootMod
IsPrimitiveRootMod( r , m )
IsPrimitiveRootMod returns true if the integer r is a primitive root modulo the positive
integer m and false otherwise. If r is less than 0 or larger than m it is replaced by its
remainder.
The integers relatively prime to m form a group under multiplication modulo m, called the
prime residue group. It can be computed with PrimeResidues (see 11.1). φ(m) (see 11.2) is
the order of this group, λ(m) (see 11.3) the exponent. If and only if m is 2, 4, an odd prime
power pe , or twice an odd prime power 2pe , this group is cyclic. In this case the generators
of the group, i.e., elements of order φ(m), are called primitive roots (see also 11.6).
gap> IsPrimitiveRootMod( 2, 541 );
true
gap> IsPrimitiveRootMod( -539, 541 );
true
# same computation as above
gap> IsPrimitiveRootMod( 4, 541 );
false
gap> ForAny( [1..29], r -> IsPrimitiveRootMod( r, 30 ) );
false
# there does not exist a primitive root modulo 30
376
CHAPTER 11. NUMBER THEORY
11.6
PrimitiveRootMod
PrimitiveRootMod( m )
PrimitiveRootMod( m, start )
PrimitiveRootMod returns the smallest primitive root modulo the positive integer m and
false if no such primitive root exists. If the optional second integer argument start is given
PrimitiveRootMod returns the smallest primitive root that is strictly larger than start.
The integers relatively prime to m form a group under multiplication modulo m, called the
prime residue group. It can be computed with PrimeResidues (see 11.1). φ(m) (see 11.2) is
the order of this group, λ(m) (see 11.3) the exponent. If and only if m is 2, 4, an odd prime
power pe , or twice an odd prime power 2pe , this group is cyclic. In this case the generators
of the group, i.e., elements of order φ(m), are called primitive roots (see also 11.5).
gap> PrimitiveRootMod( 409 );
21
# largest primitive root for a prime less than 2000
gap> PrimitiveRootMod( 541, 2 );
10
gap> PrimitiveRootMod( 337, 327 );
false
# 327 is the largest primitive root mod 337
gap> PrimitiveRootMod( 30 );
false
# the exists no primitive root modulo 30
11.7
Jacobi
Jacobi( n, m )
Jacobi returns the value of the Jacobi symbol of the integer n modulo the integer m.
Suppose that m = p1 p2 ..pk as a product of primes, not necessarily distinct. Then for n
relatively prime to m the Jacobi symbol is defined by J(n/m) = L(n/p1 )L(n/p2 )..L(n/pk ),
where L(n/p) is the Legendre symbol (see 11.8). By convention J(n/1) = 1. If the gcd of
n and m is larger than 1 we define J(n/m) = 0.
If n is an quadratic residue modulo m, i.e., if there exists an r such that r2 = n mod m
then J(n/m) = 1. However J(n/m) = 1 implies the existence of such an r only if m is a
prime.
Jacobi is very efficient, even for large values of n and m, it is about as fast as the Euclidean
algorithm (see 5.26).
gap> Jacobi( 11, 35 );
1
# 92 = 11 mod 35
gap> Jacobi( 6, 35 );
-1
# thus there is no r such that r2 = 6 mod 35
gap> Jacobi( 3, 35 );
1
# even though there is no r with r2 = 3 mod 35
11.8
Legendre
Legendre( n, m )
11.9. ROOTMOD
377
Legendre returns the value of the Legendre symbol of the integer n modulo the positive
integer m.
The value of the Legendre symbol L(n/m) is 1 if n is a quadratic residue modulo m, i.e.,
if there exists an integer r such that r2 = n mod m and -1 otherwise.
If a root of n exists it can be found by RootMod (see 11.9).
While the value of the Legendre symbol usually is only defined for m a prime, we have
extended the definition to include composite moduli too. The Jacobi symbol (see 11.7) is
another generalization of the Legendre symbol for composite moduli that is much cheaper
to compute, because it does not need the factorization of m (see 10.22).
gap> Legendre( 5, 11 );
1
# 42 = 5 mod 11
gap> Legendre( 6, 11 );
-1
# thus there is no r such that r2 = 6 mod 11
gap> Legendre( 3, 35 );
-1
# thus there is no r such that r2 = 3 mod 35
11.9
RootMod
RootMod( n, m )
RootMod( n, k , m )
In the first form RootMod computes a square root of the integer n modulo the positive integer
m, i.e., an integer r such that r2 = n mod m. If no such root exists RootMod returns false.
A root of n exists only if Legendre(n,m) = 1 (see 11.8). If m has k different prime factors
then there are 2k different roots of n mod m. It is unspecified which one RootMod returns.
You can, however, use RootsUnityMod (see 11.10) to compute the full set of roots.
In the second form RootMod computes a k th root of the integer n modulo the positive integer
m, i.e., an integer r such that rk = n mod m. If no such root exists RootMod returns false.
In the current implementation k must be a prime.
RootMod is efficient even for large values of m, actually most time is usually spent factoring
m (see 10.22).
gap> RootMod( 64, 1009 );
1001
# note RootMod does not return 8 in this case but -8
gap> RootMod( 64, 3, 1009 );
518
gap> RootMod( 64, 5, 1009 );
656
gap> List( RootMod( 64, 1009 ) * RootsUnityMod( 1009 ),
>
x -> x mod 1009 );
[ 1001, 8 ]
# set of all square roots of 64 mod 1009
11.10
RootsUnityMod
RootsUnityMod( m )
RootsUnityMod( k , m )
378
CHAPTER 11. NUMBER THEORY
In the first form RootsUnityMod computes the square roots of 1 modulo the integer m, i.e.,
the set of all positive integers r less than n such that r2 = 1 mod m.
In the second form RootsUnityMod computes the k th roots of 1 modulo the integer m, i.e.,
the set of all positive integers r less than n such that rk = 1 mod m.
In general there are k n such roots if the modulus m has n different prime factors p such
that p = 1 mod k. If k 2 divides m then there are k n+1 such roots; and especially if k = 2
and 8 divides m there are 2n+2 such roots.
If you are interested in the full set of roots of another number instead of 1 use RootsUnityMod
together with RootMod (see 11.9).
In the current implementation k must be a prime.
RootsUnityMod is efficient even for large values of m, actually most time is usually spent
factoring m (see 10.22).
gap> RootsUnityMod(7*31);
[ 1, 92, 125, 216 ]
gap> RootsUnityMod(3,7*31);
[ 1, 25, 32, 36, 67, 149, 156, 191, 211 ]
gap> RootsUnityMod(5,7*31);
[ 1, 8, 64, 78, 190 ]
gap> List( RootMod( 64, 1009 ) * RootsUnityMod( 1009 ),
>
x -> x mod 1009 );
[ 1001, 8 ]
# set of all square roots of 64 mod 1009
Chapter 12
Rationals
The rationals form a very important field. On the one hand it is the quotient field of the
integers (see 10). On the other hand it is the prime field of the fields of characteristic zero
(see 15).
The former comment suggests the representation actually used. A rational is represented as
a pair of integers, called numerator and denominator. Numerator and denominator are
reduced, i.e., their greatest common divisor is 1. If the denominator is 1, the rational is
in fact an integer and is represented as such. The numerator holds the sign of the rational,
thus the denominator is always positive.
Because the underlying integer arithmetic can compute with arbitrary size integers, the
rational arithmetic is always exact, even for rationals whose numerators and denominators
have thousands of digits.
gap> 2/3;
2/3
gap> 66/123;
22/41
# numerator and denominator are made relatively prime
gap> 17/-13;
-17/13
# the numerator carries the sign
gap> 121/11;
11
# rationals with denominator 1 (after cancelling) are integers
The first sections of this chapter describe the functions that test whether an object is a
rational (see 12.1), and select the numerator and denominator of a rational (see 12.2, 12.3).
The next sections describe the rational operations (see 12.6, and 12.7).
The GAP3 object Rationals is the field domain of all rationals. All set theoretic functions
are applicable to this domain (see chapter 4 and 12.8). Since Rationals is a field all field
functions are also applicable to this domain and its elements (see chapter 6 and 12.9).
All external functions are defined in the file "LIBNAME/rational.g".
12.1
IsRat
IsRat( obj )
379
380
CHAPTER 12. RATIONALS
IsRat returns true if obj , which can be an arbitrary object, is a rational and false otherwise. Integers are rationals with denominator 1, thus IsRat returns true for integers.
IsRat will signal an error if obj is an unbound variable or a procedure call.
gap> IsRat(
true
gap> IsRat(
true
gap> IsRat(
true
gap> IsRat(
false
#
12.2
2/3 );
17/-13 );
11 );
IsRat );
IsRat is a function, not a rational
Numerator
Numerator( rat )
Numerator returns the numerator of the rational rat. Because the numerator holds the
sign of the rational it may be any integer. Integers are rationals with denominator 1, thus
Numerator is the identity function for integers.
gap>
2
gap>
22
gap>
-17
gap>
11
Numerator( 2/3 );
Numerator( 66/123 );
# numerator and denominator are made relatively prime
Numerator( 17/-13 );
# the numerator holds the sign of the rational
Numerator( 11 );
# integers are rationals with denominator 1
Denominator (see 12.3) is the counterpart to Numerator.
12.3
Denominator
Denominator( rat )
Denominator returns the denominator of the rational rat. Because the numerator holds the
sign of the rational the denominator is always a positive integer. Integers are rationals with
the denominator 1, thus Denominator returns 1 for integers.
gap>
3
gap>
41
gap>
13
gap>
1
Denominator( 2/3 );
Denominator( 66/123 );
# numerator and denominator are made relatively prime
Denominator( 17/-13 );
# the denominator holds the sign of the rational
Denominator( 11 );
# integers are rationals with denominator 1
Numerator (see 12.2) is the counterpart to Denominator.
12.4. FLOOR
12.4
381
Floor
Floor(r )
This function returns the largest integer smaller or equal to r .
gap> Floor(-2/3);
-1
gap> Floor(2/3);
0
12.5
Mod1
Mod1(r )
The argument should be a rational or a list. If r is a rational, it returns (Numerator(r ) mod
Denominator(r ))/Denominator(r). If r is a list, it returns List(r ,Mod1). This function
is very useful for working in Q/Z.
gap> Mod1([-2/3,-1,7/4,3]);
[ 1/3, 0, 3/4, 0 ]
12.6
Comparisons of Rationals
q1 = q2
q1 <> q2
The equality operator = evaluates to true if the two rationals q1 and q2 are equal and to
false otherwise. The inequality operator <> evaluates to true if the two rationals q1 and
q2 are not equal and to false otherwise.
gap> 2/3 = -4/-6;
true
gap> 66/123 <> 22/41;
false
gap> 17/13 = 11;
false
q1 < q2
q1 <= q2
q1 > q2
q1 >= q2
The operators <, <=, >, and => evaluate to true if the rational q1 is less than, less than or
equal to, greater than, and greater than or equal to the rational q2 and to false otherwise.
One rational q1 = n1 /d1 is less than another q2 = n2 /d2 if and only if n1 d2 < n2 d2 . This
definition is of course only valid because the denominator of rationals is always defined to be
positive. This definition also extends to the comparison of rationals with integers, which are
interpreted as rationals with denominator 1. Rationals can also be compared with objects
of other types. They are smaller than objects of any other type by definition.
gap> 2/3 < 22/41;
false
gap> -17/13 < 11;
true
382
CHAPTER 12. RATIONALS
12.7
q1
q1
q1
q1
+
*
/
Operations for Rationals
q2
q2
q2
q2
The operators +, -, * and / evaluate to the sum, difference, product, and quotient of the two
rationals q1 and q2 . For the quotient / q2 must of course be nonzero, otherwise an error is
signalled. Either operand may also be an integer i , which is interpreted as a rational with
denominator 1. The result of those operations is always reduced. If, after the reduction,
the denominator is 1, the rational is in fact an integer, and is represented as such.
gap> 2/3 + 4/5;
22/15
gap> 7/6 * 2/3;
7/9
# note how the result is cancelled
gap> 67/6 - 1/6;
11
# the result is an integer
q ^ i
The powering operator ^ returns the i -th power of the rational q. i must be an integer. If
the exponent i is zero, q^i is defined as 1; if i is positive, q^i is defined as the i -fold product
q*q*..*q; finally, if i is negative, q^i is defined as (1/q)^-i . In this case q must of course
be nonzero.
gap> (2/3) ^ 3;
8/27
gap> (-17/13) ^ -1;
-13/17
# note how the sign switched
gap> (1/2) ^ -2;
4
12.8
Set Functions for Rationals
As was already mentioned in the introduction of this chapter the GAP3 object Rationals
is the domain of all rationals. All set theoretic functions, e.g., Intersection and Size, are
applicable to this domain.
gap> Intersection( Rationals, [ E(4)^0, E(4)^1, E(4)^2, E(4)^3 ] );
[ -1, 1 ]
# E(4) is the complex square root of -1
gap> Size( Rationals );
"infinity"
This does not seem to be very useful.
12.9
Field Functions for Rationals
As was already mentioned in the introduction of this chapter the GAP3 object Rationals
is the field of all rationals. All field functions, e.g., Norm and MinPol are applicable to
this domain and its elements. However, since the field of rationals is the prime field, all
12.9. FIELD FUNCTIONS FOR RATIONALS
383
those functions are trivial. Therefore, Conjugates( Rationals, q ) returns [ q ], Norm(
Rationals, q ) and Trace( Rationals, q ) return q, and CharPol( Rationals, q )
and MinPol( Rationals, q ) both return [ -q, 1 ].
384
CHAPTER 12. RATIONALS
Chapter 13
Cyclotomics
GAP3 allows computations in abelian extension fields of the rational field Q, i.e., fields with
abelian Galois group over Q. These fields are described in chapter 15. They are subfields
2πi
of cyclotomic fields Qn = Q(en ) where en = e n is a primitive n–th root of unity. Their
elements are called cyclotomics.
The internal representation of a cyclotomic does not refer to the smallest number field but
the smallest cyclotomic field containing it (the so–called conductor). This is because it
is easy to embed two cyclotomic fields in a larger one that contains both, i.e., there is a
natural way to get the sum or the product of two arbitrary cyclotomics as element of a
cyclotomic field. The disadvantage is that the arithmetical operations are too expensive
to do arithmetics in number fields, e.g., calculations in a matrix ring over a number field.
But it suffices to deal with irrationalities in character tables (see 49). (And in fact, the
comfortability of working with the natural embeddings is used there in many situations
which did not actually afford it . . . )
All functions that take a field extension as —possibly optional— argument, e.g., Trace or
Coefficients (see chapter 6), are described in chapter 15.
This chapter informs about
the representation of cyclotomics in GAP3 (see 13.1),
access to the internal data (see 13.7, 13.8)
integral elements of number fields (see 13.2, 13.3, 13.4),
characteristic functions (see 13.5, 13.6),
comparison and arithmetical operations of cyclotomics (see 13.9, 13.10),
functions concerning Galois conjugacy of cyclotomics (see 13.11, 13.14), or lists of
them (see 13.16, 13.17),
some special cyclotomics, as defined in [CCN+ 85] (see 13.13, 13.15)
The external functions are in the file LIBNAME/"cyclotom.g".
13.1
More about Cyclotomics
Elements of number fields (see chapter 15), cyclotomics for short, are arithmetical objects
like rationals and finite field elements; they are not implemented as records —like groups—
385
386
CHAPTER 13. CYCLOTOMICS
or e.g. with respect to a character table (although character tables may be the main interest
for cyclotomic arithmetics).
E( n )
2πi
returns the primitive n-th root of unity en = e n . Cyclotomics are usually entered as
(and irrational cyclotomics are always displayed as) sums of roots of unity with rational
coefficients. (For special cyclotomics, see 13.13.)
gap> E(9); E(9)^3; E(6); E(12) / 3;
-E(9)^4-E(9)^7
# the root needs not to be an element of the base
E(3)
-E(3)^2
-1/3*E(12)^7
For the representation of cyclotomics one has to recall that the cyclotomic field Qn = Q(en )
is a vector space of dimension ϕ(n) over the rationals where ϕ denotes Euler’s phi-function
(see 11.2).
Note that the set of all n-th roots of unity is linearly dependent for n > 1, so multiplication
is not the multiplication of the group ring Qhen i; given a Q-basis of Qn the result of the
multiplication (computed as multiplication of polynomials in en , using (en )n = 1) will be
converted to the base.
gap> E(5) * E(5)^2; ( E(5) + E(5)^4 ) * E(5)^2;
E(5)^3
E(5)+E(5)^3
gap> ( E(5) + E(5)^4 ) * E(5);
-E(5)-E(5)^3-E(5)^4
Cyclotomics are always represented in the smallest cyclotomic field they are contained in.
Together with the choice of a fixed base this means that two cyclotomics are equal if and
only if they are equally represented.
Addition and multiplication of two cyclotomics represented in Qn and Qm , respectively, is
computed in the smallest cyclotomic field containing both: QLcm(n,m) . Conversely, if the
result is contained in a smaller cyclotomic field the representation is reduced to the minimal
such field.
The base, the base conversion and the reduction to the minimal cyclotomic field are described
in [Zum89], more about the base can be found in 15.9.
Since n must be a short integer, the maximal cyclotomic field implemented in GAP3 is
not really the field Qab . The biggest allowed (though not very useful) n is 65535.
There is a global variable Cyclotomics in GAP3, a record that stands for the domain of all
cyclotomics (see chapter 15).
13.2
Cyclotomic Integers
A cyclotomic is called integral or cyclotomic integer if all coefficients of its minimal
polynomial are integers. Since the base used is an integral base (see 15.9), the subring
of cyclotomic integers in a cyclotomic field is formed by those cyclotomics which have not
only rational but integral coefficients in their representation as sums of roots of unity. For
example, square roots of integers are cyclotomic integers (see 13.13), any root of unity is a
13.3. INTCYC
387
cyclotomic integer, character values are always cyclotomic integers, but all rationals which
are not integers are not cyclotomic integers. (See 13.6)
gap> ER( 5 );
# The square root of 5 is a cyclotomic
E(5)-E(5)^2-E(5)^3+E(5)^4
# integer, it has integral coefficients.
gap> 1/2 * ER( 5 );
# This is not a cyclotomic integer, . . .
1/2*E(5)-1/2*E(5)^2-1/2*E(5)^3+1/2*E(5)^4
gap> 1/2 * ER( 5 ) - 1/2;
# . . . but this is one.
E(5)+E(5)^4
13.3
IntCyc
IntCyc( z )
returns the cyclotomic integer (see 13.2) with Zumbroich base coefficients (see 15.9) List(
zumb, x -> Int( x ) ) where zumb is the vector of Zumbroich base coefficients of the
cyclotomic z ; see also 13.4.
gap> IntCyc( E(5)+1/2*E(5)^2 ); IntCyc( 2/3*E(7)+3/2*E(4) );
E(5)
E(4)
13.4
RoundCyc
RoundCyc( z )
returns the cyclotomic integer (see 13.2) with Zumbroich base coefficients (see 15.9) List(
zumb, x -> Int( x+1/2 ) ) where zumb is the vector of Zumbroich base coefficients of
the cyclotomic z ; see also 13.3.
gap> RoundCyc( E(5)+1/2*E(5)^2 ); RoundCyc( 2/3*E(7)+3/2*E(4) );
E(5)+E(5)^2
-2*E(28)^3+E(28)^4-2*E(28)^11-2*E(28)^15-2*E(28)^19-2*E(28)^23
-2*E(28)^27
13.5
IsCyc
IsCyc( obj )
returns true if obj is a cyclotomic, and false otherwise. Will signal an error if obj is an
unbound variable.
gap> IsCyc( 0 ); IsCyc( E(3) ); IsCyc( 1/2 * E(3) ); IsCyc( IsCyc );
true
true
true
false
IsCyc is an internal function.
13.6
IsCycInt
IsCycInt( obj )
388
CHAPTER 13. CYCLOTOMICS
returns true if obj is a cyclotomic integer (see 13.2), false otherwise. Will signal an error
if obj is an unbound variable.
gap> IsCycInt( 0 ); IsCycInt( E(3) ); IsCycInt( 1/2 * E(3) );
true
true
false
IsCycInt is an internal function.
13.7
NofCyc
NofCyc( z )
NofCyc( list )
returns the smallest positive integer n for which the cyclotomic z is resp. for which all
2πi
cyclotomics in the list list are contained in Qn = Q(e n ) = Q(E(n)).
gap> NofCyc( 0 ); NofCyc( E(10) ); NofCyc( E(12) );
1
5
12
NofCyc is an internal function.
13.8
CoeffsCyc
CoeffsCyc( z , n )
If z is a cyclotomic which is contained in Qn , CoeffsCyc( z , n ) returns a list cfs of length
i−1
n where the entry at position i is the coefficient of E(n)
in the internal representation
1
of z as element of the cyclotomic field Qn (see 13.1, 15.9): z = cfs[1] + cfs[2] E(n) + . . . +
n−1
cfs[n] E(n)
.
Note that all positions which do not belong to base elements of Qn contain zeroes.
gap> CoeffsCyc( E(5), 5 ); CoeffsCyc( E(5), 15 );
[ 0, 1, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0 ]
gap> CoeffsCyc( 1+E(3), 9 ); CoeffsCyc( E(5), 7 );
[ 0, 0, 0, 0, 0, 0, -1, 0, 0 ]
Error, no representation of in 7th roots of unity
CoeffsCyc calls the internal function COEFFSCYC:
COEFFSCYC( z )
is equivalent to CoeffsCyc( z , NofCyc( z ) ), see 13.7.
13.9
Comparisons of Cyclotomics
To compare cyclotomics, the operators <, <=, =, >=, > and <> can be used, the result will
be true if the first operand is smaller, smaller or equal, equal, larger or equal, larger, or
inequal, respectively, and false otherwise.
13.10. OPERATIONS FOR CYCLOTOMICS
389
Cyclotomics are ordered as follows: The relation between rationals is as usual, and rationals
are smaller than irrational cyclotomics. For two irrational cyclotomics z1 , z2 which lie in different minimal cyclotomic fields, we have z1 < z2 if and only if NofCyc(z1 ) < NofCyc(z2 ));
if NofCyc(z1 ) = NofCyc(z2 )), that one is smaller that has the smaller coefficient vector, i.e.,
z1 ≤ z2 if and only if COEFFSCYC(z1 ) ≤ COEFFSCYC(z2 ).
You can compare cyclotomics with objects of other types; all objects which are not cyclotomics are larger than cyclotomics.
gap> E(5) < E(6);
# the latter value lies in Q3
false
gap> E(3) < E(3)^2;
# both lie in Q3 , so compare coefficients
false
gap> 3 < E(3); E(5) < E(7);
true
true
gap> E(728) < (1,2);
true
13.10
Operations for Cyclotomics
The operators +, -, *, / are used for addition, subtraction, multiplication and division of
two cyclotomics; note that division by 0 causes an error.
+ and - can also be used as unary operators;
^ is used for exponentiation of a cyclotomic with an integer; this is in general not equal to
Galois conjugation.
gap> E(5) + E(3); (E(5) + E(5)^4) ^ 2; E(5) / E(3); E(5) * E(3);
-E(15)^2-2*E(15)^8-E(15)^11-E(15)^13-E(15)^14
-2*E(5)-E(5)^2-E(5)^3-2*E(5)^4
E(15)^13
E(15)^8
13.11
GaloisCyc
GaloisCyc( z , k )
returns the cyclotomic obtained on raising the roots of unity in the representation of the
cyclotomic z to the k -th power. If z is represented in the field Qn and k is a fixed integer
relative prime to n, GaloisCyc( ., k ) acts as a Galois automorphism of Qn (see 15.8);
to get Galois automorphisms as functions, use 6.7 GaloisGroup.
gap> GaloisCyc(
E(5)^2+E(5)^3
gap> GaloisCyc(
E(5)^4
gap> GaloisCyc(
E(5)+E(5)^4
gap> GaloisCyc(
E(5)+E(5)^4
E(5) + E(5)^4, 2 );
E(5), -1 );
# the complex conjugate
E(5) + E(5)^4, -1 );
# this value is real
E(15) + E(15)^4, 3 );
GaloisCyc is an internal function.
390
CHAPTER 13. CYCLOTOMICS
13.12
Galois
Galois( z , e )
This function is a kind of generalized version of GaloisCyc. If z is a list it returns the list of
Galois(x,e) for each element x of z . If z is a cyclotomic, if e is an integer it is equivalent to GaloisCyc(z ,e) and if e is a Galois element it is equivalent to z^e. Finally,
if z is a record with a .operations field, it returns z .operations.Galois(z,e).
One such operations is predefined
if z is a polynomial, it does Galois(x,e) on
each coefficient of z .
gap> Galois(E(3),-1);
E(3)^2
gap> Galois(E(3),-1);
E(3)^2
gap> G:=GaloisGroup(CF(3));
Group( NFAutomorphism( CF(3) , 2 ) )
gap> E(3)^G.1;
E(3)^2
gap> Galois([E(3),E(5)],-1);
[ E(3)^2, E(5)^4 ]
gap> Galois(X(Cyclotomics)+E(3),-1);
X(Cyclotomics) + (E(3)^2)
13.13
EB(
EI(
EJ(
EJ(
ES(
ES(
NK(
ATLAS irrationalities
N ), EC( N ), . . . ,
N ), ER( N ),
N ), EK( N ), EL(
N , d ), EK( N , d
N ), ET( N ), . . . ,
N , d ), ET( N , d
N , k, d )
EH( N ),
N ), EM( N ),
), EL( N , d ), EM( N , d ),
EY( N ),
), . . . , EY( N , d ),
For N a positive integer, let z = E(N ) = e2πi/N . The following so-called atomic irrationalities (see [CCN+ 85, Chapter 7, Section 10]) can be entered by functions (Note that the
values are not necessary irrational.):
EB(N ) = bN
EC(N ) = cN
ED(N ) = dN
EE(N ) = eN
EF(N ) = fN
EG(N ) = gN
EH(N ) = hN
=
=
=
=
=
=
=
1
2
1
3
1
4
1
5
1
6
1
7
1
8
PN −1 j 2
z
Pj=1
N −1 j 3
z
Pj=1
N −1 j 4
z
Pj=1
N −1 j 5
z
Pj=1
N −1 j 6
z
Pj=1
N −1 j 7
z
Pj=1
N −1 j 8
j=1 z
(Note that in cN , . . . , hN , N must be a prime.)
(N
(N
(N
(N
(N
(N
(N
≡ 1 mod 2)
≡ 1 mod 3)
≡ 1 mod 4)
≡ 1 mod 5)
≡ 1 mod 6)
≡ 1 mod 7)
≡ 1 mod 8)
13.13. ATLAS IRRATIONALITIES
391
√
ER(N ) = √N
EI(N ) = i N
From a theorem of Gauss we know that
√
1
(−1 + √N ) if
2
bN =
1
2 (−1 + i N ) if
√
=
−N
N ≡1
N ≡ −1
mod4
,
mod4
√
so N can be (and in fact is) computed from bN . If N is a negative integer then ER(N ) =
EI(-N ).
For given N , let nk = nk (N ) be the first integer with multiplicative order exactly k modulo
N , chosen in the order of preference
1, −1, 2, −2, 3, −3, 4, −4, . . . .
We have
EY(N )
EX(N )
EW(N )
EV(N )
EU(N )
ET(N )
ES(N )
=
=
=
=
=
=
=
yn
xn
wn
vn
un
tn
sn
EM(N ) =
EL(N ) =
EK(N ) =
EJ(N ) =
(d)
=
=
=
=
=
=
=
mn
ln
kn
jn
z + zn
2
z + zn + zn
2
z + zn + zn
2
z + zn + zn
2
z + zn + zn
2
z + zn + zn
2
z + zn + zn
=
=
=
=
3
+ zn
3
4
+ zn + zn
5
+ . . . + zn
6
+ . . . + zn
7
+ . . . + zn
z − zn
2
3
z − zn + zn − zn
5
z − zn + . . . − zn
7
z − zn + . . . − zn
(n = n2 )
(n = n3 )
(n = n4 )
(n = n5 )
(n = n6 )
(n = n7 )
(n = n8 )
(n = n2 )
(n = n4 )
(n = n6 )
(n = n8 )
(d)
Let nk = nk (N ) be the d + 1-th integer with multiplicative order exactly k modulo N ,
(1)
(2)
(0)
chosen in the order of preference defined above; we write nk = nk , n0k = nk , n00k = nk
(d)
and so on. These values can be computed as NK(N ,k ,d )= nk (N ); if there is no integer
with the required multiplicative order, NK will return false.
The algebraic numbers
(1)
(2)
0
00
0
00
yN
= yN , yN
= yN , . . . , x0N , x00N , . . . , jN
, jN
,...
are obtained on replacing nk in the above definitions by n0k , n00k , . . .; they can be entered as
(d)
EY(N , d )
EX(N , d )
=
=
..
.
yN
(d)
xN
EJ(N , d )
=
jn
(d)
392
CHAPTER 13. CYCLOTOMICS
gap> EW(16,3); EW(17,2); ER(3); EI(3); EY(5); EB(9);
0
E(17)+E(17)^4+E(17)^13+E(17)^16
-E(12)^7+E(12)^11
E(3)-E(3)^2
E(5)+E(5)^4
1
13.14
StarCyc
StarCyc( z )
If z is an irrational element of a quadratic number field (i.e. if z is a quadratic irrationality),
StarCyc( z ) returns the unique Galois conjugate of z that is different from z ; this is often
called z ∗ (see 49.37). Otherwise false is returned.
gap> StarCyc( EB(5) ); StarCyc( E(5) );
E(5)^2+E(5)^3
false
13.15
Quadratic
Quadratic( z )
If z is a cyclotomic integer that
is contained in a quadratic number field over the rationals,
√
it can be written as z = a+bd n with integers a, b, n and d, where d is either 1 or 2. In
this case Quadratic( z ) returns a record with fields a, b, root, d and ATLAS where the
first four mean the integers mentioned above, and the last one is a string that is a (not
necessarily shortest) representation of z by bm , im or rm for m = |root| (see 13.13).
If z is not a quadratic irrationality or not a cyclotomic integer, false is returned.
gap> Quadratic( EB(5) ); Quadratic( EB(27) );
rec(
a := -1,
b := 1,
root := 5,
d := 2,
ATLAS := "b5" )
rec(
a := -1,
b := 3,
root := -3,
d := 2,
ATLAS := "1+3b3" )
gap> Quadratic(0); Quadratic( E(5) );
rec(
a := 0,
b := 0,
root := 1,
d := 1,
13.16. GALOISMAT
393
ATLAS := "0" )
false
13.16
GaloisMat
GaloisMat( mat )
mat must be a matrix of cyclotomics (or possibly unknowns, see 17.1). The conjugate of a
row in mat under a particular Galois automorphism is defined pointwise. If mat consists of
full orbits under this action then the Galois group of its entries acts on mat as a permutation
group, otherwise the orbits must be completed before.
GaloisMat( mat ) returns a record with fields mat, galoisfams and generators:
mat
a list with initial segment mat (not a copy of mat); the list consists of full orbits
under the action of the Galois group of the entries of mat defined above. The last
entries are those rows which had to be added to complete the orbits; so if they were
already complete, mat and mat have identical entries.
galoisfams
a list that has the same length as mat; its entries are either 1, 0, -1 or lists:
galoisfams[i] = 1 means that mat[i] consists of rationals, i.e. [mat[i]] forms an
orbit.
galoisfams[i] = −1 means that mat[i] contains unknowns; in this case [mat[i]] is
regarded as an orbit, too, even if mat[i] contains irrational entries.
If galoisfams[i] = [l1 , l2 ] is a list then mat[i] is the first element of its orbit in
mat; l1 is the list of positions of rows which form the orbit, and l2 is the list of
corresponding Galois automorphisms (as exponents, not as functions); so we have
mat[l1 [j]][k] = GaloisCyc(mat[i][k], l2 [j]).
galoisfams[i] = 0 means that mat[i] is an element of a nontrivial orbit but not the
first element of it.
generators
a list of permutations generating the permutation group corresponding to the action
of the Galois group on the rows of mat.
Note that mat should be a set, i.e. no two rows should be equal. Otherwise only the first
row of some equal rows is considered for the permutations, and a warning is printed.
gap> GaloisMat( [ [ E(3), E(4) ] ] );
rec(
mat := [ [ E(3), E(4) ], [ E(3), -E(4) ], [ E(3)^2, E(4) ],
[ E(3)^2, -E(4) ] ],
galoisfams := [ [ [ 1, 2, 3, 4 ], [ 1, 7, 5, 11 ] ], 0, 0, 0 ],
generators := [ (1,2)(3,4), (1,3)(2,4) ] )
gap> GaloisMat( [ [ 1, 1, 1 ], [ 1, E(3), E(3)^2 ] ] );
rec(
mat := [ [ 1, 1, 1 ], [ 1, E(3), E(3)^2 ], [ 1, E(3)^2, E(3) ] ],
galoisfams := [ 1, [ [ 2, 3 ], [ 1, 2 ] ], 0 ],
generators := [ (2,3) ] )
394
CHAPTER 13. CYCLOTOMICS
13.17
RationalizedMat
RationalizedMat( mat )
returns the set of rationalized rows of mat, i.e. the set of sums over orbits under the action
of the Galois group of the elements of mat (see 13.16).
This may be viewed as a kind of trace operation for the rows.
Note that mat should be a set, i.e. no two rows should be equal.
gap> mat:= CharTable( "A5" ).irreducibles;
[ [ 1, 1, 1, 1, 1 ], [ 3, -1, 0, -E(5)-E(5)^4, -E(5)^2-E(5)^3 ],
[ 3, -1, 0, -E(5)^2-E(5)^3, -E(5)-E(5)^4 ], [ 4, 0, 1, -1, -1 ],
[ 5, 1, -1, 0, 0 ] ]
gap> RationalizedMat( mat );
[ [ 1, 1, 1, 1, 1 ], [ 6, -2, 0, 1, 1 ], [ 4, 0, 1, -1, -1 ],
[ 5, 1, -1, 0, 0 ] ]
Chapter 14
Gaussians
If we adjoin a square root of -1, usually denoted by i, to the field of rationals we obtain a
field that is an extension of degree 2. This field is called the Gaussian rationals and its
ring of integers is called the Gaussian integers, because C.F. Gauss was the first to study
them.
In GAP3 Gaussian rationals are written in the form a + b*E(4), where a and b are rationals,
because E(4) is GAP3’s name for i. Because 1 and i form an integral base the Gaussian
integers are written in the form a + b*E(4), where a and b are integers.
The first sections in this chapter describe the operations applicable to Gaussian rationals
(see 14.1 and 14.2).
The next sections describe the functions that test whether an object is a Gaussian rational
or integer (see 14.3 and 14.4).
The GAP3 object GaussianRationals is the field domain of all Gaussian rationals, and
the object GaussianIntegers is the ring domain of all Gaussian integers. All set theoretic
functions are applicable to those two domains (see chapter 4 and 14.5).
The Gaussian rationals form a field so all field functions, e.g., Norm, are applicable to the
domain GaussianRationals and its elements (see chapter 6 and 14.6).
The Gaussian integers form a Euclidean ring so all ring functions, e.g., Factors, are applicable to GaussianIntegers and its elements (see chapter 5, 14.7, and 14.8).
The field of Gaussian rationals is just a special case of cyclotomic fields, so everything that
applies to those fields also applies to it (see chapters 13 and 15).
All functions are in the library file LIBNAME/"gaussian.g".
14.1
Comparisons of Gaussians
x = y
x <> y
The equality operator evaluates to true if the two Gaussians x and y are equal, and to
false otherwise. The inequality operator <> evaluates to true if the two Gaussians x and
395
396
CHAPTER 14. GAUSSIANS
y are not equal, and to false otherwise. It is also possible to compare a Gaussian with an
object of another type, of course they are never equal.
Two Gaussians a + b*E(4) and c + d *E(4) are considered equal if a = c and b = d .
gap> 1 + E(4) = 2 / (1 - E(4));
true
gap> 1 + E(4) = 1 - E(4);
false
gap> 1 + E(4) = E(6);
false
x
x
x
x
y
>= y
The operators <, <=, >, and >= evaluate to true if the Gaussian x is less than, less than or
equal to, greater than, and greater than or equal to the Gaussian y, and to false otherwise.
Gaussians can also be compared to objects of other types, they are smaller than anything
else, except other cyclotomics (see 13.9).
A Gaussian a + b*E(4) is considered less than another Gaussian c + d *E(4) if a is less
than c, or if a is equal to c and b is less than d .
gap> 1 + E(4) < 2 + E(4);
true
gap> 1 + E(4) < 1 - E(4);
false
gap> 1 + E(4) < 1/2;
false
14.2
x
x
x
x
+
*
/
Operations for Gaussians
y
y
y
y
The operators +, -, *, and / evaluate to the sum, difference, product, and quotient of the
two Gaussians x and y. Of course either operand may also be an ordinary rational (see 12),
because the rationals are embedded into the Gaussian rationals. On the other hand the
Gaussian rationals are embedded into other cyclotomic fields, so either operand may also
be a cyclotomic (see 13). Division by 0 is as usual an error.
x ^ n
The operator ^ evaluates to the n-th power of the Gaussian rational x . If n is positive, the
power is defined as the n-fold product x *x *...x ; if n is negative, the power is defined as
(1/x )^(-n); and if n is zero, the power is 1, even if x is 0.
gap> (1 + E(4)) * (E(4) - 1);
-2
14.3. ISGAUSSRAT
14.3
397
IsGaussRat
IsGaussRat( obj )
IsGaussRat returns true if obj , which may be an object of arbitrary type, is a Gaussian
rational and false otherwise. Will signal an error if obj is an unbound variable.
gap> IsGaussRat(
true
gap> IsGaussRat(
true
gap> IsGaussRat(
false
gap> IsGaussRat(
false
1/2 );
E(4) );
E(6) );
true );
IsGaussInt can be used to test whether an object is a Gaussian integer (see 14.4).
14.4
IsGaussInt
IsGaussInt( obj )
IsGaussInt returns true if obj , which may be an object of arbitrary type, is a Gaussian
integer, and false otherwise. Will signal an error if obj is an unbound variable.
gap> IsGaussInt(
true
gap> IsGaussInt(
true
gap> IsGaussInt(
false
gap> IsGaussInt(
false
1 );
E(4) );
1/2 + 1/2*E(4) );
E(6) );
IsGaussRat can be used to test whether an object is a Gaussian rational (see 14.3).
14.5
Set Functions for Gaussians
As already mentioned in the introduction of this chapter the objects GaussianRationals
and GaussianIntegers are the domains of Gaussian rationals and integers respectively. All
set theoretic functions, i.e., Size and Intersection, are applicable to these domains and
their elements (see chapter 4). There does not seem to be an important use of this however.
All functions not mentioned here are not treated specially, i.e., they are implemented by the
default function mentioned in the respective section.
in
The membership test for Gaussian rationals is implemented via IsGaussRat (14.3). The
membership test for Gaussian integers is implemented via IsGaussInt (see 14.4).
Random
398
CHAPTER 14. GAUSSIANS
A random Gaussian rational a + b*E(4) is computed by combining two random rationals a
and b (see 12.8). Likewise a random Gaussian integer a + b*E(4) is computed by combining
two random integers a and b (see 10.15).
gap> Size( GaussianRationals );
"infinity"
gap> Intersection( GaussianIntegers, [1,1/2,E(4),-E(6),E(4)/3] );
[ 1, E(4) ]
14.6
Field Functions for Gaussian Rationals
As already mentioned in the introduction of this chapter, the domain of Gaussian rationals
is a field. Therefore all field functions are applicable to this domain and its elements (see
chapter 6). This section gives further comments on the definitions and implementations
of those functions for the the Gaussian rationals. All functions not mentioned here are
not treated specially, i.e., they are implemented by the default function mentioned in the
respective section.
Conjugates
The field of Gaussian rationals is an extension of degree 2 of the rationals, its prime field.
Therefore there is one further conjugate of every element a + b*E(4), namely a - b*E(4).
Norm, Trace
According to the definition of conjugates above, the norm of a Gaussian rational a + b*E(4)
is a^2 + b^2 and the trace is 2*a.
14.7
Ring Functions for Gaussian Integers
As already mentioned in the introduction to this chapter, the ring of Gaussian integers is a
Euclidean ring. Therefore all ring functions are applicable to this ring and its elements (see
chapter 5). This section gives further comments on the definitions and implementations of
those functions for the Gaussian integers. All functions not mentioned here are not treated
specially, i.e., they are implemented by the default function mentioned in the respective
section.
IsUnit, Units, IsAssociated, Associates
The units of GaussianIntegers are [ 1, E(4), -1, -E(4) ].
StandardAssociate
The standard associate of a Gaussian integer x is the associated element y of x that lies in the
first quadrant of the complex plane. That is y is that element from x * [1,-1,E(4),-E(4)]
that has positive real part and nonnegative imaginary part.
EuclideanDegree
14.8. TWOSQUARES
399
The Euclidean degree of a Gaussian integer x is the product of x and its complex conjugate.
EuclideanRemainder
Define the integer part i of the quotient of x and y as the point of the lattice spanned by
1 and E(4) that lies next to the rational quotient of x and y, rounding towards the origin
if there are several such points. Then EuclideanRemainder( x , y ) is defined as x - i *
y. With this definition the ordinary Euclidean algorithm for the greatest common divisor
works, whereas it does not work if you always round towards the origin.
EuclideanQuotient
The Euclidean quotient of two Gaussian integers x and y is the quotient of w and y, where
w is the difference between x and the Euclidean remainder of x and y.
QuotientRemainder
QuotientRemainder uses EuclideanRemainder and EuclideanQuotient.
IsPrime, IsIrreducible
Since the Gaussian integers are a Euclidean ring, primes and irreducibles are equivalent.
The primes are the elements 1 + E(4) and 1 - E(4) of norm 2, the elements a + b*E(4)
and a - b*E(4) of norm p = a^2 + b^2 with p a rational prime congruent to 1 mod 4,
and the elements p of norm p^2 with p a rational prime congruent to 3 mod 4.
Factors
The list returned by Factors is sorted according to the norms of the primes, and among
those of equal norm with respect to <. All elements in the list are standard associates,
except the first, which is multiplied by a unit as necessary.
The above characterization already shows how one can factor a Gaussian integer. First
compute the norm of the element, factor this norm over the rational integers and then split
2 and the primes congruent to 1 mod 4 with TwoSquares (see 14.8).
gap> Factors( GaussianIntegers, 30 );
[ -1-E(4), 1+E(4), 3, 1+2*E(4), 2+E(4) ]
14.8
TwoSquares
TwoSquares( n )
TwoSquares returns a list of two integers x <= y such that the sum of the squares of x and
y is equal to the nonnegative integer n, i.e., n = x2 + y 2 . If no such representation exists
TwoSquares will return false. TwoSquares will return a representation for which the gcd
of x and y is as small as possible. If there are several such representations, it is not specified
which one TwoSquares returns.
Let a be the product of all maximal powers of primes of the form 4k + 3 dividing n. A
representation of n as a sum of two squares exists if and only if a is a perfect square. Let b
400
CHAPTER 14. GAUSSIANS
be the maximal power of 2 dividing n, or its half, whichever is a perfect square. Then the
minimal possible gcd of x and y is the square root c of ab. The number of different minimal
representations with x <= y is 2l−1 , where l is the number of different prime factors of the
form 4k + 1 of n.
gap> TwoSquares( 5 );
[ 1, 2 ]
gap> TwoSquares( 11 );
false
# no representation exists
gap> TwoSquares( 16 );
[ 0, 4 ]
gap> TwoSquares( 45 );
[ 3, 6 ]
# 3 is the minimal possible gcd because 9 divides 45
gap> TwoSquares( 125 );
[ 2, 11 ]
# not [ 5, 10 ] because this has not minimal gcd
gap> TwoSquares( 13*17 );
[ 5, 14 ]
# [10,11] would be the other possible representation
gap> TwoSquares( 848654483879497562821 );
[ 6305894639, 28440994650 ]
# 848654483879497562821 is prime
Chapter 15
Subfields of Cyclotomic Fields
The only number
√ fields that GAP3 can handle at the moment are subfields of cyclotomic
fields, e.g., Q( 5) is a number field that is not cyclotomic but contained in the cyclotomic
2πi
field Q5 = Q(e 5 ). Although this means that GAP3 does not know arbitrary algebraic
number fields but only those with abelian Galois group, here we call these fields number
fields for short. The elements of number fields are called cyclotomics (see chapter 13).
Thus number fields are the domains (see chapter 4) related to cyclotomics; they are special
field records (see 6.17) which are needed to specify the field extension with respect to which
e.g. the trace of a cyclotomic shall be computed.
In many situations cyclotomic fields need not be treated in a special way, except that there
may be more efficient algorithms for them than for arbitrary number fields. For that, there
are the global variables NumberFieldOps and CyclotomicFieldOps, both records which
contain the field operations stored in FieldOps (see chapter 6) and in which some functions
are overlaid (see 15.13). If all necessary information about a function is already given in
chapter 6, this function is not described here; this is the case e.g. for Conjugates and related
functions, like Trace and CharPol. Some functions, however, need further explanation, e.g.,
15.12 tells more about Coefficients for number fields.
There are some functions which are different for cyclotomic fields and other number fields,
e.g., the field constructors CF resp. NF. In such a situation, the special case is described in a
section immediately following the section about the general case.
Besides the single number fields, there is another domain in GAP3 related to number fields,
the domain Cyclotomics of all cyclotomics. Although this is an abstract field, namely the
field Qab , Cyclotomics is not a field record. It is used by DefaultField, DefaultRing,
Domain, Field and Ring (see 6.3, 5.3, 4.5, 6.2, 5.2) which are mainly interested in the
corresponding entries of Cyclotomics.operations since these functions know how to create
fields resp. integral rings generated by some cyclotomics.
This chapter informs about
characteristic functions (see 15.1, 15.2),
field constructors (see 15.3, 15.4),
(default) fields of cyclotomics (see 15.5), and (default) rings of cyclotomic integers
(see 15.6),
Galois groups of number fields (see 15.7, 15.8),
401
402
CHAPTER 15. SUBFIELDS OF CYCLOTOMIC FIELDS
vector space bases (see 15.9, 15.10, 15.11) and coefficients (see 15.12) and
overlaid functions in the operations records (see 15.13).
The external functions are in the file LIBNAME/"numfield.g"
15.1
IsNumberField
IsNumberField( obj )
returns true if obj is a field record (see 6.1, 6.17) of a field of characteristic zero where
F .generators is a list of cyclotomics (see chapter 13), and false else.
gap> IsNumberField( CF(9) ); IsNumberField( NF( [ ER(3) ] ) );
true
true
gap> IsNumberField( GF( 2 ) );
false
15.2
IsCyclotomicField
IsCyclotomicField( obj )
returns true if obj is a number field record (see 15.1) where obj .isCyclotomicField =
true, and false else.
gap> IsCyclotomicField( CF(9) );
true
gap> IsCyclotomicField( NF( [ ER(-3) ] ) );
true
gap> IsCyclotomicField( NF( [ ER(3) ] ) );
false
15.3
Number Field Records
NumberField(
NumberField(
NumberField(
NumberField(
gens )
n, stab )
subfield , poly )
subfield , base )
NumberField may be abbreviated NF; it returns number fields, namely
NumberField( gens ):
the number field generated by the cyclotomics in the list gens,
NumberField( n, stab ):
the fixed field of the prime residues in the list stab inside the cyclotomic field Qn (see 15.4),
NumberField( subfield , poly ):
the splitting field of the polynomial poly (which must have degree at most 2) over the number
field subfield ; subfield = 0 is equivalent to subfield = Rationals,
NumberField( subfield , base ):
the extension field of the number field subfield which is as vector space generated by the
elements of the list base of cyclotomics; that means, base must be or at least contain a
15.4. CYCLOTOMIC FIELD RECORDS
403
vector space base of this extension, if base is a base it will be assigned to the base field of
the cyclotomic field (see 15.12). subfield = 0 is equivalent to subfield = Rationals.
gap> NF( [ EB(7), ER(3) ] );
NF(84,[ 1, 11, 23, 25, 37, 71 ])
gap> NF( 7, [ 1 ] );
CF(7)
gap> NF( NF( [ EB(7) ] ), [ 1, 1, 1 ] );
NF(NF(7,[ 1, 2, 4 ]),[ 1, E(3) ])
gap> F:= NF( 0, [ 1, E(4) ] ); G:= NF( 0, NormalBaseNumberField( F ) );
GaussianRationals
CF( Rationals,[ 1/2-1/2*E(4), 1/2+1/2*E(4) ])
gap> G.base; G.basechangemat; Coefficients( G, 1 );
[ 1/2-1/2*E(4), 1/2+1/2*E(4) ]
[ [ 1, 1 ], [ -1, 1 ] ]
[ 1, 1 ]
Number field records are field records (see 6.17) representing a number field. Besides the
obligatory record components, a number field record F contains the component
stabilizer
the list of prime residues modulo NofCyc( F .generators ) which fix all elements
of F
and possibly
isIntegralBase
true if F .base is an integral vector space base of the field extension F / F .field,
false else (used by 5.2 Ring); for the case that F .field is a cyclotomic field, 15.10
describes integral bases of the field extension;
isNormalBase
true if F .base is a normal vector space base of the field extension F /F .field,
false else;
coeffslist
a list of integers used by 9.10 Coefficients; (see also 15.12);
coeffsmat
a matrix of cyclotomics used by 9.10 Coefficients; bound only if F .field is not a
cyclotomic field (see also 15.12);
basechangemat
square matrix of dimension F .dimension, representing the basechange from the default base of F / F .field (see 15.12) to the base stored in F .base if these two are
different; used by Coefficients.
Note: These fields and also the field base should not be changed by hand!
15.4
Cyclotomic Field Records
CyclotomicField(
CyclotomicField(
CyclotomicField(
CyclotomicField(
n )
gens )
subfield , n )
subfield , base )
404
CHAPTER 15. SUBFIELDS OF CYCLOTOMIC FIELDS
CyclotomicField may be abbreviated CF; it returns cyclotomic fields, namely
CyclotomicField( n )
the field Qn (over the rationals),
CyclotomicField( gens )
the smallest cyclotomic field containing the cyclotomics in the list gens (over the
rationals),
CyclotomicField( subfield , n )
the field Qn over the number field subfield ,
CyclotomicField( subfield , base )
the cyclotomic extension field of the number field subfield which is as vector space
generated by the elements of the list base of cyclotomics; that means, base must be
or at least contain a vector space base of this extension, if base is a base it will be
assigned to the base field of the cyclotomic field (see 15.12). subfield = 0 is equivalent
to subfield = Rationals.
gap> CF( 5 ); CF( [ EB(7), ER(3) ] ); CF( NF( [ ER(3) ] ), 24 );
CF(5)
CF(84)
CF(24)/NF(12,[ 1, 11 ])
gap> CF( CF(3), [ 1, E(4) ] );
CF(12)/CF(3)
A cyclotomic field record is a field record (see 6.17), in particular a number field record (see
15.3) that represents a cyclotomic field. Besides the obligatory record fields, a cyclotomic
field record F contains the fields
isCyclotomicField
always true; used by 15.2 IsCyclotomicField,
zumbroichbase
a list containing ZumbroichBase( n, m ) (see 15.9) if F represents the field extension Qn /Qm , and containing Zumbroichbase( n, 1 ) if F is an extension of a
number field that is not cyclotomic; used by 9.10 Coefficients, see 15.12
and possibly optional fields of number fields (see 15.3).
15.5
DefaultField and Field for Cyclotomics
For a set S of cyclotomics,
DefaultField( S ) = CF( S ) is the smallest cylotomic field containing S (see 6.3), the
so–called conductor of S ;
Field( S ) = NF( S ) is the smallest field containing S (see 6.2).
gap> DefaultField( [ E(5) ] ); DefaultField( [ E(3), ER(6) ] );
CF(5)
CF(24)
gap> Field( [ E(5) ] ); Field( [ E(3), ER(6) ] );
CF(5)
NF(24,[ 1, 19 ])
15.6. DEFAULTRING AND RING FOR CYCLOTOMIC INTEGERS
405
DefaultField and Field are used by functions that specify the field for which some cyclotomics are regarded as elements (see 6.3, 6.2), e.g., Trace with only one argument will
compute the trace of this argument (which must be a cyclotomic) with respect to its default
field.
15.6
DefaultRing and Ring for Cyclotomic Integers
For a set S of cyclotomic integers,
DefaultRing( S ) is the ring of integers in CF( S ) (see 5.3),
Ring( S ) is the ring of integers in NF( S ) (see 5.2).
gap> Ring( [ E(5) ] );
Ring( E(5) )
gap> Ring( [ EB(7) ] );
Ring( E(7)+E(7)^2+E(7)^4 )
gap> DefaultRing( [ EB(7) ] );
Ring( E(7) )
15.7
GeneratorsPrimeResidues
GeneratorsPrimeResidues( n )
returns a record with fields
primes
the set of prime divisors of the integer n,
exponents
the corresponding exponents in the factorization of n and
generators
generators of the group of prime residues: For each odd prime p there is one generator,
corresponding to a primitive root of the subgroup (Z/pνp )∗ of (Z/nZ)∗ , where νp is
the exponent of p in the factorization of n; for p = 2, we have one generator in
the case that 8 does not divide n, and a list of two generators (corresponding to
h∗5, ∗(2ν2 − 1)i = (Z/2ν2 )∗ ) else.
gap> GeneratorsPrimeResidues( 9 );
# 2 is a primitive root
rec(
primes := [ 3 ],
exponents := [ 2 ],
generators := [ 2 ] )
gap> GeneratorsPrimeResidues( 24 );
# 8 divides 24
rec(
primes := [ 2, 3 ],
exponents := [ 3, 1 ],
generators := [ [ 7, 13 ], 17 ] )
gap> GeneratorsPrimeResidues( 1155 );
rec(
primes := [ 3, 5, 7, 11 ],
exponents := [ 1, 1, 1, 1 ],
generators := [ 386, 232, 661, 211 ] )
406
CHAPTER 15. SUBFIELDS OF CYCLOTOMIC FIELDS
15.8
GaloisGroup for Number Fields
The Galois automorphisms of the cyclotomic field Qn are given by linear extension of
the maps ∗k : en 7→ ekn with 1 ≤ k < n and Gcd( n, k ) = 1 (see 13.11). Note that this
action is not equal to exponentiation of cyclotomics, i.e., in general z ∗k is different from z k :
gap> ( E(5) + E(5)^4 )^2; GaloisCyc( E(5) + E(5)^4, 2 );
-2*E(5)-E(5)^2-E(5)^3-2*E(5)^4
E(5)^2+E(5)^3
For Gcd( n, k ) 6= 1, the map en 7→ ekn is not a field automorphism but only a linear map:
gap> GaloisCyc( E(5)+E(5)^4, 5 ); GaloisCyc( ( E(5)+E(5)^4 )^2, 5 );
2
-6
The Galois group Gal(Qn , Q) of the field extension Qn /Q is isomorphic to the group
(Z/nZ)∗ of prime residues modulo n, via the isomorphism
(Z/nZ)∗
k
→ Gal(Qn , Q)
,
7
→
(z 7→ z ∗k )
thus the Galois group of the field extension Qn /L with L ⊆ Qn which is simply the factor
group of Gal(Qn , Q) modulo the stabilizer of L, and the Galois group of L/L0 which is
the subgroup in this group that stabilizes L0 , are easily described in terms of (Z/nZ)∗
(Generators of (Z/nZ)∗ can be computed using 15.7 GeneratorsPrimeResidues.).
The Galois group of a field extension can be computed using 6.7 GaloisGroup:
gap> f:= NF( [ EY(48) ] );
NF(48,[ 1, 47 ])
gap> g:= GaloisGroup( f );
Group( NFAutomorphism( NF(48,[ 1, 47 ]) , 17 ), NFAutomorphism( NF(48,
[ 1, 47 ]) , 11 ), NFAutomorphism( NF(48,[ 1, 47 ]) , 17 ) )
gap> Size( g ); IsCyclic( g ); IsAbelian( g );
8
false
true
gap> f.base[1]; g.1; f.base[1] ^ g.1;
E(24)-E(24)^11
NFAutomorphism( NF(48,[ 1, 47 ]) , 17 )
E(24)^17-E(24)^19
gap> Operation( g, NormalBaseNumberField( f ), OnPoints );
Group( (1,6)(2,4)(3,8)(5,7), (1,4,8,5)(2,3,7,6), (1,6)(2,4)(3,8)
(5,7) )
The number field automorphism NFAutomorphism( F , k ) maps each element x of F to
GaloisCyc( x , k ), see 13.11.
15.9
ZumbroichBase
ZumbroichBase( n, m )
15.10. INTEGRAL BASES FOR NUMBER FIELDS
407
returns the set of exponents i where ein belongs to the base Bn,m of the field extension
Qn /Qm ; for that, n and m must be positive integers where m divides n.
Bn,m is defined as follows:
Let P denote the set of prime divisors of n, n =
and {ejn1 }j∈J ⊗ {ekn2 }k∈K = {ejn1 · ekn2 }j∈J,k∈K .
Q
p∈P
pνp , m =
Q
p∈P
pµp with µp ≤ νp ,
Then
νp −1
Bn,m =
O O
{ejpk+1 }j∈Jk,p
where Jk,p
p∈P k=µp
{0}
{0, 1}
=
{1, . . . , p − 1}
p−1
{− p−1
2 ,..., 2 }
;
;
;
;
k
k
k
k
= 0, p = 2
> 0, p = 2
.
= 0, p 6= 2
> 0, p 6= 2
Bn,1 is equal to the base B(Qn ) of Qn over the rationals given in [Zum89] (Note that the
notation here is slightly different from that there.).
Bn,m consists of roots of unity, it is an integral base (that is, the integral elements in Qn
have integral coefficients, see 13.2), it is a normal base for squarefree n and closed under
complex conjugation for odd n.
gap>
[ 1,
[ 0,
gap>
[ 2,
[ 0,
15.10
ZumbroichBase( 15, 1 ); ZumbroichBase( 12, 3 );
2, 4, 7, 8, 11, 13, 14 ]
3 ]
ZumbroichBase( 10, 2 ); ZumbroichBase( 32, 4 );
4, 6, 8 ]
1, 2, 3, 4, 5, 6, 7 ]
Integral Bases for Number Fields
LenstraBase( n, stabilizer , super )
returns a list [b1 , b2 , . . . , bm ] of lists, each bi consisting of integers such that the elements
P
j
j∈bi E(n) form an integral base of the number field NF( n, stabilizer ), see 15.3.
super is a list representing a supergroup of the group described by the list stabilizer ; the
base is chosen such that the group of super acts on it, as far as this is possible.
Note: The bi are in general not sets, since for stabilizer = super , bi [1] is always an element
of ZumbroichBase( N , 1 ); this is used by NF (see 15.3) and Coefficients (see 15.12).
stabilizer must not contain the stabilizer of a proper cyclotomic subfield of Qn .
gap> LenstraBase( 24, [ 1, 19 ], [ 1, 19 ] );
#
[ [ 1, 19 ], [ 8 ], [ 11, 17 ], [ 16 ] ]
#
gap> LenstraBase( 24, [ 1, 19 ], [ 1, 5, 19, 23 ] );
#
[ [ 1, 19 ], [ 5, 23 ], [ 8 ], [ 16 ] ]
gap> LenstraBase( 15, [ 1, 4 ], PrimeResidues( 15 ) ); #
[ [ 1, 4 ], [ 2, 8 ], [ 7, 13 ], [ 11, 14 ] ]
#
a base
√ of
Q3 ( 6),
another one
normal
√ base of
Q3 ( 5)
408
CHAPTER 15. SUBFIELDS OF CYCLOTOMIC FIELDS
15.11
NormalBaseNumberField
NormalBaseNumberField( F )
NormalBaseNumberField( F , x )
returns a list of cyclotomics which form a normal base of the number field F (see 15.3), i.e.
a vector space base of the field F over its subfield F .field which is closed under the action
of the Galois group F .galoisGroup of the field extension.
The normal base is computed as described in [Art68]: Let Φ denote the polynomial of a field
extension L/L0 , Φ0 its derivative and α one of its roots; then for all except finitely many
Φ(z)
0
elements z ∈ L0 , the conjugates of (z−α)·Φ
0 (α) form a normal base of L/L .
When NormalBaseNumberField( F ) is called, z is chosen as integer, starting with 1,
NormalBaseNumberField( F , x ) starts with z = x , increasing by one, until a normal
base is found.
gap> NormalBaseNumberField( CF( 5 ) );
[ -E(5), -E(5)^2, -E(5)^3, -E(5)^4 ]
gap> NormalBaseNumberField( CF( 8 ) );
[ 1/4-2*E(8)-E(8)^2-1/2*E(8)^3, 1/4-1/2*E(8)+E(8)^2-2*E(8)^3,
1/4+2*E(8)-E(8)^2+1/2*E(8)^3, 1/4+1/2*E(8)+E(8)^2+2*E(8)^3 ]
15.12
Coefficients for Number Fields
Coefficients( z )
Coefficients( F , z )
return the coefficient vector cfs of z with respect to a particular base B , i.e., we have z =
cfs * B . If z is the only argument, B is the default base of the default field of z (see 15.5),
otherwise F must be a number field containing z , and we have B = F .base.
The default base of a number field is defined as follows:
For the field extension Qn /Qm (i.e. both F and F .field are cyclotomic fields), B is the
base Bn,m described in 15.9. This is an integral base which is closely related to the internal
representation of cyclotomics, thus the coefficients are easy to compute, using only the
zumbroichbase fields of F and F .field.
For the field extension L/Q where L is not a cyclotomic field, B is the integral base described
in 15.10 that consists of orbitsums on roots of unity. The computation of coefficients requires
the field F .coeffslist.
in future: replace Q by Qm
In all other cases, B = NormalBaseNumberField( F ). Here, the coefficients of z with
respect to B are computed using F .coeffslist and F .coeffsmat.
If F .base is not the default base of F , the coefficients with respect to the default base are
multiplied with F .basechangemat. The only possibility where it is allowed to prescribe a
base is when the field is constructed (see 15.3, 15.4).
gap> F:= NF( [ ER(3), EB(7) ] ) / NF( [ ER(3) ] );
NF(84,[ 1, 11, 23, 25, 37, 71 ])/NF(12,[ 1, 11 ])
gap> Coefficients( F, ER(3) ); Coefficients( F, EB(7) );
15.13. DOMAIN FUNCTIONS FOR NUMBER FIELDS
409
[ -E(12)^7+E(12)^11, -E(12)^7+E(12)^11 ]
[ 11*E(12)^4+7*E(12)^7+11*E(12)^8-7*E(12)^11,
-10*E(12)^4-7*E(12)^7-10*E(12)^8+7*E(12)^11 ]
gap> G:= CF( 8 ); H:= CF( 0, NormalBaseNumberField( G ) );
CF(8)
CF( 0,[ 1/4-2*E(8)-E(8)^2-1/2*E(8)^3, 1/4-1/2*E(8)+E(8)^2-2*E(8)^3,
1/4+2*E(8)-E(8)^2+1/2*E(8)^3, 1/4+1/2*E(8)+E(8)^2+2*E(8)^3 ])
gap> Coefficients( G, ER(2) ); Coefficients( H, ER(2) );
[ 0, 1, 0, -1 ]
[ -1/3, 1/3, 1/3, -1/3 ]
15.13
Domain Functions for Number Fields
The following functions of FieldOps (see chapter 6) are overlaid in NumberFieldOps:
/, Coefficients, Conjugates, GaloisGroup, in, Intersection, Norm, Order, Print,
Random, Trace.
The following functions of NumberFieldOps are overlaid in CyclotomicFieldOps:
Coefficients, Conjugates, in, Norm, Print, Trace.
410
CHAPTER 15. SUBFIELDS OF CYCLOTOMIC FIELDS
Chapter 16
Algebraic extensions of fields
If we adjoin a root α of an irreducible polynomial p ∈ K[x] to the field K we get an
algebraic extension K(α), which is again a field. By Kronecker’s construction, we may
identify K(α) with the factor ring K[x]/(p), an identification that also provides a method
for computing in these extension fields.
Currently GAP3 only allows extension fields of fields K, when K itself is not an extension
field.
As it is planned to modify the representation of field extensions to unify vector space structures and to speed up computations, All information in this chapter is subject to
change in future versions.
16.1
AlgebraicExtension
AlgebraicExtension( pol )
constructs the algebraic extension L corresponding to the polynomial pol . pol must be an
irreducible polynomial defined over a “defining”field K . The elements of K are embedded
into L in the canonical way. As L is a field, all field functions are applicable to L. Similarly,
all field element functions apply to the elements of L.
L is considered implicitely to be a field over the subfield K . This means, that functions like
Trace and Norm relative to subfields are not supported.
gap> x:=X(Rationals);;x.name:="x";;
gap> p:=x^4+3*x^2+1;
x^4 + 3*x^2 + 1
gap> e:=AlgebraicExtension(p);
AlgebraicExtension(Rationals,x^4 + 3*x^2 + 1)
gap> e.name:="e";;
gap> IsField(e);
true
gap> y:=X(GF(2));;y.name:="y";;
gap> q:=y^2+y+1;
Z(2)^0*(y^2 + y + 1)
gap> f:=AlgebraicExtension(q);
AlgebraicExtension(GF(2),Z(2)^0*(y^2 + y + 1))
411
412
CHAPTER 16. ALGEBRAIC EXTENSIONS OF FIELDS
16.2
IsAlgebraicExtension
IsAlgebraicExtension( D )
IsAlgebraicExtension returns true if the object D is an algebraic field extension and
false otherwise.
More precisely, IsAlgebraicExtension tests whether D is an algebraic field extension
record (see 16.11). So, for example, a matrix ring may in fact be a field extension, yet
IsAlgebraicExtension would return false.
gap> IsAlgebraicExtension(e);
true
gap> IsAlgebraicExtension(Rationals);
false
16.3
RootOf
RootOf( pol )
returns a root of the irreducible polynomial pol as element of the corresponding extension field AlgebraicExtension(pol ). This root is called the primitive element of this
extension.
gap> r:=RootOf(p);
RootOf(x^4 + 3*x^2 + 1)
gap> r.name:="alpha";;
16.4
Algebraic Extension Elements
According to Kronecker’s construction, the elements of an algebraic extension are considered
to be polynomials in the primitive element. Unless they are already in the defining field (in
which case they are represented as elements of this field), they are represented by records
in GAP3 (see 16.12). These records contain a representation a polynomial in the primitive
element. The extension corresponding to this primitive element is the default field for the
algebraic element.
The usual field operations are applicable to algebraic elements.
gap> r^3/(r^2+1);
-1*alpha^3-1*alpha
gap> DefaultField(r^2);
e
16.5
Set functions for Algebraic Extensions
As algebraic extensions are fields, all set theoretic functions are applicable to algebraic
elements. The following two routines are treated specially:
in
16.6. ISNORMALEXTENSION
413
tests, whether a given object is contained in an algebraic extension. The base field is
embedded in the natural way into the extension. Two extensions are considered to be
distinct, even if the minimal polynomial of one has a root in the other one.
gap> r in e;5 in e;
true
true
gap> p1:=Polynomial(Rationals,MinPol(r^2));
x^2 + 3*x + 1
gap> r2:=RootOf(p1);
RootOf(x^2 + 3*x + 1)
gap> r2 in e;
false
Random
A random algebraic element is computed by taking a linear combination of the powers of
the primitive element with random coefficients from the ground field.
gap> ran:=Random(e);
-1*alpha^3-4*alpha^2
16.6
IsNormalExtension
IsNormalExtension(L)
An algebraic extension field is called a normal extension, if it is a splitting field of the
defining polynomial. The second version returns whether L is a normal extension of K . The
first version returns whether L is a normal extension of its definition field.
gap> IsNormalExtension(e);
true
gap> p2:=x^4+x+1;;
gap> e2:=AlgebraicExtension(p2);
AlgebraicExtension(Rationals,x^4 + x + 1)
gap> IsNormalExtension(e2);
false
16.7
MinpolFactors
MinpolFactors( L )
returns the factorization of the defining polynomial of L over L.
gap> X(e).name:="X";;
gap> MinpolFactors(e);
[ X + (-1*alpha), X + (-1*alpha^3-3*alpha), X + (alpha),
X + (alpha^3+3*alpha) ]
16.8
GaloisGroup for Extension Fields
GaloisGroup( L )
414
CHAPTER 16. ALGEBRAIC EXTENSIONS OF FIELDS
returns the Galois group of the field L if L is a normal extension and issues an error if not.
The Galois group is a group of extension automorphisms (see 16.9).
The computation of a Galois group is computationally relatively hard, and can take significant time.
gap> g:=GaloisGroup(f);
Group( ExtensionAutomorphism(AlgebraicExtension(GF(2),Z(2)^0*(y^
2 + y + 1)),RootOf(Z(2)^0*(y^2 + y + 1))+Z(2)^0) )
gap> h:=GaloisGroup(e);
Group( ExtensionAutomorphism(e,alpha^3+
3*alpha), ExtensionAutomorphism(e,-1*alpha), ExtensionAutomorphism(e,
-1*alpha^3-3*alpha) )
gap> Size(h);
4
gap> AbelianInvariants(h);
[ 2, 2 ]
16.9
ExtensionAutomorphism
ExtensionAutomorphism( L, img )
is the automorphism of the extension L, that maps the primitive root of L to img. As it is
a field automorphism, section 6.13 applies.
16.10
Field functions for Algebraic Extensions
As already mentioned, algebraic extensions are fields. Thus all field functions like Norm and
Trace are applicable.
gap> Trace(r^4+2*r);
14
gap> Norm(ran);
305
DefaultField always returns the algebraic extension, which contains the primitive element
by which the number is represented, see 16.4.
gap> DefaultField(r^2);
e
As subfields are not yet supported, Field will issue an error, if several elements are given,
or if the element is not a primitive element for its default field.
You can create a polynomial ring over an algebraic extension to which all functions described
in 19.22 can be applied, for example you can factor polynomials. Factorization is done —
depending on the polynomial — by factoring the squarefree norem or using a hensel lift (with
possibly added lattice reduction) as described in [Abb89], using bounds from [BTW93].
gap> X(e).name:="X";;
gap> p1:=EmbeddedPolynomial(PolynomialRing(e),p1);
X^2 + 3*X + 1
gap> Factors(p1);
[ X + (-1*alpha^2), X + (alpha^2+3) ]
16.11. ALGEBRAIC EXTENSION RECORDS
16.11
415
Algebraic Extension Records
Since every algebraic extension is a field, it is represented as a record. This record contains
all components, a field record will contain (see 6.17). Additionally, it contains the components isAlgebraicExtension, minpol, primitiveElm and may contain the components
isNormalExtension, minpolFactors and galoisType.
isAlgebraicExtension
is always true. This indicates that F is an algebraic extension.
minpol
is the defining polynomial of F .
primitiveElm
contains RootOf(F .minpol).
isNormalExtension
indicates, whether F is a normal extension field.
minpolFactors
contains a factorization of F .minpol over F .
galoisType
contains the Galois type of the normal closure of F . See section 16.16.
16.12
Extension Element Records
Elements of an algebraic extension are represented by a record. The record for the element
e of L contains the components isAlgebraicElement, domain and coefficients:
isAlgebraicElement
is always true, and indicates, that e is an algebraic element.
domain
contains L.
coefficients
contains the coefficients of e as a polynomial in the primitive root of L.
16.13
IsAlgebraicElement
IsAlgebraicElement( obj )
returns true if obj is an algebraic element, i.e., an element of an algebraic extension, that
is not in the defining field, and false otherwise.
gap> IsAlgebraicElement(r);
true
gap> IsAlgebraicElement(3);
false
16.14
Algebraic extensions of the Rationals
The following sections describe functions that are specific to algebraic extensions of Q
0.
416
CHAPTER 16. ALGEBRAIC EXTENSIONS OF FIELDS
16.15
DefectApproximation
DefectApproximation( L )
computes a multiple of the defect of the basis of L, given by the powers of the primitive
element. The defect indicates, which denominator is necessary in the coefficients, to express
algebraic integers in L as a linear combination of the base of L. DefectApproximation takes
the maximal square in the discriminant as a first approximation, and then uses Berwicks
and Hesses method (see [Bra89]) to improve this approximation. The number returned is
not neccessarily the defect, but may be a proper multiple of it.
gap> DefectApproximation(e);
1
16.16
GaloisType
GaloisType( L )
Galois( f )
The first version returns the number of the permutation isomorphism type of the Galois
group of the normal closure of L, considered as a transitive permutation group of the roots
of the defining polynomial (see 38.6). The second version returns the Galois type of the
splitting field of f . Identification is done by factoring appropriate Galois resolvents as
proposed in [MS85]. This function is provided for rational polynomials of degree up to 15.
However, it may be not feasible to call this function for polynomials of degree 14 or 15, as
the involved computations may be enormous. For some polynomials of degree 14, a complete
discrimination is not yet possible, as it would require computations, that are not feasible
with current factoring methods.
gap> GaloisType(e);
2
gap> TransitiveGroup(e.degree,2);
E(4) = 2[x]2
16.17
ProbabilityShapes
ProbabilityShapes( pol )
returns a list of numbers, which contains most likely the isomorphism type of the galois
group of pol (see 16.16). This routine only applies the cycle structure test according to
Tschebotareff’s theorem. Accordingly, it is very fast, but the result is not guaranteed to be
correct.
gap> ProbabilityShapes(e.minpol);
[ 2 ]
16.18
DecomPoly
DecomPoly( pol )
DecomPoly( pol , "all")
returns an ideal decomposition of the polynomial pol . An ideal decomposition is given by
two polynomials g and h, such that pol divides (g ◦ h). By the Galois correspondence any
16.18. DECOMPOLY
417
ideal decomposition corresponds to a block system of the Galois group. The polynomial g
defines a subfield K(β) of K(α) with h(α) = β. The first form finds one ideal decomposition,
while the second form finds all possible different ideal decompositions (i.e. all subfields).
gap> d:=DecomPoly(e.minpol);
[ x^2 + 5, x^3 + 4*x ]
gap> p:=x^6+108;;
gap> d:=DecomPoly(p,"all");
[ [ x^2 + 108, x^3 ], [ x^3 + 108, x^2 ],
[ x^3 - 186624, x^5 + 6*x^2 ], [ x^3 + 186624, x^5 - 6*x^2 ] ]
gap> Value(d[1][1],d[1][2]);
x^6 + 108
418
CHAPTER 16. ALGEBRAIC EXTENSIONS OF FIELDS
Chapter 17
Unknowns
Sometimes the result of an operation does not allow further computations with it. In many
cases, then an error is signalled, and the computation is stopped.
This is not appropriate for some applications in character theory. For example, if a character
shall be induced up (see 51.22) but the subgroup fusion is only a parametrized map (see
chapter 52), there are positions where the value of the induced character are not known,
and other values which are determined by the fusion map:
gap> m11:= CharTable( "M11" );; m12:= CharTable( "M12" );;
gap> fus:= InitFusion( m11, m12 );
[ 1, [ 2, 3 ], [ 4, 5 ], [ 6, 7 ], 8, [ 9, 10 ], [ 11, 12 ],
[ 11, 12 ], [ 14, 15 ], [ 14, 15 ] ]
gap> Induced(m11,m12,Sublist(m11.irreducibles,[ 6 .. 9 ]),fus);
#I Induced: subgroup order not dividing sum in character 1 at class
#I Induced: subgroup order not dividing sum in character 1 at class
#I Induced: subgroup order not dividing sum in character 1 at class
#I Induced: subgroup order not dividing sum in character 1 at class
#I Induced: subgroup order not dividing sum in character 2 at class
#I Induced: subgroup order not dividing sum in character 2 at class
#I Induced: subgroup order not dividing sum in character 2 at class
#I Induced: subgroup order not dividing sum in character 2 at class
#I Induced: subgroup order not dividing sum in character 3 at class
#I Induced: subgroup order not dividing sum in character 3 at class
#I Induced: subgroup order not dividing sum in character 3 at class
#I Induced: subgroup order not dividing sum in character 3 at class
#I Induced: subgroup order not dividing sum in character 3 at class
#I Induced: subgroup order not dividing sum in character 3 at class
#I Induced: subgroup order not dividing sum in character 4 at class
#I Induced: subgroup order not dividing sum in character 4 at class
#I Induced: subgroup order not dividing sum in character 4 at class
#I Induced: subgroup order not dividing sum in character 4 at class
#I Induced: subgroup order not dividing sum in character 4 at class
#I Induced: subgroup order not dividing sum in character 4 at class
419
4
5
14
15
4
5
14
15
2
3
4
5
9
10
2
3
6
7
11
12
420
CHAPTER 17. UNKNOWNS
#I Induced: subgroup order not dividing sum in character 4 at class 14
#I Induced: subgroup order not dividing sum in character 4 at class 15
[ [ 192, 0, 0, Unknown(9), Unknown(12), 0, 0, 2, 0, 0, 0, 0, 0,
Unknown(15), Unknown(18) ],
[ 192, 0, 0, Unknown(27), Unknown(30), 0, 0, 2, 0, 0, 0, 0, 0,
Unknown(33), Unknown(36) ],
[ 528, Unknown(45), Unknown(48), Unknown(51), Unknown(54), 0, 0,
-2, Unknown(57), Unknown(60), 0, 0, 0, 0, 0 ],
[ 540, Unknown(75), Unknown(78), 0, 0, Unknown(81), Unknown(84), 0,
0, 0, Unknown(87), Unknown(90), 0, Unknown(93), Unknown(96) ] ]
For this and other situations, in GAP3 there is the data type unknown. Objects of this
type, further on called unknowns, may stand for any cyclotomic (see 13).
Unknowns are parametrized by positive integers. When a GAP3 session is started, no unknowns do exist.
The only ways to create unknowns are to call 17.1 Unknown or a function that calls it, or to
do arithmetical operations with unknowns (see 17.4).
Two properties should be noted:
Lists of cyclotomics and unknowns are no vectors, so cannot be added or multiplied like
vectors; as a consequence, unknowns never occur in matrices.
GAP3 objects which are printed to files will contain fixed unknowns, i.e., function calls
Unknown( n ) instead of Unknown(), so be careful to read files printed in different sessions,
since there may be the same unknown at different places.
The rest of this chapter contains informations about the unknown constructor (see 17.1),
the characteristic function (see 17.2), and comparison of and arithmetical operations for
unknowns (see 17.3, 17.4); more is not yet known about unknowns.
17.1
Unknown
Unknown()
Unknown( n )
Unknown() returns a new unknown value, i.e. the first one that is larger than all unknowns
which exist in the actual GAP3 session.
Unknown( n ) returns the n-th unknown; if it did not exist already, it is created.
gap> Unknown(); Unknown(2000); Unknown();
Unknown(97)
# There were created already 96 unknowns.
Unknown(2000)
Unknown(2001)
17.2
IsUnknown
IsUnknown( obj )
returns true if obj is an object of type unknown, and false otherwise. Will signal an error
if obj is an unbound variable.
gap> IsUnknown( Unknown ); IsUnknown( Unknown() );
17.3. COMPARISONS OF UNKNOWNS
421
false
true
gap> IsUnknown( Unknown(2) );
true
17.3
Comparisons of Unknowns
To compare unknowns with other objects, the operators <, <=, =, >=, > and <> can be used.
The result will be true if the first operand is smaller, smaller or equal, equal, larger or
equal, larger, or inequal, respectively, and false otherwise.
We have Unknown( n ) >= Unknown( m ) if and only if n >= m holds; unknowns are
larger than cyclotomics and finite field elements, unknowns are smaller than all objects
which are not cyclotomics, finite field elements or unknowns.
gap> Unknown() >= Unknown();
false
gap> Unknown(2) < Unknown(3);
true
gap> Unknown() > 3;
true
gap> Unknown() > Z(8);
false
gap> Unknown() > E(3);
true
gap> Unknown() > [];
false
17.4
Operations for Unknowns
The operators +, -, * and / are used for addition, subtraction, multiplication and division of
unknowns and cyclotomics. The result will be a new unknown except in one of the following
cases:
Multiplication with zero yields zero, and multiplication with one or addition of zero yields
the old unknown.
gap> Unknown() + 1; Unknown(2) + 0; last * 3; last * 1; last * 0;
Unknown(2010)
Unknown(2)
Unknown(2011)
Unknown(2011)
0
Note that division by an unknown causes an error, since an unknown might stand for zero.
422
CHAPTER 17. UNKNOWNS
Chapter 18
Finite Fields
Finite fields comprise an important algebraic domain. The elements in a field form an
additive group and the nonzero elements form a multiplicative group. For every prime
power q there exists a unique field of size q up to isomorphism. GAP3 supports finite fields
of size at most 216 .
The first section in this chapter describes how you can enter elements of finite fields and
how GAP3 prints them (see 18.1).
The next sections describe the operations applicable to finite field elements (see 18.2 and
18.3).
The next section describes the function that tests whether an object is a finite field element
(see 18.4).
The next sections describe the functions that give basic information about finite field elements (see 18.5, 18.6, and 18.7).
The next sections describe the functions that compute various other representations of finite
field elements (see 18.8 and 18.9).
The next section describes the function that constructs a finite field (see 18.10).
Finite fields are domains, thus all set theoretic functions are applicable to them (see chapter
4 and 18.12).
Finite fields are of course fields, thus all field functions are applicable to them and to their
elements (see chapter 6 and 18.13).
All functions are in LIBNAME/"finfield.g".
18.1
Finite Field Elements
Z( p^d )
The function Z returns the designated generator of the multiplicative group of the finite field
with p^d elements. p must be a prime and p^d must be less than or equal to 216 = 65536.
The root returned by Z is a generator of the multiplicative group of the finite field with pd
elements, which is cyclic. The order of the element is of course pd − 1. The pd − 1 different
powers of the root are exactly the nonzero elements of the finite field.
423
424
CHAPTER 18. FINITE FIELDS
Thus all nonzero elements of the finite field with p^d elements can be entered as Z(p^d )^i .
Note that this is also the form that GAP3 uses to output those elements.
The additive neutral element is 0*Z(p). It is different from the integer 0 in subtle ways. First
IsInt( 0*Z(p) ) (see 10.5) is false and IsFFE( 0*Z(p) ) (see 18.4) is true, whereas it
is just the other way around for the integer 0.
The multiplicative neutral element is Z(p)^0. It is different from the integer 1 in subtle
ways. First IsInt( Z(p)^0 ) (see 10.5) is false and IsFFE( Z(p)^0 ) (see 18.4) is true,
whereas it is just the other way around for the integer 1. Also 1+1 is 2, whereas, e.g., Z(2)^0
+ Z(2)^0 is 0*Z(2).
The various roots returned by Z for finite fields of the same characteristic are compatible
in the following sense. If the field GF (pn ) is a subfield of the field GF (pm ), i.e., n divides
m
n
m, then Z(pn ) = Z(pm )(p −1)/(p −1) . Note that this is the simplest relation that may hold
between a generator of GF (pn ) and GF (pm ), since Z(pn ) is an element of order pm − 1
and Z(pm ) is an element of order pn − 1. This is achieved by choosing Z(p) as the smallest
primitive root modulo p and Z(pn ) as a root of the n-th Conway polynomial of characteristic
p. Those polynomials where defined by J.H. Conway and computed by R.A. Parker.
gap> z := Z(16);
Z(2^4)
gap> z*z;
Z(2^4)^2
18.2
Comparisons of Finite Field Elements
z1 = z2
z1 <> z2
The equality operator = evaluates to true if the two elements in a finite field z1 and z2
are equal and to false otherwise. The inequality operator <> evaluates to true if the two
elements in a finite finite field z1 and z2 are not equal and to false otherwise.
Note that the integer 0 is not equal to the zero element in any finite field. There comparisons
z = 0 will always evaluate to false. Use z = 0*z instead, or even better z = F .zero,
where F is the field record for a finite field of the same characteristic.
gap> Z(2^4)^10 = Z(2^4)^25;
true
# Z(2^4) has order 15
gap> Z(2^4)^10 = Z(2^2)^2;
true
# shows the embedding of GF(4) into GF(16)
gap> Z(2^4)^10 = Z(3);
false
z1
z1
z1
z1
< z2
<= z2
> z2
>= z2
The operators <, <=, >, and => evaluate to true if the element in a finite field z1 is less
than, less than or equal to, greater than, and greater than or equal to the element in a finite
field z2 .
18.3. OPERATIONS FOR FINITE FIELD ELEMENTS
425
Elements in finite fields are ordered as follows. If the two elements lie in fields of different
characteristics the one that lies in the field with the smaller characteristic is smaller. If the
two elements lie in different fields of the same characteristic the one that lies in the smaller
field is smaller. If the two elements lie in the same field and one is the zero and the other
is not, the zero element is smaller. If the two elements lie in the same field and both are
nonzero, and are represented as Z(pd )i1 and Z(pd )i2 respectively, then the one with the
smaller i is smaller.
You can compare elements in a finite field with objects of other types. Integers, rationals,
and cyclotomics are smaller than elements in finite fields, all other objects are larger. Note
especially that the integer 0 is smaller than the zero in every finite field.
gap>
true
gap>
true
gap>
true
gap>
true
gap>
true
gap>
true
18.3
z1
z1
z1
z1
+
*
/
Z(2) < Z(3);
Z(2) < Z(4);
0*Z(2) < Z(2);
Z(4) < Z(4)^2;
0 < 0*Z(2);
Z(4) < [ Z(4) ];
Operations for Finite Field Elements
z2
z2
z2
z2
The operators +, -, * and / evaluate to the sum, difference, product, and quotient of the
two finite field elements z1 and z2 , which must lie in fields of the same characteristic. For
the quotient / z2 must of course be nonzero. The result must of course lie in a finite field
of size less than or equal to 216 , otherwise an error is signalled.
Either operand may also be an integer i . If i is zero it is taken as the zero in the finite field,
i.e., F .zero, where F is a field record for the finite field in which the other operand lies. If
i is positive, it is taken as i -fold sum F .one+F .one+..+F .one. If i is negative it is taken
as the additive inverse of -i .
gap> Z(8) +
Z(2^3)^2
gap> Z(8) Z(2^3)^3
gap> Z(8) *
Z(2)^0
gap> Z(8) /
Z(2^3)^2
gap> -Z(9);
Z(8)^4;
1;
Z(8)^6;
Z(8)^6;
426
CHAPTER 18. FINITE FIELDS
Z(3^2)^5
z ^ i
The powering operator ^ returns the i -th power of the element in a finite field z . i must be
an integer. If the exponent i is zero, z ^i is defined as the one in the finite field, even if z is
zero; if i is positive, z ^i is defined as the i -fold product z *z *..*z ; finally, if i is negative,
z ^i is defined as (1/z )^-i . In this case z must of course be nonzero.
gap> Z(4)^2;
Z(2^2)^2
gap> Z(4)^3;
Z(2)^0
# is in fact 1
gap> (0*Z(4))^0;
Z(2)^0
18.4
IsFFE
IsFFE( obj )
IsFFE returns true if obj , which may be an object of an arbitrary type, is an element in a
finite field and false otherwise. Will signal an error if obj is an unbound variable.
Note that integers, even though they can be multiplied with elements in finite fields, are
not considered themselves elements in finite fields. Therefore IsFFE will return false for
integer arguments.
gap> IsFFE( Z(2^4)^7 );
true
gap> IsFFE( 5 );
false
18.5
CharFFE
CharFFE( z ) or CharFFE( vec ) or CharFFE( mat )
CharFFE returns the characteristic of the finite field F containing the element z , respectively
all elements of the vector vec over a finite field (see 32), or matrix mat over a finite field
(see 34).
gap> CharFFE( Z(16)^7 );
2
gap> CharFFE( Z(16)^5 );
2
gap> CharFFE( [ Z(3), Z(27)^11, Z(9)^3 ] );
3
gap> CharFFE( [ [ Z(5), Z(125)^3 ], [ Z(625)^13, Z(5) ] ] );
Error, CharFFE: must be a finite field element, vector, or matrix
# The smallest finite field which contains all four of these elements
# is too large for GAP3
18.6. DEGREEFFE
18.6
427
DegreeFFE
DegreeFFE( z ) or DegreeFFE( vec ) or DegreeFFE( mat )
DegreeFFE returns the degree of the smallest finite field F containing the element z , respectively all elements of the vector vec over a finite field (see 32), or matrix mat over a
finite field (see 34). For vectors and matrices, an error is signalled if the smallest finite field
containing all elements of the vector or matrix has size larger than 216 .
gap> DegreeFFE( Z(16)^7 );
4
gap> DegreeFFE( Z(16)^5 );
2
gap> DegreeFFE( [ Z(3), Z(27)^11, Z(9)^3 ] );
6
gap> DegreeFFE( [ [ Z(5), Z(125)^3 ], [ Z(625)^13, Z(5) ] ] );
Error, DegreeFFE: must be a finite field element, vector, or matrix
# The smallest finite field which contains all four of these elements
# is too large for GAP3
18.7
OrderFFE
OrderFFE( z )
OrderFFE returns the order of the element z in a finite field. The order is the smallest
positive integer i such that z ^i is 1. The order of the zero in a finite field is defined to be 0.
gap>
15
gap>
3
gap>
26
gap>
48
gap>
1
18.8
OrderFFE( Z(16)^7 );
OrderFFE( Z(16)^5 );
OrderFFE( Z(27)^11 );
OrderFFE( Z(625)^13 );
OrderFFE( Z(211)^0 );
IntFFE
IntFFE( z )
IntFFE returns the integer corresponding to the element z , which must lie in a finite prime
field. That is IntFFE returns the smallest nonnegative integer i such that i * z ^0 = z .
The correspondence between elements from a finite prime field of characteristic p and the
integers between 0 and p-1 is defined by choosing Z(p) the smallest primitive root mod p
(see 11.6).
gap> IntFFE( Z(13) );
2
gap> PrimitiveRootMod( 13 );
428
CHAPTER 18. FINITE FIELDS
2
gap> IntFFE( Z(409) );
21
gap> IntFFE( Z(409)^116 );
311
gap> 21^116 mod 409;
311
18.9
LogFFE
LogFFE( z )
LogFFE( z , r )
In the first form LogFFE returns the discrete logarithm of the element z in a finite field with
respect to the root FieldFFE(z ).root. An error is signalled if z is zero.
In the second form LogFFE returns the discrete logarithm of the element z in a finite field
with respect to the root r . An error is signalled if z is zero, or if z is not a power of r .
The discrete logarithm of an element z with respect to a root r is the smallest nonnegative
integer i such that ri = z.
gap> LogFFE( Z(409)^116 );
116
gap> LogFFE( Z(409)^116, Z(409)^2 );
58
18.10
GaloisField
GaloisField( p^d )
GF( p^d )
GaloisField( p|S , d |pol |bas )
GF( p|S , d |pol |bas )
GaloisField returns a field record (see 6.17) for a finite field. It takes two arguments. The
form GaloisField(p,d ), where p,d are integers, can also be given as GaloisField(p^d ).
GF is an abbreviation for GaloisField.
The first argument specifies the subfield S over which the new field F is to be taken. It can
be a prime or a finite field record. If it is a prime p, the subfield is the prime field of this
characteristic. If it is a field record S , the subfield is the field described by this record.
The second argument specifies the extension. It can be an integer, an irreducible polynomial,
or a base. If it is an integer d , the new field is constructed as the polynomial extension with
the Conway polynomial of degree d over the subfield S . If it is an irreducible polynomial
pol , in which case the elements of the list pol must all lie in the subfield S , the new field is
constructed as polynomial extension of the subfield S with this polynomial. If it is a base
bas, in which case the elements of the list bas must be linear independently over the subfield
S , the new field is constructed as a linear vector space over the subfield S .
Note that the subfield over which a field was constructed determines over which field the
Galois group, conjugates, norm, trace, minimal polynom, and characteristic polynom are
computed (see 6.7, 6.12, 6.10, 6.11, 6.8, 6.9, and 18.13).
18.11. FROBENIUSAUTOMORPHISM
429
gap> GF( 2^4 );
GF(2^4)
gap> GF( GF(2^4), 2 );
GF(2^8)/GF(2^4)
18.11
FrobeniusAutomorphism
FrobeniusAutomorphism( F )
FrobeniusAutomorphism returns the Frobenius automorphism of the finite field F as a field
homomorphism (see 6.13).
The Frobenius automorphism f of a finite field F of characteristic p is the function that
takes each element z of F to its p-th power. Each automorphism of F is a power of the
Frobenius automorphism. Thus the Frobenius automorphism is a generator for the Galois
group of F (and an appropriate power of it is a generator of the Galois group of F over a
subfield S) (see 6.7).
gap> f := GF(16);
GF(2^4)
gap> x := FrobeniusAutomorphism( f );
FrobeniusAutomorphism( GF(2^4) )
gap> Z(16) ^ x;
Z(2^4)^2
The image of an element z under the i -th power of the Frobenius automorphism f of a finite
field F of characteristic p is simply computed by computing the p^i -th power of z . The
product of the i -th power and the j -th power of f is the k -th power of f , where k is i *j mod
(Size(F )-1). The zeroth power of f is printed as IdentityMapping( F ).
18.12
Set Functions for Finite Fields
Finite fields are of course domains. Thus all set theoretic functions are applicable to finite
fields (see chapter 4). This section gives further comments on the definitions and implementations of those functions for finite fields. All set theoretic functions not mentioned here are
not treated specially for finite fields.
Elements
The elements of a finite field are computed using the fact that the finite field is a vector
space over its prime field.
in
The membership test is of course very simple, we just have to test whether the element is a
finite field element with IsFFE, whether it has the correct characteristic with CharFFE, and
whether its degree divides the degree of the finite field with DegreeFFE (see 18.4, 18.5, and
18.6).
Random
A random element of GF (pn ) is computed by computing a random integer i from [0..pn − 1]
and returning 0 ∗ Z(p) if i = 0 and Z(pn )i−1 otherwise.
Intersection
The intersection of GF (pn ) and GF (pm ) is the finite field GF (pGcd(n,m) ), and is returned
as finite field record.
430
18.13
CHAPTER 18. FINITE FIELDS
Field Functions for Finite Fields
Finite fields are, as the name already implies, fields. Thus all field functions are applicable
to finite fields and their elements (see chapter 6). This section gives further comments on
the definitions and implementations of those functions for finite fields. All domain functions
not mentioned here are not treated specially for finite fields.
Field and DefaultField
Both Field and DefaultField return the smallest finite field containing the arguments as
an extension of the prime field.
GaloisGroup
The Galois group of a finite field F of size pm over a subfield S of size q = pn is a cyclic
group of size m/n. It is generated by the Frobenius automorphism that takes every
element of F to its q-th power. This automorphism of F leaves exactly the subfield S fixed.
Conjugates
According to the above theorem about the Galois group, each element of F has m/n con2
m/n−1
jugates, z, z q , z q , ..., z q
.
Norm
m
n
The norm is the product of the conjugates, i.e., z p −1/p −1 . Because we have Z(pn ) =
m
n
Z(pm )p −1/p −1 , it follows that N orm(GF (pm )/GF (pn ), Z(pm )i ) = Z(pn )i .
Chapter 19
Polynomials
Let R be a commutative ring-with-one. A (univariate) Laurent polynomial over R is a
sequence (..., c−1 , c0 , c1 , ...) of elements of R such that only finitely many are non-zero. For
a ring element r of R and polynomials f = (..., f−1 , f0 , f1 , ...) and g = (..., g−1 , g0 , g1 , ...)
we define f + g = (..., f−1 + g−1 , f0 + g0 , f1 + g1 , ...) , r · f = (..., rf−1 , rf0 , rf1 , ...), and
f ∗ g = (..., s−1 , s0 , s1 , ...), where sk = ... + fi gk−i + .... Note that sk is well-defined as only
finitely many fi and gi are non-zero. We call the largest integers d(f ), such that fd(f ) is
non-zero, the degree of f , fi the i.th coefficient of f , and fd(f ) the leading coefficient of
f . If the smallest integer v(f ), such that fv(f ) is non-zero, is negative, we say that f has a
pole of order v at 0, otherwise we say that f has a root of order v at 0. We call R the base
(or coefficient) ring of f . If f = (..., 0, 0, 0, ...) we set d(f ) = −1 and v(f ) = 0.
The set of all Laurent polynomials L(R) over a ring R together with above definitions of +
and ∗ is again a ring, the Laurent polynomial ring over R, and R is called the base ring
of L(R). The subset of all polynomials f with non-negative v(f ) forms a subring P (R) of
L(R), the polynomial ring over R. If R is indeed a field then both rings L(R) and P (R)
are Euclidean. Note that L(R) and P (R) have different Euclidean degree functions. If f is
an element of P (R) then the Euclidean degree of f is simply the degree of f . If f is viewed
as an element of L(R) then the Euclidean degree is the difference between d(f ) and v(f ).
The units of P (R) are just the units of R, while the units of L(R) are the polynomials f
such that v(f ) = d(f ) and fd(f ) is a unit in R.
GAP3 uses the above definition of polynomials. This definition has some advantages and
some drawbacks. First of all, the polynomial (..., x0 = 0, x1 = 1, x2 = 0, ...) is commonly
denoted by x and is called an indeterminate over R, (..., c−1 , c0 , c1 , ...) is written as ... +
c−1 x−1 +c0 +c1 x+c2 x2 +..., and P (R) as R[x] (note that the way GAP3 outputs a polynomial
resembles this definition). But if we introduce a second indeterminate y it is not obvious
whether the product xy lies in (R[x])[y], the polynomial ring in y over the polynomial ring
in x, in (R[y])[x], in R[x, y], the polynomial ring in two indeterminates, or in R[y, x] (which
should be equal to R[x, y]). Using the first definition we would define y as indeterminate
over R[x] and we know then that xy lies in (R[x])[y].
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> Rx := LaurentPolynomialRing(Rationals);;
gap> y := Indeterminate(Rx);; y.name := "y";;
431
432
CHAPTER 19. POLYNOMIALS
gap> y^2 + x;
y^2 + (x)
gap> last^2;
y^4 + (2*x)*y^2 + (x^2)
gap> last + x;
y^4 + (2*x)*y^2 + (x^2 + x)
gap> (x^2 + x + 1) * y^2 + y + 1;
(x^2 + x + 1)*y^2 + y + (x^0)
gap> x * y;
(x)*y
gap> y * x;
(x)*y
gap> 2 * x;
2*x
gap> x * 2;
2*x
Note that GAP3 does not embed the base ring of a polynomial into the polynomial ring.
The trivial polynomial and the zero of the base ring are always different.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> Rx := LaurentPolynomialRing(Rationals);;
gap> y := Indeterminate(Rx);; y.name := "y";;
gap> 0 = 0*x;
false
gap> nx := 0*x;
# a polynomial over the rationals
0*x^0
gap> ny := 0*y;
# a polynomial over a polynomial ring
0*y^0
gap> nx = ny;
# different base rings
false
The result 0*x 6= 0*y is probably not what you expect or want. In order to compute with
two indeterminates over R you must embed x into R[x][y].
gap> x :=
gap> Rx :=
gap> y :=
gap> x :=
x*y^0
gap> 0*x =
true
Indeterminate(Rationals);; x.name := "x";;
LaurentPolynomialRing(Rationals);;
Indeterminate(Rx);; y.name := "y";;
x * y^0;
0*y;
The other point which might be startling is that we require the supply of a base ring for a
polynomial. But this guarantees that Factor gives a predictable result.
gap> f5 := GF(5);; f5.name := "f5";;
gap> f25 := GF(25);; f25.name := "f25";;
gap> Polynomial( f5, [3,2,1]*Z(5)^0 );
Z(5)^0*(X(f5)^2 + 2*X(f5) + 3)
gap> Factors(last);
[ Z(5)^0*(X(f5)^2 + 2*X(f5) + 3) ]
19.1. MULTIVARIATE POLYNOMIALS
433
gap> Polynomial( f25, [3,2,1]*Z(5)^0 );
X(f25)^2 + Z(5)*X(f25) + Z(5)^3
gap> Factors(last);
[ X(f25) + Z(5^2)^7, X(f25) + Z(5^2)^11 ]
The first sections describe how polynomials are constructed (see 19.2, 19.3, and 19.4).
The next sections describe the operations applicable to polynomials (see 19.5 and 19.6).
The next sections describe the functions for polynomials (see 19.7, 19.12 and 19.11).
The next sections describe functions that construct certain polynomials (see 19.16, 19.17).
The next sections describe the functions for constructing the Laurent polynomial ring L(R)
and the polynomial ring P (R) (see 19.18 and 19.20).
The next sections describe the ring functions applicable to Laurent polynomial rings. (see
19.22 and 19.23).
19.1
Multivariate Polynomials
As explained above, each ring R has exactly one indeterminate associated with R. In order
to construct a polynomial ring with two indeterminates over R you must first construct the
polynomial ring P (R) and then the polynomial ring over P (R).
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> Rx := PolynomialRing(Integers);;
gap> y := Indeterminate(Rx);; y.name := "y";;
gap> x := y^0 * x;
x*y^0
gap> f := x^2*y^2 + 3*x*y + x + 4*y;
(x^2)*y^2 + (3*x + 4)*y + (x)
gap> Value( f, 4 );
16*x^2 + 13*x + 16
gap> Value( last, -2 );
54
gap> (-2)^2 * 4^2 + 3*(-2)*4 + (-2) + 4*4;
54
We plan to add support for (proper) multivariate polynomials in one of the next releases of
GAP3.
19.2
Indeterminate
Indeterminate( R )
X( R )
Indeterminate returns the polynomial (..., x0 = 0, x1 = 1, x2 = 0, ...) over R, which must
be a commutative ring-with-one or a field.
Note that you can assign a name to the indeterminate, in which case all polynomials over
R are printed using this name. Keep in mind that for each ring there is exactly one indeterminate.
gap> x := Indeterminate( Integers );; x.name := "x";;
434
CHAPTER 19. POLYNOMIALS
gap>
x^10
gap>
gap>
gap>
y^10
19.3
f := x^10 + 3*x - x^-1;
+ 3*x - x^(-1)
y := Indeterminate( Integers );;
# this is x
y.name := "y";;
f;
# so f is also printed differently from now on
+ 3*y - y^(-1)
Polynomial
Polynomial( R, l )
Polynomial( R, l , v )
l must be a list of coefficients of the polynomial f to be constructed, namely (..., fv =
l [1], fv +1 = l [2], ...) over R, which must be a commutative ring-with-one or a field. The
default for v is 0. Polynomial returns this polynomial f .
For interactive calculation it might by easier to construct the indeterminate over R and
construct the polynomial using ^, + and *.
gap> x := Indeterminate( Integers );;
gap> x.name := "x";;
gap> f := Polynomial( Integers, [1,2,0,0,4] );
4*x^4 + 2*x + 1
gap> g := 4*x^4 + 2*x + 1;
4*x^4 + 2*x + 1
19.4
IsPolynomial
IsPolynomial( obj )
IsPolynomial returns true if obj , which can be an object of arbitrary type, is a polynomial
and false otherwise. The function will signal an error if obj is an unbound variable.
gap> IsPolynomial( 1 );
false
gap> IsPolynomial( Indeterminate(Integers) );
true
19.5
Comparisons of Polynomials
f = g
f <> g
The equality operator = evaluates to true if the polynomials f and g are equal, and to
false otherwise. The inequality operator <> evaluates to true if the polynomials f and g
are not equal, and to false otherwise.
Note that polynomials are equal if and only if their coefficients and their base rings are
equal. Polynomials can also be compared with objects of other types. Of course they are
never equal.
gap> f := Polynomial( GF(5^3), [1,2,3]*Z(5)^0 );
Z(5)^3*X(GF(5^3))^2 + Z(5)*X(GF(5^3)) + Z(5)^0
19.6. OPERATIONS FOR POLYNOMIALS
435
gap> x := Indeterminate(GF(25));;
gap> g := 3*x^2 + 2*x + 1;
Z(5)^3*X(GF(5^2))^2 + Z(5)*X(GF(5^2)) + Z(5)^0
gap> f = g;
false
gap> x^0 = Z(25)^0;
false
f
f
f
f
< g
<= g
> g
>= g
The operators <, <=, >, and >= evaluate to true if the polynomial f is less than, less than or
equal to, greater than, or greater than or equal to the polynomial g, and to false otherwise.
A polynomial f is less than g if v(f ) is less than v(g), or if v(f ) and v(g) are equal and d(f )
is less than d(g). If v(f ) is equal to v(g) and d(f ) is equal to d(g) the coefficient lists of f
and g are compared.
gap> x :=
gap> (1 +
false
gap> (1 +
false
gap> (1 +
true
19.6
Indeterminate(Integers);; x.name := "x";;
x^2 + x^3)*x^3 < (2 + x^2 + x^3);
x^2 + x^4) < (2 + x^2 + x^3);
x^2 + x^3) < (2 + x^2 + x^3);
Operations for Polynomials
The following operations are always available for polynomials. The operands must have a
common base ring, no implicit conversions are performed.
f + g
The operator + evaluates to the sum of the polynomials f and g, which must be polynomials
over a common base ring.
gap> f := Polynomial( GF(2), [Z(2), Z(2)] );
Z(2)^0*(X(GF(2)) + 1)
gap> f + f;
0*X(GF(2))^0
gap> g := Polynomial( GF(4), [Z(2), Z(2)] );
X(GF(2^2)) + Z(2)^0
gap> f + g;
Error, polynomials must have the same ring
f + scl
scl + f
The operator + evaluates to the sum of the polynomial f and the scalar scl , which must lie
in the base ring of f .
gap> x := Indeterminate( Integers );; x.name := "x";;
436
CHAPTER 19. POLYNOMIALS
gap> h := Polynomial( Integers, [1,2,3,4] );
4*x^3 + 3*x^2 + 2*x + 1
gap> h + 1;
4*x^3 + 3*x^2 + 2*x + 2
gap> 1/2 + h;
Error, must lie in the base ring of
f - g
The operator - evaluates to the difference of the polynomials f and g, which must be
polynomials over a common base ring.
gap> x := Indeterminate( Integers );; x.name := "x";;
gap> h := Polynomial( Integers, [1,2,3,4] );
4*x^3 + 3*x^2 + 2*x + 1
gap> h - 2*h;
-4*x^3 - 3*x^2 - 2*x - 1
f - scl
scl - f
The operator - evaluates to the difference of the polynomial f and the scalar scl , which
must lie in the base ring of f .
gap> x := Indeterminate( Integers );; x.name := "x";;
gap> h := Polynomial( Integers, [1,2,3,4] );
4*x^3 + 3*x^2 + 2*x + 1
gap> h - 1;
4*x^3 + 3*x^2 + 2*x
gap> 1 - h;
-4*x^3 - 3*x^2 - 2*x
f * g
The operator * evaluates to the product of the two polynomials f and g, which must be
polynomial over a common base ring.
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> h := 4*x^3 + 3*x^2 + 2*x + 1;
4*x^3 + 3*x^2 + 2*x + 1
gap> h * h;
16*x^6 + 24*x^5 + 25*x^4 + 20*x^3 + 10*x^2 + 4*x + 1
f * scl
scl * f
The operator * evaluates to the product of the polynomial f and the scalar scl , which must
lie in the base ring of f .
gap> f := Polynomial( GF(2), [Z(2), Z(2)] );
Z(2)^0*(X(GF(2)) + 1)
gap> f - Z(2);
X(GF(2))
gap> Z(4) - f;
Error, must lie in the base ring of
f ^ n
19.7. DEGREE
437
The operator ^ evaluates the the n-th power of the polynomial f . If n is negative ^ will try
to invert f in the Laurent polynomial ring ring.
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> k := x - 1 + x^-1;
x - 1 + x^(-1)
gap> k ^ 3;
x^3 - 3*x^2 + 6*x - 7 + 6*x^(-1) - 3*x^(-2) + x^(-3)
gap> k^-1;
Error, cannot invert in the laurent polynomial ring
f / scl
The operator / evaluates to the product of the polynomial f and the inverse of the scalar
scl , which must be invertable in its default ring.
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> h := 4*x^3 + 3*x^2 + 2*x + 1;
4*x^3 + 3*x^2 + 2*x + 1
gap> h / 3;
(4/3)*x^3 + x^2 + (2/3)*x + (1/3)
scl / f
The operator / evaluates to the product of the scalar scl and the inverse of the polynomial
f , which must be invertable in its Laurent ring.
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> 30 / x;
30*x^(-1)
gap> 3 / (1+x);
Error, cannot invert in the laurent polynomial ring
f / g
The operator / evaluates to the quotient of the two polynomials f and g, if such quotient
exists in the Laurent polynomial ring. Otherwise / signals an error.
gap> x
gap> f
-2*x^4
gap> f
-2*x^2
gap> f
Error,
19.7
:= Indeterminate(Integers);; x.name := "x";;
:= (1+x+x^2) * (3-x-2*x^2);
- 3*x^3 + 2*x + 3
/ (1+x+x^2);
- x + 3
/ (1+x);
cannot divide by
Degree
Degree( f )
Degree returns the degree df of f (see 19).
Note that this is only equal to the Euclidean degree in the polynomial ring P (R). It is not
equal in the Laurent polynomial ring L(R).
gap> x := Indeterminate(Rationals);; x.name := "x";;
438
CHAPTER 19. POLYNOMIALS
gap>
10
gap>
10
gap>
-10
gap>
1
19.8
Degree( x^10 + x^2 + 1 );
EuclideanDegree( x^10 + x^2 + 1 );
# the default ring is the polynomial ring
Degree( x^-10 + x^-11 );
EuclideanDegree( x^-10 + x^-11 );
# the default ring is the Laurent polynomial ring
Valuation
Valuation( f )
Valuation returns the valuation f (see 19).
gap>
gap>
0
gap>
2
gap>
-11
19.9
x := Indeterminate(Rationals);; x.name := "x";;
Valuation( x^10 + x^2 + 1 );
Valuation( x^10 + x^2);
Valuation( x^-10 + x^-11 );
LeadingCoefficient
LeadingCoefficient( f )
LeadingCoefficient returns the last non-zero coefficient of f (see 19).
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> LeadingCoefficient( 3*x^2 + 2*x + 1);
3
19.10
Coefficient
Coefficient( f , i )
Coefficient returns the i -th coefficient of f (see 19).
for other objects the function looks if f has a Coefficient method in its operations record
and then returns f.operations.Coefficient(f,i).
gap>
gap>
3
gap>
2
gap>
0
x := Indeterminate(Rationals);; x.name := "x";;
Coefficient(3*x^2 + 2*x, 2);
Coefficient(3*x^2 + 2*x, 1);
Coefficient(3*x^2 + 2*x, 0);
19.11. VALUE
19.11
439
Value
Value( f , w )
Let f be a Laurent polynomial (..., f−1 , f0 , f1 , ...). Then Value returns the finite sum ... +
f−1 w −1 + f0 w 0 + f1 w + ....
Note that x need not be contained in the base ring of f .
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> k := -x + 1;
-x + 1
gap> Value( k, 2 );
-1
gap> Value( k, [[1,1],[0,1]] );
[ [ 0, -1 ], [ 0, 0 ] ]
19.12
Derivative
Derivative( f )
If f is a Laurent polynomial (..., f−1 , f0 , f1 , ...), then Derivative returns the polynomial
g = (..., gi−1 = i ∗ fi , ...).
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> Derivative( x^10 + x^-11 );
10*x^9 - 11*x^(-12)
gap> y := Indeterminate(GF(5));; y.name := "y";;
gap> Derivative( y^10 + y^-11 );
Z(5)^2*y^(-12)
In a second form f is a list interpreted as the coefficients of a polynomial; then Derivative
returns the coefficients of the derivative polynomial, that is the list [f[2],2*f[3],..].
gap> Derivative([1,2,1,2,1,2]);
[ 2, 2, 6, 4, 10 ]
19.13
Resultant
Resultant( f , g )
f and g must be polynomials, not Laurent polynomials. The function returns their resultant.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> Resultant(x^3+1,3*x^2);
27
19.14
Discriminant
Discriminant( f )
f must be a polynomial, not a Laurent polynomial. The function returns its discriminant.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> Discriminant(x^3+1);
-27
440
19.15
CHAPTER 19. POLYNOMIALS
InterpolatedPolynomial
InterpolatedPolynomial( R, x , y )
InterpolatedPolynomial returns the unique polynomial of degree less than n which has
value y[i] at x[i] for all i = 1, ..., n, where x and y must be lists of elements of the ring or
field R, if such a polynomial exists. Note that the elements in x must be distinct.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> p := InterpolatedPolynomial( Rationals, [1,2,3,4], [3,2,4,1] );
(-4/3)*x^3 + (19/2)*x^2 + (-121/6)*x + 15
gap> List( [1,2,3,4], x -> Value(p,x) );
[ 3, 2, 4, 1 ]
gap> Unbind( x.name );
19.16
ConwayPolynomial
ConwayPolynomial( p, n )
returns the Conway polynomial of the finite field GF (pn ) as polynomial over the Rationals.
The Conway polynomial Φn,p of GF (pn ) is defined by the following properties.
First define an ordering of polynomials of degree n over GF (p) as follows.
Pn
Pn
i
i
i
i
f =
i=0 (−1) fi x is smaller than g =
i=0 (−1) gi x if and only if there is an index
˜
m ≤ n such that fi = gi for all i > m, and fm < g˜m , where c̃ denotes the integer value in
{0, 1, . . . , p − 1} that is mapped to c ∈ GF (p) under the canonical epimorphism that maps
the integers onto GF (p).
Φn,p is primitive over GF (p), that is, it is irreducible, monic, and is the minimal polynomial
of a primitive element of GF (pn ) over GF (p).
pn −1
For all divisors d of n the compatibility condition Φd,p (x pm −1 ) ≡ 0 (mod Φn,p (x)) holds.
With respect to the ordering defined above, Φn,p shall be minimal.
gap> ConwayPolynomial( 7, 3 );
X(Rationals)^3 + 6*X(Rationals)^2 + 4
gap> ConwayPolynomial( 41, 3 );
X(Rationals)^3 + X(Rationals) + 35
The global list CONWAYPOLYNOMIALS contains Conway polynomials for small values of p and
n. Note that the computation of Conway polynomials may be very expensive, especially if
n is not a prime.
19.17
CyclotomicPolynomial
CyclotomicPolynomial( R, n )
returns the n-th cyclotomic polynomial over the field R.
gap> CyclotomicPolynomial( GF(2), 6 );
Z(2)^0*(X(GF(2))^2 + X(GF(2)) + 1)
gap> CyclotomicPolynomial( Rationals, 5 );
X(Rationals)^4 + X(Rationals)^3 + X(Rationals)^2 + X(Rationals) + 1
In every GAP3 session the computed cyclotomic polynomials are stored in the global list
CYCLOTOMICPOLYNOMIALS.
19.18. POLYNOMIALRING
19.18
441
PolynomialRing
PolynomialRing( R )
PolynomialRing returns the ring of all polynomials over a field R or ring-with-one R.
gap> f2 := GF(2);;
gap> R := PolynomialRing( f2 );
PolynomialRing( GF(2) )
gap> Z(2) in R;
false
gap> Polynomial( f2, [Z(2),Z(2)] ) in R;
true
gap> Polynomial( GF(4), [Z(2),Z(2)] ) in R;
false
gap> R := PolynomialRing( GF(2) );
PolynomialRing( GF(2) )
19.19
IsPolynomialRing
IsPolynomialRing( domain )
IsPolynomialRing returns true if the object domain is a ring record, representing a polynomial ring (see 19.18), and false otherwise.
gap> IsPolynomialRing( Integers );
false
gap> IsPolynomialRing( PolynomialRing( Integers ) );
true
gap> IsPolynomialRing( LaurentPolynomialRing( Integers ) );
false
19.20
LaurentPolynomialRing
LaurentPolynomialRing( R )
LaurentPolynomialRing returns the ring of all Laurent polynomials over a field R or ringwith-one R.
gap> f2 := GF(2);;
gap> R := LaurentPolynomialRing( f2 );
LaurentPolynomialRing( GF(2) )
gap> Z(2) in R;
false
gap> Polynomial( f2, [Z(2),Z(2)] ) in R;
true
gap> Polynomial( GF(4), [Z(2),Z(2)] ) in R;
false
gap> Indeterminate(f2)^-1 in R;
true
442
CHAPTER 19. POLYNOMIALS
19.21
IsLaurentPolynomialRing
IsLaurentPolynomialRing( domain )
IsLaurentPolynomialRing returns true if the object domain is a ring record, representing
a Laurent polynomial ring (see 19.20), and false otherwise.
gap> IsPolynomialRing( Integers );
false
gap> IsLaurentPolynomialRing( PolynomialRing( Integers ) );
false
gap> IsLaurentPolynomialRing( LaurentPolynomialRing( Integers ) );
true
19.22
Ring Functions for Polynomial Rings
As was already noted in the introduction to this chapter polynomial rings are rings, so all
ring functions (see chapter 5) are applicable to polynomial rings. This section comments on
the implementation of those functions.
Let R be a commutative ring-with-one or a field and let P be the polynomial ring over R.
EuclideanDegree( P , f )
P is an Euclidean ring if and only if R is field. In this case the Euclidean degree of f is
simply the degree of f . If R is not a field then the function signals an error.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> EuclideanDegree( x^10 + x^2 + 1 );
10
gap> EuclideanDegree( x^0 );
0
EuclideanRemainder( P , f , g )
P is an Euclidean ring if and only if R is field. In this case it is possible to divide f by g
with remainder.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> EuclideanRemainder( (x+1)*(x+2)+5, x+1 );
5*x^0
EuclideanQuotient( P , f , g )
P is an Euclidean ring if and only if R is field. In this case it is possible to divide f by g
with remainder.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> EuclideanQuotient( (x+1)*(x+2)+5, x+1 );
x + 2
QuotientRemainder( P , f , g )
19.22. RING FUNCTIONS FOR POLYNOMIAL RINGS
443
P is an Euclidean ring if and only if R is field. In this case it is possible to divide f by g
with remainder.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> QuotientRemainder( (x+1)*(x+2)+5, x+1 );
[ x + 2, 5*x^0 ]
Gcd( P , f , g )
P is an Euclidean ring if and only if R is field. In this case you can compute the greatest
common divisor of f and g using Gcd.
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> g := x^2 + 2*x + 1;;
gap> h := x^2 - 1;;
gap> Gcd( g, h );
x + 1
gap> GcdRepresentation( g, h );
[ 1/2*x^0, -1/2*x^0 ]
gap> g * (1/2) * x^0 - h * (1/2) * x^0;
x + 1
Factors( P , f )
This method is implemented for polynomial rings P over a domain R, where R is either
a finite field, the rational numbers, or an algebraic extension of either one. If char R is a
prime, f is factored using a Cantor-Zassenhaus algorithm.
gap> f5 := GF(5);; f5.name := "f5";;
gap> x := Indeterminate(f5);; x.name := "x";;
gap> g := x^20 + x^8 + 1;
Z(5)^0*(x^20 + x^8 + 1)
gap> Factors(g);
[ Z(5)^0*(x^8 + 4*x^4 + 2), Z(5)^0*(x^12 + x^8 + 4*x^4 + 3) ]
If char R is 0, a quadratic Hensel lift is used.
gap> x := Indeterminate(Rationals);; x.name
gap> f:=x^105-1;
x^105 - 1
gap> Factors(f);
[ x - 1, x^2 + x + 1, x^4 + x^3 + x^2 + x +
x^6 + x^5 + x^4 + x^3 + x^2 + x + 1,
x^8 - x^7 + x^5 - x^4 + x^3 - x + 1,
x^12 - x^11 + x^9 - x^8 + x^6 - x^4 + x^3
x^24 - x^23 + x^19 - x^18 + x^17 - x^16 +
11 + x^10 - x^8 + x^7 - x^6 + x^5 - x +
x^48 + x^47 + x^46 - x^43 - x^42 - 2*x^41
35 + x^34 + x^33 + x^32 + x^31 - x^28 20 + x^17 + x^16 + x^15 + x^14 + x^13 +
7 - x^6 - x^5 + x^2 + x + 1 ]
:= "x";;
1,
- x + 1,
x^14 - x^13 + x^12 - x^
1,
- x^40 - x^39 + x^36 + x^
x^26 - x^24 - x^22 - x^
x^12 - x^9 - x^8 - 2*x^
444
CHAPTER 19. POLYNOMIALS
As f is an element of P if and only if the base ring of f is R you must embed the polynomial
into the polynomial ring P if it is written as polynomial over a subring.
gap> f25 := GF(25);; Indeterminate(f25).name := "y";;
gap> l := Factors( EmbeddedPolynomial( PolynomialRing(f25), g ) );
[ y^4 + Z(5^2)^13, y^4 + Z(5^2)^17, y^6 + Z(5)^3*y^2 + Z(5^2)^3,
y^6 + Z(5)^3*y^2 + Z(5^2)^15 ]
gap> l[1] * l[2];
y^8 + Z(5)^2*y^4 + Z(5)
gap> l[3] * l[4];
y^12 + y^8 + Z(5)^2*y^4 + Z(5)^3
StandardAssociate( P , f )
For a ring R the standard associate a of f is a multiple of f such that the leading coefficient
of a is the standard associate in R. For a field R the standard associate a of f is a multiple
of f such that the leading coefficient of a is 1.
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> StandardAssociate( -2 * x^3 - x );
2*x^3 + x
19.23
Ring Functions for Laurent Polynomial Rings
As was already noted in the introduction to this chapter Laurent polynomial rings are
rings, so all ring functions (see chapter 5) are applicable to polynomial rings. This section
comments on the implementation of those functions.
Let R be a commutative ring-with-one or a field and let P be the polynomial ring over R.
EuclideanDegree( P , f )
P is an Euclidean ring if and only if R is field. In this case the Euclidean degree of f is the
difference of d(f ) and v(f ) (see 19). If R is not a field then the function signals an error.
gap>
gap>
gap>
8
gap>
0
gap>
7
gap>
4
gap>
4
x := Indeterminate(Rationals);; x.name := "x";;
LR := LaurentPolynomialRing(Rationals);;
EuclideanDegree( LR, x^10 + x^2 );
EuclideanDegree( LR, x^7 );
EuclideanDegree( x^7 );
EuclideanDegree( LR, x^2 + x^-2 );
EuclideanDegree( x^2 + x^-2 );
Gcd( P , f , g )
P is an Euclidean ring if and only if R is field. In this case you can compute the greatest
common divisor of f and g using Gcd.
19.23. RING FUNCTIONS FOR LAURENT POLYNOMIAL RINGS
445
gap> x := Indeterminate(Rationals);; x.name := "x";;
gap> LR := LaurentPolynomialRing(Rationals);;
gap> g := x^3 + 2*x^2 + x;;
gap> h := x^3 - x;;
gap> Gcd( g, h );
x^2 + x
gap> Gcd( LR, g, h );
x + 1
# x is a unit in LR
gap> GcdRepresentation( LR, g, h );
[ (1/2)*x^(-1), (-1/2)*x^(-1) ]
Factors( P , f )
This method is only implemented for a Laurent polynomial ring P over a finite field R. In
this case f is factored using a Cantor-Zassenhaus algorithm. As f is an element of P if and
only if the base ring of f is R you must embed the polynomial into the polynomial ring P
if it is written as polynomial over a subring.
gap> f5 := GF(5);; f5.name := "f5";;
gap> x := Indeterminate(f5);; x.name := "x";;
gap> g := x^10 + x^-2 + x^-10;
Z(5)^0*(x^10 + x^(-2) + x^(-10))
gap> Factors(g);
[ Z(5)^0*(x^(-2) + 4*x^(-6) + 2*x^(-10)),
Z(5)^0*(x^12 + x^8 + 4*x^4 + 3) ]
gap> f25 := GF(25);; Indeterminate(f25).name := "y";;
gap> gg := EmbeddedPolynomial( LaurentPolynomialRing(f25), g );
y^10 + y^(-2) + y^(-10)
gap> l := Factors( gg );
[ y^(-6) + Z(5^2)^13*y^(-10), y^4 + Z(5^2)^17,
y^6 + Z(5)^3*y^2 + Z(5^2)^3, y^6 + Z(5)^3*y^2 + Z(5^2)^15 ]
gap> l[1] * l[2];
y^(-2) + Z(5)^2*y^(-6) + Z(5)*y^(-10)
gap> l[3]*[4];
[ Z(5)^2*y^6 + Z(5)*y^2 + Z(5^2)^15 ]
StandardAssociate( P , f )
For a ring R the standard associate a of f is a multiple of f such that the leading coefficient
of a is the standard associate in R and v(a) is zero. For a field R the standard associate a
of f is a multiple of f such that the leading coefficient of a is 1 and v(a) is zero.
gap> x := Indeterminate(Integers);; x.name := "x";;
gap> LR := LaurentPolynomialRing(Integers);;
gap> StandardAssociate( LR, -2 * x^3 - x );
2*x^2 + 1
446
CHAPTER 19. POLYNOMIALS
Chapter 20
Permutations
GAP3 is a system especially designed for the computations in groups. Permutation groups
are a very important class of groups and GAP3 offers a data type permutation to describe
the elements of permutation groups.
Permutations in GAP3 operate on positive integers. Whenever group elements operate
on a domain we call the elements of this domain points. Thus in this chapter we often call
positive integers points, if we want to emphasize that a permutation operates on them. An
integer i is said to be moved by a permutation p if the image ip of i under p is not i. The
largest integer moved by any permutation may not be larger than 228 − 1.
Note that permutations do not belong to a specific group. That means that you can work
with permutations without defining a permutation group that contains them. This is just
like it is with integers, with which you can compute without caring about the domain
Integers that contains them. It also means that you can multiply any two permutations.
Permutations are entered and displayed in cycle notation.
gap> (1,2,3);
(1,2,3)
gap> (1,2,3) * (2,3,4);
(1,3)(2,4)
The first sections in this chapter describe the operations that are available for permutations
(see 20.1 and 20.2). The next section describes the function that tests whether an object is
a permutation (see 20.3). The next sections describe the functions that find the largest and
smallest point moved by a permutation (see 20.4 and 20.5). The next section describes the
function that computes the sign of a permutation (see 20.6). The next section describes the
function that computes the smallest permutation that generates the same cyclic subgroup
as a given permutation (see 20.7). The final sections describe the functions that convert
between lists and permutations (see 20.8, 20.9, 20.10, and 20.11).
Permutations are elements of groups operating on positive integers in a natural way, thus
see chapter 7 and chapter 2.10 for more functions.
The external functions are in the file LIBNAME/"permutat.g".
447
448
CHAPTER 20. PERMUTATIONS
20.1
Comparisons of Permutations
p1 = p2
p1 <> p2
The equality operator = evaluates to true if the two permutations p1 and p2 are equal, and
to false otherwise. The inequality operator <> evaluates to true if the two permutations
p1 and p2 are not equal, and to false otherwise. You can also compare permutations with
objects of other types, of course they are never equal.
Two permutations are considered equal if and only if they move the same points and if the
images of the moved points are the same under the operation of both permutations.
gap> (1,2,3) = (2,3,1);
true
gap> (1,2,3) * (2,3,4) = (1,3)(2,4);
true
p1
p1
p1
p1
p2
>= p2
The operators <, <=, >, and >= evaluate to true if the permutation p1 is less than, less than
or equal to, greater than, or greater than or equal to the permutation p2 , and to false
otherwise.
Let p1 and p2 be two permutations that are not equal. Then there exists at least one point
i such that ip1 <> ip2 . Let k be the smallest such point. Then p1 is considered smaller
than p2 if and only if k p1 < k p2 . Note that this implies that the identity permutation is
the smallest permutation.
You can also compare permutations with objects of other types. Integers, rationals, cyclotomics, unknowns, and finite field elements are smaller than permutations. Everything else
is larger.
gap> (1,2,3) < (1,3,2);
true
# 1(1,2,3) = 2 < 3 = 1(1,3,2)
gap> (1,3,2,4) < (1,3,4,2);
false
# 2(1,3,2,4) = 4 > 1 = 2(1,3,4,2)
20.2
Operations for Permutations
p1 * p2
The operator * evaluates to the product of the two permutations p1 and p2 .
p1 / p2
The operator / evaluates to the quotient p1 ∗ p2−1 of the two permutations p1 and p2 .
LeftQuotient( p1 , p2 )
LeftQuotient returns the left quotient p1−1 ∗ p2 of the two permutations p1 and p2 . (This
can also be written p1 mod p2 .)
p ^ i
20.3. ISPERM
449
The operator ^ evaluates to the i -th power of the permutation p.
p1 ^ p2
The operator ^ evaluates to the conjugate p2−1 ∗ p1 ∗ p2 of the permutation p1 by the
permutation p2 .
Comm( p1 , p2 )
Comm returns the commutator p1−1 ∗ p2−1 ∗ p1 ∗ p2 of the two permutations p1 and p2 .
i ^ p
The operator ^ evaluates to the image ip of the positive integer i under the permutation p.
i / p
The operator / evaluates to the preimage ip
−1
of the integer i under the permutation p.
list * p
p * list
The operator * evaluates to the list of products of the permutations in list with the permutation p. That means that the value is a new list new such that new [i ] = list[i ] * p
respectively new [i ] = p * list[i ].
list / p
The operator / evaluates to the list of quotients of the permutations in list with the permutation p. That means that the value is a new list new such that new [i ] = list[i ] /
p.
For the precedence of the operators see 2.10.
20.3
IsPerm
IsPerm( obj )
IsPerm returns true if obj , which may be an object of arbitrary type, is a permutation and
false otherwise. It will signal an error if obj is an unbound variable.
gap> IsPerm( (1,2) );
true
gap> IsPerm( 1 );
false
20.4
LargestMovedPointPerm
LargestMovedPointPerm( perm )
LargestMoverPointPerm returns the largest point moved by the permutation perm, i.e.,
the largest positive integer i such that i ^perm <> i . It will signal an error if perm is trivial
(see also 20.5).
gap> LargestMovedPointPerm( (2,3,1) );
3
gap> LargestMovedPointPerm( (1,2)(1000,1001) );
1001
450
CHAPTER 20. PERMUTATIONS
20.5
SmallestMovedPointPerm
SmallestMovedPointPerm( perm )
SmallestMovedPointPerm returns the smallest point moved by the permutation perm, i.e.,
the smallest positive integer i such that i ^perm <> i . It will signal an error if perm is
trivial (see also 20.4).
gap> SmallestMovedPointPerm( (4,7,5) );
4
20.6
SignPerm
SignPerm( perm )
SignPerm returns the sign of the permutation perm.
Q
Q
The sign s of a permutation p is defined by s = i SignPerm( (1,2,3)(5,6) );
-1
20.7
SmallestGeneratorPerm
SmallestGeneratorPerm( perm )
SmallestGeneratorPerm returns the smallest permutation that generates the same cyclic
group as the permutation perm.
gap> SmallestGeneratorPerm( (1,4,3,2) );
(1,2,3,4)
Note that SmallestGeneratorPerm is very efficient, even when perm has huge order.
20.8
ListPerm
ListPerm( perm )
ListPerm returns a list list that contains the images of the positive integers under the
permutation perm. That means that list[i ] = i ^perm, where i lies between 1 and the
largest point moved by perm (see 20.4).
gap> ListPerm( (1,2,3,4) );
[ 2, 3, 4, 1 ]
gap> ListPerm( () );
[ ]
PermList (see 20.9) performs the inverse operation.
20.9. PERMLIST
20.9
451
PermList
PermList( list )
PermList returns the permutation perm that moves points as describes by the list list. That
means that i ^perm = list[i ] if i lies between 1 and the length of list, and i ^perm = i if
i is larger than the length of the list list. It will signal an error if list does not define a
permutation, i.e., if list is not a list of integers without holes, or if list contains an integer
twice, or if list contains an integer not in the range [1..Length(list)].
gap> PermList( [6,2,4,1,5,3] );
(1,6,3,4)
gap> PermList( [] );
()
ListPerm (see 20.8) performs the inverse operation.
20.10
RestrictedPerm
RestrictedPerm( perm, list )
RestrictedPerm returns the new permutation new that operates on the points in the list
list in the same way as the permutation perm, and that fixes those points that are not in
list. list must be a list of positive integers such that for each i in list the image i ^perm is
also in list, i.e., it must be the union of cycles of perm.
gap> RestrictedPerm( (1,2,3)(4,5), [4,5] );
(4,5)
20.11
MappingPermListList
MappingPermListList( list1 , list2 )
MappingPermListList returns a permutation perm such that list1 [i ] ^ perm = list2 [i ].
perm fixes all points larger then the maximum of the entries in list1 and list2 . If there are
several such permutations, it is not specified which MappingPermListList returns. list1
and list2 must be lists of positive integers of the same length, and neither may contain an
element twice.
gap> MappingPermListList( [3,4], [6,9] );
(3,6,4,9,8,7,5)
gap> MappingPermListList( [], [] );
()
452
CHAPTER 20. PERMUTATIONS
Chapter 21
Permutation Groups
A permutation group is a group of permutations on a set Ω of positive integers (see chapters
7 and 20).
Our standard example in this chapter will be the symmetric group of degree 4, which is
defined by the following GAP3 statements.
gap> s4 := Group( (1,2), (1,2,3,4) );
Group( (1,2), (1,2,3,4) )
This introduction is followed by a section that describes the function that tests whether
an object is a permutation group or not (see section 21.1). The next sections describe the
functions that are related to the set of points moved by a permutation group (see 21.2, 21.3,
21.4, and 21.5). The following section describes the concept of stabilizer chains, which are
used by most functions for permutation groups (see 21.6). The following sections describe
the functions that compute or change a stabilizer chain (see 21.7, 21.9, 21.10, 21.11). The
next sections describe the functions that extract information from stabilizer chains (see
21.12, 21.15, 21.13, and 21.14). The next two sections describe the functions that find
elements or subgroups of a permutation group with a property (see 21.16 and 21.17).
If the permutation groups become bigger, computations become slower. In many cases it is
preferable then, to use random methods for computation. This is explained in section 21.24.
Because each permutation group is a domain all set theoretic functions can be applied to
it (see chapter 4 and 21.20). Also because each permutation group is after all a group all
group functions can be applied to it (see chapter 7 and 21.21). Finally each permutation
group operates naturally on the positive integers, so all operations functions can be applied
(see chapter 8 and 21.22). The last section in this chapter describes the representation of
permutation groups (see 21.25).
The external functions are in the file LIBNAME/"permgrp.g".
21.1
IsPermGroup
IsPermGroup( obj )
IsPermGroup returns true if the object obj , which may be an object of an arbitrary type,
is a permutation group, and false otherwise. It will signal an error if obj is an unbound
variable.
453
454
CHAPTER 21. PERMUTATION GROUPS
gap> s4 := Group( (1,2), (1,2,3,4) );; s4.name := "s4";;
gap> IsPermGroup( s4 );
true
gap> f := FactorGroup( s4, Subgroup( s4, [(1,2)(3,4),(1,3)(2,4)] ) );
(s4 / Subgroup( s4, [ (1,2)(3,4), (1,3)(2,4) ] ))
gap> IsPermGroup( f );
false
# see section 7.33
gap> IsPermGroup( [ 1, 2 ] );
false
21.2
PermGroupOps.MovedPoints
PermGroupOps.MovedPoints( G )
PermGroupOps.MovedPoints returns the set of moved points of the permutation group G,
i.e., points which are moved by at least one element of G (also see 21.5).
gap>
gap>
[ 1,
gap>
[ ]
21.3
s4 := Group( (1,3,5,7), (1,3) );;
PermGroupOps.MovedPoints( s4 );
3, 5, 7 ]
PermGroupOps.MovedPoints( Group( () ) );
PermGroupOps.SmallestMovedPoint
PermGroupOps.SmallestMovedPoint( G )
PermGroupOps.SmallestMovedPoint returns the smallest positive integer which is moved
by the permutation group G (see also 21.4). This function signals an error if G is trivial.
gap> s3b := Group( (2,3), (2,3,4) );;
gap> PermGroupOps.SmallestMovedPoint( s3b );
2
21.4
PermGroupOps.LargestMovedPoint
PermGroupOps.LargestMovedPoint( G )
PermGroupOps.LargestMovedPoint returns the largest positive integer which is moved by
the permutation group G (see also 21.3). This function signals an error if G is trivial.
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> PermGroupOps.LargestMovedPoint( s4 );
4
21.5
PermGroupOps.NrMovedPoints
PermGroupOps.NrMovedPoints( G )
PermGroupOps.NrMovedPoints returns the number of moved points of the permutation
group G, i.e., points which are moved by at least one element of G (also see 21.2).
gap> s4 := Group( (1,3,5,7), (1,3) );;
21.6. STABILIZER CHAINS
455
gap> PermGroupOps.NrMovedPoints( s4 );
4
gap> PermGroupOps.NrMovedPoints( Group( () ) );
0
21.6
Stabilizer Chains
Most of the algorithms for permutation groups need a stabilizer chain of the group. The
concept of stabilizer chains was introduced by Charles Sims in [Sim70].
If [b1 , . . . , bn ] is a list of points, G(1) = G and G(i+1) = StabG(i) (bi ) such that G(n+1) = {()}.
The list [b1 , . . . , bn ] is called a base of G, the points bi are called basepoints. A set S of
generators for G satisfying the condition < S ∩ G(i) > = G(i) for each 1 ≤ i ≤ n, is called
a strong generating set (SGS) of G. More precisely we ought to say that a set S that
satisfies the conditions above is a SGS of G relative to B. The chain of subgroups of G
itself is called the stabilizer chain of G relative to B.
Since [b1 , . . . , bn ], where n is the degree of G and bi are the moved points of G, certainly is a
base for G there exists a base for each permutation group. The number of points in a base
is called the length of the base. A base B is called reduced if no stabilizer in the chain
relative to B is trivial, i.e., there exists no i such that G(i) = G(i+1) . Note that different
reduced bases for one group G may have different length. For example, the Chevalley Group
G2 (4) possesses reduced bases of length 5 and 7.
Let R(i) be a right transversal of G(i+1) in G(i) , i.e., a set of right coset representatives of
the cosets of G(i+1) in G(i) . Then each element g of G has a unique representation of the
following form g = rn . . . r1 with ri ∈ R(i) . Thus with the knowledge of the transversals
R(i) we know each element of G, in principle. This is one reason why stabilizer chains are
one of the most useful tools for permutation groups. Furthermore basic group theory tells
(i)
us that we can identify the cosets of G(i+1) in G(i) with the points in O(i) := biG . So
we could represent a transversal as a list T such that T [p] is a representative of the coset
corresponding to the point p ∈ O(i) , i.e., an element of G(i) that takes bi to p.
For permutation groups of small degree this might be possible, but for permutation groups of
large degree it is still not good enough. Our goal then is to store as few different permutations
as possible such that we can still reconstruct each representative in R(i) , and from them the
elements in G. A factorized inverse transversal T is a list where T [p] is a generator of
G(i) such that pT [p] is a point that lies earlier in O(i) than p (note that we consider O(i) as
a list not as a set). If we assume inductively that we know an element r ∈ G(i) that takes
bi to pT [p] , then rT [p]−1 is an element in G(i) that takes bi to p.
A stabilizer chain (see 21.7, 21.25) is stored recursively in GAP3. The group record of a
permutation group G with a stabilizer chain has the following additional components.
orbit
List of orbitpoints of orbit[1] (which is the basepoint) under the action of the
generators.
transversal
Factorized inverse transversal as defined above.
stabilizer
Record for the stabilizer of the point orbit[1] in the group generated by generators.
456
CHAPTER 21. PERMUTATION GROUPS
The components of this record are again generators, orbit, transversal, identity
and stabilizer. The last stabilizer in the stabilizer chain only contains the components generators, which is an empty list, and identity.
stabChain
A record, that contains all information about the stabilizer chain. Functions acessing
the stabilizer chain should do it using this record, as it is planned to remove the
above three components from the group record in the future. The components of the
stabChain record are described in section 21.25.
Note that the values of these components are changed by functions that change, extend, or
reduce a base (see 21.7, 21.9, and 21.10).
Note that the records that represent the stabilizers are not group records (see 7.118). Thus
you cannot take such a stabilizer and apply group functions to it. The last stabilizer in
the stabilizer chain is a record whose component generators is empty.
Below you find an example for a stabilizer chain for the symmetric group of degree 4.
rec(
identity
:= (),
generators := [ (1,2), (1,2,3,4) ],
orbit
:= [ 1, 2, 4, 3 ],
transversal := [ (), (1,2), (1,2,3,4), (1,2,3,4) ],
stabilizer := rec(
identity
:= (),
generators := [ (3,4), (2,4) ],
orbit
:= [ 2, 4, 3 ],
transversal := [ , (), (3,4), (2,4) ],
stabilizer := rec(
identity
:= (),
generators := [ (3,4) ],
orbit
:= [ 3, 4 ],
transversal := [ ,, (), (3,4) ],
stabilizer := rec(
identity
:= (),
generators := [ ]
)
)
)
)
21.7
StabChain
StabChain( G )
StabChain( G, opt )
StabChain computes and returns a stabilizer chain for G. The option record opt can be given
and may contain information that will be used when computing the stabilizer chain. Giving
this information might speed up computations. When using random methods (see 21.24),
StabChain also guarantees, that the computed stabilizer chain confirms to the information
given. For example giving the size ensures correctness of the stabilizer chain.
21.8. MAKESTABCHAIN
457
If information of this kind can also be gotten from the parent group, StabChain does so.
The following components of the option record are currectly supported:
size
The group size.
limit
An upper limit for the group size.
base
A list of points. If given, StabChain computes a reduced base starting with the points
in base.
knownBase
A list of points, representing a known base.
random
A value to supersede global or parent group setting of StabChainOptions.random
(see 21.24).
21.8
MakeStabChain
MakeStabChain( G )
MakeStabChain( G, lst )
MakeStabChain computes a reduced stabilizer chain for the permutation group G.
If no stabilizer chain for G is already known and no argument lst is given, it computes a
reduced stabilizer chain for the lexicographically smallest reduced base of G.
If no stabilizer chain for G is already known and an argument lst is given, it computes a
reduced stabilizer chain with a base that starts with the points in lst. Note that points in
lst that would lead to trivial stabilizers will be skipped (see 21.9).
Deterministically, the stabilizer chain is computed using the Schreier-Sims-Algorithm,
which is described in [Leo80]. The time used is in practice proportional to the third power
of the degree of the group.
If a stabilizer chain for G is already known and no argument lst is given, it reduces the
known stabilizer chain.
If a stabilizer chain for G is already known and an argument lst is given, it changes the
stabilizer chain such that the result is a reduced stabilizer chain with a base that starts
with the points in lst (see 21.9). Note that points in lst that would lead to trivial stabilizers
will be skipped.
The algorithm used in this case is called basechange, which is described in [But82]. The
worst cases for the basechange algorithm are groups of large degree which have a long base.
gap> s4 := Group( (1,2), (1,2,3,4) );
Group( (1,2), (1,2,3,4) )
gap> MakeStabChain( s4 );
# compute a stabilizer chain
gap> Base( s4 );
[ 1, 2, 3 ]
gap> MakeStabChain( s4, [4,3,2,1] );
# perform a basechange
gap> Base( s4 );
[ 4, 3, 2 ]
MakeStabChain mainly works by calling StabChain with appropriate parameters.
458
CHAPTER 21. PERMUTATION GROUPS
21.9
ExtendStabChain
ExtendStabChain( G, lst )
ExtendStabChain inserts trivial stabilizers into the known stabilizer chain of the permutation group G such that lst becomes the base of G. The stabilizer chain which belongs to
the base lst must reduce to the old stabilizer chain (see 21.10).
This function is useful if two different (sub-)groups have to have exactly the same base.
gap> s4 := Group( (1,2), (1,2,3,4) );;
gap> MakeStabChain( s4, [3,2,1] ); Base( s4 );
[ 3, 2, 1 ]
gap> h := Subgroup( Parent(s4), [(1,2,3,4), (2,4)] );
Subgroup( Group( (1,2), (1,2,3,4) ), [ (1,2,3,4), (2,4) ] )
gap> Base( h );
[ 1, 2 ]
gap> MakeStabChain( h, Base( s4 ) ); Base( h );
[ 3, 2 ]
gap> ExtendStabChain( h, Base( s4 ) ); Base( h );
[ 3, 2, 1 ]
21.10
ReduceStabChain
ReduceStabChain( G )
ReduceStabChain removes trivial stabilizers from a known stabilizer chain of the permutation group G. The result is a reduced stabilizer chain (also see 21.9).
gap>
gap>
[ 1,
gap>
[ 1,
gap>
[ 4,
gap>
[ 1,
21.11
s4 := Group( (1,2), (1,2,3,4) );;
Base( s4 );
2, 3 ]
ExtendStabChain( s4, [ 1, 2, 3, 4 ] );
2, 3, 4 ]
PermGroupOps.Indices( s4 );
3, 2, 1 ]
ReduceStabChain( s4 ); Base( s4 );
2, 3 ]
Base( s4 );
MakeStabChainStrongGenerators
MakeStabChainStrongGenerators( G, base, stronggens )
MakeStabChainStrongGenerators computes a reduced stabilizer chain for the permutation group G with the base base and the strong generating set stronggens. stronggens
must be a strong generating set for G relative to the base base; note that this is not
tested. Since the generators for G are not changed the strong generating set of G got by
PermGroupOps.StrongGenerators is not exactly stronggens afterwards. This function is
mostly used to reconstruct a stabilizer chain for a group G and works considerably faster
than MakeStabChain (see 21.8).
gap> G := Group( (1,2), (1,2,3), (4,5) );;
21.12. BASE FOR PERMUTATION GROUPS
459
gap> Base( G );
[ 1, 2, 4 ]
gap> ExtendStabChain( G, [1,2,3,4] );
gap> PermGroupOps.Indices( G ); base := Base( G );
[ 3, 2, 1, 2 ]
# note that the stabilizer chain is not reduced
[ 1, 2, 3, 4 ]
gap> stronggens := PermGroupOps.StrongGenerators( G );
[ (4,5), (2,3), (1,2), (1,2,3) ]
gap> H := Group( (1,2), (1,3), (4,5) );
Group( (1,2), (1,3), (4,5) )
# of course G = H
gap> MakeStabChainStrongGenerators( H, base, stronggens );
gap> PermGroupOps.Indices( H ); Base( H );
[ 3, 2, 2 ]
# note that the stabilizer chain is reduced
[ 1, 2, 4 ]
gap> PermGroupOps.StrongGenerators( H );
[ (4,5), (2,3), (1,2), (1,3) ]
# note that this is different from stronggens
21.12
Base for Permutation Groups
Base( G )
Base returns a base for the permutation group G. If a stabilizer chain for G is already
known, Base returns the base for this stabilizer chain. Otherwise a stabilizer chain for the
lexicographically smallest reduced base is computed and its base is returned (see 21.6).
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> Base( s4 );
[ 1, 2, 3 ]
21.13
PermGroupOps.Indices
PermGroupOps.Indices( G )
PermGroupOps.Indices returns a list l of indices of the permutation group G with respect to
a stabilizer chain of G, i.e., l [i ] is the index of G(i+1) in G(i) . Thus the size of G is the product of all indices in l . If a stabilizer chain for G is already known, PermGroupOps.Indices
returns the indices corresponding to this stabilizer chain. Otherwise a stabilizer chain with
the lexicographically smallest reduced base is computed and the indices corresponding to
this chain are returned (see 21.6).
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> PermGroupOps.Indices( s4 );
[ 4, 3, 2 ]
# note that for s4 the indices are
# actually independent of the base
21.14
PermGroupOps.StrongGenerators
PermGroupOps.StrongGenerators( G )
PermGroupOps.StrongGenerators returns a list of strong generators for the permutation
group G. If a stabilizer chain for G is already known, PermGroupOps.StrongGenerators
460
CHAPTER 21. PERMUTATION GROUPS
returns a strong generating set corresponding to this stabilizer chain. Otherwise a stabilizer
chain with the lexicographically smallest reduced base is computed and a strong generating
set corresponding to this chain is returned (see 21.6).
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> Base( s4 );
[ 1, 2, 3 ]
gap> PermGroupOps.StrongGenerators( s4 );
[ (3,4), (2,3,4), (1,2), (1,2,3,4) ]
21.15
ListStabChain
ListStabChain( G )
ListStabChain returns a list of stabilizer records of the stabilizer chain of the permutation
group G, i.e., the result is a list l such that l [i ] is the i -th stabilizer G(i) . The records in
that list are identical to the records of the stabilizer chain. Thus changes made in a record
l [i ] are simultaneously done in the stabilizer chain (see 46.3).
21.16
PermGroupOps.ElementProperty
PermGroupOps.ElementProperty( G, prop )
PermGroupOps.ElementProperty( G, prop, K )
PermGroupOps.ElementProperty returns an element g in the permutation group G such
that prop(g) is true. prop must be a function of one argument that returns either true or
false when applied to an element of G. If G has no such element, false is returned.
gap> V4 := Group((1,2),(3,4));;
gap> PermGroupOps.ElementProperty( V4, g -> (1,2)^g = (3,4) );
false
PermGroupOps.ElementProperty first computes a stabilizer chain for G, if necessary. Then
it performs a backtrack search through G for an element satisfying prop, i.e., enumerates
all elements of G as described in section 21.6, and applies prop to each until one element g
is found for which prop(g) is true. This algorithm is described in detail in [But82].
gap> S8 := Group( (1,2), (1,2,3,4,5,6,7,8) );; S8.name := "S8";;
gap> Size( S8 );
40320
gap> V := Subgroup( S8, [(1,2),(1,2,3),(6,7),(6,7,8)] );;
gap> Size( V );
36
gap> U := V ^ (1,2,3,4)(5,6,7,8);;
gap> PermGroupOps.ElementProperty( S8, g -> U ^ g = V );
(1,4,2)(5,6)
# another permutation conjugating U to V
This search will of course take quite a while if G is large, especially if no element of G
satisfies prop, and therefore all elements of G must be tried.
To speed up the computation you may pass a subgroup K of G as optional third argument.
This subgroup must preserve prop in the sense that either all elements of a left coset g*K
satisfy prop or no element of g*K does.
21.17. PERMGROUPOPS.SUBGROUPPROPERTY
461
In our example above such a subgroup is the normalizer NG (V ) because h ∈ gNG (V ) takes
U to V if and only if g does. Of course every subgroup of NG (V ) has this property too.
Below we use the subgroup V itself. In this example this speeds up the computation by a
factor of 4.
gap> K := Subgroup( S8, V.generators );;
gap> PermGroupOps.ElementProperty( S8, g -> U ^ g = V, K );
(1,4,2)(5,6)
In the following example, we use the same subgroup, but with a larger generating system.
This speeds up the computation by another factor of 3. Something like this may happen
frequently. The reason is too complicated to be explained here.
gap> K2 := Subgroup( S8, Union( V.generators, [(2,3),(7,8)] ) );;
gap> K2 = K;
true
gap> PermGroupOps.ElementProperty( S8, g -> U ^ g = V, K2 );
(1,4,2)(5,6)
Passing the full normalizer speeds up the computation in this example by another factor
of 2. Beware though that in other examples the computation of the normalizer alone may
take longer than calling PermGroupOps.ElementProperty with only the subgroup itself as
argument.
gap> N := Normalizer( S8, V );
Subgroup( S8, [ (1,2), (1,2,3), (6,7), (6,7,8), (2,3), (7,8),
(1,6)(2,7)(3,8), (4,5) ] )
gap> Size( N );
144
gap> PermGroupOps.ElementProperty( S8, g -> U ^ g = V, N );
(1,4)(5,6)
21.17
PermGroupOps.SubgroupProperty
PermGroupOps.SubgroupProperty( G, prop )
PermGroupOps.SubgroupProperty( G, prop, K )
PermGroupOps.SubgroupProperty returns the subgroup U of the permutation group G of
all elements in G that satisfy prop, i.e., the subgroup of all elements g in G such that
prop(g) is true. prop must be a function of one argument that returns either true or
false when applied to an element of G. Of course the elements that satisfy prop must form
a subgroup of G. PermGroupOps.SubgroupProperty builds a stabilizer chain for U .
gap> S8 := Group( (1,2), (1,2,3,4,5,6,7,8) );; S8.name := "S8";;
gap> Size(S8);
40320
gap> V := Subgroup( S8, [(1,2),(1,2,3),(6,7),(6,7,8)] );;
gap> Size(V);
36
gap> PermGroupOps.SubgroupProperty( S8, g -> V ^ g = V );
Subgroup( S8, [ (7,8), (6,7), (4,5), (2,3)(4,5)(6,8,7), (1,2),
(1,6,3,8)(2,7) ] )
462
CHAPTER 21. PERMUTATION GROUPS
# the normalizer of V in S8
PermGroupOps.SubgroupProperty first computes a stabilizer chain for G, if necessary. Then
it performs a backtrack search through G for the elements satisfying prop, i.e., enumerates
all elements of G as described in section 21.6, and applies prop to each, adding elements
for which prop(g) is true to the subgroup U . Once U has become non-trivial, it is used
to eliminate whole cosets of stabilizers in the stabilizer chain of G if they cannot contain
elements with the property prop that are not already in U . This algorithm is described in
detail in [But82].
This search will of course take quite a while if G is large. To speed up the computation you
may pass a subgroup K of U as optional third argument.
Passing the subgroup V itself, speeds up the computation in this example by a factor of 2.
gap> K := Subgroup( S8, V.generators );;
gap> PermGroupOps.SubgroupProperty( S8, g -> V ^ g = V, K );
Subgroup( S8, [ (1,2), (1,2,3), (6,7), (6,7,8), (2,3), (7,8), (4,5),
(1,6,3,8)(2,7) ] )
21.18
CentralCompositionSeriesPPermGroup
CentralCompositionSeriesPPermGroup( G )
This function calculates a central composition series for the p-group G. The method used
is known as Holt’s algorithm. If G is not a p-group, an error is signalled.
gap> D := Group( (1,2,3,4), (1,3) );; D.name := "d8";;
gap> CentralCompositionSeriesPPermGroup( D );
[ d8, Subgroup( d8, [ (2,4), (1,3) ] ),
Subgroup( d8, [ (1,3)(2,4) ] ), Subgroup( d8, [ ] ) ]
21.19
PermGroupOps.PgGroup
PermGroupOps.PgGroup( G )
This function converts a permutation group G of prime power order pd into an ag group P
such that the presentation corresponds to a p-step central series of G. This central composition series is constructed by calling CentralCompositionSeriesPPermGroup (see 21.18).
An isomorphism from the ag group to the permutation group is bound to P .bijection.
There is no dispatcher to this function, it must be called as PermGroupOps.PgGroup.
21.20
Set Functions for Permutation Groups
All set theoretic functions described in chapter 4 are also applicable to permutation groups.
This section describes which functions are implemented specially for permutation groups.
Functions not mentioned here are handled by the default methods described in the respective
sections.
Random( G )
21.21. GROUP FUNCTIONS FOR PERMUTATION GROUPS
463
To compute a random element in a permutation group G GAP3 computes a stabilizer chain
for G, takes on each level a random representative and returns the product of those. All
elements of G are chosen with equal probability by this method.
Size( G )
Size calls StabChain (see 21.7), if necessary, and returns the product of the indices of the
stabilizer chain (see 21.6).
Elements( G )
Elements calls StabChain (see 21.7), if necessary, and enumerates the elements of G as
described in 21.6. It returns the set of those elements.
Intersection( G1 , G2 )
Intersection first computes stabilizer chains for G1 and G2 for a common base. If either
group already has a stabilizer chain a basechange is performed (see 21.8). Intersection
enumerates the elements of G1 and G2 using a backtrack algorithm, eliminating whole
cosets of stabilizers in the stabilizer chains if possible (see 21.17). It builds a stabilizer chain
for the intersection.
21.21
Group Functions for Permutation Groups
All group functions for groups described in chapter 7.9 are also applicable to permutation
groups. This section describes which functions are implemented specially for permutation
groups. Functions not mentioned here are handled by the default methods described in the
respective sections.
G ^ p
ConjugateSubgroup( G, p )
Returns the conjugate permutation group of G with the permutation p. p must be an
element of the parent group of G. If a stabilizer chain for G is already known, it is also
conjugated.
Centralizer( G, U )
Centralizer( G, g )
Normalizer( G, U )
These functions first compute a stabilizer chain for G. If a stabilizer chain is already known
a basechange may be performed to obtain a base that is better suited for the problem. These
functions then enumerate the elements of G with a backtrack algorithm, eliminating whole
cosets of stabilizers in the stabilizer chain if possible (see 21.17). They build a stabilizer
chain for the resulting subgroup.
SylowSubgroup( G, p )
464
CHAPTER 21. PERMUTATION GROUPS
If G is not transitive, its p-Sylow subgroup is computed by starting with P :=G, and for
each transitive constituent homomorphism hom iterating
P := PreImage( SylowSubgroup( Image( hom, P ), p ) ).
If G is transitive but not primitive, its p-Sylow subgroup is computed as
SylowSubgroup( PreImage( SylowSubgroup(Image(hom,G),p) ), p ).
If G is primitive, SylowSubgroup takes random elements in G, until it finds a p-element g,
whose centralizer in G contains the whole p-Sylow subgroup. Such an element must exist,
because a p-group has a nontrivial centre. Then the p-Sylow subgroup of the centralizer is
computed and returned. Note that the centralizer must be a proper subgroup of G, because
it operates imprimitively on the cycles of g.
Coset( U , g )
Returns the coset U *g. The representative chosen is the lexicographically smallest element
of that coset. It is computed with an algorithm that is very similar to the backtrack
algorithm.
gap> s4 := Group( (1,2,3,4), (1,2) );;
gap> u := Subgroup( s4, [(1,2,3)] );;
gap> Coset( u, (1,3,2) );
(Subgroup( s4, [ (1,2,3) ] )*())
gap> Coset( u, (3,2) );
(Subgroup( s4, [ (1,2,3) ] )*(2,3))
s4.name := "s4";;
Cosets( G, U )
Returns the cosets of U in G. Cosets first computes stabilizer chains for G and U with a
common base. If either subgroup already has a stabilizer chain, a basechange is performed
(see 21.8). A transversal is computed recursively using the fact that if S is a transversal
of U (2) = StabU (b1 ) in G(2) = StabG (b1 ), and R(1) is a transversal of G(2) in G, then a
transversal of U in G is a subset of S ∗ R(1) .
gap> Cosets(
[ (Subgroup(
(Subgroup(
(Subgroup(
(Subgroup(
(Subgroup(
(Subgroup(
(Subgroup(
(Subgroup(
s4,
s4,
s4,
s4,
s4,
s4,
s4,
s4,
s4,
u
[
[
[
[
[
[
[
[
);
(1,2,3)
(1,2,3)
(1,2,3)
(1,2,3)
(1,2,3)
(1,2,3)
(1,2,3)
(1,2,3)
]
]
]
]
]
]
]
]
)*()),
)*(3,4)),
)*(2,3)),
)*(2,3,4)),
)*(2,4,3)),
)*(2,4)),
)*(1,2,3,4)),
)*(1,2,4)) ]
PermutationCharacter( P )
Computes the character of the natural permutation representation of P , i.e. it does the
same as PermutationCharacter( P , StabP (1) ) but works much faster.
gap> G := SymmetricPermGroup(5);;
gap> PermutationCharacter(G);
[ 5, 3, 1, 2, 0, 1, 0 ]
21.21. GROUP FUNCTIONS FOR PERMUTATION GROUPS
465
ElementaryAbelianSeries( G )
This function builds an elementary abelian series of G by iterated construction of normal
closures. If a partial elementary abelian series reaches up to a subgroup U of G which does
not yet contain the generator s of G then the series is extended up to the normal closure
N of U and s. If the factor N /U is not elementary abelian, i.e., if some commutator of s
with one of its conjugates under G does not lie in U , intermediate subgroups are calculated
recursively by extending U with that commutator. If G is solvable this process must come
to an end since commutators of arbitrary depth cannot exist in solvable groups.
Hence this method gives an elementary abelian series if G is solvable and gives an infinite
recursion if it is not. For permutation groups, however, there is a bound on the derived length
that depends only on the degree d of the group. According to Dixon this is (5 log3 (d))/2. So
if the commutators get deeper than this bound the algorithm stops and sets G.isSolvable
to false, signalling an error. Otherwise G.isSolvable is set to true and the elementary
abelian series is returned as a list of subgroups of G.
gap> S := Group( (1,2,3,4), (1,2) );; S.name := "s4";;
gap> ElementaryAbelianSeries( S );
[ Subgroup( s4, [ (1,2), (1,3,2), (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,3,2), (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,4)(2,3), (1,2)(3,4) ] ), Subgroup( s4, [
gap> A := Group( (1,2,3), (3,4,5) );;
gap> ElementaryAbelianSeries( A );
Error, must be solvable
] ) ]
IsSolvable( G )
Solvability of a permutation group G is tested by trying to construct an elementary abelian
series as described above. After this has been done the flag G.isSolvable is set correctly,
so its value is returned.
gap> S := Group(
gap> IsSolvable(
true
gap> A := Group(
gap> IsSolvable(
false
(1,2,3,4), (1,2) );;
S );
(1,2,3), (3,4,5) );;
A );
CompositionSeries( G )
A composition series for the solvable group G is calculated either from a given subnormal
series, which must be bound to G.subnormalSeries, in which case G.bssgs must hold
the corresponding base-strong subnormal generating system, or from an elementary abelian
series (as computed by ElementaryAbelianSeries( G ) above) by inserting intermediate
subgroups (i.e. powers of the polycyclic generators or composition series along bases of
the vector spaces in the elementary abelian series). In either case, after execution of this
function, G.bssgs holds a base-strong pag system corresponding to the composition series
calculated.
gap> S := Group( (1,2,3,4), (1,2) );; S.name := "s4";;
466
CHAPTER 21. PERMUTATION GROUPS
gap> CompositionSeries( S );
[ Subgroup( s4, [ (1,2), (1,3,2), (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,3,2), (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( s4, [ (1,2)(3,4) ] ), Subgroup( s4, [ ] ) ]
If G is not solvable then a composition series cs is computed with an algorithm by A.
Seress and R. Beals. In this case the factor group of each element cs[i ] in the composition
series modulo the next one cs[i +1] are represented as primitive permutation groups. One
should call cs[i ].operations.FactorGroup( cs[i ], cs[i +1] ) directly to avoid the check
in FactorGroup that cs[i +1] is normal in cs[i ]. The natural homomorphism of cs[i ] onto
this factor group will be given as a GroupHomomorphismByImages (see 7.113).
gap> pyl29 := Group( (1,2,3)(4,5,6)(7,8,9), (2,6,4,9,3,8,7,5),
>
(4,7)(5,8)(6,9), (1,10)(4,7)(5,6)(8,9) );;
gap> pyl29.name := "pyl29";;
gap> cs := CompositionSeries( pyl29 );
[ Subgroup( pyl29, [ (1,9,5)(2,7,6)(3,8,4), (2,7,3,4)(5,8,9,6),
( 1, 2,10)( 4, 9, 5)( 6, 8, 7), (2,6,4,9,3,8,7,5),
(4,7)(5,8)(6,9) ] ),
Subgroup( pyl29, [ (1,9,5)(2,7,6)(3,8,4), (2,7,3,4)(5,8,9,6),
( 1, 2,10)( 4, 9, 5)( 6, 8, 7), (2,6,4,9,3,8,7,5) ] ),
Subgroup( pyl29, [ (1,9,5)(2,7,6)(3,8,4), (2,7,3,4)(5,8,9,6),
( 1, 2,10)( 4, 9, 5)( 6, 8, 7) ] ), Subgroup( pyl29, [ ] ) ]
gap> List( [1..3], i->cs[i].operations.FactorGroup(cs[i],cs[i+1]) );
[ Group( (1,2) ), Group( (1,2) ),
Group( (1,9,5)(2,7,6)(3,8,4), (2,7,3,4)(5,8,9,6), ( 1, 2,10)
( 4, 9, 5)( 6, 8, 7) ) ]
gap> List( last, Size );
[ 2, 2, 360 ]
ExponentsPermSolvablePermGroup( G, perm [, start ] )
ExponentsPermSolvablePermGroup returns a list e, such that perm = G.bssgs[1]^e[1]
* G.bssgs[2]^e[2] * ... * G.bssgs[n]^e[n], where G.bssgs must be a prime-step
base-strong subnormal generating system as calculated by ElementaryAbelianSeries (see
7.39 and above). If the optional third argument start is given, the list entries exps[1],
..., exps[start-1] are left unbound and the element perm is decomposed as product of
the remaining pag generators G.bssgs[start], ..., G.bssgs[n].
gap> S := Group( (1,2,3,4), (1,2) );; S.name := "s4";;
gap> ElementaryAbelianSeries( S );;
gap> S.bssgs;
[ (1,2), (1,3,2), (1,4)(2,3), (1,2)(3,4) ]
gap> ExponentsPermSolvablePermGroup( S, (1,2,3) );
[ 0, 2, 0, 0 ]
AgGroup( G )
This function converts a solvable permutation group into an ag group. It calculates an
elementary abelian series and a prime-step bssgs for G (see ElementaryAbelianSeries
21.22. OPERATIONS OF PERMUTATION GROUPS
467
above) and then finds the relators belonging to this prime-step bssgs using the function
ExponentsPermSolvablePermGroup (see above). An isomorphism from the ag group to the
permutation group is bound to AgGroup( G ).bijection.
gap> G := WreathProduct( SymmetricGroup( 4 ), CyclicGroup( 3 ) );;
gap> A := AgGroup( G );
Group( g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11, g12, g13 )
gap> (A.1*A.3)^A.bijection;
( 1, 6,10, 2, 5, 9)( 3, 7,11)( 4, 8,12)
DirectProduct( G, H )
If G and H are both permutation groups, DirectProduct constructs the direct product of
G and H as an intransitive permutation group. There are special routines for Centre,
Centralizer and SylowSubgroup for such groups that will work faster than the standard permutation group functions. These functions are DirectProductPermGroupCentre,
DirectProductPermGroupCentralizer and DirectProductPermGroupSylowSubgroup. You
can enforce that these routines will be always used for direct products of permutation groups
by issuing the following three commands (They are not performed by standard as the code
has not been well-tested).
gap>
gap>
>
gap>
>
21.22
DirectProductPermGroupOps.Centre:=DirectProductPermGroupCentre;;
DirectProductPermGroupOps.Centralizer:=
DirectProductPermGroupCentralizer;;
DirectProductPermGroupOps.SylowSubgroup:=
DirectProductPermGroupSylowSubgroup;;
Operations of Permutation Groups
All functions that deal with operations of groups are applicable to permutation groups
(see 8). This section describes which functions are implemented specially for permutation
groups. Functions not mentioned here are handled by the default methods described in the
respective sections.
IsSemiRegular( G, D, opr )
IsSemiRegular returns true if G operates semiregularly on the domain D and false otherwise.
If D is a list of integers and opr is OnPoints, IsSemiRegular uses the lemma that says
that such an operation is semiregular if all orbits of G on D have the same length, and if
for an arbitrary point p of D and for each generator g of G there is a permutation zg (not
necessarily in G) such that pzg = pg and which commutes with all elements of G, and if
there is a permutation z (again not necessarily in G) that permutes the orbits of G on D
setwise and commutes with all elements of G. This can be tested in time proportional to
on2 + dn, where o is the size of a single orbit, n is the number of generators of G, and d is
the size of D.
RepresentativeOperation( G, d , e, opr )
468
CHAPTER 21. PERMUTATION GROUPS
RepresentativeOperation returns a permutation perm in G that maps d to e in respect
to the given operation opr if such a permutation exists, and false otherwise.
If the operation is OnPoints, OnPairs, OnTuples, or OnSets and d and e are positive
integers or lists of integers, a basechange is performed and the representative is computed
from the factorized inverse transversal (see 21.6 and 21.7).
If the operation is OnPoints, OnPairs, OnTuples or OnSets and d and e are permutations
or lists of permutations, a backtrack search is performed (see 21.16).
Stabilizer( G, D, opr )
Stabilizer returns the stabilizer of D in G using the operation opr on the D. If D is a
positive integer (respectively a list of positive integers) and the operation opr is OnPoints
(respectively OnPairs or OnTuples) a basechange of G is performed (see 21.8). If D is a set
of positive integers and the operation opr is OnSets a backtrack algorithm for set-stabilizers
of permutation groups is performed.
Blocks( G, D [, seed ] [, operation ] )
Returns a partition of D being a minimal block system of G in respect to the operation
opreration on the objects of D. If the argument seed is given the objects of seed are contained
in the same block. If D is a list of positive integers an Atkinson algorithm is performed.
Theoretically the algorithm lies in O(n3 m) but in practice it is mostly in O(n2 m) with m
the number of generators and n the cardinality of D.
21.23
Homomorphisms for Permutation Groups
This section describes the various homomorphisms that are treated specially for permutation
groups.
GroupHomomorphisByImages( P , H , gens, imgs )
The group homomorphism of a permutation group P into another group H is handled
especially by GroupHomomorphisByImages. Below we describe how the various mapping
functions are implemented for such a group homomorphism ghom. The mapping functions
not mentioned below are implemented by the default functions described in 7.113.
To work with ghom, a stabilizer chain for the source of ghom is computed and stored
as ghom.orbit, ghom.transversal, ghom.stabilizer. For every stabilizer stab in the
stabilizer chain there is a list parallel to stab.generators, which is called stab.genimages,
and contains images of the generators. The stabilizer chain is computed with a random
Schreier Sims algorithm, using the size of the source to know when to stop.
IsMapping( ghom )
To test if ghom is a (single valued) mapping, all Schreier generatores are computed. Each
Schreier generator is then reduced along the stabilizer chain. Because the chain is complete,
each one must reduce to the identity. Parallel the images of the strong generators are
21.23. HOMOMORPHISMS FOR PERMUTATION GROUPS
469
multiplied. If they also reduce to the identity (in the range), ghom is a function, otherwise
the remainders form a normal generating set for the subgroup of images of the identity of
the source.
Image( ghom, elm )
The image of an element elm can be computed by reducing the element along the stabilizer
chain, and at each step multiplying the corresponding images of the strong generators.
CompositionMapping( hom, ghom )
The composition of an arbitrary group homomorphism hom and ghom the stabilizer chain of
ghom is copied. On each level the images of the generators in stab.genimages are replaced
by their images under hom.
OperationHomomorphism( P , Operation( P , list ) )
The operation of a permutation group P on a list list of integers is handled especially by
OperationHomomorphism. (Note that list must be a union of orbits of P for Operation
to work.) We call the resulting homomorphism a transitive constituent homomorphism.
Below we describe how the various mapping functions are implemented for a transitive
constituent homomorphism tchom. The mapping functions not mentioned below are implemented by the default functions described in 8.21.
Image( tchom, elm )
The image of an element is computed by restricting elm to list (see 20.10) and conjugating the restricted permutation with tchom.conperm, which maps it to a permutation that
operates on [1..Length(list)] instead of list.
Image( tchom, H )
The image of a subgroup H is computed as follows. First a stabilizer chain for H is computed.
This stabilizer chain is such that the base starts with points in list. Then the images of the
strong generators of sub form a strong generating set of the image.
PreImages( tchom, H )
The preimage of a subgroup H is computed as follows. First a stabilizer chain for the source
of tchom is computed. This stabilizer chain is such that the base starts with the point in
list. Then the kernel of tchom is a stabilizer in this stabilizer chain. The preimages of the
strong generators for H together with the strong generators for the kernel form a strong
generating set of the preimage subgroup.
OperationHomomorphism( P , Operation( P , blocks, OnSets ) )
The operation of a permutation group P on a block system blocks (see 8.22) is handled
especially by OperationHomomorphism. We call the resulting homomorphism a blocks homomorphism. Below we describe how the various mapping functions are implemented for a
470
CHAPTER 21. PERMUTATION GROUPS
blocks homomorphism bhom. The mapping functions not mentioned below are implemented
by the default functions described in 8.21.
Image( bhom, elm )
To compute the image of an element elm under bhom, the record for bhom contains a list
bhom.reps, which contains for each point in the union of the blocks the position of this
block in blocks. Then the image of an element can simply be computed by applying the
element to a representative of each block and using bhom.reps to find in which block the
image lies.
Image( bhom, H )
PreImage( bhom, elm )
PreImage( bhom, H )
Kernel( bhom )
The image of a subgroup, the preimage of an element, and the preimage of a subgroup
are computed by rather complicated algorithms. For a description of these algorithms see
[But85].
21.24
Random Methods for Permutation Groups
When permutation groups become larger, computations become slower. This increase might
make it impossible to compute with these groups. The reason is mainly the creation of
stabilizer chains (see 21.7): During this process a lot of schreier generators are produced for
the next point stabilizer in the chain, and these generators must be processed. In actual
examples, it is observed, however, that much fewer generators are needed. This observation
can be justified theoretically and the random methods exploit it by using a method of the
Schreier-Sims algorithm which gives the correct result with an user-given error probability.
Advantage
Computations become much faster. In fact, large problems may be handled only by
using random methods.
Disadvantages
Computations might produce wrong results. However, you can set an error margin,
which is guaranteed. The practical performance is even better than our guarantee.
You should also keep in mind, that it is impossible, to eliminate system, user or
programming errors.
However, there are many situations, when theory offers methods to check correctness of
the results. As an example, consider the following situation. You want to compute some
maximal subgroups of large sporadic groups. The ATLAS of finite groups then tells you the
sizes of the groups as well as the sizes of the subgroups. The error of the random methods
is one-sided in the sense that they never create strong generators which are not elements
of the group. Hence if the resulting group sizes are correct, you have indeed obtained the
correct result. You might also give this information to StabChain, and computation will
not only be much faster, but also corresponding to the information, i.e. if you give the size,
the stabilizer chain is computed correctly.
The stabilizer chain is computed using methods from [BCFS91].
21.24. RANDOM METHODS FOR PERMUTATION GROUPS
471
How to use the random methods
GAP3 provides the global variable StabChainOptions. This record might contain a component random. If it is set to a number i between 1 and 1000 at the beginning, random
i
methods with guaranteed correctness 10
percent are used (though practically the probability
for correctness is much higher). This means that at all applicable places random methods
will be used automatically by the same function calls. If the component is not set or set to
1000, all computations are deterministic. By standard, this component is not set, so unless
you explicitely allow random computations none are used.
If the group acts on not more than a hundered points, the use of random methods has no
advantage. For these groups always the deterministic methods are used.
gap> g:=SL(4,7);
SL(4,7)
gap> o:=Orbit(g,[1,0,0,0]*Z(7)^0,OnLines);;Length(o);
400
gap> op:=Operation(g,o,OnLines);;
We create a large permutation group on 400 points. First we compute deterministic.
gap> g:=Group(op.generators,());;
gap> StabChain(g);;time;
164736
gap> Size(g);
2317591180800
Now random methods will be used. We allow that the result is guaranteed correct only with
10 percent probability. The group is created anew.
gap> StabChainOptions.random:=100;
100
gap> g:=Group(op.generators,());;
gap> StabChain(g);;time;
10350
gap> Size(g);
2317591180800
The result is still correct, though it took only less than one tenth of the time (your mileage
may vary). If you give the algorithm a chance to check its results, things become even faster.
gap> g:=Group(op.generators,());;
gap> StabChain(g,rec(size:=2317591180800));;time;
5054
More about random methods
When stabilizer chains are created, while random methods are allowed, it is noted in the
respective groups, by setting of a record component G.stabChainOptions, which is itself
a record, containg the component random. This component has the value indicated by
StabChainOptions at the time the group was created. Values set in this component override
the global setting of StabChainOptions. Whenever stabilizer chains are created for a group
not posessing the .stabChainOptions.random entry, it is created anew from the global
value StabChainOptions.
472
CHAPTER 21. PERMUTATION GROUPS
If a subgroup has no own record stabChainOptions, the one of the parent group is used
instead.
As errors induced by the random functions might propagate, any (applicable) object created
from the group inherits the component .stabChainOptions from the group. This applies
for example to Operations and Homomorphisms.
21.25
Permutation Group Records
All groups are represented by a record that contains information about the group. A permutation group record contains the following components in addition to those described in
section 7.118.
isPermGroup
always true.
isFinite
always true as permutation groups are always of finite order.
A stabilizer chain (see 21.6) is stored recursively in GAP3. The group record of a permutation
group G with a stabilizer chain has the following additional components.
orbit
List of orbitpoints of orbit[1] (which is the basepoint) under the action of the
generators.
transversal
Factorized inverse transversal as defined in 21.6.
stabilizer
Record for the stabilizer of the point orbit[1] in the group generated by generators.
The components of this record are again generators, orbit, transversal and
stabilizer. The last stabilizer in the stabilizer chain only contains the component
generators, which is an empty list.
stabChainOptions
A record, that contains information about creation of the stabilizer chain. For example, whether it has been computed using random methods (see 21.24). Some functions
also use this record for passing local information about basechanges.
stabChain
A record, that contains all information about the stabilizer chain. Functions acessing
the stabilizer chain should do it using this record, as it is planned to remove the
above three components from the group record in the future. The components of the
stabChain record are described below.
The components of the stabChain record for a group G are
identity
Contains G.identity.
generators
Contains a copy of the generators of G, created by ShallowCopy(G.generators).
orbit
is the same as G.orbit.
21.25. PERMUTATION GROUP RECORDS
473
transversal
is the same as G.transversal.
stabilizer
is the same as G.stabilizer.
Note that the values of all these components are changed by functions that change, extend,
or reduce a base (see 21.8, 21.9, and 21.10).
Note that the records that represent the stabilizers are not themselves group records (see
7.118). Thus you cannot take such a stabilizer and apply group functions to it. The last
stabilizer in the stabilizer chain is a record whose component generators is empty.
474
CHAPTER 21. PERMUTATION GROUPS
Chapter 22
Words in Abstract Generators
Words in abstract generators are a type of group elements in GAP3. In the following
we will abbreviate their full name to abstract words or just to words.
A word is just a sequence of letters, where each letter is an abstract generator or its inverse.
Words are multiplied by concatenating them and removing adjacent pairs of a generator
and its inverse. Abstract generators are created by the function AbstractGenerator (see
22.1).
Note that words do not belong to a certain group. Any two words can be multiplied. In
effect we compute with words in a free group of potentially infinite rank (potentially infinite
because we can always create new abstract generators with AbstractGenerator).
Words are entered as expressions in abstract generators and are displayed as product of
abstract generators (and powers thereof). The trivial word can be entered and is displayed
as IdWord.
gap> a := AbstractGenerator( "a" );
a
gap> b := AbstractGenerator( "b" );
b
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> a^0;
IdWord
The first sections in this chapter describe the functions that create abstract generators (see
22.1 and 22.2). The next sections define the operations for words (see 22.3 and 22.4). The
next section describes the function that tests whether an object is a word (see 22.5). The
next sections describe the functions that compute the number of letters of a word (see 22.6
and 22.7). The next sections describe the functions that extract or find a subword (see 22.8
and 22.9). The final sections describe the functions that modify words (see 22.10, 22.11,
and 22.12).
Note that words in abstract generators are different from words in finite polycyclic groups
(see 24).
475
476
CHAPTER 22. WORDS IN ABSTRACT GENERATORS
22.1
AbstractGenerator
AbstractGenerator( string )
AbstractGenerator returns a new abstract generator. This abstract generator is printed
using the string string passed as argument to AbstractGenerator.
gap> a := AbstractGenerator( "a" );
a
gap> a^5;
a^5
Note that the string is only used to print the abstract generator and to order abstract
generators (see 22.3). It is possible for two different abstract generators to use the same
string and still be different.
gap> b := AbstractGenerator( "a" );
a
gap> a = b;
false
Also when you define abstract generators interactively it is a good idea to use the identifier
of the variable as the name of the abstract generator, because then what GAP3 will output
for a word is equal to what you can input to obtain this word. The following is an example
of what you should probably not do.
gap> c := AbstractGenerator( "d" );
d
gap> d := AbstractGenerator( "c" );
c
gap> (c*d)^3;
d*c*d*c*d*c
gap> d*c*d*c*d*c;
c*d*c*d*c*d
22.2
AbstractGenerators
AbstractGenerators( string, n )
AbstractGenerators returns a list of n new abstract generators. These new generators are
printed using string1, string2, ..., stringn.
gap> AbstractGenerators( "a", 3 );
[ a1, a2, a3 ]
AbstractGenerators could be defined as follows (see 22.1).
AbstractGenerators := function ( string, n )
local
gens, i;
gens := [];
for i in [1..n] do
Add( gens,
AbstractGenerator(
ConcatenationString( string, String(i) ) ) );
22.3. COMPARISONS OF WORDS
477
od;
return gens;
end;
22.3
Comparisons of Words
w1 = w2
w1 <> w2
The equality operator = evaluates to true if the two words w1 and w2 are equal and to
false otherwise. The inequality operator <> evaluates to true if the two words w1 and w2
are not equal and to false otherwise.
You can compare words with objects of other types, but they are never equal of course.
gap> a := AbstractGenerator( "a" );;
gap> b := AbstractGenerator( "b" );;
gap> a = b;
false
gap> (a^2*b)^5*b^-1 = a^2*b*a^2*b*a^2*b*a^2*b*a^2;
true
w1
w1
w1
w1
< w2
<= w2
> w2
>= w2
The operators <, <=, >, and => evaluate to true if the word w1 is less than, less than or
equal to, greater than, and greater than or equal to the word w2 .
Words are ordered as follows. One word w1 is considered smaller than another word w2 it
it is shorted, or, if they have the same length, if it is first in the lexicographical ordering
implied by the ordering of the abstract generators. The ordering of abstract generators is
as follows. The abstract generators are ordered with respect to the strings that were passed
to AbstractGenerator when creating these abstract generators. Each abstract generator g
is also smaller than its inverse, but this inverse is smaller than any abstract generator that
is larger than g.
Words can also be compared with objects of other types. Integers, rationals, cyclotomics,
finite field elements, and permutations are smaller than words, everything else is larger.
gap> IdWord a := AbstractGenerator("a");;
gap> b := AbstractGenerator("b");;
22.6. LENGTHWORD
479
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> IsWord( w );
true
gap> a := (1,2,3);;
gap> IsWord( a^2 );
false
22.6
LengthWord
LengthWord( w )
LengthWord returns the length of the word w , i.e., the number of letters in the word.
gap> a := AbstractGenerator("a");;
gap> b := AbstractGenerator("b");;
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> LengthWord( w );
14
gap> LengthWord( a^13 );
13
gap> LengthWord( IdWord );
0
22.7
ExponentSumWord
ExponentSumWord( w , gen )
ExponentSumWord returns the number of times the generator gen appears in the word w
minus the number of times its inverse appears in w . If gen and its inverse do no occur in
w , 0 is returned. gen may also be the inverse of a generator of course.
gap> a := AbstractGenerator("a");;
gap> b := AbstractGenerator("b");;
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> ExponentSumWord( w, a );
10
gap> ExponentSumWord( w, b );
4
gap> ExponentSumWord( (a*b*a^-1)^3, a );
0
gap> ExponentSumWord( (a*b*a^-1)^3, b^-1 );
-3
22.8
Subword
Subword( w , from, to )
Subword returns the subword of the word w that begins at position from and ends at position
to. from and to must be positive integers. Indexing is done with origin 1.
480
CHAPTER 22. WORDS IN ABSTRACT GENERATORS
gap> a := AbstractGenerator("a");;
gap> b := AbstractGenerator("b");;
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> Subword( w, 5, 8 );
a*b*a^2
22.9
PositionWord
PositionWord( w , sub, from )
PositionWord returns the position of the first occurrence of the word sub in the word w
starting at position from. If there is no such occurrence, false is returned. from must be
a positive integer. Indexing is done with origin 1.
In other words, PositionWord(w ,sub,from) returns the smallest integer i larger than or
equal to from such that Subword( w , i , i +LengthWord(sub)-1 ) = sub (see 22.8).
gap> a := AbstractGenerator("a");;
gap> b := AbstractGenerator("b");;
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> PositionWord( w, a^2*b, 2 );
4
gap> PositionWord( w, a*b^2, 2 );
false
22.10
SubstitutedWord
SubstitutedWord( w , from, to, by )
SubstitutedWord returns a new word where the subword of the word w that begins at
position from and ends at position to is replaced by the word by. from and to must be
positive integers. Indexing is done with origin 1.
In other words SubstitutedWord(w ,from,to,by) is the word Subword(w ,1,from-1) * by
* Subword(w ,to+1,LengthWord(w ) (see 22.8).
gap> a := AbstractGenerator("a");;
gap> b := AbstractGenerator("b");;
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> SubstitutedWord(w,5,8,b^-1);
a^2*b*a^3*b*a^2
22.11
EliminatedWord
EliminatedWord( word , gen, by )
EliminatedWord returns a new word where each occurrence of the generator gen is replaced
by the word by.
gap> a := AbstractGenerator("a");;
22.12. MAPPEDWORD
481
gap> b := AbstractGenerator("b");;
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> EliminatedWord( w, b, b^2 );
a^2*b^2*a^2*b^2*a^2*b^2*a^2*b^2*a^2
22.12
MappedWord
MappedWord( w , gens, imgs )
MappedWord returns the new group element that is obtained by replacing each occurrence
of a generator gen in the list of generators gens by the corresponding group element img
in the list of group elements imgs. The lists gens and imgs must of course have the same
length.
gap> a := AbstractGenerator("a");;
gap> b := AbstractGenerator("b");;
gap> w := (a^2*b)^5*b^-1;
a^2*b*a^2*b*a^2*b*a^2*b*a^2
gap> MappedWord( w, [a,b], [(1,2,3),(1,2)] );
(1,3,2)
If the images in imgs are all words, and some of them are equal to the corresponding
generators in gens, then those may be omitted.
gap> MappedWord( w, [a], [a^2] );
a^4*b*a^4*b*a^4*b*a^4*b*a^4
Note that the special case that the list gens and imgs have only length 1 is handled more
efficiently by EliminatedWord (see 22.11).
482
CHAPTER 22. WORDS IN ABSTRACT GENERATORS
Chapter 23
Finitely Presented Groups
A finitely presented group is a group generated by a set of abstract generators subject
to a set of relations that these generators satisfy. Each group can be represented as finitely
presented group.
A finitely presented group is constructed as follows. First create an appropriate free group
(see 23.1). Then create the finitely presented group as a factor of this free group by the
relators.
gap> F2 := FreeGroup( "a", "b" );
Group( a, b )
gap> A5 := F2 / [ F2.1^2, F2.2^3, (F2.1*F2.2)^5 ];
Group( a, b )
gap> Size( A5 );
60
gap> a := A5.1;; b := A5.2;;
gap> Index( A5, Subgroup( A5, [ a*b ] ) );
12
Note that, even though the generators print with the names given to FreeGroup, no variables of that name are defined. That means that the generators must be entered as freegroup.number and fp-group.number .
Note that the generators of the free group are different from the generators of the finitely
presented group (even though they print with the same name). That means that words in
the generators of the free group are not elements of the finitely presented group.
Note that the relations are entered as relators, i.e., as words in the generators of the free
group. To enter an equation use the quotient operator, i.e., for the relation ab = ab you
have to enter a^b/(a*b).
You must not change the relators of a finitely presented group at all.
The elements of a finitely presented group are words. There is one fundamental problem with
this. Different words can correspond to the same element in a finitely presented group. For
example in the group A5 defined above, a and a^3 are actually the same element. However,
a is not equal to a^3 (in the sense that a = a^3 is false). This leads to the following
anomaly: a^3 in A5 is true, but a^3 in Elements(A5) is false. Some set and group
483
484
CHAPTER 23. FINITELY PRESENTED GROUPS
functions will not work correctly because of this problem. You should therefore
only use the functions mentioned in 23.2 and 23.3.
The first section in this chapter describes the function FreeGroup that creates a free group
(see 23.1). The next sections describe which set theoretic and group functions are implemented specially for finitely presented groups and how they work (see 23.2 and 23.3). The
next section describes the basic function CosetTableFpGroup that is used by most other
functions for finitely presented groups (see 23.4). The next section describes how you can
compute a permutation group that is a homomorphic image of a finitely presented group
(see 23.5). The final section describes the function that finds all subgroups of a finitely
presented group of small index (see 23.7).
23.1
FreeGroup
FreeGroup( n )
FreeGroup( n, string )
FreeGroup( name1 , name2 ..
)
FreeGroup returns the free group on n generators. The generators are displayed as string.1,
string.2, ..., string.n. If string is missing it defaults to "f". If string is the name of the
variable that you use to refer to the group returned by FreeGroup you can also enter the
generators as string.i .
gap> F2 := FreeGroup( 2, "A5" );;
gap> A5 := F2 / [ F2.1^2, F2.2^3, (F2.1*F2.2)^5 ];
Group( A5.1, A5.2 )
gap> Size( A5 );
60
gap> F2 := FreeGroup( "a", "b" );;
gap> D8 := F2 / [ F2.1^4, F2.2^2, F2.1^F2.2 / F2.1 ];
Group( a, b )
gap> a := D8.1;; b := D8.2;;
gap> Index( D8, Subgroup( D8, [ a ] ) );
2
23.2
Set Functions for Finitely Presented Groups
Finitely presented groups are domains, thus in principle all set theoretic functions are applicable to them (see chapter 4). However because words that are not equal may denote
the same element of a finitely presented group many of them will not work correctly. This
sections describes which set theoretic functions are implemented specially for finitely presented groups and how they work. You should not use the set theoretic functions that are
not mentioned in this section.
The general information that enables GAP3 to work with a finitely presented group G is
a coset table (see 23.4). Basically a coset table is the permutation representation of the
finitely presented group on the cosets of a subgroup (which need not be faithful if the
subgroup has a nontrivial core). Most of the functions below use the regular representation
of G, i.e., the coset table of G over the trivial subgroup. Such a coset table is computed by
a method called coset enumeration.
23.3. GROUP FUNCTIONS FOR FINITELY PRESENTED GROUPS
485
Size( G )
The size is simply the degree of the regular representation of G.
w in G
A word w lies in a parent group G if all its letters are among the generators of G.
w in H
To test whether a word w lies in a subgroup H of a finitely presented group G, GAP3
computes the coset table of G over H . Then it tests whether the permutation one gets by
replacing each generator of G in w with the corresponding permutation is trivial.
Elements( G )
The elements of a finitely presented group are computed by computing the regular representation of G. Then for each point p GAP3 adds the smallest word w that, when viewed
as a permutation, takes 1 to p to the set of elements. Note that this implies that each word
in the set returned is the smallest word that denotes an element of G.
Elements( H )
The elements of a subgroup H of a finitely presented group G are computed by computing
the elements of G and returning those that lie in H .
Intersection( H1 , H2 )
The intersection of two subgroups H1 and H2 of a finitely presented group G is computed
as follows. First GAP3 computes the coset tables of G over H1 and H2 . Then it computes
the tensor product of those two permutation representations. The coset table of the intersection is the transitive constituent of 1 in this tensored permutation representation. Finally
GAP3 computes a set of Schreier generators for the intersection by performing another coset
enumeration using the already complete coset table. The intersection is returned as the
subgroup generated by those Schreier generators.
23.3
Group Functions for Finitely Presented Groups
Finitely presented groups are after all groups, thus in principle all group functions are
applicable to them (see chapter 7). However because words that are not equal may denote
the same element of a finitely presented group many of them will not work correctly. This
sections describes which group functions are implemented specially for finitely presented
groups and how they work. You should not use the group functions that are not mentioned
in this section.
The general information that enables GAP3 to work with a finitely presented group G is
a coset table (see 23.4). Basically a coset table is the permutation representation of the
finitely presented group on the cosets of a subgroup (which need not be faithful if the
subgroup has a nontrivial core). Most of the functions below use the regular representation
486
CHAPTER 23. FINITELY PRESENTED GROUPS
of G, i.e., the coset table of G over the trivial subgroup. Such a coset table is computed by
a method called coset enumeration.
Order( G, g )
The order of an element g is computed by translating the element into the regular permutation representation and computing the order of this permutation (which is the length of
the cycle of 1).
Index( G, H )
The index of a subgroup H in a finitely presented group G is simply the degree of the
permutation representation of the group G on the cosets of H .
Normalizer( G, H )
The normalizer of a subgroup H of a finitely presented group G is the union of those cosets
of H in G that are fixed by all the generators of H when viewed as permutations in the
permutation representation of G on the cosets of H . The normalizer is returned as the
subgroup generated by the generators of H and representatives of such cosets.
CommutatorFactorGroup( G )
The commutator factor group of a finitely presented group G is returned as a new finitely
presented group. The relations of this group are the relations of G plus the commutator of
all the pairs of generators of G.
AbelianInvariants( G )
The abelian invariants of a abelian finitely presented group (e.g., a commutator factor group
of an arbitrary finitely presented group) are computed by building the relation matrix of G
and transforming this matrix to diagonal form with ElementaryDivisorsMat (see 34.23).
AbelianInvariantsSubgroupFpGroup( G, H )
AbelianInvariantsSubgroupFpGroup( G, cosettable )
This function is equivalent to AbelianInvariantsSubgroupFpGroupRrs below, but note
that there is an alternative function, AbelianInvariantsSubgroupFpGroupMtc.
AbelianInvariantsSubgroupFpGroupRrs( G, H )
AbelianInvariantsSubgroupFpGroupRrs( G, cosettable )
AbelianInvariantsSubgroupFpGroupRrs returns the invariants of the commutator factor
group H/H’ of a subgroup H of a finitely presented group G. They are computed by
first applying an abelianized Reduced Reidemeister-Schreier procedure (see 23.11) to construct a relation matrix of H/H’ and then transforming this matrix to diagonal form with
ElementaryDivisorsMat (see 34.23).
As second argument, you may provide either the subgroup H itself or its coset table in G.
23.3. GROUP FUNCTIONS FOR FINITELY PRESENTED GROUPS
487
AbelianInvariantsSubgroupFpGroupMtc( G, H )
AbelianInvariantsSubgroupFpGroupMtc returns the invariants of the commutator factor
group H/H’ of a subgroup H of a finitely presented group G. They are computed by applying
an abelianized Modified Todd-Coxeter procedure (see 23.11) to construct a relation matrix
of H/H’ and then transforming this matrix to diagonal form with ElementaryDivisorsMat
(see 34.23).
AbelianInvariantsNormalClosureFpGroup( G, H )
This function is equivalent to AbelianInvariantsNormalClosureFpGroupRrs below.
AbelianInvariantsNormalClosureFpGroupRrs( G, H )
AbelianInvariantsNormalClosureFpGroupRrs returns the invariants of the commutator
factor group N/N’ of the normal closure N a subgroup H of a finitely presented group G.
They are computed by first applying an abelianized Reduced Reidemeister-Schreier procedure (see 23.11) to construct a relation matrix of N/N’ and then transforming this matrix
to diagonal form with ElementaryDivisorsMat (see 34.23).
gap> # Define the Coxeter group E1.
gap> F5 := FreeGroup( "x1", "x2", "x3", "x4", "x5" );;
gap> E1 := F5 / [ F5.1^2, F5.2^2, F5.3^2, F5.4^2, F5.5^2,
> ( F5.1 * F5.3 )^2, ( F5.2 * F5.4 )^2, ( F5.1 * F5.2 )^3,
> ( F5.2 * F5.3 )^3, ( F5.3 * F5.4 )^3, ( F5.4 * F5.1 )^3,
> ( F5.1 * F5.5 )^3, ( F5.2 * F5.5 )^2, ( F5.3 * F5.5 )^3,
> ( F5.4 * F5.5 )^2,
> ( F5.1 * F5.2 * F5.3 * F5.4 * F5.3 * F5.2 )^2 ];;
gap> x1:=E1.1;; x2:=E1.2;; x3:=E1.3;; x4:=E1.4;; x5:=E1.5;;
gap> # Get normal subgroup generators for B1.
gap> H := Subgroup( E1, [ x5 * x2^-1, x5 * x4^-1 ] );;
gap> # Compute the abelian invariants of B1/B1’.
gap> A := AbelianInvariantsNormalClosureFpGroup( E1, H );
[ 2, 2, 2, 2, 2, 2, 2, 2 ]
gap> # Compute a presentation for B1.
gap> P := PresentationNormalClosure( E1, H );
<< presentation with 18 gens and 46 rels of total length 132 >>
gap> SimplifyPresentation( P );
#I there are 8 generators and 30 relators of total length 148
gap> B1 := FpGroupPresentation( P );
Group( _x1, _x2, _x3, _x4, _x6, _x7, _x8, _x11 )
gap> # Compute normal subgroup generators for B1’.
gap> gens := B1.generators;;
gap> numgens := Length( gens );;
gap> comms := [ ];;
gap> for i in [ 1 .. numgens - 1 ] do
>
for j in [i+1 .. numgens ] do
>
Add( comms, Comm( gens[i], gens[j] ) );
>
od;
488
CHAPTER 23. FINITELY PRESENTED GROUPS
>
gap>
gap>
gap>
[ 0,
od;
# Compute the abelian invariants of B1’/B1".
K := Subgroup( B1, comms );;
A := AbelianInvariantsNormalClosureFpGroup( B1, K );
0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2 ]
The prededing calculation for B1 and a similar one for B0 have been used to prove that
B10 /B100 ∼
= Z29 × Z 3 and B00 /B000 ∼
= Z291 × Z 27 as stated in Proposition 5 in [FJNT95].
The following functions are not implemented specially for finitely presented groups, but they
work nevertheless. However, you probably should not use them for larger finitely presented
groups.
Core( G, U )
SylowSubgroup( G, p )
FittingSubgroup( G )
23.4
CosetTableFpGroup
CosetTableFpGroup( G, H )
CosetTableFpGroup returns the coset table of the finitely presented group G on the cosets
of the subgroup H .
Basically a coset table is the permutation representation of the finitely presented group on
the cosets of a subgroup (which need not be faithful if the subgroup has a nontrivial core).
Most of the set theoretic and group functions use the regular representation of G, i.e., the
coset table of G over the trivial subgroup.
The coset table is returned as a list of lists. For each generator of G and its inverse the table
contains a generator list. A generator list is simply a list of integers. If l is the generator
list for the generator g and l [i ] = j then generator g takes the coset i to the coset j by
multiplication from the right. Thus the permutation representation of G on the cosets of
H is obtained by applying PermList to each generator list (see 20.9). The coset table is
standardized, i.e., the cosets are sorted with respect to the smallest word that lies in each
coset.
gap> F2 := FreeGroup( "a", "b" );
Group( a, b )
gap> A5 := F2 / [ F2.1^2, F2.2^3, (F2.1*F2.2)^5 ];
Group( a, b )
gap> CosetTableFpGroup( A5,
>
Subgroup( A5, [ A5.1, A5.2*A5.1*A5.2*A5.1*A5.2^-1 ] ) );
[ [ 1, 3, 2, 5, 4 ],
[ 1, 3, 2, 5, 4 ],
# inverse of above, A5.1 is an involution
[ 2, 4, 3, 1, 5 ],
[ 4, 1, 3, 2, 5 ] ]
# inverse of above
gap> List( last, PermList );
[ (2,3)(4,5), (2,3)(4,5), (1,2,4), (1,4,2) ]
The coset table is computed by a method called coset enumeration. A Felsch strategy
is used to decide how to define new cosets.
23.5. OPERATIONCOSETSFPGROUP
489
The variable CosetTableFpGroupDefaultLimit determines for how many cosets the table
has initially room. CosetTableFpGroup will automatically extend this table if need arises,
but this is an expensive operation. Thus you should set CosetTableFpGroupDefaultLimit
to the number of cosets that you expect will be needed at most. However you should not
set it too high, otherwise too much space will be used by the coset table.
The variable CosetTableFpGroupDefaultMaxLimit determines the maximal size of the coset
table. If a coset enumeration reaches this limit it signals an error and enters the breakloop.
You can either continue or quit the computation from there. Setting the limit to 0 allows
arbitrary large coset tables.
23.5
OperationCosetsFpGroup
OperationCosetsFpGroup( G, H )
OperationCosetsFpGroup returns the permutation representation of the finitely presented
group G on the cosets of the subgroup H as a permutation group. Note that this permutation
representation is faithful if and only if H has a trivial core in G.
gap> F2 := FreeGroup( "a", "b" );
Group( a, b )
gap> A5 := F2 / [ F2.1^2, F2.2^3, (F2.1*F2.2)^5 ];
Group( a, b )
gap> OperationCosetsFpGroup( A5,
>
Subgroup( A5, [ A5.1, A5.2*A5.1*A5.2*A5.1*A5.2^-1 ] ) );
Group( (2,3)(4,5), (1,2,4) )
gap> Size( last );
60
OperationCosetsFpGroup simply calls CosetTableFpGroup, applies PermList to each row
of the table, and returns the group generated by those permutations (see 23.4, 20.9).
23.6
IsIdenticalPresentationFpGroup
IsIdenticalPresentationFpGroup( G, H )
IsIdenticalPresentationFpGroup returns true if the presentations of the parent groups
G and H are identical and false otherwise.
Two presentations are considered identical if the have the same number of generators, i.e.,
G is generated by g1 ... gn and H by h1 ... hn, and if the set of relators of G stored in
G.relators is equal to the set of relators of H stored in H .relators after replacing hi
by gi in these words.
gap> F2 := FreeGroup(2);
Group( f.1, f.2 )
gap> g := F2 / [ F2.1^2 / F2.2 ];
Group( f.1, f.2 )
gap> h := F2 / [ F2.1^2 / F2.2 ];
Group( f.1, f.2 )
gap> g = h;
false
gap> IsIdenticalPresentationFpGroup( g, h );
true
490
CHAPTER 23. FINITELY PRESENTED GROUPS
23.7
LowIndexSubgroupsFpGroup
LowIndexSubgroupsFpGroup( G, H , index )
LowIndexSubgroupsFpGroup( G, H , index , excluded )
LowIndexSubgroupsFpGroup returns a list of representatives of the conjugacy classes of
subgroups of the finitely presented group G that contain the subgroup H of H and that
have index less than or equal to index .
The function provides some intermediate output if InfoFpGroup2 has been set to Print (its
default value is Ignore).
If the optional argument excluded has been specified, then it is expected to be a list of words
in the generators of G, and LowIndexSubgroupsFpGroup returns only those subgroups of
index at most index that contain H , but do not contain any conjugate of any of the group
elements defined by these words.
gap> F2 := FreeGroup( "a", "b" );
Group( a, b )
gap> A5 := F2 / [ F2.1^2, F2.2^3, (F2.1*F2.2)^5 ];
Group( a, b )
gap> A5.name := "A5";;
gap> S := LowIndexSubgroupsFpGroup( A5, TrivialSubgroup( A5 ), 12 );
[ A5, Subgroup( A5, [ a, b*a*b^-1 ] ),
Subgroup( A5, [ a, b*a*b*a^-1*b^-1 ] ),
Subgroup( A5, [ a, b*a*b*a*b^-1*a^-1*b^-1 ] ),
Subgroup( A5, [ b*a^-1 ] ) ]
gap> List( S, H -> Index( A5, H ) );
[ 1, 6, 5, 10, 12 ]
# the indices of the subgroups
gap> List( S, H -> Index( A5, Normalizer( A5, H ) ) );
[ 1, 6, 5, 10, 6 ]
# the lengths of the conjugacy classes
As an example for an application of the optional parameter excluded , we compute all conjugacy classes of torsion free subgroups of index at most 24 in the group G = hx, y, z |
x2 , y 4 , z 3 , (xy)3 , (yz)2 , (xz)3 i. It is know from theory that each torsion element of this group
is conjugate to a power of x, y, z, xy, xz, or yz.
gap> G := FreeGroup( "x", "y", "z" );
Group( x, y, z )
gap> x := G.1;; y := G.2;; z := G.3;;
gap> G.relators := [ x^2, y^4, z^3, (x*y)^3, (y*z)^2, (x*z)^3 ];;
gap> torsion := [ x, y, y^2, z, x*y, x*z, y*z ];;
gap> InfoFpGroup2 := Print;;
gap> lis :=
>
LowIndexSubgroupsFpGroup( G, TrivialSubgroup( G ), 24, torsion );;
#I
class 1 of index 24 and length 8
#I
class 2 of index 24 and length 24
#I
class 3 of index 24 and length 24
#I
class 4 of index 24 and length 24
#I
class 5 of index 24 and length 24
gap> InfoFpGroup2 := Ignore;;
gap> lis;
23.8. PRESENTATION RECORDS
491
[ Subgroup( Group( x, y, z ),
[ x*y*z^-1, z*x*z^-1*y^-1, x*z*x*y^-1*z^-1, y*x*z*y^-1*z^-1 ] ),
Subgroup( Group( x, y, z ),
[ x*y*z^-1, z^2*x^-1*y^-1, x*z*y*x^-1*z^-1 ] ),
Subgroup( Group( x, y, z ),
[ x*y*z^-1, x*z^2*x^-1*y^-1, y^2*x*y^-1*z^-1*x^-1 ] ),
Subgroup( Group( x, y, z ), [ x*y*z^-1, y^3*x^-1*z^-1*x^-1,
y^2*z*x^-1*y^-1 ] ),
Subgroup( Group( x, y, z ), [ y*x*z^-1, x*y*z*y^-1*z^-1,
y^2*z*x^-1*z^-1*x^-1 ] ) ]
The function LowIndexSubgroupsFpGroup finds the requested subgroups by systematically
running through a tree of all potential coset tables of G of length at most index (where
it skips all branches of that tree for which it knows in advance that they cannot provide
new classes of such subgroups). The time required to do this depends, of course, on the
presentation of G, but in general it will grow exponentially with the value of index . So you
should be careful with the choice of index .
23.8
Presentation Records
In GAP3, finitely presented groups are distinguished from group presentations which
are GAP3 objects of their own and which are stored in presentation records. The reason is
that very often presentations have to be changed (e.g. simplified) by Tietze transformations,
but since in these new generators and relators are introduced, all words in the generators
of a finitely presented group would also have to be changed if such a Tietze transformation
were applied to the presentation of a finitely presented group. Therefore, in GAP3 the
presentation defining a finitely presented group is never changed; changes are only allowed
for group presentations which are not considered to define a particular group.
GAP3 offers a bundle of commands to perform Tietze transformations on finite group presentations (see 23.12, 23.13). In order to speed up the respective routines, the relators in
such a presentation record are not represented by ordinary (abstract) GAP3 words, but by
lists of positive or negative generator numbers which we call Tietze words.
The term “Tietze record” will sometimes be used as an alias for “presentation record”.
It occurs, in particular, in certain error messages.
The following two commands can be used to create a presentation record from a finitely
presented group or, vice versa, to create a finitely presented group from a presentation.
PresentationFpGroup( G )
PresentationFpGroup( G, printlevel )
PresentationFpGroup returns a presentation record containing a copy of the presentation
of the given finitely presented group G on the same set of generators.
The optional printlevel parameter can be used to restrict or to extend the amount of output
provided by Tietze transformation commands when being applied to the created presentation
record. The default value 1 is designed for interactive use and implies explicit messages to be
displayed by most of these commands. A printlevel value of 0 will suppress these messages,
whereas a printlevel value of 2 will enforce some additional output.
492
CHAPTER 23. FINITELY PRESENTED GROUPS
FpGroupPresentation( P )
FpGroupPresentation returns a finitely presented group defined by the presentation in the
given presentation record P .
If some presentation record P , say, contains a large presentation, then it would be nasty
to wait for the end of an unintentionally started printout of all of its components (or,
more precisely, of its component P .tietze which contains the essential lists). Therefore,
whenever you use the standard print facilities to display a presentation record, GAP3 will
provide just one line of text containing the number of generators, the number of relators,
and the total length of all relators. Of course, you may use the RecFields and PrintRec
commands to display all components of P .
In addition, you may use the following commands to extract and print different amounts of
information from a presentation record.
TzPrintStatus( P )
TzPrintStatus prints the current state of a presentation record P , i.e., the number of
generators, the number of relators, and the total length of all relators.
If you are working interactively, you can get the same information by just typing P ;
TzPrintGenerators( P )
TzPrintGenerators( P , list )
TzPrintGenerators prints the current list of generators of a presentation record P , providing for each generator its name, the total number of its occurrences in the relators, and, if
that generator is known to be an involution, an appropriate message.
If a list list has been specified as second argument, then it is expected to be a list of the
position numbers of the generators to be printed. list need not be sorted and may contain
duplicate elements. The generators are printed in the order in which and as often as their
numbers occur in list. Position numbers out of range (with respect to the list of generators)
will be ignored.
TzPrintRelators( P )
TzPrintRelators( P , list )
TzPrintRelators prints the current list of relators of a presentation record P .
If a list list has been specified as second argument, then it is expected to be a list of the
position numbers of the relators to be printed. list need not be sorted and may contain
duplicate elements. The relators are printed as Tietze words in the order in which (and as
often as) their numbers occur in list. Position numbers out of range (with respect to the
list of relators) will be ignored.
TzPrintPresentation( P )
TzPrintPresentation prints the current lists of generators and relators and the current
state of a presentation record P . In fact, the command
TzPrintPresentation( P )
23.8. PRESENTATION RECORDS
493
is an abbreviation of the command sequence
Print( "generators:\n" ); TzPrintGenerators( P );
Print( "relators:\n" ); TzPrintRelators( P );
TzPrintStatus( P );
TzPrint( P )
TzPrint( P , list )
TzPrint provides a kind of fast print out for a presentation record P .
Remember that in order to speed up the Tietze transformation routines, each relator in a
presentation record P is internally represented by a list of positive or negative generator
numbers, i.e., each factor of the proper GAP3 word is represented by the position number
of the corresponding generator with respect to the current list of generators, or by the
respective negative number, if the factor is the inverse of a generator which is not known to be
an involution. In contrast to the commands TzPrintRelators and TzPrintPresentation
described above, TzPrint does not convert these lists back to the corresponding GAP3
words.
TzPrint prints the current list of generators, and then for each relator its length and its
internal representation as a list of positive or negative generator numbers.
If a list list has been specified as second argument, then it is expected to be a list of the
position numbers of the relators to be printed. list need not be sorted and may contain
duplicate elements. The relators are printed in the order in which and as often as their
numbers occur in list. Position numbers out of range (with respect to the list of relators)
will be ignored.
There are four more print commands for presentation records which are convenient in the
context of the interactive Tietze transformation commands:
TzPrintGeneratorImages( P )
See 23.13.
TzPrintLengths( P )
See 23.13.
TzPrintPairs( P )
TzPrintPairs( P , n )
See 23.13.
TzPrintOptions( P )
See 23.13.
Moreover, there are two functions which allow to convert abstract words to Tietze words or
Tietze words to abstract words.
TietzeWordAbstractWord( word , generators )
494
CHAPTER 23. FINITELY PRESENTED GROUPS
Let generators be a list of abstract generators and word an abstract word in these generators.
The function TietzeWordAbstractWord returns the corresponding (reduced) Tietze word.
gap> F := FreeGroup( "a", "b", "c" );
Group( a, b, c )
gap> tzword := TietzeWordAbstractWord(
> Comm(F.1,F.2) * (F.3^2 * F.2)^-1, F.generators );
[ -1, -2, 1, -3, -3 ]
AbstractWordTietzeWord( word , generators )
Let generators be a list of abstract generators and word a Tietze word in these generators.
The function AbstractWordTietzeWord returns the corresponding abstract word.
gap> AbstractWordTietzeWord( tzword, F.generators );
a^-1*b^-1*a*c^-2
Save( file, P , name )
The function Save allows to save a presentation and to recover it in a later GAP3 session.
Let P be a presentation, and let file and name be strings denoting a file name and a variable
name, respectively. The function Save generates a new file file and writes P and name to
that file in such a way that a copy of P can be reestablished by just reading the file with
the function Read. This copy of P will be assigned to a variable called name.
Warning: It is not guaranteed that the functions Save and Read work properly if the presentation record P contains additional, user defined components. For instance, components
involving abstract words cannot be read in again as soon as the associated generators are
not available any more.
Example.
gap> F2 := FreeGroup( "a", "b" );;
gap> G := F2 / [ F2.1^2, F2.2^7, Comm(F2.1,F2.1^F2.2),
>
Comm(F2.1,F2.1^(F2.2^2))*(F2.1^F2.2)^-1 ];
Group( a, b )
gap> a := G.1;; b := G.2;;
gap> P := PresentationFpGroup( G );
<< presentation with 2 gens and 4 rels of total length 30 >>
gap> TzPrintGenerators( P );
#I 1. a
11 occurrences
involution
#I 2. b
19 occurrences
gap> TzPrintRelators( P );
#I 1. a^2
#I 2. b^7
#I 3. a*b^-1*a*b*a*b^-1*a*b
#I 4. a*b^-2*a*b^2*a*b^-2*a*b*a*b
gap> TzPrint( P );
#I generators: [ a, b ]
#I relators:
#I 1. 2 [ 1, 1 ]
23.9. CHANGING PRESENTATIONS
495
#I 2. 7 [ 2, 2, 2, 2, 2, 2, 2 ]
#I 3. 8 [ 1, -2, 1, 2, 1, -2, 1, 2 ]
#I 4. 13 [ 1, -2, -2, 1, 2, 2, 1, -2, -2, 1, 2, 1, 2 ]
gap> TzPrintStatus( P );
#I there are 2 generators and 4 relators of total length 30
gap> Save( "checkpoint", P, "P0" );
gap> Read( "checkpoint" );
#I presentation record P0 read from file
gap> P0;
<< presentation with 2 gens and 4 rels of total length 30 >>
23.9
Changing Presentations
The commands described in this section can be used to change the presentation in a presentation record. Note that, in general, they will change the isomorphism type of the group
defined by the presentation. Hence, though they sometimes are called as subroutines by
Tietze transformations commands like TzSubstitute (see 23.13), they do not perform Tietze transformations themselves.
AddGenerator( P )
AddGenerator( P , generator )
AddGenerator adds a new generator to the list of generators.
If you don’t specify a second argument, then AddGenerator will define a new abstract
generator xi and save it in a new component P .i of the given presentation record where
i is the least positive integer which has not yet been used as a generator number. Though
this new generator will be printed as xi , you will have to use the external variable P .i if
you want to access it.
If you specify a second argument, then generator must be an abstract generator which does
not yet occur in the presentation. AddGenerator will add it to the presentation and save it
in a new component P .i in the same way as described for xi above.
AddRelator( P , word )
AddRelator adds the word word to the list of relators. word must be a word in the generators
of the given presentation.
RemoveRelator( P , n )
RemoveRelator removes the nth relator and then resorts the list of relators in the given
presentation record P .
23.10
Group Presentations
In section 23.8 we have described the funtion PresentationFpGroup which supplies a presentation record for a finitely presented group. The following function can be used to compute
a presentation record for a concrete (e. g. permutation or matrix) group.
496
CHAPTER 23. FINITELY PRESENTED GROUPS
PresentationViaCosetTable( G )
PresentationViaCosetTable( G, F , words )
PresentationViaCosetTable constructs a presentation record for the given group G. The
method being used is John Cannon’s relations finding algorithm which has been described
in [Can73] or in [Neu82].
In its first form, if only the group G has been specified, it applies Cannon’s single stage
algorithm which, by plain element multiplication, computes a coset table of G with respect
to its trivial subgroup and then uses coset enumeration methods to find a defining set of
relators for G.
gap> G := GeneralLinearGroup( 2, 7 );
GL(2,7)
gap> G.generators;
[ [ [ Z(7), 0*Z(7) ], [ 0*Z(7), Z(7)^0 ] ],
[ [ Z(7)^3, Z(7)^0 ], [ Z(7)^3, 0*Z(7) ] ] ]
gap> Size( G );
2016
gap> P := PresentationViaCosetTable( G );
<< presentation with 2 gens and 5 rels of total length 46 >>
gap> TzPrintRelators( P );
#I 1. f.2^3
#I 2. f.1^6
#I 3. f.1*f.2*f.1*f.2*f.1*f.2*f.1*f.2*f.1*f.2*f.1*f.2
#I 4. f.1*f.2*f.1^-1*f.2*f.1*f.2^-1*f.1^-1*f.2*f.1*f.2*f.1^-1*f.2^-1
#I 5. f.1^2*f.2*f.1*f.2*f.1*f.2^-1*f.1^-1*f.2^-1*f.1^3*f.2^-1
The second form allows to call Cannon’s two stage algorithm which first applies the single
stage algorithm to an appropriate subgroup H of G and then uses the resulting relators of
H and a coset table of G with respect to H to find relators of G. In this case the second
argument, F , is assumed to be a free group with the same number of generators as G, and
words is expected to be a list of words in the generators of F which, when being evaluated
in the corresponding generators of G, provide subgroup generators for H .
gap> M12 := MathieuGroup( 12 );;
gap> M12.generators;
[ ( 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11), ( 3, 7,11, 8)( 4,10, 5, 6),
( 1,12)( 2,11)( 3, 6)( 4, 8)( 5, 9)( 7,10) ]
gap> F := FreeGroup( "a", "b", "c" );
Group( a, b, c )
gap> words := [ F.1, F.2 ];
[ a, b ]
gap> P := PresentationViaCosetTable( M12, F, words );
<< presentation with 3 gens and 10 rels of total length 97 >>
gap> G := FpGroupPresentation( P );
Group( a, b, c )
gap> G.relators;
[ c^2, b^4, a*c*a*c*a*c, a*b^-2*a*b^-2*a*b^-2, a^11,
a^2*b*a^-2*b^-2*a*b^-1*a^2*b^-1,
a*b*a^-1*b*a^-1*b^-1*a*b*a^-1*b*a^-1*b^-1,
23.11. SUBGROUP PRESENTATIONS
497
a^2*b*a^2*b^-2*a^-1*b*a^-1*b^-1*a^-1*b^-1,
a^2*b^-1*a^-1*b^-1*a*c*b*c*a*b*a*b, a^3*b*a^2*b*a^-2*c*a*b*a^-1*c*a
]
Before it is returned, the resulting presentation is being simplified by appropriate calls
of the function SimplifyPresentation (see 23.13), but without allowing it to eliminate
any generators. This restriction guarantees that we get a bijection between the list of
generators of G and the list of generators in the presentation. Hence, if the generators of
G are redundant and if you don’t care for the bijection, it may be convenient to apply the
function SimplifyPresentation again.
gap> H := Group(
> [ (2,5,3), (2,7,5), (1,8,4), (1,8,6), (4,8,6), (3,5,7) ], () );;
gap> P := PresentationViaCosetTable( H );
<< presentation with 6 gens and 12 rels of total length 42 >>
gap> SimplifyPresentation( P );
#I there are 4 generators and 10 relators of total length 36
23.11
Subgroup Presentations
PresentationSubgroupRrs(
PresentationSubgroupRrs(
PresentationSubgroupRrs(
PresentationSubgroupRrs(
G,
G,
G,
G,
H )
H , string )
cosettable )
cosettable, string )
PresentationSubgroupRrs returns a presentation record (see 23.8) containing a presentation for the subgroup H of the finitely presented group G. It uses the Reduced ReidemeisterSchreier method to construct this presentation.
As second argument, you may provide either the subgroup H itself or its coset table in G.
The generators in the resulting presentation will be named by string1, string2, ..., the
default string is " x".
The Reduced Reidemeister-Schreier algorithm is a modification of the Reidemeister-Schreier
algorithm of George Havas [Hav74]. It was proposed by Joachim Neubüser and first implemented in 1986 by Andrea Lucchini and Volkmar Felsch in the SPAS system [Leh89b]. Like
George Havas’ Reidemeister-Schreier algorithm, it needs only the presentation of G and a
coset table of H in G to construct a presentation of H .
Whenever you call the PresentationSubgroupRrs command, it checks first whether a coset
table of H in G has already been computed and saved in the subgroup record of H by a
preceding call of some appropriate command like CosetTableFpGroup (see 23.4), Index (see
7.51), or LowIndexSubgroupsFpGroup (see 23.7). Only if the coset table is not yet available,
it is now constructed by PresentationSubgroupRrs which calls CosetTableFpGroup for this
purpose. In this case, of course, a set of generators of H is required, but they will not be
used any more in the subsequent steps.
Next, a set of generators of H is determined by reconstructing the coset table and introducing
in that process as many Schreier generators of H in G as are needed to do a Felsch strategy
coset enumeration without any coincidences. (In general, though containing redundant
generators, this set will be much smaller than the set of all Schreier generators. That’s why
we call the method the Reduced Reidemeister-Schreier.)
498
CHAPTER 23. FINITELY PRESENTED GROUPS
After having constructed this set of primary subgroup generators , say, the coset table is
extended to an augmented coset table which describes the action of the group generators
on coset representatives, i.e., on elements instead of cosets. For this purpose, suitable words
in the (primary) subgroup generators have to be associated to the coset table entries. In
order to keep the lengths of these words short, additional secondary subgroup generators
are introduced as abbreviations of subwords. Their number may be large.
Finally, a Reidemeister rewriting process is used to get defining relators for H from the
relators of G. As the resulting presentation of H is a presentation on primary and secondary
generators, in general you will have to simplify it by appropriate Tietze transformations (see
23.13) or by the DecodeTree command (see 23.14) before you can use it. Therefore it is
returned in the form of a presentation record, P say.
Compared with the Modified Todd-Coxeter method described below, the Reduced Reidemeister-Schreier method (as well as Havas’ original Reidemeister-Schreier program) has the
advantage that it does not require generators of H to be given if a coset table of H in G
is known. This provides a possibility to compute a presentation of the normal closure of a
given subgroup (see the PresentationNormalClosureRrs command below).
As you may be interested not only to get the resulting presentation, but also to know
what the involved subgroup generators are, the function PresentationSubgroupRrs will
also return a list of the primary generators of H as words in the generators of G. It is
provided in form of an additional component P .primaryGeneratorWords of the resulting
presentation record P .
Note however: As stated in the description of the function Save (see 23.8), the function Read
cannot properly recover a component involving abstract generators different from the current
generators when it reads a presentation which has been written to a file by the function Save.
Therefore the function Save will ignore the component P .primaryGeneratorWords if you
call it to write the presentation P to a file. Hence this component will be lost if you read the
presentation back from that file, and it will be left to your own responsibility to remember
what the primary generators have been.
A few examples are given in section 23.13.
PresentationSubgroupMtc(
PresentationSubgroupMtc(
PresentationSubgroupMtc(
PresentationSubgroupMtc(
G,
G,
G,
G,
H )
H , string )
H , printlevel )
H , string, printlevel )
PresentationSubgroupMtc returns a presentation record (see 23.8) containing a presentation for the subgroup H of the finitely presented group G. It uses a Modified Todd-Coxeter
method to construct this presentation.
The generators in the resulting presentation will be named by string1, string2, ..., the
default string is " x".
The optional printlevel parameter can be used to restrict or to extend the amount of output
provided by the PresentationSubgroupMtc command. In particular, by specifying the
printlevel parameter to be 0, you can suppress the output of the DecodeTree command
which is called by the PresentationSubgroupMtc command (see below). The default value
of printlevel is 1.
23.11. SUBGROUP PRESENTATIONS
499
The so called Modified Todd-Coxeter method was proposed, in slightly different forms, by
Nathan S. Mendelsohn and William O. J. Moser in 1966. Moser’s method was proved by
Michael J. Beetham and Colin M. Campbell (see [BC76]). Another proof for a special version
was given by D. H. McLain (see [McL77]). It was generalized to cover a broad spectrum
of different versions (see the survey [Neu82]). Moser’s method was implemented by Harvey
A. Campbell (see [Cam71]. Later, a Modified Todd-Coxeter program was implemented in
St. Andrews by David G. Arrell, Sanjiv Manrai, and Michael F. Worboys (see [AMW82])
and further developed by David G. Arrel and Edmund F. Robertson (see [AR84]) and by
Volkmar Felsch in the SPAS system [Leh89b].
The Modified Todd-Coxeter method performs an enumeration of coset representatives.
It proceeds like an ordinary coset enumeration (see CosetTableFpGroup 23.4), but as the
product of a coset representative by a group generator or its inverse need not be a coset
representative itself, the Modified Todd-Coxeter has to store a kind of correction element
for each coset table entry. Hence it builds up a so called augmented coset table of H in
G consisting of the ordinary coset table and a second table in parallel which contains the
associated subgroup elements.
Theoretically, these subgroup elements could be expressed as words in the given generators
of H , but in general these words tend to become unmanageable because of their enormous
lengths. Therefore, a highly redundant list of subgroup generators is built up starting from
the given (“primary”) generators of H and adding additional (“secondary”) generators
which are defined as abbreviations of suitable words of length two in the preceding generators
such that each of the subgroup elements in the augmented coset table can be expressed as a
word of length at most one in the resulting (primary and secondary) subgroup generators.
Then a rewriting process (which is essentially a kind of Reidemeister rewriting process) is
used to get relators for H from the defining relators of G.
The resulting presentation involves all the primary, but not all the secondary generators
of H . In fact, it contains only those secondary generators which explicitly occur in the
augmented coset table. If we extended this presentation by those secondary generators
which are not yet contained in it as additional generators, and by the definitions of all
secondary generators as additional relators, we would get a presentation of H , but, in
general, we would end up with a large number of generators and relators.
On the other hand, if we avoid this extension, the current presentation will not necessarily define H although we have used the same rewriting process which in the case of the
SubgroupPresentationRrs command computes a defining set of relators for H from an
augmented coset table and defining relators of G. The different behaviour here is caused by
the fact that coincidences may have occurred in the Modified Todd-Coxeter coset enumeration.
To overcome this problem without extending the presentation by all secondary generators,
the SubgroupPresentationMtc command applies the so called tree decoding algorithm
which provides a more economical approach. The reader is strongly recommended to carefully read section 23.14 where this algorithm is described in more detail. Here we will
only mention that this procedure adds many fewer additional generators and relators in a
process which in fact eliminates all secondary generators from the presentation and hence
finally provides a presentation of H on the primary, i.e., the originally given, generators of
H . This is a remarkable advantage of the SubgroupPresentationMtc command compared
to the SubgroupPresentationRrs command. But note that, for some particular subgroup
500
CHAPTER 23. FINITELY PRESENTED GROUPS
H , the Reduced Reidemeister-Schreier method might quite well produce a more concise
presentation.
The resulting presentation is returned in the form of a presentation record, P say.
As the function PresentationSubgroupRrs desribed above (see there for details), the function PresentationSubgroupMtc returns a list of the primary subgroup generators of H in
form of a component P .primaryGeneratorWords. In fact, this list is not very exciting here
because it is just a copy of the list H .generators, however it is needed to guarantee a
certain consistency between the results of the different functions for computing subgroup
presentations.
Though the tree decoding routine already involves a lot of Tietze transformations, we recommend that you try to further simplify the resulting presentation by appropriate Tietze
transformations (see 23.13).
An example is given in section 23.14.
PresentationSubgroup(
PresentationSubgroup(
PresentationSubgroup(
PresentationSubgroup(
G,
G,
G,
G,
H )
H , string )
cosettable )
cosettable, string )
PresentationSubgroup returns a presentation record (see 23.8) containing a presentation
for the subgroup H of the finitely presented group G.
As second argument, you may provide either the subgroup H itself or its coset table in G.
In the case of providing the subgroup H itself as argument, the current GAP3 implementation offers a choice between two different methods for constructing subgroup presentations, namely the Reduced Reidemeister-Schreier and the Modified Todd-Coxeter procedure. You can specify either of them by calling the commands PresentationSubgroupRrs
or PresentationSubgroupMtc, respectively. Further methods may be added in a later GAP3
version. If, in some concrete application, you don’t care for the method to be selected, you
may use the PresentationSubgroup command as a kind of default command. In the present
installation, it will call the Reduced Reidemeister-Schreier method, i.e., it is identical with
the PresentationSubgroupRrs command.
A few examples are given in section 23.13.
PresentationNormalClosureRrs( G, H )
PresentationNormalClosureRrs( G, H , string )
PresentationNormalClosureRrs returns a presentation record (see 23.8), P say, containing
a presentation for the normal closure of the subgroup H of the finitely presented group G.
It uses the Reduced Reidemeister-Schreier method to construct this presentation. This
provides a possibility to compute a presentation for a normal subgroup for which only
“normal subgroup generators”, but not necessarily a full set of generators are known.
The generators in the resulting presentation will be named by string1, string2, ..., the
default string is " x".
PresentationNormalClosureRrs first establishes an intermediate group record for the factor group of G by the normal closure N , say, of H in G. Then it performs a coset enumeration
23.12. SIMPLIFIEDFPGROUP
501
of the trivial subgroup in that factor group. The resulting coset table can be considered as
coset table of N in G, hence a presentation for N can be constructed using the Reduced
Reidemeister-Schreier algorithm as described for the PresentationSubgroupRrs command.
As the function PresentationSubgroupRrs desribed above (see there for details), the function PresentationNormalClosureRrs returns a list of the primary subgroup generators of
N in form of a component P .primaryGeneratorWords.
PresentationNormalClosure( G, H )
PresentationNormalClosure( G, H , string )
PresentationNormalClosure returns a presentation record (see 23.8) containing a presentation for the normal closure of the subgroup H of the finitely presented group G. This
provides a possibility to compute a presentation for a normal subgroup for which only “normal subgroup generators”, but not necessarily a full set of generators are known.
If, in a later release, GAP3 offers different methods for the construction of normal closure
presentations, then PresentationNormalClosure will call one of these procedures as a
kind of default method. At present, however, the Reduced Reidemeister-Schreier algorithm
is the only one implemented so far. Therefore, at present the PresentationNormalClosure
command is identical with the PresentationNormalClosureRrs command described above.
23.12
SimplifiedFpGroup
SimplifiedFpGroup( G )
SimplifiedFpGroup applies Tietze transformations to a copy of the presentation of the given
finitely presented group G in order to reduce it with respect to the number of generators,
the number of relators, and the relator lengths.
SimplifiedFpGroup returns the resulting finitely presented group (which is isomorphic to
G).
gap> F6 := FreeGroup( 6, "G" );;
gap> G := F6 / [ F6.1^2, F6.2^2, F6.4*F6.6^-1, F6.5^2, F6.6^2,
>
F6.1*F6.2^-1*F6.3, F6.1*F6.5*F6.3^-1, F6.2*F6.4^-1*F6.3,
>
F6.3*F6.4*F6.5^-1, F6.1*F6.6*F6.3^-2, F6.3^4 ];;
gap> H := SimplifiedFpGroup( G );
Group( G.1, G.3 )
gap> H.relators;
[ G.1^2, G.1*G.3^-1*G.1*G.3^-1, G.3^4 ]
In fact, the command
H := SimplifiedFpGroup( G );
is an abbreviation of the command sequence
P := PresentationFpGroup( G, 0 );;
SimplifyPresentation( P );
H := FpGroupPresentation( P );
which applies a rather simple-minded strategy of Tietze transformations to the intermediate
presentation record P (see 23.8). If for some concrete group the resulting presentation is
unsatisfying, then you should try a more sophisticated, interactive use of the available Tietze
transformation commands (see 23.13).
502
23.13
CHAPTER 23. FINITELY PRESENTED GROUPS
Tietze Transformations
The GAP3 commands being described in this section can be used to modify a group presentation in a presentation record by Tietze transformations.
In general, the aim of such modifications will be to simplify the given presentation, i.e., to
reduce the number of generators and the number of relators without increasing too much
the sum of all relator lengths which we will call the total length of the presentation.
Depending on the concrete presentation under investigation one may end up with a nice,
short presentation or with a very huge one.
Unfortunately there is no algorithm which could be applied to find the shortest presentation
which can be obtained by Tietze transformations from a given one. Therefore, what GAP3
offers are some lower-level Tietze transformation commands and, in addition, some higherlevel commands which apply the lower-level ones in a kind of default strategy which of
course cannot be the optimal choice for all presentations.
The design of these commands follows closely the concept of the ANU Tietze transformation
program designed by George Havas [Hav69] which has been available from Canberra since
1977 in a stand-alone version implemented by Peter Kenne and James Richardson and later
on revised by Edmund F. Robertson (see [HKRR84], [Rob88]).
In this section, we first describe the higher-level commands SimplifyPresentation, TzGo,
and TzGoGo (the first two of these commands are identical).
Then we describe the lower-level commands TzEliminate, TzSearch, TzSearchEqual, and
TzFindCyclicJoins. They are the bricks of which the preceding higher-level commands
have been composed. You may use them to try alternative strategies, but if you are satisfied
by the performance of TzGo and TzGoGo, then you don’t need them.
Some of the Tietze transformation commands listed so far may eliminate generators and
hence change the given presentation to a presentation on a subset of the given set of generators, but they all do not introduce new generators. However, sometimes you will need to
substitute certain words as new generators in order to improve your presentation. Therefore GAP3 offers the two commands TzSubstitute and TzSubstituteCyclicJoins which
introduce new generators. These commands will be described next.
Then we continue the section with a description of the commands TzInitGeneratorImages
and TzPrintGeneratorImages which can be used to determine and to display the images
or preimages of the involved generators under the isomorphism which is defined by the
sequence of Tietze transformations which are applied to a presentation.
Subsequently we describe some further print commands, TzPrintLengths, TzPrintPairs,
and TzPrintOptions, which are useful if you run the Tietze transformations interactively.
At the end of the section we list the Tietze options and give their default values. These are
parameters which essentially influence the performance of the commands mentioned above.
However, they are not specified as arguments of function calls. Instead, they are associated
to the presentation records: Each presentation record keeps its own set of Tietze option
values in the form of ordinary record components.
SimplifyPresentation( P )
TzGo( P )
23.13. TIETZE TRANSFORMATIONS
503
SimplifyPresentation performs Tietze transformations on a presentation P . It is perhaps
the most convenient of the interactive Tietze transformation commands. It offers a kind of
default strategy which, in general, saves you from explicitly calling the lower-level commands
it involves.
Roughly speaking, SimplifyPresentation consists of a loop over a procedure which involves two phases: In the search phase it calls TzSearch and TzSearchEqual described
below which try to reduce the relator lengths by substituting common subwords of relators,
in the elimination phase it calls the command TzEliminate described below (or, more
precisely, a subroutine of TzEliminate in order to save some administrative overhead) which
tries to eliminate generators that can be expressed as words in the remaining generators.
If SimplifyPresentation succeeds in reducing the number of generators, the number of
relators, or the total length of all relators, then it displays the new status before returning
(provided that you did not set the print level to zero). However, it does not provide any output if all these three values have remained unchanged, even if the TzSearchEqual command
involved has changed the presentation such that another call of SimplifyPresentation
might provide further progress. Hence, in such a case it makes sense to repeat the call
of the command for several times (or to call instead the TzGoGo command which we will
describe next).
As an example we compute a presentation of a subgroup of index 408 in P SL(2, 17).
gap> F2 := FreeGroup( "a", "b" );;
gap> G := F2 / [ F2.1^9, F2.2^2, (F2.1*F2.2)^4, (F2.1^2*F2.2)^3 ];;
gap> a := G.1;; b := G.2;;
gap> H := Subgroup( G, [ (a*b)^2, (a^-1*b)^2 ] );;
gap> Index( G, H );
408
gap> P := PresentationSubgroup( G, H );
<< presentation with 8 gens and 36 rels of total length 111 >>
gap> P.primaryGeneratorWords;
[ b, a*b*a ]
gap> P.protected := 2;;
gap> P.printLevel := 2;;
gap> SimplifyPresentation( P );
#I eliminating _x7 = _x5
#I eliminating _x5 = _x4
#I eliminating _x18 = _x3
#I eliminating _x8 = _x3
#I there are 4 generators and 8 relators of total length 21
#I there are 4 generators and 7 relators of total length 18
#I eliminating _x4 = _x3^-1*_x2^-1
#I eliminating _x3 = _x2*_x1^-1
#I there are 2 generators and 4 relators of total length 14
#I there are 2 generators and 4 relators of total length 13
#I there are 2 generators and 3 relators of total length 9
gap> TzPrintRelators( P );
#I 1. _x1^2
#I 2. _x2^3
#I 3. _x2*_x1*_x2*_x1
504
CHAPTER 23. FINITELY PRESENTED GROUPS
Note that the number of loops over the two phases as well as the number of subword searches
or generator eliminations in each phase are determined by a set of option parameters which
may heavily influence the resulting presentation and the computing time (see Tietze options
below).
TzGo is just another name for the SimplifyPresentation command. It has been introduced
for the convenience of those GAP3 users who are used to that name from the go option of
the ANU Tietze transformation stand-alone program or from the go command in SPAS.
TzGoGo( P )
TzGoGo performs Tietze transformations on a presentation P . It repeatedly calls the TzGo
command until neither the number of generators nor the number of relators nor the total
length of all relators have changed during five consecutive calls of TzGo.
This may remarkably save you time and effort if you handle small presentations, however it
may lead to annoyingly long and fruitless waiting times in case of large presentations.
TzEliminate( P )
TzEliminate( P , gen )
TzEliminate( P , n )
TzEliminate tries to eliminate a generator from a presentation P via Tietze transformations.
Any relator which contains some generator just once can be used to substitute that generator by a word in the remaining generators. If such generators and relators exist, then
TzEliminate chooses a generator for which the product of its number of occurrences and
the length of the substituting word is minimal, and then it eliminates this generator from
the presentation, provided that the resulting total length of the relators does not exceed the
associated Tietze option parameter P .spaceLimit. The default value of P .spaceLimit is
infinity, but you may alter it appropriately (see Tietze options below).
If you specify a generator gen as second argument, then TzEliminate only tries to eliminate
that generator.
If you specify an integer n as second argument, then TzEliminate tries to eliminate up
to n generators. Note that the calls TzEliminate( P ) and TzEliminate( P , 1 ) are
equivalent.
TzSearch( P )
TzSearch performs Tietze transformations on a presentation P . It tries to reduce the relator
lengths by substituting common subwords of relators by shorter words.
The idea is to find pairs of relators r1 and r2 of length l1 and l2 , respectively, such that
l1 ≤ l2 and r1 and r2 coincide (possibly after inverting or conjugating one of them) in some
maximal subword w, say, of length greater than l1 /2, and then to substitute each copy of
w in r2 by the inverse complement of w in r1 .
Two of the Tietze option parameters which are listed at the end of this section may strongly
influence the performance and the results of the TzSearch command. These are the parameters P .saveLimit and P .searchSimultaneous. The first of them has the following
effect.
23.13. TIETZE TRANSFORMATIONS
505
When TzSearch has finished its main loop over all relators, then, in general, there are
relators which have changed and hence should be handled again in another run through the
whole procedure. However, experience shows that it really does not pay to continue this
way until no more relators change. Therefore, TzSearch starts a new loop only if the loop
just finished has reduced the total length of the relators by at least P .saveLimit per cent.
The default value of P .saveLimit is 10.
To understand the effect of the parameter P .searchSimultaneous, we have to look in more
detail at how TzSearch proceeds.
First, it sorts the list of relators by increasing lengths. Then it performs a loop over this list.
In each step of this loop, the current relator is treated as short relator r1 , and a subroutine
is called which loops over the succeeding relators, treating them as long relators r2 and
performing the respective comparisons and substitutions.
As this subroutine performs a very expensive process, it has been implemented as a C
routine in the GAP3 kernel. For the given relator r1 of length l1 , say, it first determines the
minimal match length l which is l1 /2 + 1, if l1 is even, or (l1 + 1)/2, otherwise. Then it
builds up a hash list for all subwords of length l occurring in the conjugates of r1 or r1−1 ,
and finally it loops over all long relators r2 and compares the hash values of their subwords
of length l against this list. A comparison of subwords which is much more expensive is only
done if a hash match has been found.
To improve the efficiency of this process we allow the subroutine to handle several short
relators simultaneously provided that they have the same minimal match length. If, for
example, it handles n short relators simultaneously, then you save n − 1 loops over the
long relators r2 , but you pay for it by additional fruitless subword comparisons. In general,
you will not get the best performance by always choosing the maximal possible number
of short relators to be handled simultaneously. In fact, the optimal choice of the number
will depend on the concrete presentation under investigation. You can use the parameter
P .searchSimultaneous to prescribe an upper bound for the number of short relators to
be handled simultaneously.
The default value of P .searchSimultaneous is 20.
TzSearchEqual( P )
TzSearchEqual performs Tietze transformations on a presentation P . It tries to alter relators
by substituting common subwords of relators by subwords of equal length.
The idea is to find pairs of relators r1 and r2 of length l1 and l2 , respectively, such that l1
is even, l1 ≤ l2 , and r1 and r2 coincide (possibly after inverting or conjugating one of them)
in some maximal subword w, say, of length at least l1 /2. Let l be the length of w. Then, if
l > l1 /2, the pair is handled as in TzSearch. Otherwise, if l = l1 /2, then TzSearchEqual
substitutes each copy of w in r2 by the inverse complement of w in r1 .
The Tietze option parameter P .searchSimultaneous is used by TzSearchEqual in the
same way as described for TzSearch.
However, TzSearchEqual does not use the parameter P .saveLimit: The loop over the
relators is executed exactly once.
TzFindCyclicJoins( P )
506
CHAPTER 23. FINITELY PRESENTED GROUPS
TzFindCyclicJoins performs Tietze transformations on a presentation P . It searches for
pairs of generators which generate the same cyclic subgroup and eliminates one of the two
generators of each such pair it finds.
More precisely: TzFindCyclicJoins searches for pairs of generators a and b such that
(possibly after inverting or conjugating some relators) the set of relators contains the commutator [a, b], a power an , and a product of the form as bt with s prime to n. For each such
pair, TzFindCyclicJoins uses the Euclidian algorithm to express a as a power of b, and
then it eliminates a.
TzSubstitute( P , word )
TzSubstitute( P , word , string )
There are two forms of the command TzSubstitute. This is the first one. It expects P to
be a presentation and word to be either an abstract word or a Tietze word in the generators
of P . It substitutes the given word as a new generator of P . This is done as follows.
First, TzSubstitute creates a new abstract generator, g say, and adds it to the presentation
P , then it adds a new relator g −1 ·word to P . If a string string has been specified as third
argument, the new generator g will be named by string, otherwise it will get a default name
xi as described with the function AddGenerator (see 23.9).
More precisely: If, for instance, word is an abstract word, a call
TzSubstitute( P, word );
is more or less equivalent to
AddGenerator( P );
g := P.generators[Length( P.generators )];
AddRelator( P, g^-1 * word );
whereas a call
TzSubstitute( P, word, string );
is more or less equivalent to
g := AbstractGenerator( string );
AddGenerator( P, g );
AddRelator( P, g^-1 * word );
The essential difference is, that TzSubstitute, as a Tietze transformation of P , saves and
updates the lists of generator images and preimages if they are being traced under the Tietze
transformations applied to P (see the function TzInitGeneratorImages below), whereas
a call of the function AddGenerator (which does not perform Tietze transformations) will
delete these lists and hence terminate the tracing.
Example.
gap> G := PerfectGroup( 960, 1 );
PerfectGroup(960,1)
gap> P := PresentationFpGroup( G );
<< presentation with 6 gens and 21 rels of total length 84 >>
gap> P.generators;
[ a, b, s, t, u, v ]
23.13. TIETZE TRANSFORMATIONS
gap> TzGoGo( P );
#I there are 3 generators and 10 relators of total
#I there are 3 generators and 10 relators of total
gap> TzPrintGenerators( P );
#I 1. a
31 occurrences
involution
#I 2. b
26 occurrences
#I 3. t
23 occurrences
involution
gap> a := P.generators[1];;
gap> b := P.generators[2];;
gap> TzSubstitute( P, a*b, "ab" );
#I substituting new generator ab defined by a*b
#I there are 4 generators and 11 relators of total
gap> TzGo(P);
#I there are 3 generators and 10 relators of total
gap> TzPrintGenerators( P );
#I 1. a
23 occurrences
involution
#I 2. t
23 occurrences
involution
#I 3. ab
28 occurrences
507
length 81
length 80
length 83
length 74
TzSubstitute( P )
TzSubstitute( P , n )
TzSubstitute( P , n, eliminate )
This is the second form of the command TzSubstitute. It performs Tietze transformations
on the presentation P . Basically, it substitutes a squarefree word of length 2 as a new
generator and then eliminates a generator from the extended generator list. We will describe
this process in more detail.
The parameters n and eliminate are optional. If you specify arguments for them, then n is
expected to be a positive integer, and eliminate is expected to be 0, 1, or 2. The default
values are n = 1 and eliminate = 0.
TzSubstitute first determines the n most frequently occurring squarefree relator subwords
of length 2 and sorts them by decreasing numbers of occurrences. Let ab be the nth word
in that list, and let i be the smallest positive integer which has not yet been used as a
generator number. Then TzSubstitute defines a new generator P .i (see AddGenerator for
details), adds it to the presentation together with a new relator P.i−1 ab, and replaces all
occurrences of ab in the given relators by P .i .
Finally, it eliminates some generator from the extended presentation. The choice of that
generator depends on the actual value of the eliminate parameter:
If eliminate is zero, then the generator to be eliminated is chosen as by the TzEliminate
command. This means that in this case it may well happen that it is the generator P .i just
introduced which is now deleted again so that you do not get any remarkable progress in
transforming your presentation. On the other hand, this procedure guaranties that the total
length of the relators will not be increased by a call of TzSubstitute with eliminate = 0.
Otherwise, if eliminate is 1 or 2, then TzSubstitute eliminates the respective factor of the
substituted word ab, i.e., a for eliminate = 1 or b for eliminate = 2. In this case, it may well
happen that the total length of the relators increases, but sometimes such an intermediate
extension is the only way to finally reduce a given presentation.
508
CHAPTER 23. FINITELY PRESENTED GROUPS
In order to decide which arguments might be appropriate for the next call of TzSubstitute,
often it is helpful to print out a list of the most frequently occurring squarefree relator
subwords of length 2. You may use the TzPrintPairs command described below to do this.
As an example we handle a subgroup of index 266 in the Janko group J1 .
gap> F2 := FreeGroup( "a", "b" );;
gap> J1 := F2 / [ F2.1^2, F2.2^3, (F2.1*F2.2)^7,
>
Comm(F2.1,F2.2)^10, Comm(F2.1,F2.2^-1*(F2.1*F2.2)^2)^6 ];;
gap> a := J1.1;; b := J1.2;;
gap> H := Subgroup ( J1, [ a, b^(a*b*(a*b^-1)^2) ] );;
gap> P := PresentationSubgroup( J1, H );
<< presentation with 23 gens and 82 rels of total length 530 >>
gap> TzGoGo( P );
#I there are 3 generators and 47 relators of total length 1368
#I there are 2 generators and 46 relators of total length 3773
#I there are 2 generators and 46 relators of total length 2570
gap> TzGoGo( P );
#I there are 2 generators and 46 relators of total length 2568
gap> TzGoGo( P );
gap> # We do not get any more progress without substituting a new
gap> # generator
gap> TzSubstitute( P );
#I substituting new generator _x28 defined by _x6*_x23^-1
#I eliminating _x28 = _x6*_x23^-1
gap> # GAP cannot substitute a new generator without extending the
gap> # total length, so we have to explicitly ask for it
gap> TzPrintPairs( P );
#I 1. 504 occurrences of _x6 * _x23^-1
#I 2. 504 occurrences of _x6^-1 * _x23
#I 3. 448 occurrences of _x6 * _x23
#I 4. 448 occurrences of _x6^-1 * _x23^-1
gap> TzSubstitute( P, 2, 1 );
#I substituting new generator _x29 defined by _x6^-1*_x23
#I eliminating _x6 = _x23*_x29^-1
#I there are 2 generators and 46 relators of total length 2867
gap> TzGoGo( P );
#I there are 2 generators and 45 relators of total length 2417
#I there are 2 generators and 45 relators of total length 2122
gap> TzSubstitute( P, 1, 2 );
#I substituting new generator _x30 defined by _x23*_x29^-1
#I eliminating _x29 = _x30^-1*_x23
#I there are 2 generators and 45 relators of total length 2192
gap> TzGoGo( P );
#I there are 2 generators and 42 relators of total length 1637
#I there are 2 generators and 40 relators of total length 1286
#I there are 2 generators and 36 relators of total length 807
#I there are 2 generators and 32 relators of total length 625
#I there are 2 generators and 22 relators of total length 369
23.13. TIETZE TRANSFORMATIONS
509
#I there are 2 generators and 18 relators of total length 213
#I there are 2 generators and 13 relators of total length 141
#I there are 2 generators and 12 relators of total length 121
#I there are 2 generators and 10 relators of total length 101
gap> TzPrintPairs( P );
#I 1. 19 occurrences of _x23 * _x30^-1
#I 2. 19 occurrences of _x23^-1 * _x30
#I 3. 14 occurrences of _x23 * _x30
#I 4. 14 occurrences of _x23^-1 * _x30^-1
gap> # If we save a copy of the current presentation, then later we
gap> # will be able to restart the computation from the current state
gap> P1 := Copy( P );;
gap> # Just for demonstration, let’s make an inconvenient choice
gap> TzSubstitute( P, 3, 1 );
#I substituting new generator _x31 defined by _x23*_x30
#I eliminating _x23 = _x31*_x30^-1
#I there are 2 generators and 10 relators of total length 122
gap> TzGoGo( P );
#I there are 2 generators and 9 relators of total length 105
gap> # The presentation is worse than the one we have saved, so let’s
gap> # restart from that one again
gap> P := Copy( P1 );
<< presentation with 2 gens and 10 rels of total length 101 >>
gap> TzSubstitute( P, 2, 1);
#I substituting new generator _x31 defined by _x23^-1*_x30
#I eliminating _x23 = _x30*_x31^-1
#I there are 2 generators and 10 relators of total length 107
gap> TzGoGo( P );
#I there are 2 generators and 9 relators of total length 84
#I there are 2 generators and 8 relators of total length 75
gap> TzSubstitute( P, 2, 1);
#I substituting new generator _x32 defined by _x30^-1*_x31
#I eliminating _x30 = _x31*_x32^-1
#I there are 2 generators and 8 relators of total length 71
gap> TzGoGo( P );
#I there are 2 generators and 7 relators of total length 56
#I there are 2 generators and 5 relators of total length 36
gap> TzPrintRelators( P );
#I 1. _x32^5
#I 2. _x31^5
#I 3. _x31^-1*_x32^-1*_x31^-1*_x32^-1*_x31^-1*_x32^-1
#I 4. _x31*_x32*_x31^-1*_x32*_x31^-1*_x32*_x31*_x32^-2
#I 5. _x31^-1*_x32^2*_x31*_x32^-1*_x31^2*_x32^-1*_x31*_x32^2
As shown in the preceding example, you can use the Copy command to save a copy of a
presentation record and to restart from it again if you want to try an alternative strategy.
However, this copy will be lost as soon as you finish your current GAP3 session. If you use
the Save command (see 23.8) instead, then you get a permanent copy on a file which you
510
CHAPTER 23. FINITELY PRESENTED GROUPS
can read in again in a later session.
TzSubstituteCyclicJoins( P )
TzSubstituteCyclicJoins performs Tietze transformations on a presentation P . It tries to
find pairs of generators a and b, say, for which among the relators (possibly after inverting
or conjugating some of them) there are the commutator [a, b] and powers am and bn with
mutually prime exponents m and n. For each such pair, it substitutes the product ab as a
new generator, and then it eliminates the generators a and b.
TzInitGeneratorImages( P )
Any sequence of Tietze transformations applied to a presentation record P , starting from an
“old” presentation P1 and ending up with a “new” presentation P2 , defines an isomorphism,
ϕ say, between the groups defined by P1 and P2 , respectively. Sometimes it is desirable
to know the images of the old generators or the preimages of the new generators under
ϕ. The GAP3 Tietze transformations functions are able to trace these images. This is not
automatically done because the involved words may grow to tremendous length, but it will
be done if you explicitly request for it by calling the function TzInitGeneratorImages.
TzInitGeneratorImages initializes three components of P :
P .oldGenerators
This is the list of the old generators. It is initialized by a copy of the current list of
generators, P .generators.
P .imagesOldGens
This will be the list of the images of the old generators as Tietze words in the new
generators. For each generator gi , the i-th entry of the list is initialized by the Tietze
word [i].
P .preImagesNewGens
This will be the list of the preimages of the new generators as Tietze words in the
old generators. For each generator gi , the i-th entry of the list is initialized by the
Tietze word [i].
This means, that P1 is defined to be the current presentation and ϕ to be the identity on
P1 . From now on, the existence of the component P .imagesOldGens will cause the Tietze
transformations functions to update the lists of images and preimages whenever they are
called.
You can reinitialize the tracing of the generator images at any later state by just calling
the function TzInitGeneratorImages again. For, if the above components do already exist
when TzInitGeneratorImages is being called, they will first be deleted and then initialized
again.
There are a few restrictions concerning the tracing of generator images:
In general, the functions AddGenerator, AddRelator, and RemoveRelator described in
section 23.9 do not perform Tietze transformations as they may change the isomorphism
type of the presentation. Therefore, if any of them is called for a presentation in which
generator images and preimages are being traced, it will delete these lists.
23.13. TIETZE TRANSFORMATIONS
511
If the function DecodeTree is called for a presentation in which generator images and preimages are being traced, it will not continue to trace them. Instead, it will delete the corresponding lists, then decode the tree, and finally reinitialize the tracing for the resulting
presentation.
As stated in the description of the function Save (see 23.8), the function Read cannot properly recover a component involving abstract generators different from the current generators
when it reads a presentation which has been written to a file by the function Save. Therefore the function Save will ignore the component P .oldGenerators if you call it to write
the presentation P to a file. Hence this component will be lost if you read the presentation
back from that file, and it will be left to your own responsibility to remember what the old
generators have been.
TzPrintGeneratorImages( P )
If P is a presentation in which generator images and preimages are being traced through
all Tietze transformations applied to P , TzPrintGeneratorImages prints the preimages
of the current generators as Tietze words in the old generators and the images of the old
generators as Tietze words in the current generators.
gap> G := PerfectGroup( 960, 1 );
PerfectGroup(960,1)
gap> P := PresentationFpGroup( G );
<< presentation with 6 gens and 21 rels of total length 84 >>
gap> TzInitGeneratorImages( P );
gap> TzGo( P );
#I there are 3 generators and 11 relators of total length 96
#I there are 3 generators and 10 relators of total length 81
gap> TzPrintGeneratorImages( P );
#I preimages of current generators as Tietze words in the old ones:
#I 1. [ 1 ]
#I 2. [ 2 ]
#I 3. [ 4 ]
#I images of old generators as Tietze words in the current ones:
#I 1. [ 1 ]
#I 2. [ 2 ]
#I 3. [ 1, -2, 1, 3, 1, 2, 1 ]
#I 4. [ 3 ]
#I 5. [ -2, 1, 3, 1, 2 ]
#I 6. [ 1, 3, 1 ]
gap> # Print the old generators as words in the new generators.
gap> gens := P.generators;
[ a, b, t ]
gap> oldgens := P.oldGenerators;
[ a, b, s, t, u, v ]
gap> for i in [ 1 .. Length( oldgens ) ] do
> Print( oldgens[i], " = ",
> AbstractWordTietzeWord( P.imagesOldGens[i], gens ), "\n" );
> od;
512
CHAPTER 23. FINITELY PRESENTED GROUPS
a
b
s
t
u
v
=
=
=
=
=
=
a
b
a*b^-1*a*t*a*b*a
t
b^-1*a*t*a*b
a*t*a
TzPrintLengths( P )
TzPrintLengths prints the list of the lengths of all relators of the given presentation P .
TzPrintPairs( P )
TzPrintPairs( P , n )
TzPrintPairs determines in the given presentation P the n most frequently occurring
squarefree relator subwords of length 2 and prints them together with their numbers of
occurrences. The default value of n is 10. A value n = 0 is interpreted as infinity.
This list is a useful piece of information in the context of using the TzSubstitute command
described above.
TzPrintOptions( P )
Several of the Tietze transformation commands described above are controlled by certain
parameters, the Tietze options, which often have a tremendous influence on their performance and results. However, in each application of the commands, an appropriate choice
of these option parameters will depend on the concrete presentation under investigation.
Therefore we have implemented the Tietze options in such a way that they are associated
to the presentation records: Each presentation record keeps its own set of Tietze option
parameters in the form of ordinary record components. In particular, you may alter the
value of any of these Tietze options by just assigning a new value to the respective record
component.
TzPrintOptions prints the Tietze option components of the specified presentation P .
The Tietze options have the following meaning.
protected
The first P .protected generators in a presentation P are protected from being eliminated by the Tietze transformations functions. There are only two exceptions:
The option P .protected is ignored by the functions TzEliminate(P ,gen) and
TzSubstitute(P ,n,eliminate) because they explicitly specify the generator to be
eliminated. The default value of protected is 0.
eliminationsLimit
Whenever the elimination phase of the TzGo command is entered for a presentation P ,
then it will eliminate at most P .eliminationsLimit generators (except for further
ones which have turned out to be trivial). Hence you may use the eliminationsLimit
parameter as a break criterion for the TzGo command. Note, however, that it is
ignored by the TzEliminate command. The default value of eliminationsLimit is
100.
23.13. TIETZE TRANSFORMATIONS
513
expandLimit
Whenever the routine for eliminating more than 1 generators is called for a presentation P by the TzEliminate command or the elimination phase of the TzGo
command, then it saves the given total length of the relators, and subsequently it
checks the current total length against its value before each elimination. If the total
length has increased to more than P .expandLimit per cent of its original value, then
the routine returns instead of eliminating another generator. Hence you may use the
expandLimit parameter as a break criterion for the TzGo command. The default
value of expandLimit is 150.
generatorsLimit
Whenever the elimination phase of the TzGo command is entered for a presentation
P with n generators, then it will eliminate at most n−P .generatorsLimit generators (except for generators which turn out to be trivial). Hence you may use the
generatorsLimit parameter as a break criterion for the TzGo command. The default
value of generatorsLimit is 0.
lengthLimit
The Tietze transformation commands will never eliminate a generator of a presentation P , if they cannot exclude the possibility that the resulting total length of the
relators exceeds the value of P .lengthLimit. The default value of lengthLimit is
infinity.
loopLimit
Whenever the TzGo command is called for a presentation P , then it will loop over at
most P .loopLimit of its basic steps. Hence you may use the loopLimit parameter as
a break criterion for the TzGo command. The default value of loopLimit is infinity.
printLevel
Whenever Tietze transformation commands are called for a presentation P with
P .printLevel = 0, they will not provide any output except for error messages. If
P .printLevel = 1, they will display some reasonable amount of output which allows
you to watch the progress of the computation and to decide about your next commands. In the case P .printLevel = 2, you will get a much more generous amount
of output. Finally, if P .printLevel = 3, various messages on internal details will be
added. The default value of printLevel is 1.
saveLimit
Whenever the TzSearch command has finished its main loop over all relators of a
presentation P , then it checks whether during this loop the total length of the relators
has been reduced by at least P .saveLimit per cent. If this is the case, then TzSearch
repeats its procedure instead of returning. Hence you may use the saveLimit parameter as a break criterion for the TzSearch command and, in particular, for the
search phase of the TzGo command. The default value of saveLimit is 10.
searchSimultaneous
Whenever the TzSearch or the TzSearchEqual command is called for a presentation
P , then it is allowed to handle up to P .searchSimultaneously short relators simultaneously (see for the description of the TzSearch command for more details). The
choice of this parameter may heavily influence the performance as well as the result of
the TzSearch and the TzSearchEqual commands and hence also of the search phase
of the TzGo command. The default value of searchSimultaneous is 20.
514
CHAPTER 23. FINITELY PRESENTED GROUPS
As soon as a presentation record has been defined, you may alter any of its Tietze option
parameters at any time by just assigning a new value to the respective component.
To demonstrate the effect of the eliminationsLimit parameter, we will give an example in
which we handle a subgroup of index 240 in a group of order 40320 given by a presentation
due to B. H. Neumann. First we construct a presentation of the subgroup, and then we
apply to it the TzGoGo command for different values of the eliminationsLimit parameter
(including the default value 100). In fact, we also alter the printLevel parameter, but this
is only done in order to suppress most of the output. In all cases the resulting presentations
cannot be improved any more by applying the TzGoGo command again, i.e., they are the
best results which we can get without substituting new generators.
gap> F3 := FreeGroup( "a", "b", "c" );;
gap> G := F3 / [ F3.1^3, F3.2^3, F3.3^3, (F3.1*F3.2)^5,
>
(F3.1^-1*F3.2)^5, (F3.1*F3.3)^4, (F3.1*F3.3^-1)^4,
>
F3.1*F3.2^-1*F3.1*F3.2*F3.3^-1*F3.1*F3.3*F3.1*F3.3^-1,
>
(F3.2*F3.3)^3, (F3.2^-1*F3.3)^4 ];;
gap> a := G.1;; b := G.2;; c := G.3;;
gap> H := Subgroup( G, [ a, c ] );;
gap> P := PresentationSubgroup( G, H );
<< presentation with 224 gens and 593 rels of total length 2769 >>
gap> for i in [ 28, 29, 30, 94, 100 ] do
>
Pi := Copy( P );
>
Pi.eliminationsLimit := i;
>
Print( "#I eliminationsLimit set to ", i, "\n" );
>
Pi.printLevel := 0;
>
TzGoGo( Pi );
>
TzPrintStatus( Pi );
>
od;
#I eliminationsLimit set to 28
#I there are 2 generators and 95 relators of total length 10817
#I eliminationsLimit set to 29
#I there are 2 generators and 5 relators of total length 35
#I eliminationsLimit set to 30
#I there are 3 generators and 98 relators of total length 2928
#I eliminationsLimit set to 94
#I there are 4 generators and 78 relators of total length 1667
#I eliminationsLimit set to 100
#I there are 3 generators and 90 relators of total length 3289
Similarly, we demonstrate the influence of the saveLimit parameter by just continuing
the preceding example for some different values of the saveLimit parameter (including its
default value 10), but without changing the eliminationsLimit parameter which keeps its
default value 100.
gap> for i in [ 9, 10, 11, 12, 15 ] do
>
Pi := Copy( P );
>
Pi.saveLimit := i;
>
Print( "#I saveLimit set to ", i, "\n" );
>
Pi.printLevel := 0;
>
TzGoGo( Pi );
23.14. DECODETREE
>
>
#I
#I
#I
#I
#I
#I
#I
#I
#I
#I
23.14
TzPrintStatus( Pi );
od;
saveLimit set to 9
there are 3 generators and
saveLimit set to 10
there are 3 generators and
saveLimit set to 11
there are 3 generators and
saveLimit set to 12
there are 2 generators and
saveLimit set to 15
there are 3 generators and
515
97 relators of total length 5545
90 relators of total length 3289
103 relators of total length 3936
4 relators of total length 21
143 relators of total length 18326
DecodeTree
DecodeTree( P )
DecodeTree eliminates the secondary generators from a presentation P constructed by
the Modified Todd-Coxeter (see PresentationSubgroupMtc) or the Reduced ReidemeisterSchreier procedure (see PresentationSubgroupRrs, PresentationNormalClosureRrs). It
is called automatically by the PresentationSubgroupMtc command where it reduces P to
a presentation on the given subgroup generators.
In order to explain the effect of this command we need to insert a few remarks on the
subgroup presentation commands described in section 23.11. All these commands have the
common property that in the process of constructing a presentation for a given subgroup
H of a finitely presented group G they first build up a highly redundant list of generators
of H which consists of an (in general small) list of “primary” generators, followed by an
(in general large) list of “secondary” generators, and then construct a presentation P0 , say,
on a sublist of these generators by rewriting the defining relators of G. This sublist
contains all primary, but, at least in general, by far not all secondary generators.
The role of the primary generators depends on the concrete choice of the subgroup presentation command. If the Modified Todd-Coxeter method is used, they are just the given
generators of H , whereas in the case of the Reduced Reidemeister-Schreier algorithm they
are constructed by the program.
Each of the secondary generators is defined by a word of length two in the preceding generators and their inverses. By historical reasons, the list of these definitions is called the
subgroup generators tree though in fact it is not a tree but rather a kind of bush.
Now we have to distinguish two cases. If P0 has been constructed by the Reduced Reidemeister-Schreier routines, it is a presentation of H . However, if the Modified Todd-Coxeter
routines have been used instead, then the relators in P0 are valid relators of H , but they do
not necessarily define H . We handle these cases in turn, starting with the latter one.
Also in the case of the Modified Todd-Coxeter method, we could easily extend P0 to a
presentation of H by adding to it all the secondary generators which are not yet contained
in it and all the definitions from the generators tree as additional generators and relators.
Then we could recursively eliminate all secondary generators by Tietze transformations
using the new relators. However, this procedure turns out to be too inefficient to be of
interest.
516
CHAPTER 23. FINITELY PRESENTED GROUPS
Instead, we use the so called tree decoding procedure which has been developed in St. Andrews by David G. Arrell, Sanjiv Manrai, Edmund F. Robertson, and Michael F. Worboys
(see [AMW82], [AR84]). It proceeds as follows.
Starting from P = P0 , it runs through a number of steps in each of which it eliminates the
current “last” generator (with respect to the list of all primary and secondary generators).
If the last generator g, say, is a primary generator, then the procedure finishes. Otherwise it
checks whether there is a relator in the current presentation which can be used to substitute g
by a Tietze transformation. If so, this is done. Otherwise, and only then, the tree definition
of g is added to P as a new relator, and the generators involved are added as new generators
if they have not yet been contained in P . Subsequently, g is eliminated.
Note that the extension of P by one or two new generators is not a Tietze transformation.
In general, it will change the isomorphism type of the group defined by P . However, it
is a remarkable property of this procedure, that at the end, i.e., as soon as all secondary
generators have been eliminated, it provides a presentation P = P1 , say, which defines a
group isomorphic to H . In fact, it is this presentation which is returned by the DecodeTree
command and hence by the PresentationSubgroupMtc command.
If, in the other case, the presentation P0 has been constructed by the Reduced ReidemeisterSchreier algorithm, then P0 itself is a presentation of H , and the corresponding subgroup
presentation command (PresentationSubgroupRrs or PresentationNormalClosureRrs)
just returns P0 .
As mentioned in section 23.11, we recommend further simplifying this presentation before
using it. The standard way to do this is to start from P0 and to apply suitable Tietze
transformations, e.g., by calling the TzGo or TzGoGo commands. This is probably the most
efficient approach, but you will end up with a presentation on some unpredictable set of
generators. As an alternative, GAP3 offers you the DecodeTree command which you can use
to eliminate all secondary generators (provided that there are no space or time problems).
For this purpose, the subgroup presentation commands do not only return the resulting
presentation, but also the tree (together with some associated lists) as a kind of side result
in a component P .tree of the resulting presentation record P .
Note, however, that the tree decoding routines will not work correctly any more on a presentation from which generators have already been eliminated by Tietze transformations.
Therefore, to prevent you from getting wrong results by calling the DecodeTree command
in such a situation, GAP3 will automatically remove the subgroup generators tree from a
presentation record as soon as one of the generators is substituted by a Tietze transformation.
Nevertheless, a certain misuse of the command is still possible, and we want to explicitly
warn you from this. The reason is that the Tietze option parameters described in section
23.13 apply to the DecodeTree command as well. Hence, in case of inadequate values of
these parameters, it may happen that the DecodeTree routine stops before all the secondary
generators have vanished. In this case GAP3 will display an appropriate warning. Then you
should change the respective parameters and continue the process by calling the DecodeTree
command again. Otherwise, if you would apply Tietze transformations, it might happen
because of the convention described above that the tree is removed and that you end up
with a wrong presentation.
After a successful run of the DecodeTree command it is convenient to further simplify the
resulting presentation by suitable Tietze transformations.
23.14. DECODETREE
517
As an example of an explicit call of the DecodeTree command we compute two presentations of a subgroup of order 384 in a group of order 6912. In both cases we use the Reduced
Reidemeister-Schreier algorithm, but in the first run we just apply the Tietze transformations offered by the TzGoGo command with its default parameters, whereas in the second
run we call the DecodeTree command before.
gap> F2 := FreeGroup( "a", "b" );;
gap> G := F2 / [ F2.1*F2.2^2*F2.1^-1*F2.2^-1*F2.1^3*F2.2^-1,
>
F2.2*F2.1^2*F2.2^-1*F2.1^-1*F2.2^3*F2.1^-1 ];;
gap> a := G.1;; b := G.2;;
gap> H := Subgroup( G, [ Comm(a^-1,b^-1), Comm(a^-1,b), Comm(a,b) ] );;
gap> #
gap> # We use the Reduced Reidemeister Schreier method and default
gap> # Tietze transformations to get a presentation for H.
gap> P := PresentationSubgroupRrs( G, H );
<< presentation with 18 gens and 35 rels of total length 169 >>
gap> TzGoGo( P );
#I there are 3 generators and 20 relators of total length 488
#I there are 3 generators and 20 relators of total length 466
gap> # We end up with 20 relators of total length 466.
gap> #
gap> # Now we repeat the procedure, but we call the tree decoding
gap> # algorithm before doing the Tietze transformations.
gap> P := PresentationSubgroupRrs( G, H );
<< presentation with 18 gens and 35 rels of total length 169 >>
gap> DecodeTree( P );
#I there are 9 generators and 26 relators of total length 185
#I there are 6 generators and 23 relators of total length 213
#I there are 3 generators and 20 relators of total length 252
#I there are 3 generators and 20 relators of total length 244
gap> TzGoGo( P );
#I there are 3 generators and 19 relators of total length 168
#I there are 3 generators and 17 relators of total length 138
#I there are 3 generators and 15 relators of total length 114
#I there are 3 generators and 13 relators of total length 96
#I there are 3 generators and 12 relators of total length 84
gap> # This time we end up with a shorter presentation.
As an example of an implicit call of the command via the PresentationSubgroupMtc command we handle a subgroup of index 240 in a group of order 40320 given by a presentation
due to B. H. Neumann.
gap>
gap>
gap>
>
gap>
gap>
gap>
gap>
F3 := FreeGroup( "a", "b", "c" );;
a := F3.1;; b := F3.2;; c := F3.3;;
G := F3 / [ a^3, b^3, c^3, (a*b)^5, (a^-1*b)^5, (a*c)^4,
(a*c^-1)^4, a*b^-1*a*b*c^-1*a*c*a*c^-1, (b*c)^3, (b^-1*c)^4 ];;
a := G.1;; b := G.2;; c := G.3;;
H := Subgroup( G, [ a, c ] );;
InfoFpGroup1 := Print;;
P := PresentationSubgroupMtc( G, H );;
518
CHAPTER 23. FINITELY PRESENTED GROUPS
#I index = 240 total = 4737 max = 4507
#I MTC defined 2 primary and 4446 secondary subgroup generators
#I there are 246 generators and 617 relators of total length 2893
#I calling DecodeTree
#I there are 115 generators and 382 relators of total length 1837
#I there are 69 generators and 298 relators of total length 1785
#I there are 44 generators and 238 relators of total length 1767
#I there are 35 generators and 201 relators of total length 2030
#I there are 26 generators and 177 relators of total length 2084
#I there are 23 generators and 167 relators of total length 2665
#I there are 20 generators and 158 relators of total length 2848
#I there are 20 generators and 148 relators of total length 3609
#I there are 21 generators and 148 relators of total length 5170
#I there are 24 generators and 148 relators of total length 7545
#I there are 27 generators and 146 relators of total length 11477
#I there are 32 generators and 146 relators of total length 18567
#I there are 36 generators and 146 relators of total length 25440
#I there are 39 generators and 146 relators of total length 38070
#I there are 43 generators and 146 relators of total length 54000
#I there are 41 generators and 143 relators of total length 64970
#I there are 8 generators and 129 relators of total length 20031
#I there are 7 generators and 125 relators of total length 27614
#I there are 4 generators and 113 relators of total length 36647
#I there are 3 generators and 108 relators of total length 44128
#I there are 2 generators and 103 relators of total length 35394
#I there are 2 generators and 102 relators of total length 34380
gap> TzGoGo( P );
#I there are 2 generators and 101 relators of total length 19076
#I there are 2 generators and 84 relators of total length 6552
#I there are 2 generators and 38 relators of total length 1344
#I there are 2 generators and 9 relators of total length 94
#I there are 2 generators and 8 relators of total length 86
gap> TzPrintGenerators( P );
#I 1. _x1
43 occurrences
#I 2. _x2
43 occurrences
Chapter 24
Words in Finite Polycyclic
Groups
Ag words are the GAP3 datatype for elements of finite polycyclic groups. Unlike permutations, which are all considered to be elements of one large symmetric group, each ag word
belongs to a specified group. Only ag words of the same finite polycyclic group can be
multiplied.
The following sections describe ag words and their parent groups (see 24.1), how ag words
are compared (see 24.2), functions for ag words and some low level functions for ag words
(starting at 24.3 and 24.9).
For operations and functions defined for group elements in general see 7.2, 7.3.
24.1
More about Ag Words
Let G be a group and G = G0 > G1 > ... > Gn = 1 be a subnormal series of G 6= 1
with finite cyclic factors, i.e., Gi C Gi−1 for all i = 1, ..., n and Gi−1 = hGi , gi i. Then G
will be called an ag group with AG generating sequence or, for short, AG system
(g1 , ..., gn ). Let oi be the order of Gi−1 /Gi . If all o1 , ..., on are primes the system (g1 , ..., gn )
is called a PAG system . With respect to a given AG system the group G has a so called
power-commutator presentation
gi oi
[gi , gj ]
=
=
wii (gi+1 , ..., gn )
wij (gj+1 , ..., gn )
for 1 ≤ i ≤ n,
for 1 ≤ j < i ≤ n
and a so called power-conjugate presentation
gi oi
g
gi j
=
=
wii (gi+1 , ..., gn )
0
wij
(gj+1 , ..., gn )
for 1 ≤ i ≤ n,
for 1 ≤ j < i ≤ n.
For both kinds of presentations we shall use the term AG presentation. Each element g
of G can be expressed uniquely in the form
g = g1ν1 ∗ ... ∗ gnνn
519
for 0 ≤ νi < oi .
520
CHAPTER 24. WORDS IN FINITE POLYCYCLIC GROUPS
We call the composition series G0 > G1 > ... > Gn the AG series of G and define
νi (g) := νi . If νi = 0 for i = 1, ..., k − 1 and νk 6= 0, we call νk the leading exponent and
k the depth of g and denote them by νk =: λ(g) and k =: δ(g). We call ok the relative
order of g.
Each element g of G is called ag word and we say that G is the parent group of g. A parent
group is constructed in GAP3 using AgGroup (see 25.25) or AgGroupFpGroup (see 25.27).
Our standard example in the following sections is the symmetric group of degree 4, defined
by the following sequence of GAP3 statements. You should enter them before running any
example. For details on AbstractGenerators see 22.1.
gap> a := AbstractGenerator( "a" );; # (1,2)
gap> b := AbstractGenerator( "b" );; # (1,2,3)
gap> c := AbstractGenerator( "c" );; # (1,3)(2,4)
gap> d := AbstractGenerator( "d" );; # (1,2)(3,4)
gap> s4 := AgGroupFpGroup( rec(
>
generators := [ a, b, c, d ],
>
relators
:= [ a^2, b^3, c^2, d^2, Comm( b, a ) / b,
>
Comm( c, a ) / d, Comm( d, a ),
>
Comm( c, b ) / ( c*d ), Comm( d, b ) / c,
>
Comm( d, c ) ] ) );
Group( a, b, c, d )
gap> s4.name := "s4";;
gap> a := s4.generators[1];; b := s4.generators[2];;
gap> c := s4.generators[3];; d := s4.generators[4];;
24.2
g
g
g
g
Ag Word Comparisons
< h
<= h
>= h
> h
The operators <, >, <= and >= return true if g is strictly less, strictly greater, not greater,
not less, respectively, than h. Otherwise they return false.
If g and h have a common parent group they are compared with respect to the AG series
of this group. If two ag words have different depths, the one with the higher depth is less
than the other one. If two ag words have the same depth but different leading exponents,
the one with the smaller leading exponent is less than the other one. Otherwise the leading
generator is removed in both ag words and the remaining ag words are compared.
If g and h do not have a common parent group, then the composition lengths of the parent
groups are compared.
You can compare ag words with objects of other types. Field elements, unkowns, permutations and abstract words are smaller than ag words. Objects of other types, i.e., functions,
lists and records are larger.
gap> 123/47 < a;
true
24.3. CENTRALWEIGHT
521
gap> (1,2,3,4) < a;
true
gap> [1,2,3,4] < a;
false
gap> true < a;
false
gap> rec() < a;
false
gap> c < a;
true
gap> a*b < a*b^2;
true
24.3
CentralWeight
CentralWeight( g )
CentralWeight returns the central weight of an ag word g, with respect to the central series
used in the combinatorial collector, as integer.
This presumes that g belongs to a parent group for which the combinatorial collector is
used. See 25.33 for details.
If g is the identity, 0 is returned.
Note that CentralWeight allows records that mimic ag words as arguments.
gap> d8 := AgGroup( Subgroup( s4, [ a, c, d ] ) );
Group( g1, g2, g3 )
gap> ChangeCollector( d8, "combinatorial" );
gap> List( d8.generators, CentralWeight );
[ 1, 1, 2 ]
24.4
CompositionLength
CompositionLength( g )
Let G be the parent group of the ag word g. Then CompositionLength returns the length
of the AG series of G as integer.
Note that CompositionLength allows records that mimic ag words as arguments.
gap> CompositionLength( c );
5
24.5
Depth
Depth( g )
Depth returns the depth of an ag word g with respect to the AG series of its parent group
as integer.
Let G be the parent group of g and G = G0 > ... > Gn = {1} the AG series of G. Let δ be
the maximal positive integer such that g is an element of Gδ−1 . Then δ is the depth of g.
522
CHAPTER 24. WORDS IN FINITE POLYCYCLIC GROUPS
Note that Depth allows record that mimic ag words as arguments.
gap> Depth( a );
1
gap> Depth( d );
4
gap> Depth( a^0 );
5
24.6
IsAgWord
IsAgWord( obj )
IsAgWord returns true if obj , which can be an arbitrary object, is an ag word and false
otherwise.
gap> IsAgWord( 5 );
false
gap> IsAgWord( a );
true
24.7
LeadingExponent
LeadingExponent( g )
LeadingExponent returns the leading exponent of an ag word g as integer.
Let G be the parent group of g and (g1 , ..., gn ) the AG system of G and let oi be the relative
order of gi . Then the element g can be expressed uniquely in the form g1ν1 ∗ ... ∗ gnνn for
integers νi such that 0 ≤ νi < oi . The leading exponent of g is the first nonzero νi .
If g is the identity 0 is returned.
Although ExponentAgWord( g, Depth( g ) ) returns the leading exponent of g, too, this
function is faster and is able to handle the identity.
Note that LeadingExponent allows records that mimic ag words as arguments.
gap> LeadingExponent( a * b^2 * c^2 * d );
1
gap> LeadingExponent( b^2 * c^2 * d );
2
24.8
RelativeOrder
RelativeOrder( g )
RelativeOrder returns the relative order of an ag word g as integer.
Let G be the parent group of g and G = G0 > ... > Gn = {1} the AG series of G. Let δ be
the maximal positive integer such that g is an element of Gδ−1 . The relative order of g
is the index of Gδ+1 in Gδ , that is the order of the factor group Gδ /Gδ+1 .
If g is the identity 1 is returned.
Note that RelativeOrder allows records that mimic agwords as arguments.
24.9. CANONICALAGWORD
523
gap> RelativeOrder( a );
2
gap> RelativeOrder( b );
3
gap> RelativeOrder( b^2 * c * d );
3
24.9
CanonicalAgWord
CanonicalAgWord( U , g )
Let U be an ag group with parent group G, let g be an element of G. Let (u1 , ..., um ) be
an induced generating system of U and (g1 , ..., gn ) be a canonical generating system of G.
Then CanonicalAgWord returns a word x = g ∗ u = gie11 ∗ ... ∗ giekk such that u ∈ U and no
ij is equal to the depth of any generator ul .
gap> v4 := MergedCgs( s4, [ a*b^2, c*d ] );
Subgroup( s4, [ a*b^2, c*d ] )
gap> CanonicalAgWord( v4, a*c );
b^2*d
gap> CanonicalAgWord( v4, a*b*c*d );
b
gap> (a*b*c*d) * (a*b^2);
b*c*d
gap> last * (c*d);
b
24.10
DifferenceAgWord
DifferenceAgWord( u, v )
DifferenceAgWord returns an ag word s representing the difference of the exponent vectors
of u and v .
Let G be the parent group of u and v . Let (g1 , ..., gn ) be the AG system of G and oi be
the relative order or gi . Then u can be expressed uniquely as g1u1 ∗ ... ∗ gnun for integers ui
between 0 and oi − 1 and v can be expressed uniquely as g1v1 ∗ ... ∗ gnvn for integers vi between
0 and oi − 1. The function DifferenceAgWord returns an ag word s = g1s1 ∗ ... ∗ gnsn with
integer si such that 0 ≤ si < oi and si ≡ ui − vi mod oi .
gap> DifferenceAgWord( a * b, a );
b
gap> DifferenceAgWord( a, b );
a*b^2
gap> z27 := CyclicGroup( AgWords, 27 );
Group( c27_1, c27_2, c27_3 )
gap> x := z27.1 * z27.2;
c27_1*c27_2
gap> x * x;
c27_1^2*c27_2^2
gap> DifferenceAgWord( x, x );
IdAgWord
524
CHAPTER 24. WORDS IN FINITE POLYCYCLIC GROUPS
24.11
ReducedAgWord
ReducedAgWord( b, x )
Let b and x be ag words of the same depth, then ReducedAgWord returns an ag word a such
that a is an element of the coset U b, where U is the cyclic group generated by x , and a has
a higher depth than b and x .
Note that the relative order of b and x must be a prime.
Let p be the relative order of b and x . Let β and ξ be the leading exponent of b and
x respectively. Then there exits an integer i such that ξ ∗ i = β modulo p. We can set
a = x −i b.
Typically this function is used when b and x occur in a generating set of a subgroup W .
Then b can be replaced by a in the generating set of W , but a and x have different depth.
gap> ReducedAgWord( a*b^2*c, a );
b^2*c
gap> ReducedAgWord( last, b );
c
24.12
SiftedAgWord
SiftedAgWord( U , g )
SiftedAgWord tries to sift an ag word g, which must be an element of the parent group
of an ag group U , through an induced generating system of U . SiftedAgWord returns the
remainder of this shifting process.
The identity is returned if and only if g is an element of U .
Let u1 , ..., um be an induced generating system of U . If there exists an ui such that ui and
g have the same depth, then g is reduced with ui using ReducedAgWord (see 24.11). The
process is repeated until no ui can be found or the g is reduced to the identity.
SiftedAgWord allows factor group arguments. See 25.57 for details.
Note that SiftedAgGroup adds a record component U .shiftInfo to the ag group record
of U . This entry is used by subsequent calls with the same ag group in order to speed up
computation. If you ever change the component U .igs by hand, not using Normalize,
you must unbind U .shiftInfo, otherwise all following results of SiftedAgWord will be
corrupted.
gap> s3 := Subgroup( s4, [ a, b ] );
Subgroup( s4, [ a, b ] )
gap> SiftedAgWord( s3, a * b^2 * c );
c
24.13
SumAgWord
SumAgWord( u, v )
SumAgWord returns an ag word s representing the sum of the exponent vectors of u and v .
Let G be the parent group of u and v . Let (g1 , ..., gn ) be the AG system of G and oi be
the relative order or gi . Then u can be expressed uniquely as g1u1 ∗ ... ∗ gnun for integers ui
24.14. EXPONENTAGWORD
525
between 0 and oi − 1 and v can be expressed uniquely as g1v1 ∗ ... ∗ gnvn for integers vi between
0 and oi − 1. Then SumAgWord returns an ag word s = g1s1 ∗ ... ∗ gnsn with integer si such
that 0 ≤ si < oi and si ≡ ui + vi mod oi .
gap> SumAgWord( b, a );
a*b
gap> SumAgWord( a*b, a );
b
gap> RelativeOrderAgWord( a );
2
gap> z27 := CyclicGroup( AgWords, 27 );
Group( c27_1, c27_2, c27_3 )
gap> x := z27.1 * z27.2;
c27_1*c27_2
gap> y := x ^ 2;
c27_1^2*c27_2^2
gap> x * y;
c27_2*c27_3
gap> SumAgWord( x, y );
IdAgWord
24.14
ExponentAgWord
ExponentAgWord( g, k )
ExponentAgWord returns the exponent of the k .th generator in an ag word g as integer,
where k refers to the numbering of generators of the parent group of g.
Let G be the parent group of g and (g1 , ..., gn ) the AG system of G and let oi be the relative
order of gi . Then the element g can be expressed uniquely in the form g1ν1 ∗ ... ∗ gnνn for
integers νi between 0 and oi − 1. The exponent of the k .th generator is νk .
See also 24.15 and 25.73.
gap> ExponentAgWord(
2
gap> ExponentAgWord(
1
gap> ExponentAgWord(
0
gap> a * b^2 * c^2 *
a*b^2*d
24.15
a * b^2 * c^2 * d, 2 );
a * b^2 * c^2 * d, 4 );
a * b^2 * c^2 * d, 3 );
d;
ExponentsAgWord
ExponentsAgWord( g )
ExponentsAgWord( g, s, e )
ExponentsAgWord( g, s, e, root )
In its first form ExponentsAgWord returns the exponent vector of an ag word g, with respect to the AG system of the supergroup of g, as list of integers. In the second form
ExponentsAgWord returns the sublist of the exponent vector of g starting at position s and
526
CHAPTER 24. WORDS IN FINITE POLYCYCLIC GROUPS
ending at position e as list of integers. In the third form the vector is returned as list of
finite field elements over the same finite field as root.
Let G be the parent group of g and (g1 , ..., gn ) the AG system of G and let oi be the relative
order of gi . Then the element g can be expressed uniquely in the form g1ν1 ∗ ... ∗ gnνn for
integers νi between 0 and oi − 1. The exponent vector of g is the list [ν1 , ..., νn ].
Note that you must use Exponents if you want to get the exponent list of g with respect not
to the parent group of g but to a given subgroup, which contains g. See 25.73 for details.
gap> ExponentsAgWord( a * b^2 * c^2 * d );
[ 1, 2, 0, 1 ]
gap> a * b^2 * c^2 * d;
a*b^2*d
Chapter 25
Finite Polycyclic Groups
Ag groups (see 24) are a subcategory of finitely generated groups (see 7).
The following sections describe how subgroups of ag groups are represented (see 25.1),
additional operators and record components of ag groups (see 25.3 and 25.4) and functions
which work only with ag groups (see 25.24 and 25.61). Some additional information about
generating systems of subgroups and factor groups are given in 25.48 and 25.57.
25.85 describes how to compute the groups of one coboundaries and one cocycles for given
ag groups. 25.88 gives informations how to obtain complements and conjugacy classes of
complements for given ag groups.
25.1
More about Ag Groups
Let G be a finite polycyclic group with PAG system (g1 , ..., gn ) as described in 24. Let U be
a subgroup of G. A generating system (u1 , ..., ur ) of U is called the canonical generating
system, CGS for short, of U with respect to (g1 , ..., gn ) if and only if
(i)
(ii)
(iii)
(iv)
(u1 , ..., ur ) is a PAG system for U ,
δ(ui ) > δ(uj ) for i > j,
λ(ui ) = 1 for i = 1, ..., r,
νδ(ui ) (uj ) = 0 for i 6= j.
If a generating system (u1 , ..., ur ) fulfills only conditions (i) and (ii) this system is called an
induced generating system, IGS for short, of U . With respect to the PAG system of G
a CGS but not an IGS of U is unique.
If a power-commutator or power-conjugate presentation of G is known, a finite polycyclic
group with collector can be initialized in GAP3 using AgGroupFpGroup (see 25.27). AgGroup
(see 25.25) converts other types of finite solvable groups, for instance solvable permutation
groups, into an ag group. The collector can be changed by ChangeCollector (see 25.33).
The elements of these group are called ag words.
A canonical generating system of a subgroup U of G is returned by Cgs (see 25.50) if a
generating set of ag words for U is known. See 25.48 for details.
527
528
CHAPTER 25. FINITE POLYCYCLIC GROUPS
We call G a parent, that is a ag group with collector and U a subgroup, that is a group
which is obtained as subgroup of a parent group. An ag group is either a parent group
with PAG system or a subgroup of such a parent group.
Although parent groups need only an AG system, only AgGroupFpGroup (see 25.27) and
RefinedAgSeries (see 25.32) work correctly with a parent group represented by an AG
system which is not a PAG system, because subgroups are identified by canonical generating
systems with respect to the PAG system of the parent group. Inconsistent power-conjugate
or power-commutator presentations are not allowed (see 25.28). Some functions support
factor group arguments. See 25.57 and 25.60 for details.
Our standard example in the following sections is the symmetric group of degree 4, defined
by the following sequence of GAP3 statements. You should enter them before running any
example. For details on AbstractGenerators see 22.1.
gap>
gap>
gap>
gap>
gap>
>
>
>
>
>
gap>
gap>
gap>
25.2
:= AbstractGenerator( "a" );; # (1,2)
:= AbstractGenerator( "b" );; # (1,2,3)
:= AbstractGenerator( "c" );; # (1,3)(2,4)
:= AbstractGenerator( "d" );; # (1,2)(3,4)
:= AgGroupFpGroup( rec(
generators := [ a, b, c, d ],
relators
:= [ a^2, b^3, c^2, d^2, Comm( b, a ) / b,
Comm( c, a ) / d, Comm( d, a ),
Comm( c, b ) / ( c*d ), Comm( d, b ) / c,
Comm( d, c ) ] ) );;
s4.name := "s4";;
a := s4.generators[1];; b := s4.generators[2];;
c := s4.generators[3];; d := s4.generators[4];;
a
b
c
d
s4
Construction of Ag Groups
The most fundamental way to construct a new finite polycyclic group is AgGroupFpGroup
(see 25.27) together with RefinedAgSeries (see 25.32), if a presentation for an AG system
of a finite polycyclic group is known.
But usually new finite polycyclic groups are constructed from already existing finite polycyclic groups. The direct product of known ag groups can be formed by DirectProduct
(see 7.99); also, if for instance a permutation representation P of a finite polycyclic group
G is known, WreathProduct (see 7.104) returns the P -wreath product of G with a second
ag group. If a homomorphism of a finite polycyclic group G into the automorphism group
of another finite polycyclic group H is known, SemidirectProduct returns the semi direct
product of G with H.
Fundamental finite polycyclic groups, such as elementary abelian, arbitrary finite abelian
groups, and cyclic groups, are constructed by the appropriate functions (see 38.1).
25.3
Ag Group Operations
In addition to the operators described in 7.117 the following operator can be used for ag
groups.
25.4. AG GROUP RECORDS
529
G mod H
mod returns a record representing an factor group argument, which can be used as argument
for some functions (see 25.73). See 25.57 and 25.60 for details.
25.4
Ag Group Records
In addition to the record components described in 7.118 the following components may be
present in the group record of an ag group G.
isAgGroup
is always true.
isConsistent
is true if G has a consistent presentation (see 25.28).
compositionSeries
contains a composition series of G (see 7.38).
cgs
contains a canonical generating system for G. If G is a parent group, it is always
present. See 25.48 for details.
igs
contains an induced generating system for G. See 25.48 for details.
elementaryAbelianFactors
see 7.39.
sylowSystem
contains a Sylow system (see 25.67).
25.5
Set Functions for Ag Groups
As already mentioned in the introduction of the chapter, ag groups are domains. Thus all
set theoretic functions, for example Intersection and Size, can be applied to ag groups.
This and the following sections give further comments on the definition and implementations
of those functions for ag groups. All set theoretic functions not mentioned here not treated
special for ag groups.
Elements( G )
The elements of a group G are constructed using a canonical generating system. See 25.6.
g in G
Membership is tested using SiftedAgWord (see 24.12), if g lies in the parent group of G.
Otherwise false is returned.
IsSubset( G, H )
If G and H are groups then IsSubset tests if the generators of H are elements of G.
Otherwise DomainOps.IsSubset is used.
530
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Intersection( G, H )
The intersection of ag groups G and H is computed using Glasby’s algorithm. See 25.7.
Size( G )
The size of G is computed using a canonical generating system of G. See 25.8.
25.6
Elements for Ag Groups
AgGroupOps.Elements( G )
Let G be an ag group with canonical generating system (g1 , ..., gn ) where the relative order
of gi is oi . Then {g1e1 ...gnen ; 0 ≤ ei < oi } is the set of elements of G.
25.7
Intersection for Ag Groups
AgGroupOps.Intersection( U , V )
If either V or U is not an ag group then GroupOps.Intersection is used in order to
compute the intersection of U and V . If U and V have different parent groups then the
empty list is returned.
Let U and V be two ag group with common parent group G. If one subgroup if known
to be normal in G the NormalIntersection (see 7.26) is used in order to compute the
intersection.
If the size of U or V is smaller than GS SIZE then the intersection is computed using
GroupOps.Intersection. By default GS SIZE is 20.
If an elementary abelian ag series of G is known, Glasby’s generalized covering algorithm is
used (see [GS90]). Otherwise a warning is given and GroupOps.Intersection is used, but
this may be too slow.
gap> d8_1 := Subgroup( s4, [ a, c, d ] );
Subgroup( s4, [ a, c, d ] )
gap> d8_2 := Subgroup( s4, [ a*b, c, d ] );
Subgroup( s4, [ a*b, c, d ] )
gap> Intersection( d8_1, d8_2 );
Subgroup( s4, [ c, d ] )
gap> Intersection( d8_1^b, d8_2^b );
Subgroup( s4, [ c*d, d ] )
25.8
Size for Ag Groups
AgGroupOps.Size( G )
Let G be an ag group with induced generating system (g1 , ..., gn ) where the relative order
of gi is oi . Then the size of G is o1 ∗ ... ∗ on .
AgGroupOps.Size allows a factor argument (see 25.60) for G. It uses Index (see 7.51) in
such a case.
25.9. GROUP FUNCTIONS FOR AG GROUPS
25.9
531
Group Functions for Ag Groups
As ag groups are groups, all group functions, for example IsAbelian and Normalizer, can
be applied to ag groups. This and the following sections give further comments on the
definition and implementations of those functions for ag groups. All group functions not
mentioned here are not treated in a special way.
Group( U )
See 25.11.
CompositionSeries( G )
Let (g1 , ..., gn ) be an induced generating system of G with respect to the parent group of
G. Then for i ∈ {1, ..., n} the i.th composition subgroup Si of the AG system is generated
by (gi , ..., gn ). The n + 1.th composition subgroup Sn+1 is the trivial subgroup of G. The
AG series of G is the series {S1 , ..., Sn+1 }.
Centralizer( U )
The centralizer of an ag group U in its parent group is computed using linear methods while
stepping down an elementary abelian series of its parent group.
Centralizer( U , H )
This function call computes the centralizer of H in U using linear methods. H and U must
have a common parent.
Centralizer( U , g )
The centralizer of a single element g in an ag group U may be computed whenever g lies in
the parent group of U . In that case the same algorithm as for the centralizer of subgroups
is used.
ConjugateSubgroup( U , g )
If g is an element of U then U is returned. Otherwise the remainder of the shifting
of g through U is used to conjugate an induced generating system of U . In that case
the information bound to U .isNilpotent, U .isAbelian, U .isElementaryAbelian and
U .isCyclic, if known, is copied to the conjugate subgroup.
Core( S , U )
AgGroupOps.Core computes successively the core of U stepping up a composition series of
S . See [Thi87].
CommutatorSubgroup( G, H )
See 25.12 for details.
532
CHAPTER 25. FINITE POLYCYCLIC GROUPS
ElementaryAbelianSeries( G )
AgGroupOps.ElementaryAbelianSeries returns a series of normal subgroups of G with
elementary abelian factors.
gap> ElementaryAbelianSeries( s4 );
[ s4, Subgroup( s4, [ b, c, d ] ), Subgroup( s4, [ c, d ] ),
Subgroup( s4, [ ] ) ]
gap> d8 := Subgroup( s4, [ a*b^2, c, d ] );
Subgroup( s4, [ a*b^2, c, d ] )
gap> ElementaryAbelianSeries( d8 );
[ Subgroup( s4, [ a*b^2, c, d ] ), Subgroup( s4, [ c, d ] ),
Subgroup( s4, [ ] ) ]
If G is no parent group then AgGroupOps.ElementaryAbelianSeries will compute a elementary abelian series for the parent group and intersect this series with G. If G is a parent
group then IsElementaryAbelianAgSeries (see 25.29) is used in order to check if such a
series exists. Otherwise an elementary abelian is computed refining the derived series (see
[LNS84, Gla87]).
ElementaryAbelianSeries( L )
L must be a list of ag groups S1 = H, ..., Sm = {1} with a common parent group such that
Si is a subgroup of Si−1 and Si is normal in G for all i ∈ {2, ..., m}. Then the function
returns a series of normal subgroups of G with elementary abelian factors refining the series
L.
NormalIntersection( V , W )
If V is an element of the AG series of G, then AgGroupOps.NormalIntersection uses
the depth of V in order to compute the intersection. Otherwise it uses the Zassenhaus
sum-intersection algorithm (see [GS90]).
Normalizer( G, U )
See 25.13.
SylowSubgroup( G, p )
AgGroupOps.SylowSubgroup uses HallSubgroup (see 25.63) in order to compute the sylow
subgroup of G.
DerivedSeries( G )
AgGroupOps.DerivedSeries uses DerivedSubgroup (see 7.22) in order to compute the derived series of G. It checks if G is normal in its parent group H. If it is normal all the
derived subgroups are also normal in H. G is always the first element of this list and the
trivial group always the last one since G is soluble.
LowerCentralSeries( G )
25.9. GROUP FUNCTIONS FOR AG GROUPS
533
AgGroupOps.LowerCentralSeries uses CommutatorSubgroup (see 7.19) in order to compute the lower central series of G. It checks if G is normal in its parent group H. If it is
normal all subgroups of the lower central series are also normal in H.
Random( U )
Let (u1 , ..., ur ) be a induced generating system of U . Let e1 , ..., er be the relative order of
u1 , ..., ur . Then for r random integers νi between 0 and ei − 1 the word uν11 ∗ ... ∗ urνr is
returned.
IsCyclic( G )
See 25.14.
IsFinite( G )
As G is a finite solvable group AgGroupOps.IsFinite returns true.
IsNilpotent( U )
AgGroupOps.IsNilpotent uses Glasby’s nilpotency test for ag groups (see [Gla87]).
IsNormal( G, U )
See 25.15.
IsPerfect( G )
As G is a finite solvable group it is perfect if and only if G is trivial.
IsSubgroup( G, U )
See 25.16.
ConjugacyClasses( H )
The conjugacy classes of elements are computed using linear methods. The algorithm depends on the ag series of the parent group of H being a refinement of an elementary abelian
series. Thus if this is not true or if H is not a member of the elementary abelian series, an
isomorphic group, in which the computation can be done, is created.
The algorithm that is used steps down an elementary abelian series of the parent group of
H , basically using affine operation to construct the conjugacy classes of H step by step from
its factorgroups.
Orbit( U , pt, op )
AgGroupOps.Orbit returns the orbit of pt under U using the operation op. The function
calls AgOrbitStabilizer in order to compute the orbit, so please refer to 25.78 for details.
534
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Stabilizer( U , pt, op )
See 25.17.
AsGroup( D )
See 25.10.
FpGroup( U )
See 25.23.
RightCoset( U , g )
See 25.22.
AbelianGroup( D, L )
Let L be the list [o1 , ..., on ] of nonnegative integers oi > 1. Then AgWordsOps.AbelianGroup
returns the direct product of the cyclic groups of order oi using the domain description D.
The generators of these cyclic groups are named beginning with “a”, “b”, “c”, ... followed
by a number if oi is a composite integer.
CyclicGroup( D, n )
See 25.18.
ElementaryAbelianGroup( D, n )
See 25.19.
DirectProduct( L )
See 25.20.
WreathProduct( G, H , α )
See 25.21.
25.10
AsGroup for Ag Groups
AgGroupOps.AsGroup( G )
AgGroupOps.AsGroup returns a copy H of G. It does not change the parent status. If G is
a subgroup so is H.
AgWordsOps.AsGroup( L )
Let L be a list of ag words. Then AgWordsOps.AsGroup uses MergedCgs (see 25.55) in order
to compute a canonical generating system for the subgroup generated by L in the parent
group of the elements of L.
25.11. GROUP FOR AG GROUPS
25.11
535
Group for Ag Groups
AgGroupOps.Group( G )
AgGroupOps.Group returns an isomorphic group H such that H is a parent group and
H.bijection is bond to an isomorphism between H and G.
AgWordsOps.Group( D, gens, id )
Constructs the group G generated by gens with identity id . If these generators do not
generate a parent group, a new parent group H is construct. In that case new generators
are used and H.bijection is bound to isomorphism between H and G.
25.12
CommutatorSubgroup for Ag Groups
AgGroupOps.CommutatorSubgroup( G, H )
Let g1 , ..., gn be an canonical generating system for G and h1 , ..., hm be an canonical generating system for H . The normal closure of the subgroup S generated by Comm(gi , hj ) for
1 ≤ i ≤ n and 1 ≤ j ≤ m under G and H is the commutator subgroup of G and H .
But if G or H is known to be normal in the common parent of G amd H then the subgroup
S is returned because if G normalizes H or vice versa then S is already the commutator
subgroup (see [Gla87]).
If G = H the commutator subgroup is generated by Comm(gi , gj ) for 1 ≤ i < j ≤ n
(see [LNS84]). Note that AgGroupOps.CommutatorSubgroup checks G.derivedSubgroup
in that case.
25.13
Normalizer for Ag Groups
AgGroupOps.Normalizer( S , U )
Note that the AG series of G should be the refinement of an elementary abelian series,
see 25.29. Otherwise the calculation of the normalizer is done using an orbit algorithm,
which is generally too slow or space extensive. You can construct a new polycyclic presentation for G such that AG series is a refinement of an elementary abelian series with
ElementaryAbelianSeries (see 7.39) and IsomorphismAgGroup.
For details on the implementation see [GS90, CNW90].
25.14
IsCyclic for Ag Groups
AgGroupOps.IsCyclic( G )
AgGroupOps.IsCyclic returns false if G is no abelian group. Otherwise G is finite of
order pe11 ...penn where the pi are distinct primes then G is cyclic if and only if each G pi has
index pi in G.
AgGroupOps.IsCyclic computes the groups G pi using the fact that the map x 7→ xpi is a
homomorphism of G, so that the pi .th powers of an induced generating system of G are a
homomorphic image of an igs (see [Cel92]).
536
CHAPTER 25. FINITE POLYCYCLIC GROUPS
25.15
IsNormal for Ag Groups
AgGroupOps.IsNormal( G, U )
Let G be a parent group. Then AgGroupOps.IsNormal checks if the conjugate of each
generator of U under each induced generator of G which has a depth not contained in U is
an element of U . Otherwise AgGroupOps.IsNormal checks if the conjugate of each generator
of U under each generator of G is an element of U .
25.16
IsSubgroup for Ag Groups
AgGroupOps.IsSubgroup( G, U )
If G is a parent group of U , then AgGroupOps.IsSubgroup returns true. If the CGS of U
is longer than that of G, U cannot be a subgroup of G. Otherwise AgGroupOps.IsSubgroup
shifts each generator of U through G (see 24.12) in order to check if U is a subgroup of G.
25.17
Stabilizer for Ag Groups
AgGroupOps.Stabilizer( U , pt, op )
Let U be an ag group acting on a set Ω by op. Let pt be an element of Ω. Then
AgGroupOps.Stabilizer returns the stabilizer of pt in U .
op must be a function taking two arguments such that op(p, u) is the image of a point p ∈ Ω
under the action of an element u of U . If conjugation should be used op must be OnPoints.
The stabilizer is computed by stepping up the composition series of U . The whole orbit pt U
is not stored during the computation (see [LNS84]). Of course this saving of space is bought
at the cost of time. If you need a faster function, which may use more memory, you can use
AgOrbitStabilizer (see 25.78) instead.
25.18
CyclicGroup for Ag Groups
AgWordsOps.CyclicGroup( D, n )
AgWordsOps.CyclicGroup( D, n, str )
Let n be a nonnegative integer. AgWordsOps.CyclicGroup returns the cyclic group of order
n.
Let n be a composite number with r prime factors. If no str is given, the names of the
r generators are cn 1, ..., cn r. Otherwise, the names of the r generators are str 1, ..., str r,
where str must be a string of letters, digits and the special symbol “ ”.
If the order n is a prime, the name of the generator is either cn or str .
gap> CyclicGroup( AgWords, 31 );
Group( c31 )
gap> AgWordsOps.CyclicGroup( AgWords, 5 * 5, "e" );
Group( e1, e2 )
25.19. ELEMENTARYABELIANGROUP FOR AG GROUPS
25.19
537
ElementaryAbelianGroup for Ag Groups
AgWordsOps.ElementaryAbelianGroup( D, n )
AgWordsOps.ElementaryAbelianGroup( D, n, str )
AgWordsOps.ElementaryAbelianGroup returns the elementary abelian group of order n,
which must be a prime power.
Let n be a prime power pr . If no str is given the names of the r generators are mn 1, ..., mn r.
Otherwise the names of the r generators are str 1, ..., str r, where str must be a string of
letters, digits and the special symbol “ ”.
If the order n is a prime, the name of the generator is either mn or str .
gap> ElementaryAbelianGroup( AgWords, 31 );
Group( m31 )
gap> ElementaryAbelianGroup( AgWords, 31^2 );
Group( m961_1, m961_2 )
gap> AgWordsOps.ElementaryAbelianGroup( AgWords, 31^2, "e" );
Group( e1, e2 )
25.20
DirectProduct for Ag Groups
AgGroupOps.DirectProduct( L )
L must be list of groups or pairs of group and name as described below. If not all groups
are ag groups GroupOps.DirectProduct (see 7.99) is used in order to construct the direct
product.
Let L be a list of ag groups L = [U1 , ..., Un ]. AgGroupOps.DirectProduct returns the direct
product of all Ui as new ag group with collector.
If L is a pair [ Ui , S ] instead of a group Ui the generators of the direct product corresponding to Ui are named S j for integers j starting with 1 up to the number of induced
generators for Ui . If the group is cyclic of prime order the name is just S .
AgGroupOps.DirectProduct computes for each Ui its natural power-commutator presentation for an induced generating system of Ui .
Note that the arguments need no common parent group.
gap> z3 := CyclicGroup( AgWords, 3 );;
gap> g := AgGroupOps.DirectProduct( [ [z3, "a"], [z3, "b"] ] );
Group( a, b )
25.21
WreathProduct for Ag Groups
AgGroupOps.WreathProduct( G, H , α )
If H and G are not both ag group GroupOps.WreathProduct (see 7.104) is used.
Let H and G be two ag group with possible different parent group and let α be a homomorphism H into a permutation group of degree d.
Let (g1 , ..., gr ) be an IGS of G, (h1 , ..., hn ) an IGS of H . The wreath product has a PAG
system (b1 , ..., bn , a11 , ..., a1r , ad1 , ..., adr ) such that b1 , ..., bn generate a subgroup isomorph
538
CHAPTER 25. FINITE POLYCYCLIC GROUPS
to H and ai1 , ..., air generate a subgroup isomorph to G for each i in {1, ..., r}. The names
of b1 , ..., bn are h1, ..., hn, the names of ai1 , ..., air are ni 1, ..., ni r.
AgGroupOps.WreathProduct uses the natural power-commutator presentations of H and G
for induced generating system of H and G (see [Thi87]).
gap> s3 := Subgroup( s4, [ a, b ] );
Subgroup( s4, [ a, b ] )
gap> c2 := Subgroup( s4, [ a ] );
Subgroup( s4, [ a ] )
gap> r := RightCosets( s3, c2 );;
gap> S3 := Operation( s3, r, OnRight );
Group( (2,3), (1,2,3) )
gap> f := GroupHomomorphismByImages(s3,S3,[a,b],[(2,3),(1,2,3)]);
GroupHomomorphismByImages( Subgroup( s4, [ a, b ] ), Group( (2,3),
(1,2,3) ), [ a, b ], [ (2,3), (1,2,3) ] )
gap> WreathProduct( c2, s3, f );
Group( h1, h2, n1_1, n2_1, n3_1 )
25.22
RightCoset for Ag Groups
AgGroupOps.Coset( G )
A coset C = G∗x is represented as record with the following components.
representative
contains the representative x.
group
contains the group G.
isDomain
is true.
isRightCoset
is true.
isFinite
is true.
operations
contains the operations record RightCosetAgGroupOps.
RightCosetAgGroupOps.<( C1 , C2 )
If C1 and C2 do not have a common group or if one argument is no coset then the functions
uses DomainOps.< in order to compare C1 and C2 . Note that this will compute the set of
elements of C1 and C2 .
If C1 and C2 have a common group then AgGroupCosetOps.< will use SiftedAgWord (see
24.12) and ConjugateSubgroup (see 7.20) in order to compare C1 and C2 . It does not
compute the set of elements of C1 and C2 .
25.23. FPGROUP FOR AG GROUPS
25.23
539
FpGroup for Ag Groups
AgGroupOps.FpGroup( U )
AgGroupOps.FpGroup( U , str )
AgGroupOps.FpGroup returns a finite presentation of an ag group U .
If no str is given, the abstract group generators have the same names as the generators of
the ag group U . Otherwise they have names of the form str i for integers i from 1 to the
number of induced generators.
AgGroupOps.FpGroup computes the natural power-commutator presentation of an induced
generating system of the finite polycyclic group U .
25.24
Ag Group Functions
The following functions either construct new parent ag group (see 25.25 and 25.27), test
properties of parent ag groups (see 25.28 and 25.29) or change the collector (see 25.33) but
they do not compute subgroups. These functions are either described in general in chapter
7 or in 25.61 for specialized functions.
25.25
AgGroup
AgGroup( D )
AgGroup converts a finite polycyclic group D into an ag group G. G.bijection is bound
to isomorphism between G and D.
gap> S4p := Group( (1,2,3,4), (1,2) );
Group( (1,2,3,4), (1,2) )
gap> S4p.name := "S4_PERM";;
gap> S4a := AgGroup( S4p );
Group( g1, g2, g3, g4 )
gap> S4a.name := "S4_AG";;
gap> L := CompositionSeries( S4a );
[ S4_AG, Subgroup( S4_AG, [ g2, g3, g4 ] ),
Subgroup( S4_AG, [ g3, g4 ] ), Subgroup( S4_AG, [ g4 ] ),
Subgroup( S4_AG, [ ] ) ]
gap> List( L, x -> Image( S4a.bijection, x ) );
[ Subgroup( S4_PERM, [ (1,2), (1,3,2), (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( S4_PERM, [ (1,3,2), (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( S4_PERM, [ (1,4)(2,3), (1,2)(3,4) ] ),
Subgroup( S4_PERM, [ (1,2)(3,4) ] ), Subgroup( S4_PERM, [ ] ) ]
Note that the function will not work for finitely presented groups, see 25.27 for details.
25.26
IsAgGroup
IsAgGroup( obj )
IsAgGroup returns true if obj , which can be an arbitrary object, is an ag group and false
otherwise.
540
CHAPTER 25. FINITE POLYCYCLIC GROUPS
gap> IsAgGroup( s4 );
true
gap> IsAgGroup( a );
false
25.27
AgGroupFpGroup
AgGroupFpGroup( F )
AgGroupFpGroup returns an ag group isomorphic to a finitely presented finite polycyclic
group F .
A finitely presented finite polycyclic group F must be a record with components generators
and relators, such that generators is a list of abstract generators and relators a list of
words in these generators describing a power-commutator or power-conjugate presentation.
Let g1 , ..., gn be the generators of F . Then the words of relators must be the power relators
g
−1
−1
−1
gkek ∗ wkk
for
and commutator relator Comm(gi , gj ) ∗ wij
or conjugate relators gi j ∗ wij
all 1 ≤ k ≤ n and 1 ≤ j < i ≤ n, such that wkk are words in gk+1 , ..., gn and wij are words
in gj+1 , ..., gn . It is possible to omit some of the commutator or conjugate relators. Pairs of
generators without commutator or conjugate relator are assumed to commute.
The relative order ei of gi need not to be primes, but as all functions for ag groups need a
PAG system, not only an AG system, you must refine the AG series using RefinedAgSeries
(see 25.32) in case some ei are composite numbers.
Note that it is not checked if the AG presentation is consistent. You can use IsConsistent
(see 25.28) to test the consistency of a presentation. Inconsistent presentations may cause
other ag group functions to return incorrect results.
Initially a collector from the left following the algorithm described in [LGS90] is used in
order to collect elements of the ag group. This could be changed using ChangeCollector
(see 25.33).
Note that AgGroup will not work with finitely presented groups, you must use the function AgGroupFpGroup instead. As no checks are done you can construct an ag group with
inconsistent presentation using AgGroupFpGroup.
25.28
IsConsistent
IsConsistent( G )
IsConsistent( G, all )
IsConsistent returns true if the finite polycyclic presentation of a parent group G is
consistent and false otherwise.
If all is true then G.inconsistencies contains a list for pairs [w1 , w2 ] such that the words
w1 and w2 are equal in G but have different normal forms.
Note that IsConsistent check and sets G.isConsistent.
gap>
gap>
gap>
gap>
InfoAgGroup2 := Print;;
x := AbstractGenerator( "x" );;
y := AbstractGenerator( "y" );;
z := AbstractGenerator( "z" );;
25.29. ISELEMENTARYABELIANAGSERIES
541
gap> G := AgGroupFpGroup( rec(
>
generators := [ x, y, z ],
>
relators
:= [ x^2 / y, y^2 / z, z^2,
>
Comm( y, x ) / ( y * z ),
>
Comm( z, x ) / ( y * z )] ) );
Group( x, y, z )
gap> IsConsistent( G );
#I IsConsistent: y * ( y * x ) <> ( y * y ) * x
false
gap> IsConsistent( G, true );
#I IsConsistent: y * ( y * x ) <> ( y * y ) * x
#I IsConsistent: z * ( z * x ) <> ( z * z ) * x
#I IsConsistent: y * ( x * x ) <> ( y * x ) * x
#I IsConsistent: z * ( x * x ) <> ( z * x ) * x
#I IsConsistent: x * ( x * x ) <> ( x * x ) * x
false
gap> G.inconsistencies;
[ [ x, x*y ], [ x*z, x ], [ z, y ], [ y*z, y ], [ x*y, x ] ]
gap> InfoAgGroup2 := Ignore;;
25.29
IsElementaryAbelianAgSeries
IsElementaryAbelianAgSeries( G )
Let G be a parent group. IsElementaryAbelianAgSeries returns true if and only if the
AG series of G is the refinement of an elementary abelian series of G.
The function sets G.elementaryAbelianSeries G in case of a true result. This component
is described in 7.39.
gap> IsElementaryAbelianAgSeries( s4 );
true
gap> ElementaryAbelianSeries( s4 );
[ s4, Subgroup( s4, [ b, c, d ] ), Subgroup( s4, [ c, d ] ),
Subgroup( s4, [ ] ) ]
gap> CompositionSeries( s4 );
[ s4, Subgroup( s4, [ b, c, d ] ), Subgroup( s4, [ c, d ] ),
Subgroup( s4, [ d ] ), Subgroup( s4, [ ] ) ]
25.30
MatGroupAgGroup
MatGroupAgGroup( U , M )
Let U and M be two ag groups with a common parent group and let M be a elementary
abelian group normalized by U . Then MatGroupAgGroup returns the matrix representation
of U acting on M .
See also 25.79.
gap> v4 := AgSubgroup( s4, [ c, d ], true );
Subgroup( s4, [ c, d ] )
gap> a4 := AgSubgroup( s4, [ b, c, d ], true );
542
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Subgroup( s4, [ b, c, d ] )
gap> MatGroupAgGroup( s4, v4 );
Group( [ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ],
[ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, Z(2)^0 ] ] )
25.31
PermGroupAgGroup
PermGroupAgGroup( G, U )
Let U be a subgroup of a ag group G. Then PermGroupAgGroup returns the permutation
representation of G acting on the cosets of U .
gap> v4 := AgSubgroup( s4, [ s4.1, s4.4 ], true );
Subgroup( s4, [ a, d ] )
gap> PermGroupAgGroup( s4, v4 );
Group( (3,5)(4,6), (1,3,5)(2,4,6), (1,2)(3,4), (3,4)(5,6) )
25.32
RefinedAgSeries
RefinedAgSeries( G )
RefinedAgSeries returns a new parent group isomorphic to a parent group G with a PAG
series, if the ag group G has only an AG series.
Note that in the case that G has a PAG series, G is returned without any further action.
The names of the new generators are constructed as follows. Let (g1 , ..., gn ) be the AG
system of the ag group G and n(gi ) the name of gi . If the relative order of gi is a prime,
then n(gi ) is the name of a new generator. If the relative order is a composite number with
r prime factors, then there exist r new generators with names n(gi ) 1, ..., n(gi ) r.
gap> c12 := AbstractGenerator( "c12" );;
gap> F := rec( generators := [ c12 ],
>
relators
:= [ c12 ^ ( 2 * 2 * 3 ) ] );
rec(
generators := [ c12 ],
relators := [ c12^12 ] )
gap> G := AgGroupFpGroup( F );
#W AgGroupFpGroup: composite index, use ’RefinedAgSeries’
Group( c12 )
gap> RefinedAgSeries( G );
Group( c121, c122, c123 )
25.33
ChangeCollector
ChangeCollector( G, name )
ChangeCollector( G, name, n )
ChangeCollector changes the collector of a parent group G and all its subgroups. name is
the name of the new collector. The following collectors are supported.
“single” initializes a collector from the left following the algorithm described in [LGS90].
25.34. THE PRIME QUOTIENT ALGORITHM
543
“triple” initializes a collector from the left collecting with triples gi ˆgjr for j < i and r =
1, ..., n (see [Bis89]).
“quadruple” initializes a collector from the left collecting with quadruples gis ˆgjr for j < i,
r = 1, ..., n and s = 1, ..., n. Note that r and s have the same upper bound (see [Bis89]).
“combinatorial” initializes a combinatorial collector from the left for a p-group G. In that
g
case the commutator or conjugate relations of the G must be of the form gi j = wij or
Comm(gi , gj ) = wij for 1 ≤ j < i ≤ n, such that wij are words in gi+1 , ..., gn fulfilling
the central weight condition (see [HN80, VL84]). If these conditions are not fulfilled, the
collector could not be initialized, a warning will be printed and collection will be done with
the old collector.
For collectors which collect with tuples a maximal bound of those tuples is n, set to 5 by
default.
25.34
The Prime Quotient Algorithm
The following sections describe the np-quotient functions. PQuotient allows to compute
quotient of prime power order of finitely presented groups. For further references see [HN80]
and [VL84].
There is a C standalone version of the p-quotient algorithm, the ANU p-Quotient Program,
which can be called from GAP3. For further information see chapter 58.
25.35
PQuotient
PQuotient( G, p, cl )
PrimeQuotient( G, p, cl )
PQuotient computes quotients of prime power order of finitely presented groups. G must
be a group given by generators and relations. PQuotient expects G to be a record with
the record fields generators and relators. The record field generators must be a list
of abstract generators created by the function AbstractGenerator (see 22.1). The record
field relators must be a list of words in the generators which are the relators of the group.
p must be a prime. cl has to be an integer, which specifies that the quotient of prime power
order computed by PQuotient is the largest p-quotient of G of class at most cl . PQuotient
returns a record Q, the PQp record, which has, among others, the following record fields
describing the p-quotient Q.
generators
A list of abstract generators which generate Q.
pcp
The internal power-commutator presentation for Q.
dimensions
A list, where dimensions[i] is the dimension of the i-th factor in the lower exponentp central series calculated by the p-quotient algorithm.
prime
The integer p, which is a prime.
definedby
A list which contains the definition of the k-th generator in the k-th place. There are
544
CHAPTER 25. FINITE POLYCYCLIC GROUPS
three different types of entries, namely lists, positive and negative integers.
[ j, i ]
the generator is defined to be the commutator of the j-th and the i-th element in
generators.
i
the generator is defined as the p-th power of the i-th element in generators.
-i
the generator is defined as an image of the i-th generator in the finite presentation
for G, consequently it must be a generator of weight 1.
epimorphism
A list containing an image in Q of each generator of G. The image is either an integer
i if it is the i-th element of generators of Q or an abstract word w if it is the abstract
word w in the generators of Q.
An example of the computation of the largest quotient of class 4 of the group given by the
finite presentation {x, y | x25 /(x · y)5 , [x, y]5 , (xy )25 }.
# Define the group
gap> x := AbstractGenerator("x");;
gap> y := AbstractGenerator("y");;
gap> G := rec( generators := [x,y],
>
relators := [ x^25/(x*y)^5, Comm(x,y)^5, (x^y)^25] );
rec(
generators := [ x, y ],
relators :=
[ x^25*y^-1*x^-1*y^-1*x^-1*y^-1*x^-1*y^-1*x^-1*y^-1*x^-1,
x^-1*y^-1*x*y*x^-1*y^-1*x*y*x^-1*y^-1*x*y*x^-1*y^-1*x*y*x^-1*y^-\
1*x*y, y^-1*x^25*y ] )
# Call pQuotient
gap> P := PQuotient( G, 5, 4 );
#I PQuotient: class 1 : 2
#I PQuotient: Runtime : 0
#I PQuotient: class 2 : 2
#I PQuotient: Runtime : 27
#I PQuotient: class 3 : 2
#I PQuotient: Runtime : 1437
#I PQuotient: class 4 : 3
#I PQuotient: Runtime : 1515
PQp( rec(
generators := [ g1, g2, a3, a4, a6, a7, a11, a12, a14 ],
definedby
:= [ -1, -2, [ 2, 1 ], 1, [ 3, 1 ], [ 3, 2 ],
[ 5, 1 ], [ 5, 2 ], [ 6, 2 ] ],
prime
:= 5,
dimensions := [ 2, 2, 2, 3 ],
epimorphism := [ 1, 2 ],
powerRelators := [ g1^5/(a4), g2^5/(a4^4), a3^5, a4^5, a6^5, a7^
5, a11^5, a12^5, a14^5 ],
commutatorRelators := [ Comm(g2,g1)/(a3), Comm(a3,g1)/(a6), Comm(a3\
25.36. SAVE
545
,g2)/(a7), Comm(a6,g1)/(a11), Comm(a6,g2)/(a12), Comm(a7,g1)/(a12), Co\
mm(a7,g2)/(a14) ],
definingCommutators := [ [ 2, 1 ], [ 3, 1 ], [ 3, 2 ], [ 5, 1 ],
[ 5, 2 ], [ 6, 1 ], [ 6, 2 ] ] ) )
The p-quotient algorithm returns a PQp record for the exponent-5 class 4 quotient. Note
that instead of printing the PQp record P an equivalent representation is printed which can
be read in to GAP3. See 25.37 for details.
The quotient defined by P has nine generators, g1, g2, a3, a4, a6, a7,a11, a12, a14,
stored in the list P.generators. From powerRelators we can read off that g1^5 =:
a4 and g2^5 = a4^4 and all other generators have trivial 5-th powers. From the list
commutatorRelators we can read off the non-trivial commutator relations Comm(g2,g1)
=: a3, Comm(a3,g1) =: a6, Comm(a3,g2) =: a7, Comm(a6,g1) =: a11,Comm(a6,g2) =:
a12, Comm(a7,g1) = a12 and Comm(a7,g2) =: a14. In this list =: denotes that the generator on the right hand side is defined as the left hand side. This information is given
by the list definedby. The list dimensions shows that P is a class-4 quotient of order
52 · 52 · 52 · 53 = 59 . The epimorphism of G onto the quotient P is given by the map x 7→ g1
and y 7→ g2.
25.36
Save
Save( file, Q, N )
Save saves the PQp record Q to the file file in such a way that the file can be read by GAP3.
The name of the record in the file will be N . This differs from printing Q to a file in that
the required abstract generators are also created in file.
gap> x := AbstractGenerator("x");;
gap> y := AbstractGenerator("y");;
gap> G := rec( generators := [x,y],
>
relators := [ x^25/(x*y)^5, Comm(x,y)^5, (x^y)^25] );;
gap> P := PQuotient( G, 5, 4 );;
#I PQuotient: class 1 : 2
#I PQuotient: Runtime : 0
#I PQuotient: class 2 : 2
#I PQuotient: Runtime : 27
#I PQuotient: class 3 : 2
#I PQuotient: Runtime : 78
#I PQuotient: class 4 : 3
#I PQuotient: Runtime : 156
gap> Save( "Quo54", P, "Q" );
gap> # The Unix command ’cat’ in the next statement should be
gap> # replaced appropriately if you are working under a different
gap> # operating system.
gap> Exec( "cat Quo54" );
g1 := AbstractGenerator("g1");
g2 := AbstractGenerator("g2");
a3 := AbstractGenerator("a3");
a4 := AbstractGenerator("a4");
a6 := AbstractGenerator("a6");
546
CHAPTER 25. FINITE POLYCYCLIC GROUPS
a7 := AbstractGenerator("a7");
a11 := AbstractGenerator("a11");
a12 := AbstractGenerator("a12");
a14 := AbstractGenerator("a14");
Q := PQp( rec(
generators := [ g1, g2, a3, a4, a6, a7, a11, a12, a14 ],
definedby
:= [ -1, -2, [ 2, 1 ], 1, [ 3, 1 ], [ 3, 2 ],
[ 5, 1 ], [ 5, 2 ], [ 6, 2 ] ],
prime
:= 5,
dimensions := [ 2, 2, 2, 3 ],
epimorphism := [ 1, 2 ],
powerRelators := [ g1^5/(a4), g2^5/(a4^4), a3^5, a4^5, a6^5, a7^
5, a11^5, a12^5, a14^5 ],
commutatorRelators := [ Comm(g2,g1)/(a3), Comm(a3,g1)/(a6), Comm(a3\
,g2)/(a7), Comm(a6,g1)/(a11), Comm(a6,g2)/(a12), Comm(a7,g1)/(a12), Co\
mm(a7,g2)/(a14) ],
definingCommutators := [ [ 2, 1 ], [ 3, 1 ], [ 3, 2 ], [ 5, 1 ],
[ 5, 2 ], [ 6, 1 ], [ 6, 2 ] ] ) );
25.37
PQp
PQp( r )
PQp takes as argument a record r containing all information necessary to restore a PQp
record Q. A PQp record Q is printed as function call to PQp with an argument describing Q.
This is necessary because the internal power-commutator representation cannot be printed.
Therefore all information about Q is encoded in a record r and Q is printed as PQp(
).
25.38
InitPQp
InitPQp( n, p )
InitPQp creates a PQp record for an elementary abelian group of rank n and of order p n
for a prime p.
25.39
FirstClassPQp
FirstClassPQp( G, p )
FirstClassPQp returns a PQp record for the exponent-p class 1 quotient of G.
25.40
NextClassPQp
NextClassPQp( G, P )
Let P be the PQp record for the exponent-p class c quotient of G. NextClassPQp returns
a PQp record for the class c + 1 quotient of G, if such a quotient exists, and P otherwise.
In latter case there exists a maximal p-quotient of G which has class c and this is indicated
by a comment if InfoPQ1 is set the Print.
25.41. WEIGHT
25.41
547
Weight
Weight( P , w )
Let P be a PQp record and w a word in the generators of P . The function Weight returns
the weight of w with respect to the lower exponent-p central series defined by P .
25.42
Factorization for PQp
Factorization( P , w )
Let P be a PQp record and w a word in the generators of P . The function Factorization
returns a word in the weight 1 generators of P expressing w .
25.43
The Solvable Quotient Algorithm
The following sections describe the solvable quotient functions (or sq functions for short).
SolvableQuotient allows to compute finite solvable quotients of finitely presented groups.
The solvable quotient algorithm tries to find solvable quotients of a given finitely presented
group G. First it computes the commutator factor group Q, which must be finite. It then
chooses a prime p and repeats the following three steps:(1) compute all irreducible modules
of Q over GF (p), (2) for each module M compute (up to equivalence) all extensions of Q
by M , (3) for each extension E check whether E is isomorphic to a factor group of G. As
soon as a non-trivial extension of Q is found which is still isomorphic to a factor group of
G the process is repeated.
25.44
SolvableQuotient
SolvableQuotient( G, primes )
Let G be a finitely presented group and primes a list of primes. SolvableQuotient tries
to compute the largest finite solvable quotient Q of G, such that the prime decomposition
of the order the derived subgroup Q0 of Q only involves primes occuring in the list primes.
The quotient Q is returned as finitely presented group. You can use AgGroupFpGroup (see
25.27) to convert the finitely presented group into a polycyclic one.
Note that the commutator factor group of G must be finite.
gap> f := FreeGroup( "a", "b", "c", "d" );;
gap> f4 := f / [ f.1^2, f.2^2, f.3^2, f.4^2, f.1*f.2*f.1*f.2*f.1*f.2,
>
f.2*f.3*f.2*f.3*f.2*f.3*f.2*f.3, f.3*f.4*f.3*f.4*f.3*f.4,
>
f.1^-1*f.3^-1*f.1*f.3, f.1^-1*f.4^-1*f.1*f.4,
>
f.2^-1*f.4^-1*f.2*f.4 ];
Group( a, b, c, d )
gap> InfoSQ1 := Ignore;;
gap> g := SolvableQuotient( f4, [3] );
Group( e1, e2, m3, m4 )
gap> Size(AgGroupFpGroup(g));
36
gap> g := SolvableQuotient( f4, [2] );
Group( e1, e2 )
548
CHAPTER 25. FINITE POLYCYCLIC GROUPS
gap> Size(AgGroupFpGroup(g));
4
gap> g := SolvableQuotient( f4, [2,3] );
Group( e1, e2, m3, m4, m5, m6, m7, m8, m9 )
gap> Size(AgGroupFpGroup(g));
1152
Note that the order in which the primes occur in primes is important. If primes is the list
[2, 3] then in each step SolvableQuotient first tries a module over GF(2) and only if this
fails a module over GF(3). Whereas if primes is the list [3, 2] the function first tries to find
a downward extension by a module over GF(3) before considering modules over GF(2).
SolvableQuotient( G, n )
Let G be a finitely presented group. SolvableQuotient attempts to compute a finite
solvable quotient of G of order n.
Note that n must be divisible by the order of the commutator factor group of G, otherwise
the function terminates with an error message telling you the order of the commutator factor
group.
Note that a warning is printed if there does not exist a solvable quotient of order n. In this
case the largest solvable quotient whose order divides n is returned.
Providing the order n or a multiple of the order makes the algorithm run much faster than
providing only the primes which should be tested, because it can restrict the dimensions of
modules it has to investigate. Thus if the order or a small enough multiple of it is known,
SolvableQuotient should be called in this way to obtain a power conjugate presentation
for the group.
gap> f := FreeGroup( "a", "b", "c", "d" );;
gap> f4 := f / [ f.1^2, f.2^2, f.3^2, f.4^2, f.1*f.2*f.1*f.2*f.1*f.2,
>
f.2*f.3*f.2*f.3*f.2*f.3*f.2*f.3, f.3*f.4*f.3*f.4*f.3*f.4,
>
f.1^-1*f.3^-1*f.1*f.3, f.1^-1*f.4^-1*f.1*f.4,
>
f.2^-1*f.4^-1*f.2*f.4 ];;
gap> g := SolvableQuotient( f4, 12 );
Group( e1, e2, m3 )
gap> Size(AgGroupFpGroup(g));
12
gap> g := SolvableQuotient( f4, 24 );
#W largest quotient has order 2^2*3
Group( e1, e2, m3 )
gap> g := SolvableQuotient( f4, 2 );
Error, commutator factor group is of size 2^2
SolvableQuotient( G, l )
If something is already known about the structure of the finite soluble quotient to be constructed then SolvableQuotient can be aided in its construction.
l must be a list of lists each of which is a list of integers occurring in pairs p, n.
SolvableQuotient first constructs the commutator factor group of G, it then tries to extend
this group by modules over GF (p) of dimension at most n where p is a prime occurring in the
first list of l . If n is zero no bound on the dimension of the module is imposed. For example,
25.45. INITSQ
549
if l is [[2, 0, 3, 4], [5, 0, 2, 0]] then SolvableQuotient will try to extend the commutator factor
group by a module over GF(2). If no such module exists all modules over GF(3) of dimension
at most 4 are tested. If neither a GF(2) nor a GF(3) module extend SolvableQuotient
terminates. Otherwise the algorithm tries to extend this new factor group with a GF(5)
and then a GF(2) module.
Note that it is possible to influence the construction even more precisely by using the
functions InitSQ, ModulesSQ, and NextModuleSQ. These functions allow you to interactively
select the modules. See 25.45, 25.46, and 25.47 for details.
Note that the ordering inside the lists of l is important. If l is the list [[2, 0, 3, 0]] then
SolvableQuotient will first try a module over GF(2) and attempt to construct an extension
by a module over GF(3) only if the GF(2) extension fails, whereas in the case that l is the
list [[3, 0, 2, 0]] the function first attempts to extend with modules over GF(3) and then with
modules over GF(2).
gap> f := FreeGroup( "a", "b", "c", "d" );;
gap> f4 := f / [ f.1^2, f.2^2, f.3^2, f.4^2, f.1*f.2*f.1*f.2*f.1*f.2,
>
f.2*f.3*f.2*f.3*f.2*f.3*f.2*f.3, f.3*f.4*f.3*f.4*f.3*f.4,
>
f.1^-1*f.3^-1*f.1*f.3, f.1^-1*f.4^-1*f.1*f.4,
>
f.2^-1*f.4^-1*f.2*f.4 ];;
gap> g := SolvableQuotient( f4, [[5,0],[2,0,3,0]] );
Group( e1, e2 )
gap> Size(AgGroupFpGroup(g));
4
gap> g := SolvableQuotient( f4, [[3,0],[2,0]] );
Group( e1, e2, m3, m4, m5, m6, m7, m8, m9 )
gap> Size(AgGroupFpGroup(g));
1152
25.45
InitSQ
InitSQ( G )
Let G be a finitely presented group. InitSQ computes an SQ record for the commutator
factor group of G. This record can be used to investigate finite solvable quotients of G .
Note that the commutator factor group of G must be finite otherwise an error message is
printed.
See also 25.46 and 25.47.
gap> f := FreeGroup( "a", "b", "c", "d" );;
gap> f4 := f / [ f.1^2, f.2^2, f.3^2, f.4^2, f.1*f.2*f.1*f.2*f.1*f.2,
>
f.2*f.3*f.2*f.3*f.2*f.3*f.2*f.3, f.3*f.4*f.3*f.4*f.3*f.4,
>
f.1^-1*f.3^-1*f.1*f.3, f.1^-1*f.4^-1*f.1*f.4,
>
f.2^-1*f.4^-1*f.2*f.4 ];;
gap> s := InitSQ(f4);
<< solvable quotient of size 2^2 >>
25.46
ModulesSQ
ModulesSQ( S , F )
ModulesSQ( S , F , d )
550
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Let S be an SQ record describing a finite solvable quotient Q of a finitely presented group G.
ModulesSQ computes all irreducible representations of Q over the prime field F of dimension
at most d . If d is zero or missing no restriction on the dimension is enforced.
gap> f := FreeGroup( "a", "b", "c", "d" );;
gap> f4 := f / [ f.1^2, f.2^2, f.3^2, f.4^2, f.1*f.2*f.1*f.2*f.1*f.2,
>
f.2*f.3*f.2*f.3*f.2*f.3*f.2*f.3, f.3*f.4*f.3*f.4*f.3*f.4,
>
f.1^-1*f.3^-1*f.1*f.3, f.1^-1*f.4^-1*f.1*f.4,
>
f.2^-1*f.4^-1*f.2*f.4 ];;
gap> s := InitSQ(f4);
<< solvable quotient of size 2^2 >>
gap> ModulesSQ( s, GF(2) );;
25.47
NextModuleSQ
NextModuleSQ( s, M )
Let S be an SQ record describing a finite solvable quotient Q of a finitely presented group
G. NextModuleSQ tries to extend Q by the module M such that the extension is still a
quotient of G
gap> f := FreeGroup( "a", "b", "c", "d" );;
gap> f4 := f / [ f.1^2, f.2^2, f.3^2, f.4^2, f.1*f.2*f.1*f.2*f.1*f.2,
>
f.2*f.3*f.2*f.3*f.2*f.3*f.2*f.3, f.3*f.4*f.3*f.4*f.3*f.4,
>
f.1^-1*f.3^-1*f.1*f.3, f.1^-1*f.4^-1*f.1*f.4,
>
f.2^-1*f.4^-1*f.2*f.4 ];;
gap> s := InitSQ(f4);
<< solvable quotient of size 2^2 >>
gap> m := ModulesSQ( s, GF(3) );;
gap> NextModuleSQ( s, m[1] );
<< solvable quotient of size 2^2 >>
gap> NextModuleSQ( s, m[2] );
<< solvable quotient of size 2^2*3 >>
gap> NextModuleSQ( s, m[3] );
<< solvable quotient of size 2^2 >>
gap> NextModuleSQ( s, m[4] );
<< solvable quotient of size 2^2*3 >>
25.48
Generating Systems of Ag Groups
For an ag group G there exists three different types of generating systems. The generating
system in G.generators is a list of ag words generating the group G with the only condition
that none of the ag words is the identity of G. If an induced generating system for G is
known it is bound to G.igs, while an canonical generating system is bound to G.cgs. But
as every canonical generating system is also an induced one, G.cgs and G.igs may contain
the same system.
The functions Cgs, Igs, Normalize, Normalized and IsNormalized change or manipulate
these systems. The following overview shows when to use this functions. For details see
25.50, 25.51, 25.53, 25.54 and 25.52.
25.49. AGSUBGROUP
551
Igs returns an induced generating system for G. If neither G.igs nor G.cgs are present,
it uses MergedIgs (see 25.56) in order to construct an induced generating system from
G.generators. In that case the induced generating system is bound to G.igs. If G.cgs
but not G.igs is present, this is returned, as every canonical generating system is also an
induced one. If G.igs is present this is returned.
Cgs returns a canonical generating system for G. If neither G.igs nor G.cgs are present,
it uses MergedCgs (see 25.55) in order to construct a canonical generating system from
G.generators. In that case the canonical generating system is bound to G.cgs. If G.igs
but not G.cgs is present, this is normalized and bound to G.cgs, but G.igs is left unchanged. If G.cgs is present this is returned.
Normalize computes a canonical generating system, binds it to G.cgs and unbinds an
induced generating bound to G.igs. Normalized normalizes a copy without changing the
original ag group. This function should be preferred.
IsNormalized checks if an induced generating system is a canonical one and, if being canonical, binds it to G.cgs and unbinds G.igs. If G.igs is unbound IsNormalized computes
a canonical generating system, binds it to G.cgs and returns true.
Most functions need an induced or canonical generating system, all function descriptions
state clearly what is used, if this is relevant, see 25.73 for example.
25.49
AgSubgroup
AgSubgroup( U , gens, flag )
Let U be an ag group with ag group G, gens be an induct or canonical generating system
for a subgroup S of U and flag a boolean. Then AgSubgroup returns the record of an ag
group representing this finite polycyclic group S as subgroup of G.
If flag is true, gens must be a canonical generating with respect to G. If flag is false gens
must be a an induced generating with respect to G.
gens will be bound to S.generators. If flag is true, it is also bound to S.cgs, if it is
false, gens is also bound to S.igs. Note that AgSubgroup does not copy gens.
Note that it is not check whether gens are an induced or canonical system. If gens fails to
be one, all following computations with this group are most probably wrong.
gap> v4 := AgSubgroup( s4, [ c, d ], true );
Subgroup( s4, [ c, d ] )
25.50
Cgs
Cgs( U )
Cgs returns a canonical generating system of U with respect to the parent group of U as
list of ag words (see 25.1).
If U .cgs is bound, this is returned without any further action. If U .igs is bound, a copy of
this component is normalized, bound to U .cgs and returned. If neither U .igs nor U .cgs
are bound, a canonical generating system for U is computed using MergedCgs (see 25.55)
and bound to U .cgs.
552
25.51
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Igs
Igs( U )
Igs returns an induced generating system of U with respect to the parent group of U as
list of ag words (see 25.1).
If U .igs is bound, this is returned without any further action. If U .cgs but not U .igs
is bound, this is returned. If neither U .igs nor U .cgs are bound, an induced generating
system for U is computed using MergedIgs (see 25.56) and bound to U .igs.
25.52
IsNormalized
IsNormalized( U )
IsNormalized returns true if no induced generating system but an canonical generating
system for U is known.
If U .cgs but not U .igs is bound, true is returned. If neither U .cgs nor U .igs are
bound, a canonical generating system is computed, bound to U .cgs and true is retuned.
If U .igs is present, it is check, if U .igs is a canonical generating. If so, the canonical
generating system is bound to U .cgs and U .igs is unbound.
25.53
Normalize
Normalize( U )
Normalize converts an induced generating system of an ag group U into a canonical one.
If U .cgs and not U .igs is bound, U is returned without any further action. If U contains
both components U .cgs and U .igs, U .igs is unbound. If only U .igs but not U .cgs
is bound the generators in U .igs are converted into a canonical generating and bound
to U .cgs, while U .igs is unbound. If neither U .igs nor U .cgs are bound a canonical
generating system is computed using Cgs (see 25.50).
25.54
Normalized
Normalized( U )
Normalized returns a normalized copy of an ag group U . For details see 25.53.
Note that this function does not alter the record of U and always returns a copy of U , even
if U is already normalized.
25.55
MergedCgs
MergedCgs( U , objs )
Let U be an ag group with parent group G and objs be a list of elements and subgroups of
U . Then MergedCgs returns the subgroup S of G generated by the elements and subgroups
in the list objs. The subgroup S contains a canonical generating system bound to S.cgs.
As objs contains only elements and subgroups of U , the subgroup S is not only a subgroup
of G but also of U . Its parent group is nevertheless G and MergedCgs computes a canonical
generating system of S with respect to G.
25.56. MERGEDIGS
553
If subgroups of S are known at least the largest should be an element of objs, because
MergedCgs is much faster in such cases.
Note that this function may return a wrong subgroup, if the elements of objs do not belong
to U . See also 25.48 for differences between canonical and induced generating systems.
gap> d8 := MergedCgs( s4, [ a*c, c ] );
Subgroup( s4, [ a, c, d ] )
gap> MergedCgs( s4, [ a*b*c*d, d8 ] );
s4
gap> v4 := MergedCgs( d8, [ c*d, c ] );
Subgroup( s4, [ c, d ] )
25.56
MergedIgs
MergedIgs( U , S , gens, normalize )
Let U and S be ag groups with a common parent group G such that S is a subgroup of U .
Let gens be a list of elements of U . Then MergedIgs returns the subgroup K of G generated
by S and gens.
As gens contains only elements of U , the subgroup K is not only a subgroup of G but also
of U . Its parent group is nevertheless G and MergedIgs computes a induced generating
system of S with respect to G.
If normalize is true, a canonical generating system for K is computed and bound to K.cgs.
If normalize is false only an induced generating system is computed and bound to K.igs
or K.cgs. If no subgroup S is known, rec() can be given instead.
Note that U must be an ag group which contains S and gens.
25.57
Factor Groups of Ag Groups
It is possible to deal with factor groups of ag groups in three different ways. If an ag group
G and a normal subgroup N of G is given, you can construct a new polycyclic presentation
for F = G/N using FactorGroup. You can apply all functions for ag groups to that new
parent group F and even switch between G and F using the homomorphisms returned by
NaturalHomomorphism. See 7.33 for more information on that kind of factor groups.
But if you are only interested in an easy way to test a property or an easy way to calculate
a subgroup of a factor group, the first approach might be too slow, as it involves the construction of a new polycyclic presentation for the factor group together with the creation of
a new collector for that factor group. In that case you can use CollectorlessFactorGroup
in order to construct a new ag group without initializing a new collector but using records
faking ag words instead. But now multiplication is still done in G and the words must be
canonicalized with respect to N , so that multiplication in this group is rather slow. However if you for instance want to check if a chief factor, which is not part of the AG series,
is central this may be faster then constructing a new collector. But generally FactorGroup
should be used.
The third possibility works only for Exponents (see 25.73) and SiftedAgWord (see 24.12).
If you want to compute the action of G on a factor M/N then you can pass M/N as factor
group argument using M mod N or FactorArg (see 25.60).
554
CHAPTER 25. FINITE POLYCYCLIC GROUPS
25.58
FactorGroup for AgGroups
AgGroupOps.FactorGroup( U , N )
Let N and U be ag groups with a common parent group, such that N is a normal subgroup
of U . Let H be the factor group U /N . FactorGroup returns the finite polycyclic group H
as new parent group.
If the ag group U is not a parent group or if N is not an element of the AG series of U
(see 25.70), then FactorGroup constructs a new polycyclic presentation and collector for the
factor group using both FpGroup (see 25.23) and AgGroupFpGroup (see 25.27). Otherwise
FactorGroup copies the old collector of U and cuts of the tails which lie in N .
Note that N must be a normal subgroup of U . You should keep in mind, that although the
new generators and the old ones may have the same names, they cannot be multiplitied as
they are elements of different groups. The only way to transfer information back and forth
is to use the homomorphisms returned by NaturalHomomorphism (see 7.33).
gap> c2 := Subgroup( s4, [ d ] );
Subgroup( s4, [ d ] )
gap> d8 := Subgroup( s4, [ a, c, d ] );
Subgroup( s4, [ a, c, d ] )
gap> v4 := FactorGroup( d8, c2 );
Group( g1, g2 )
gap> v4.2 ^ v4.1;
g2
gap> d8 := Subgroup( s4, [ a, c, d ] );
Subgroup( s4, [ a, c, d ] )
gap> d8.2^d8.1;
c*d
25.59
CollectorlessFactorGroup
CollectorlessFactorgroup( G, N )
CollectorlessFactorgroup constructs the factorgroup F = G/N without initializing a
new collector. The elements of F are records faking ag words.
Each element f of F contains the following components.
representative
a canonical representative d in G for f .
isFactorGroupElement contains true.
info
a record containing information about the factor group.
operations
the operations record FactorGroupAgWordsOps.
25.60
FactorArg
FactorArg( U , N )
25.61. SUBGROUPS AND PROPERTIES OF AG GROUPS
555
Let N be a normal subgroup of an ag group U . Then FactorArg returns a record with the
following components with can be used as argument for Exponents.
isFactorArg
is true.
factorNum
contains U .
factorDen
contains N .
identity
contains the identity of U .
generators
contains a list of those induced generators ui of U of depth di such that no induced
generator in N has depth di .
operations
contains the operations record FactorArgOps.
Note that FactorArg is bound to AgGroupOps.mod.
gap> d8 := Subgroup( s4, [ a, c, d ] );
Subgroup( s4, [ a, c, d ] )
gap> c2 := Subgroup( s4, [ d ] );
Subgroup( s4, [ d ] )
gap> M := d8 mod c2;;
gap> d8.1 * d8.2 * d8.3;
a*c*d
gap> Exponents( M, last );
[ 1, 1 ]
gap> d8 := AgSubgroup( s4, [ a*c, c, d ], false );
Subgroup( s4, [ a*c, c, d ] )
gap> M := d8 mod c2;;
gap> Exponents( M, a*c*d );
[ 1, 0 ]
25.61
Subgroups and Properties of Ag Groups
The subgroup functions compute subgroups or series of subgroups from given ag groups,
e.g. PRump (see 25.64) or ElementaryAbelianSeries (see 7.39). They return group records
described in 7.118 and 25.4 for the computed subgroups.
All the following functions only work for ag groups. Subgroup functions which work for
various types of groups are described in 7.14. Properties and property tests which work for
various types of groups are described in 7.45.
25.62
CompositionSubgroup
CompositionSubgroup( G, i )
CompositionSubgroup returns the i .th subgroup of the AG series of an ag group G.
556
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Let (g1 , ..., gn ) be an induced generating system of G with respect to the parent group of
G. Then the i .th composition subgroup S of the AG series is generated by (gi , ..., gn ).
gap> CompositionSubgroup(
Subgroup( s4, [ b, c, d ]
gap> CompositionSubgroup(
Subgroup( s4, [ d ] )
gap> CompositionSubgroup(
Subgroup( s4, [ ] )
25.63
s4, 2 );
)
s4, 4 );
s4, 5 );
HallSubgroup
HallSubgroup( G, n )
HallSubgroup( G, L )
Let G be an ag group. Then HallSubgroup returns a π-Hall-subgroup of G for the set π of
all prime divisors of the integer n or the join π of all prime divisors of the integers of L.
The Hall-subgroup is constructed using Glasby’s algorithm (see [Gla87]), which descends
along an elementary abelian series for G and constructs complements in the coprime case
(see 25.91). If no such series is known for G the function uses ElementaryAbelianSeries
(see 7.39) in order to construct such a series for G.
gap> HallSubgroup( s4, 2 );
Subgroup( s4, [ a, c, d ] )
gap> HallSubgroup( s4, [ 3 ] );
Subgroup( s4, [ b ] )
gap> z5 := CyclicGroup( AgWords, 5 );
Group( c5 )
gap> DirectProduct( s4, z5 );
Group( a1, a2, a3, a4, b )
gap> HallSubgroup( last, [ 5, 3 ] );
Subgroup( Group( a1, a2, a3, a4, b ), [ a2, b ] )
25.64
PRump
PRump( G, p )
PRump returns the p-rump of an ag group G for a prime p.
The p-rump of a group G is the normal closure under G of the subgroup generated by the
commutators and p.th powers of the generators of G.
gap> PRump( s4, 2 );
Subgroup( s4, [ b, c, d ] )
gap> PRump( s4, 3 );
s4
25.65
RefinedSubnormalSeries
RefinedSubnormalSeries( L )
25.66. SYLOWCOMPLEMENTS
557
Let L be a list of ag groups G1 , ..., Gn , such that Gi+1 is a normal subgroup of Gi . Then
the function computes a composition series H1 = G1 , ..., Hm = Gn which refines the given
subnormal series L and has cyclic factors of prime order (see also 7.43).
gap> v4 := Subgroup( s4, [ c, d ] );
Subgroup( s4, [ c, d ] )
gap> T := TrivialSubgroup( s4 );
Subgroup( s4, [ ] )
gap> RefinedSubnormalSeries( [ s4, v4, T ] );
[ s4, Subgroup( s4, [ b, c, d ] ), Subgroup( s4, [ c, d ] ),
Subgroup( s4, [ d ] ), Subgroup( s4, [ ] ) ]
25.66
SylowComplements
SylowComplements( U )
SylowComplements returns a Sylow complement system of U . This system S is represented
as a record with at least the components S.primes and S.sylowComplements, additionally
there may be a component S.sylowSubgroups (see 25.67).
primes
A list of all prime divisors of the group order of U .
sylowComplements
contains a list of Sylow complements for all primes in S.primes, so that if the i.th
element of S.primes is p, then the i.th element of sylowComplements is a Sylow-pcomplement of U .
sylowSubgroups
contains a list of Sylow subgroups for all primes in S.primes, such that if the i.th
element of S.primes is p, then the i.th element of S.sylowSubgroups is a Sylow-psubgroup of U .
SylowComplements uses HallSubgroup (see 25.63) in order to compute the various Sylow
complements of U , if no Sylow system is known for U . If a Sylow system {S1 , ..., Sn } is
known, SylowComplements computes the various Hall subgroups Hi using the fact that Hi
is the product of all Sj except Si .
SylowComplements sets and checks U .sylowSystem.
gap> SylowComplements( s4 );
rec(
primes := [ 2, 3 ],
sylowComplements :=
[ Subgroup( s4, [ b ] ), Subgroup( s4, [ a, c, d ] ) ] )
25.67
SylowSystem
SylowSystem( U )
SylowSystem returns a Sylow system {S1 , ..., Sn } of an ag group U . The system S is represented as a record with at least the components S.primes and S.sylowSubgroups, additionally there may be a component S.sylowComplements, see 25.66 for information about
this addtional component.
558
CHAPTER 25. FINITE POLYCYCLIC GROUPS
primes
A list of all prime divisors of the group order of U .
sylowComplements
contains a list of Sylow complements for all primes in S.primes, so that if the i.th
element of S.primes is p, then the i.th element of sylowComplements is a Sylow-pcomplement of U .
sylowSubgroups
contains a list of Sylow subgroups for all primes in S.primes, such that if the i.th
element of S.primes is p, then the i.th element of S.sylowSubgroups is a Sylow-psubgroup of U .
A Sylow system of a group U is a system of Sylow subgroups Si for each prime divisor of
the group order of U such that Si ∗ Sj = Sj ∗ Si is fulfilled for each pair i, j.
SylowSystem uses SylowComplements (see 25.67) in order to compute the various Sylow
complements Hi of U . Then the Sylow system is constructed using the fact that the intersection Si of all Sylow complements Hj except Hi is a Sylow subgroup and that all these
subgroups Si form a Sylow system of U . See [Gla87].
SylowSystem sets and checks S.sylowSystem.
gap> z5 := CyclicGroup( AgWords, 5 );
Group( c5 )
gap> D := DirectProduct( z5, s4 );
Group( a, b1, b2, b3, b4 )
gap> D.name := "z5Xs4";;
gap> SylowSystem( D );
rec(
primes := [ 2, 3, 5 ],
sylowComplements :=
[ Subgroup( z5Xs4, [ a, b2 ] ), Subgroup( z5Xs4, [ a, b1, b3, b4
] ), Subgroup( z5Xs4, [ b1, b2, b3, b4 ] ) ],
sylowSubgroups :=
[ Subgroup( z5Xs4, [ b1, b3, b4 ] ), Subgroup( z5Xs4, [ b2 ] ),
Subgroup( z5Xs4, [ a ] ) ] )
25.68
SystemNormalizer
SystemNormalizer( G )
SystemNormalizer returns the system normalizer of a Sylow system of the group G.
The system normalizer of a Sylow system is the intersection of all normalizers of subgroups
in the Sylow system in G.
gap> SystemNormalizer( s4 );
Subgroup( s4, [ a ] )
gap> SystemNormalizer( D );
Subgroup( z5Xs4, [ a, b1 ] )
25.69. MINIMALGENERATINGSET
25.69
559
MinimalGeneratingSet
MinimalGeneratingSet( G )
Let G be an ag group. Then MinimalGeneratingSet returns a subset L of G of minimal
cardinality with the property that L generates G.
gap> l := MinimalGeneratingSet(s4);
[ b, a*c*d ]
gap> s4 = Subgroup( s4, l );
true
25.70
IsElementAgSeries
IsElementAgSeries( U )
IsElementAgSeries returns true if the ag group U is part of the AG series of the parent
group G of U and false otherwise.
25.71
IsPNilpotent
IsPNilpotent( U , p )
IsPNilpotent returns true, if the ag group U is p-nilpotent for the prime p, and false
otherwise.
IsPNilpotent uses Glasby’s p-nilpotency test (see [Gla87]).
gap> IsPNilpotent( s4, 2
false
gap> s3 := Subgroup( s4,
Subgroup( s4, [ a, b ] )
gap> IsPNilpotent( s3, 2
true
gap> IsPNilpotent( s3, 3
false
25.72
);
[ a, b ] );
);
);
NumberConjugacyClasses
NumberConjugacyClasses( H )
This functions computes the number of conjugacy classes of elements of a group H .
The function uses an algorithm that steps down an elementary abelian series of the parent group of H and computes the number of conjugacy classes using the same method as
AgGroupOps.ConjugacyClasses does, up to the last factor group. In the last step the
Cauchy-Frobenius-Burnside lemma is used.
This algorithm is especially designed to supply at least the number of conjugacy classes of
H , whenever ConjugacyClasses fails because of storage reasons. So one would rather use
this function if the last normal subgroup of the elementary abelian series is too big to be
dealt with ConjugacyClasses.
NumberConjugacyClasses( U , H )
560
CHAPTER 25. FINITE POLYCYCLIC GROUPS
This version of the call to NumberConjugacyClasses computes the number of conjugacy
classes of H under the operation of U . Thus for the operation to be well defined, U must
be a subgroup of the normalizer of H in their common parent group.
gap>
gap>
5
gap>
6
gap>
4
gap>
3
25.73
a4 := DerivedSubgroup(s4);;
NumberConjugacyClasses( s4 );
NumberConjugacyClasses( a4, s4 );
NumberConjugacyClasses( a4 );
NumberConjugacyClasses( s4, a4 );
Exponents
Exponents( U , u )
Exponents( U , u, F )
Exponents returns the exponent vector of an ag word u with respect to an induced generating system of U as list of integers if no field F is given. Otherwise the product of the
exponent vector and F .one is returned. Note that u must be an element of U .
Let (u1 , ..., ur ) be an induced generating system of U . Then u can be uniquely written as
uν11 ∗ ... ∗ uνrr for integer νi . The exponent vector of u is [ν1 , ..., νr ].
Exponents allows factor group arguments. See 25.57 for details.
Note that Exponents adds a record component U .shiftInfo. This entry is used by subsequent calls with the same ag group in order to speed up computation. If you ever change
the component U .igs by hand, not using Normalize, you must unbind the component
U .shiftInfo, otherwise all following results of Exponents will be corrupted. In case U
is a parent group you can use ExponentsAgWord (see 24.15), which is slightly faster but
requires a parent group U .
Note that you you may get a weird error message if u is no element of U . So it is strictly
required that u is an element of U .
Note that Exponents uses ExponentsAgWord but not ExponentAgWord, so for records that
mimic agwords Exponents may be used in ExponentAgWord.
gap> v4 := AgSubgroup( s4, [ c, d ], true );
Subgroup( s4, [ c, d ] )
gap> Exponents( v4, c * d );
[ 1, 1 ]
gap> Exponents( s4 mod v4, a * b^2 * c * d );
[ 1, 2 ]
25.74
FactorsAgGroup
FactorsAgGroup( U )
FactorsAgGroup returns the factorization of the group order of an ag group U as list of
positive integers.
25.75. MAXIMALELEMENT
561
Note that it is faster to use FactorsAgGroup than to use Factors and Size.
gap>
gap>
[ 2,
gap>
[ 2,
25.75
v4 := Subgroup( s4, [ c, d ] );;
FactorsAgGroup( s4 );
2, 2, 3 ]
Factors( Size( s4 ) );
2, 2, 3 ]
MaximalElement
MaximalElement( U )
MaximalElement returns the ag word in U with maximal exponent vector.
Let G be the parent group of U with canonical generating system (g1 , ..., gn ) and let
(u1 , ..., um ) be the canonical generating system of U , di is the depth
Pm of ui with respect
to G. Then an ag word u = g1ν1 ∗ ... ∗ gnνn ∈ U is returned such that i=1 νdi is maximal.
25.76
Orbitalgorithms of Ag Groups
The functions Orbit (see 8.16) and Stabilizer (see 8.24 and 25.17) compute the orbit and
stabilizer of an ag group acting on a domain.
AgOrbitStabilizer (see 25.78) computes the orbit and stabilizer in case that a compatible
homomorphism into a group H exists, such that the action of H on the domain is more
efficient than the operation of the ag group; for example, if an ag group acts linearly on a
vector space, the operation can by described using matrices.
The functions AffineOperation (see 25.77) and LinearOperation (see 25.79) compute
matrix groups describing the affine or linear action of an ag group on a vector space.
25.77
AffineOperation
AffineOperation( U , V , ϕ, τ )
Let U be an ag group with an induced generating system u1 , ..., um and let V be a vector
space with base (o1 , ..., on ). Further U should act affinely on V . So if v is an element of V
and u is an element of U , then v u = vu + xu , such that the function which maps v to vu is
linear and xu is an element of V . These actions are given by the functions ϕ and τ as follows.
ϕ(v, u) must return the representation of vu with respect to the base (o1 , ..., on ) as sequence
of finite field elements. τ (u) must return the representation of xu in the base (o1 , ..., on ) as
sequence of finite field elements. If these conditions are fulfilled, AffineOperation returns
a matrix group M describing this action.
Note that M .images contains a list of matrices mi , such that mi describes the action of ui
and mi is of the form
Lui
xui
0
1
,
where Lu is the matrix which describes the linear operation v ∈ V 7→ vu .
gap> v4 := AgSubgroup( s4, [ c, d ], true );
562
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Subgroup( s4, [ c, d ] )
gap> v4.field := GF( 2 );
GF(2)
gap> phi := function( v, g )
>
return Exponents( v4, v^g, v4.field );
>
end;
function ( v, g ) ... end
gap> tau := g -> Exponents( v4, v4.identity, v4.field );
function ( g ) ... end
gap> V := rec( base := [ c, d ], isDomain := true );
rec(
base := [ c, d ],
isDomain := true )
gap> AffineOperation( s4, V, phi, tau );
Group( [ [ Z(2)^0, Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), Z(2)^0 ] ],
[ [ 0*Z(2), Z(2)^0, 0*Z(2) ], [ Z(2)^0, Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), Z(2)^0 ] ] )
25.78
AgOrbitStabilizer
AgOrbitStabilizer( U , gens, ω )
AgOrbitStabilizer( U , gens, ω, f )
Let U be an ag group acting on a set Ω. Let ω be an element of Ω. Then AgOrbitStabilizer
returns the point-stabilizer of ω in the group U and the orbit of ω under this group. The
stabilizer and orbit are returned as record R with components R.stabilizer and R.orbit.
R.stabilizer is the point-stabilizer of ω. R.orbit is the list of the elements of ω U .
Let (u1 , ..., un ) be an induced generating system of U and gens be a list h1 , ..., hn of generators of a group H, such that the map ui 7→ hi extends to an homomorphism α from U
to H, which is compatible with the action of G and H on Ω, such that g ∈ StabU (ω) if
and only if g α ∈ StabH (ω). If f is missing OnRight is assumed, a typical application of this
function being the linear action of U on an vector space. If f is OnPoints then ^ is used as
operation of H on Ω. Otherwise f must be a function, which takes two arguments, the first
one must be a point p of Ω and the second an element h of H and which returns ph .
gap> AgOrbitStabilizer( s4, [a,b,c,d], d, OnPoints );
rec(
stabilizer := Subgroup( s4, [ a, c, d ] ),
orbit := [ d, c*d, c ] )
25.79
LinearOperation
LinearOperation( U , V , ϕ )
Let U be an ag group with an induced generating system u1 , ..., um and V a vector space
with base (o1 , ..., on ). U must act linearly on V . Let v be an element of V , u be an element
of U . The action of U on V should be given as follows. If v u = a1 ∗ o1 + ... + an ∗ on , then
the function ϕ(v, u) must return (a1 , ..., an ) as list of finite field elements. If these condition
are fulfilled, LinearOperation returns a matrix group M describing this action.
25.80. INTERSECTIONS OF AG GROUPS
563
Note that M .images is bound to a list of matrices mi , such that mi describes the action
of ui .
gap> v4 := AgSubgroup( s4, [ c, d ], true );
Subgroup( s4, [ c, d ] )
gap> v4.field := GF( 2 );
GF(2)
gap> V := rec( base := [ c, d ], isDomain := true );
rec(
base := [ c, d ],
isDomain := true )
gap> phi := function( v, g )
>
return Exponents( v4, v^g, v4.field );
>
end;
function ( v, g ) ... end
gap> LinearOperation( s4, V, phi );
Group( [ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ],
[ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, Z(2)^0 ] ] )
25.80
Intersections of Ag Groups
There are two kind of intersection algorithms. Whenever the product of two subgroups
is a subgroup, a generalized Zassenhaus algorithm can be used in order to compute the
intersection and sum (see [GS90]). In case one subgroup is a normalized by the other, an
element of the sum can easyly be decomposed. The functions IntersectionSumAgGroup (see
25.82), NormalIntersection (see 7.26 ), SumFactorizationFunctionAgGroup (see 25.84)
and SumAgGroup (see 25.83) should be used in such cases.
These functions are faster than the general function Intersection (see 4.12 and 25.7),
which can compute the intersection of two subgroups even if their product is no subgroup.
25.81
ExtendedIntersectionSumAgGroup
ExtendedIntersectionSumAgGroup( V , W )
Let V and W be ag groups with a common parent group, such that W ≤ N (V ). Then
V ∗ W is a subgroup and ExtendedIntersectionSumAgGroup returns the intersection and
the sum of V and W . The information about these groups is returned as a record with the
components intersection, sum and the additional information leftSide and rightSide.
intersection
is bound to the intersection W ∩ V .
sum
is bound to the sum V ∗ W .
leftSide
is lists of ag words, see below.
rightSide
is lists of agwords, see below.
The function uses the Zassenhaus sum-intersection algorithm. Let V be generated by
v1 , ..., va , W be generated by w1 , ..., wb . Then the matrix
564
CHAPTER 25. FINITE POLYCYCLIC GROUPS
v1
..
.
va
w1
.
..
wb
1
..
.
1
w1
..
.
wb
is echelonized by using the sifting algorithm to produce the following matrix
l1
..
.
lc
1
.
..
k1
..
.
kc
kc+1
..
.
1
ka+b
.
Then l1 , ..., lc is a generating sequence for the sum, while the sequence kc+1 , ..., ka+b is is
a generating sequence for the intersection. leftSide is bound to a list, such that the i.th
list element is lj , if there exists a j, such that lj has depth i, and IdAgWord otherwise.
rightSide is bound to a list, such that the i.th list element is kj , if there exists a j less
than c + 1, such that kj has depth i, and IdAgWord otherwise. See also 25.84.
Note that this functions returns an incorrect result if W 6≤ N (V ).
gap> v4_1 := AgSubgroup( s4, [ a*b, c ], true );
Subgroup( s4, [ a*b, c ] )
gap> v4_2 := AgSubgroup( s4, [ c, d ], true );
Subgroup( s4, [ c, d ] )
gap> ExtendedIntersectionSumAgGroup( v4_1, v4_2 );
rec(
leftSide := [ a*b, IdAgWord, c, d ],
rightSide := [ IdAgWord, IdAgWord, c, d ],
sum := Subgroup( s4, [ a*b, c, d ] ),
intersection := Subgroup( s4, [ c ] ) )
25.82
IntersectionSumAgGroup
IntersectionSumAgGroup( V , W )
Let V and W be ag groups with a common parent group, such that W ≤ N (V ). Then
V ∗ W is a subgroup and IntersectionSumAgGroup returns the intersection and the sum
of V and W as record R with components R.intersection and R.sum.
The function uses the Zassenhaus sum-intersection algorithm. See also 7.26 and 25.83. For
more information about the Zassenhaus algorithm see 25.81 and 25.84.
Note that this functions returns an incorrect result if W 6≤ N (V ).
25.83. SUMAGGROUP
565
gap> d8_1 := AgSubgroup( s4, [ a, c, d ], true );
Subgroup( s4, [ a, c, d ] )
gap> d8_2 := AgSubgroup( s4, [ a*b, c, d ], true );
Subgroup( s4, [ a*b, c, d ] )
gap> IntersectionSumAgGroup( d8_1, d8_2 );
rec(
sum := Group( a*b, b^2, c, d ),
intersection := Subgroup( s4, [ c, d ] ) )
25.83
SumAgGroup
SumAgGroup( V , W )
Let V and W be ag groups with a common parent group, such that W ≤ N (V ). Then
V ∗ W is a subgroup and SumAgGroup returns V ∗ W .
The function uses the Zassenhaus sum-intersection algorithm (see [GS90]).
Note that this functions returns an incorrect result if W 6≤ N (V ).
gap> d8_1 := Subgroup( s4, [ a, c, d ] );
Subgroup( s4, [ a, c, d ] )
gap> d8_2 := Subgroup( s4, [ a*b, c, d ] );
Subgroup( s4, [ a*b, c, d ] )
gap> SumAgGroup( d8_1, d8_2 );
Group( a*b, b^2, c, d )
25.84
SumFactorizationFunctionAgGroup
SumFactorizationFunctionAgGroup( U , N )
Let U and N be ag group with a common parent group such that U normalizes N . Then
the function returns a record R with the following components.
intersection
is bound to the intersection U ∩ N .
sum
is bound to the sum U ∗ N .
factorization
is bound to function, which takes an element g of U ∗ N and returns the factorization
of g in an element u of U and n of N , such that g = u∗n. This factorization is
returned as record r with components r.u and r.n, where r.u is bound to the ag
word u, r.n to the ag word n.
Note that N must be a normal subgroup of U ∗ N , it is not sufficient that U ∗ N = N ∗ U .
gap> v4 := AgSubgroup( s4, [ a*b, c ], true );
Subgroup( s4, [ a*b, c ] )
gap> a4 := AgSubgroup( s4, [ b, c, d ], true );
Subgroup( s4, [ b, c, d ] )
gap> sd := SumFactorizationFunctionAgGroup;
function ( U, N ) ... end
566
CHAPTER 25. FINITE POLYCYCLIC GROUPS
gap> sd := SumFactorizationFunctionAgGroup( v4, a4 );
rec(
sum := Group( a*b, b, c, d ),
intersection := Subgroup( s4, [ c ] ),
factorization := function ( un ) ... end )
gap> sd.factorization( a*b*c*d );
rec(
u := a*b*c,
n := d )
gap> sd.factorization( a*b^2*c*d );
rec(
u := a*b*c,
n := b*c )
25.85
One Cohomology Group
Let G be a finite group, M a normal p-elementary abelian subgroup of G. Then the group
of one coboundaries B 1 (G/M, M ) is defined as
B 1 (G/M, M ) = {γ : G/M → M ; ∃m ∈ M ∀g ∈ G : γ(gM ) = (m−1 )g · m}
and is a Zp -vector space. The group of cocycles Z 1 (G/M, M ) is defined as
Z 1 (G/M, M ) = {γ : G/M → M ; ∀g1 , g2 ∈ G : γ(g1 M · g2 M ) = γ(g1 M )g2 · γ(g2 M )}
and is also a Zp -vector space.
Let α be the isomorphism of M into a row vector space W and (g1 , ..., gl ) representatives for
a generating set of G/M . Then there exists a monomorphism β of Z 1 (G/M, M ) in the l-fold
direct sum of W, such that β(γ) = (α(γ(g1 M )), ..., α(γ(gl M ))) for every γ ∈ Z 1 (G/M, M ).
OneCoboundaries (see 25.86) and OneCocycles (see 25.87) compute the group of one
coboundaries and one cocyles given a ag group G and a elementary abelian normal subgroup M . If Info1Coh1, Info1Coh2 and Info1Coh3 are set to Print information about the
computation is given.
25.86
OneCoboundaries
OneCoboundaries( G, M )
Let M be a normal p-elementary abelian subgroup of G. Then OneCoboundaries computes
the vector space V = β(B 1 (G/M , M )), which is isomorphic to the group of one coboundaries B 1 (G, M ) as described in 25.85. The functions returns a record C with the following
components.
oneCoboundaries
contains the vector space V.
generators
contains representatives (g1 , ..., gl ) for the canonical generating system of G/M
25.87. ONECOCYCLES
567
cocycleToList
contains a functions which takes an element v of V as argument and returns a list
[n1 , ..., nl ], where ni is an element of M , such that ni = (β −1 (v))(gi M ).
listToCocycles
is the inverse of cocycleToList.
OneCoboundaries( G, α, M )
In that form OneCoboundaries computes the one coboundaries in the semidirect product
of G and M where G acts on M using α (see 7.101).
gap> s4xc2 := DirectProduct( s4, CyclicGroup( AgWords, 2 ) );
Group( a1, a2, a3, a4, b )
gap> m := CompositionSubgroup( s4xc2, 3 );
Subgroup( Group( a1, a2, a3, a4, b ), [ a3, a4, b ] )
gap> oc := OneCoboundaries( s4xc2, m );
rec(
oneCoboundaries := RowSpace( GF(2),
[ [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ] ] ),
generators := [ a1, a2 ],
cocycleToList := function ( c ) ... end,
listToCocycle := function ( L ) ... end )
gap> v := Base( oc.oneCoboundaries );
[ [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ] ]
gap> oc.cocycleToList( v[1] );
[ a4, a4 ]
gap> oc.cocycleToList( v[2] );
[ IdAgWord, a3 ]
gap> oc.cocycleToList( v[1]+v[2] );
[ a4, a3*a4 ]
25.87
OneCocycles
OneCocycles( G, M )
Let M be a normal p-elementary abelian subgroup of G. Then OneCocycles computes the
vector space V = β(Z 1 (G/M , M )), which is isomorphic to the group of one cocyles Z 1 (G, M )
as described in 25.85. The function returns a record C with the following components.
oneCoboundaries
contains the vector space isomorphic to B 1 (G, M ).
oneCocycles
contains the vector space V.
generators
contains representatives (g1 , ..., gl ) for the canonical generating system of G/M
isSplitExtension
If G splits over M , C.isSplitExtension is true, otherwise it is false. In case of
568
CHAPTER 25. FINITE POLYCYCLIC GROUPS
a split extension three more components C.complement, C.cocycleToComplement
and C.complementToCycles are returned.
complement
contains a subgroup of G which is a complement of M .
cocycleToList
contains a functions which takes an element v of V as argument and returns a list
[n1 , ..., nl ], where ni is an element of M , such that ni = (β −1 (v))(gi M ).
listToCocycles
is the inverse of cocycleToList.
cocycleToComplement
contains a function which takes an element of V as argument and returns a complement of M .
complementToCocycle
is its inverse. This is possible, because in a split extension there is a one to one
correspondence between the elements of V and the complements of M .
OneCocycles( G, α, M )
In that form OneCocycles computes the one cocycles in the semidirect product of G and M
where G acts on M using α (see 7.101). In that case C only contains C.oneCoboundaries,
C.oneCocycles, C.generators, C.cocycleToList and C.listToCocycle.
gap> s4xc2 := DirectProduct( s4, CyclicGroup( AgWords, 2 ) );;
gap> s4xc2.name := "s4xc2";;
gap> m := CompositionSubgroup( s4xc2, 3 );
Subgroup( s4xc2, [ a3, a4, b ] )
gap> oc := OneCocycles( s4xc2, m );;
gap> oc.oneCocycles;
RowSpace( GF(2), [ [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2) ],
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ] ] )
gap> v := Base( oc.oneCocycles );
[ [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2) ],
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ] ]
gap> oc.cocycleToList( v[1] );
[ a4, a4 ]
gap> oc.cocycleToList( v[2] );
[ b, IdAgWord ]
gap> oc.cocycleToList( v[2] );
[ b, IdAgWord ]
gap> oc.cocycleToList( v[3] );
[ IdAgWord, a3 ]
gap> Igs( oc.complement );
[ a1, a2 ]
gap> Igs( oc.cocycleToComplement( v[1]+v[2]+v[3] ) );
[ a1*a4*b, a2*a3*a4 ]
gap> z4 := CyclicGroup( AgWords, 4 );
25.88. COMPLEMENTS
569
Group( c4_1, c4_2 )
gap> m := CompositionSubgroup( z4, 2 );
Subgroup( Group( c4_1, c4_2 ), [ c4_2 ] )
gap> OneCocycles( z4, m );
rec(
oneCoboundaries := RowSpace( GF(2), [ [ 0*Z(2) ] ] ),
oneCocycles := RowSpace( GF(2), [ [ Z(2)^0 ] ] ),
generators := [ c4_1 ],
isSplitExtension := false )
25.88
Complements
Complement (see 25.89) tries to find one complement to a given normal subgroup, while
Complementclasses (see 25.90) finds all complements and returns representatives for the
conjugacy classes of complements in a given ag group.
If InfoAgCo1 and InfoAgCo2 are set to Print information about the computation is given.
25.89
Complement
Complement( U , N )
Let N and U be ag group such that N is a normal subgroup of U . Complement returns a
complement of N in U if the U splits over N . Otherwise false is returned.
Complement descends along an elementary abelian series of U containing N . See [CNW90]
for details.
gap> v4 := Subgroup( s4, [ c, d ] );
Subgroup( s4, [ c, d ] )
gap> Complement( s4, v4 );
Subgroup( s4, [ a, b ] )
gap> z4 := CyclicGroup( AgWords, 4 );
Group( c4_1, c4_2 )
gap> z2 := Subgroup( z4, [ z4.2 ] );
Subgroup( Group( c4_1, c4_2 ), [ c4_2 ] )
gap> Complement( z4, z2 );
false
gap> m9 := ElementaryAbelianGroup( AgWords, 9 );
Group( m9_1, m9_2 )
gap> m3 := Subgroup( m9, [ m9.2 ] );
Subgroup( Group( m9_1, m9_2 ), [ m9_2 ] )
gap> Complement( m9, m3 );
Subgroup( Group( m9_1, m9_2 ), [ m9_1 ] )
25.90
Complementclasses
Complementclasses( U , N )
Let U and N be ag groups such that N is a normal subgroup of U . Complementclasses
returns a list of representatives for the conjugacy classes of complements of N in U .
570
CHAPTER 25. FINITE POLYCYCLIC GROUPS
Note that the empty list is returned if U does not split over N .
Complementclasses descends along an elementary abelian series of U containing N . See
[CNW90] for details.
gap> v4 := Subgroup( s4, [ c, d ] );
Subgroup( s4, [ c, d ] )
gap> Complementclasses( s4, v4 );
[ Subgroup( s4, [ a, b ] ) ]
gap> z4 := CyclicGroup( AgWords, 4 );
Group( c4_1, c4_2 )
gap> z2 := Subgroup( z4, [ z4.2 ] );
Subgroup( Group( c4_1, c4_2 ), [ c4_2 ] )
gap> Complementclasses( z4, z2 );
[ ]
gap> m9 := ElementaryAbelianGroup( AgWords, 9 );
Group( m9_1, m9_2 )
gap> m3 := Subgroup( m9, [ m9.2 ] );
Subgroup( Group( m9_1, m9_2 ), [ m9_2 ] )
gap> Complementclasses( m9, m3 );
[ Subgroup( Group( m9_1, m9_2 ), [ m9_1 ] ),
Subgroup( Group( m9_1, m9_2 ), [ m9_1*m9_2 ] ),
Subgroup( Group( m9_1, m9_2 ), [ m9_1*m9_2^2 ] ) ]
25.91
CoprimeComplement
CoprimeComplement( U , N )
CoprimeComplement returns a complement of a normal p-elementary abelian Hall subgroup
N of U .
Note that, as N is a normal Hall-subgroup of U , the theorem of Schur guarantees the
existence of a complement.
gap> s4xc25 := DirectProduct( s4, CyclicGroup( AgWords, 25 ) );
Group( a1, a2, a3, a4, b1, b2 )
gap> s4xc25.name := "s4xc25";;
gap> a4xc25 := Subgroup( s4xc25,
>
Sublist( s4xc25.generators, [2..5] ) );
Subgroup( s4xc25, [ a2, a3, a4, b1 ] )
gap> N := Subgroup( s4xc25, [ s4xc25.3, s4xc25.4 ] );
Subgroup( s4xc25, [ a3, a4 ] )
gap> CoprimeComplement( a4xc25, N );
Subgroup( s4xc25, [ a2, b1, b2 ] )
25.92
ComplementConjugatingAgWord
ComplementConjugatingAgWord( N , U , V )
ComplementConjugatingAgWord( N , U , V , K )
Let N , U , V and K be ag groups with a common parent group G, such that N is pelementary abelian and normal in G, U ∗ N = V ∗ N , U ∩ N = V ∩ N = {1}, K is a normal
25.93. HALLCONJUGATINGWORDAGGROUP
571
subgroup of U N contained in U ∩ V and U is conjugate to V under an element n of N .
Then this function returns an element n of N such that U n = V as ag word. If K is not
given, the trivial subgroup is assumed.
In a typical application N is a normal p-elementary abelian subgroup and U , V and K are
subgroups such that U /K is a q-group with q 6= p.
Note that this function does not check any of the above conditions. So the result may either
be false or an ag word with does not conjugate U into V , if U and V are not conjugate.
gap> c3a := Subgroup( s4, [ b ] );
Subgroup( s4, [ b ] )
gap> c3b := Subgroup( s4, [ b*c ] );
Subgroup( s4, [ b*c ] )
gap> v4 := Subgroup( s4, [ c, d ] );
Subgroup( s4, [ c, d ] )
gap> ComplementConjugatingAgWord( v4, c3a, c3b );
d
gap> c3a ^ d;
Subgroup( s4, [ b*c ] )
25.93
HallConjugatingWordAgGroup
HallConjugatingAgWord( S , H , K )
Let H , K and S be ag group with a common parent group such that H and K are Hallsubgroups of S , then HallConjugatingAgWord returns an element g of S as ag word, such
that H g = K .
gap> d8 := HallSubgroup( s4, 2 );
Subgroup( s4, [ a, c, d ] )
gap> d8 ^ b;
Subgroup( s4, [ a*b^2, c*d, d ] )
gap> HallConjugatingAgWord( s4, d8, d8 ^ b );
b
gap> HallConjugatingAgWord( s4, d8 ^ b, d8 );
b^2
25.94
Example, normal closure
We will now show you how to write a GAP3 function, which computes the normal closure of
an ag group. Such a function already exists in the library (see 7.25), but this should be an
example on how to put functions together. You should at least be familiar with the basic
definitions and functions for ag groups, so please refer to 24, 25 and 25.1 for the definitions
of finite polycyclic groups and its subgroups, see 25.48 for information about calculating
induced or canonical generating system for subgroups.
Let U and S be subgroups of a group G. Then the normal closure N of U under S is the
smallest subgroup in G, which contains U and is invariant under conjugation with elements
of S. It is clear that N is invariant under conjugating with generators of S if and only if it
is invariant under conjugating with all elements of S.
572
CHAPTER 25. FINITE POLYCYCLIC GROUPS
So in order to compute the normal closure of U , we can start with N := U , conjugate N
with a generator s of S and set N to the subgroup generated by N and N s . Then we take
the next generator of S. The whole process is repeated until N is stable. A GAP3 function
doing this looks like
NormalClosure := function( S, U )
local
G,
N,
M,
s;
#
#
#
#
the common supergroup of S and U
closure computed so far
next closure under generators of S
one generator of S
G := Parent( S, U );
M := U;
repeat
N := M;
for s in Igs( S ) do
M := MergedCgs( G, [ M ^ s, M ] );
od;
until M = N;
return N;
end;
Let S = G be the wreath product of the symmetric group on four points with itself using
the natural permutation representation. Let U be a randomly chosen subgroup of order 12.
The above functions needs, say, 100 time units to compute the normal closure of U under
S, which is a subgroup N of index 2 in G.
gap> prms := [ (1,2), (1,2,3), (1,3)(2,4), (1,2)(3,4) ];
[ (1,2), (1,2,3), (1,3)(2,4), (1,2)(3,4) ]
gap> f := GroupHomomorphismByImages( s4, Group( prms, () ),
>
s4.generators, prms );;
gap> G := WreathProduct( s4, s4, f );
Group( h1, h2, h3, h4, n1_1, n1_2, n1_3, n1_4, n2_1, n2_2, n2_3,
n2_4, n3_1, n3_2, n3_3, n3_4, n4_1, n4_2, n4_3, n4_4 )
gap> G.name := "G";;
gap> u := Random( G );
h1*h3*h4*n1_1*n1_3*n1_4*n2_1*n2_2*n2_3*n2_4*n3_2*n3_3*n4_1*n4_3*n4_4
gap> U := MergedCgs( G, [ u ] );
Subgroup( G,
[ h1*h3*n1_2^2*n1_3*n1_4*n2_1*n2_3*n3_1*n3_2*n3_4*n4_1*n4_3,
h4*n1_4*n2_1*n2_4*n3_1*n3_2*n4_2^2*n4_4,
n1_1*n2_1*n3_1*n3_2^2*n3_3*n3_4*n4_1*n4_4 ] )
gap> Size( U );
8
Now we can ask to speed up things. The first observation is that computing a canonical
generating system is usablely a more time consuming task than computing a conjugate
subgroup. So we form a canonical generating system after we have computed all conjugate
subgroups, although now an additional repeat-until loop could be necessary.
25.94. EXAMPLE, NORMAL CLOSURE
573
NormalClosure := function( S, U )
local
G, N, M, s, gens;
G := Parent( S, U );
M := U;
repeat
N := M;
gens := [ M ];
for s in Igs( S ) do
Add( gens, M ^ s );
od;
M := MergedCgs( G, gens );
until M = N;
return N;
end;
If we now test this new normal closure function with the above groups, we see that the
running time has decreased to 48 time units. The canonical generating system algorithm is
faster if it knows a large subgroup of the group which should be generated but it does not
gain speed if it knows several of them. A canonical generating system for the conjugated
subgroup M^s is computed, although we only need generators for this subgroup. So we can
rewrite our algorithm.
NormalClosure := function( S, U )
local
G,
N,
M,
gensS,
gens;
#
#
#
#
#
the common supergroup of S and U
closure computed so far
next closure under generators of S
generators of S
generators of next step
G := Parent( S, U );
M := U;
gens := Igs( S );
repeat
N := M;
gens := Concatenation( [ M ], Concatenation( List( S, s ->
List( Igs( M ), m -> m ^ s ) ) ) );
M := MergedCgs( G, gens );
until M = N;
return N;
end;
Now a canonical generating system is generated only once per repeat-until loop. This reduces
the running time to 33 time units. Let m ∈ M and s ∈ S. Then hM, ms i = hM, m−1 ms i.
So we can substitute m^s by Comm( m, s ). If m is invariant under s the new generator
would be 1 instead of m. With this modification the running times drops to 23 time units.
As next step we can try to compute induced generating systems instead of canonical ones.
574
CHAPTER 25. FINITE POLYCYCLIC GROUPS
In that case we cannot compare aggroups by =, but as N is a subgroup M it is sufficient to
compare the composition lengths.
NormalClosure := function( S, U )
local
G,
N,
M,
gensS,
gens;
#
#
#
#
#
the common supergroup of S and U
closure computed so far
next closure under generators of S
generators of S
generators of next step
G := Parent( S, U );
M := U;
gens := Igs( S );
repeat
N := M;
gens := Concatenation( List( S, s -> List( Igs( M ),
m -> Comm( m, s ) ) ) );
M := MergedIgs( G, N, gens, false );
until Length( Igs( M ) ) = Length( Igs( M ) );
Normalize( N );
return N;
end;
But if we try the example above the running time has increased to 31. As the normal
closure has index 2 in G the agwords involved in a canonical generating system are of length
one or two. But agwords of induced generating system may have much large length. So we
have avoided some collections but made the collection process itself much more complicated.
Nevertheless in examples with subgroups of greater index the last function is slightly faster.
Chapter 26
Special Ag Groups
Special ag groups are a subcategory of ag groups (see 25).
Let G be an ag group with PAG system (g1 , . . . , gn ). Then (g1 , . . . , gn ) is a special ag
system if it is an ag system with some additional properties, which are described below.
In general a finite polycyclic group has several different ag systems and at least one of this is
a special ag system, but in GAP3 an ag group is defined by a fixed ag system and according
to this an ag group is called a special ag group if its ag system is a special ag system.
Special ag systems give more information about their corresponding group than arbitrary
ag systems do (see 26.1) and furthermore there are many algorithms, which are much more
efficient for a special ag group than for an arbitrary one. (See 26.7)
The following sections describe the special ag system (see 26.1), their construction in GAP3
(see 26.2 and 26.3) and their additional record entries (see 26.4). Then follow two sections
with functions which do only work for special ag groups (see 26.5 and 26.6).
26.1
More about Special Ag Groups
Now the properties of a special ag system are described. First of all the Leedham-Green
series will be introduced.
Let G = G1 > G2 > . . . > Gm > Gm+1 = {1} be the lower nilpotent series of G, i.e., Gi
is the smallest normal subgroup of Gi−1 such that Gi−1 /Gi is nilpotent.
To refine this series the lower elementary abelian series of a nilpotent group N will be
constructed. Let N = P1 · . . . · Pl be the direct product of its Sylow-subgroups such that Ph
is a ph -group and p1 < p2 < . . . < pl holds. Let λj (Ph ) be the j-th term of the ph -central
series of Ph and let kh be the length of this series (see 7.42). Define Nj,ph as the subgroup
of N with
Nj,ph = λj+1 (P1 ) · · · λj+1 (Ph−1 ) · λj (Ph ) · · · λj (Pl ).
With k =max{k1 , . . . , kl } the series
N = N1,p1 ≥ N1,p2 ≥ . . . ≥ N1,pl ≥ N2,p1 ≥ . . . ≥ Nk,pl = {1}
is obtained. Since the p-central series may have different lengths for different primes, some
subgroups might be equal. The lower elementary abelian series is obtained, if for all pairs
575
576
CHAPTER 26. SPECIAL AG GROUPS
of equal subgroups the one with the lexicographically greater index is removed. This series
is a characteristic central series with maximal elementary abelian factors.
To get the Leedham-Green series of G, each factor of the lower nilpotent series of G is refined
by its lower elementary abelian series. The subgroups of the Leedham-Green series are
denoted by Gi,j,pi,h such that Gi,j,pi,h /Gi+1 = (Gi /Gi+1 )j,pi,h for each prime pi,h dividing
the order of Gi /Gi+1 . The Leedham-Green series is a characteristic series with elementary
abelian factors.
A PAG system corresponds naturally to a composition series of its group. The first additional
property of a special ag system is that the corresponding composition series refines the
Leedham-Green series.
Secondly, all the elements of a special ag system are of prime-power order, and furthermore,
if a set of primes π = {q1 , . . . , qr } is given, all elements of a special ag system which are
of qh -power order for some qh in π generate a Hall-π-subgroup of G. In fact they form
a canonical generating sequence of the Hall-π-subgroup. These Hall subgroups are called
public subgroups, since a subset of the PAG system is an induced generating set for the
subgroup. Note that the set of all public Sylow subgroups forms a Sylow system of G.
The last property of the special ag systems is the existence of public local head complements. For a nilpotent group N , the group
λ2 (N ) = λ2 (P1 ) · · · λ2 (Pl )
is the Frattini subgroup of N . The local heads of the group G are the factors
(Gi /Gi+1 )/λ2 (Gi /Gi+1 ) = Gi /Gi,2,pi,1
for each i. A local head complement is a subgroup Ki of G such that Ki /Gi,2,pi,1 is a
complement of Gi /Gi,2,pi1 . Now a special ag system has a public local head complement
for each local head. This complement is generated by the elements of the special ag system
which do not lie in Gi \Gi,2,pi,1 . Note that all complements of a local head are conjugate.
The factors
λ2 (Gi /Gi+1 ) = Gi,2,pi,1 /Gi+1
are called the tails of the group G.
To handle the special ag system the weights are introduced. Let (g1 , . . . , gn ) be a special ag
system. The triple (w1 , w2 , w3 ) is called the weight of the generator gi if gi lies in Gw1 ,w2 ,w3
but not lower down in the Leedham-Green series. That means w1 corresponds to the subgroup in the lower nilpotent series and w2 to the subgroup in the elementary-abelian series
of this factor, and w3 is the prime dividing the order of gi . Then weight(gi ) = (w1 , w2 , w3 )
and weightj (gi ) = wj for j = 1, 2, 3 is set. With this definition {gi |weight3 (gi ) ∈ π} is a
Hall-π-subgroup of G and {gi |weight(gi ) 6= (j, 1, p) for some p} is a local head complement.
Now some advantages of a special ag system are summarized.
1. You have a characteristic series with elementary abelian factors of G explicitly given
in the ag system. This series is refined by the composition series corresponding to the
ag system.
2. You can see whether G is nilpotent or even a p-group, and if it is, you have a central
series explicitly given by the Leedham-Green series. Analogously you can see whether
the group is even elementary abelian.
26.2. CONSTRUCTION OF SPECIAL AG GROUPS
577
3. You can easily calculate Hall-π-subgroups of G. Furthermore the set of public Sylow
subgroups forms a Sylow system.
4. You get a smaller generating set of the group by taking only the elements which
correspond to local heads of the group.
5. The collection with a special ag system may be faster than the collection with an arbitrary ag system, since in the calculation of the public subgroups of G the commutators
of the ag generators are shortened.
6. Many algorithms are faster for special ag groups than for arbitrary ag groups.
26.2
Construction of Special Ag Groups
SpecialAgGroup( G )
The function SpecialAgGroup takes an ag group G as input and calculates a special ag
group H, which is isomorphic to G.
To obtain the additional information of a special ag system see 26.4.
26.3
Restricted Special Ag Groups
If one is only interested in some of the information of special ag systems then it is possible
to suppress the calculation of one or all types of the public subgroups by calling the function
SpecialAgGroup( G, flag ), where flag is ”noHall”, ”noHead”or ”noPublic”. With this
options the algorithm takes less time. It calculates an ag group H, which is isomorphic to
G. But be careful, because the output H is not handled as a special ag group by GAP3 but
as an arbitrary ag group. Exspecially none of the functions listet in 26.7 use the algorithms
for special ag groups.
SpecialAgGroup( G, "noPublic")
calculates an ag group H, which is isomorphic to G and whose ag system is corresponding
to the Leedham-Green series.
SpecialAgGroup( G, "noHall")
calculates an ag group H, which is isomorphic to G and whose ag system is corresponding
to the Leedham-Green series and has public local head complements.
SpecialAgGroup( G, "noHead")
calculates an ag group H, which is isomorphic to G and whose ag system is corresponding
to the Leedham-Green series and has public Hall subgroups.
To obtain the additional information of a special ag system see 26.4.
578
CHAPTER 26. SPECIAL AG GROUPS
26.4
Special Ag Group Records
In addition to the record components of ag groups (see 25) the following components are
present in the group record of a special ag group H.
weights
This is a list of weights such that the i-th entry gives the weight of the element
hi , i.e., the triple (w1 , w2 , w3 ) when hi lies in Gw1 ,w2 ,w3 but not lower down in the
Leedham-Green series (see 26.1).
The entries layers, first, head and tail only depend on the weights. These entries are
useful in many of the programs using the special ag system.
layers
This is a list of integers. Assume that the subgroups of the Leedham-Green series are
numbered beginning at G and ending at the trivial group. Then the i-th entry gives
the number of the subgroup in the Leedham-Green series to which hi corresponds as
described in weights.
first
This is a list of integers, and first[j] = i if hi is the first element of the j-th layer.
Additionally the last entry of the list first is always n + 1.
head
This is a list of integers, and head[j] = i if hi is the first element of the j-th local
head. Additionally the last entry of the list head is always n + 1 (see 26.1).
tail
This is a list of integers, and tail[j] = i if hi−1 is the last element of the j-th local
head. In other words hi is either the first element of the tail of the j-th layer in
the lower nilpotent series, or in case this tail is trivial, then hi is the first element of
the j + 1-st layer in the lower nilpotent series. If the tail of the smallest nontrivial
subgroup of the lower nilpotent series is trivial, then the last entry of the list tail is
n + 1 (see 26.1).
bijection
This is the isomorphism from H to G given through the images of the generators of
H.
The next four entries indicate if any flag and which one is used in the calculation of the
special ag system (see 26.2 and 26.3).
isHallSystem
This entry is a Boolean. It is true if public Hall subgroups have been calculated, and
false otherwise.
isHeadSystem
This entry is a Boolean. It is true if public local head complements have been calculated, and false otherwise.
isSagGroup
This entry is a Boolean. It is true if public Hall subgroups and public local head
complements have been calculated, and false otherwise.
Note that in GAP3 an ag group is called a special ag group if and only if the record entry
isSagGroup is true.
26.5. MATGROUPSAGGROUP
579
# construct a wreath product of a4 with s3 where s3 operates on 3 points.
gap> s3 := SymmetricGroup( AgWords, 3 );;
gap> a4 := AlternatingGroup( AgWords, 4 );;
gap> a4wrs3 := WreathProduct(a4, s3, s3.bijection);
Group( h1, h2, n1_1, n1_2, n1_3, n2_1, n2_2, n2_3, n3_1, n3_2, n3_3 )
# now calculate the special ag group
gap> S := SpecialAgGroup( a4wrs3 );
Group( h1, n3_1, h2, n2_1, n1_1, n1_2, n1_3, n2_2, n2_3, n3_2, n3_3 )
gap> S.weights;
[ [ 1, 1, 2 ], [ 1, 1, 3 ], [ 2, 1, 3 ], [ 2, 1, 3 ], [ 2, 2, 3 ],
[ 3, 1, 2 ], [ 3, 1, 2 ], [ 3, 1, 2 ], [ 3, 1, 2 ], [ 3, 1, 2 ],
[ 3, 1, 2 ] ]
gap> S.layers;
[ 1, 2, 3, 3, 4, 5, 5, 5, 5, 5, 5 ]
gap> S.first;
[ 1, 2, 3, 5, 6, 12 ]
gap> S.head;
[ 1, 3, 6, 12 ]
gap> S.tail;
[ 3, 5, 12 ]
gap> S.bijection;
GroupHomomorphismByImages( Group( h1, n3_1, h2, n2_1, n1_1, n1_2,
n1_3, n2_2, n2_3, n3_2, n3_3 ), Group( h1, h2, n1_1, n1_2, n1_3,
n2_1, n2_2, n2_3, n3_1, n3_2, n3_3 ),
[ h1, n3_1, h2, n2_1, n1_1, n1_2, n1_3, n2_2, n2_3, n3_2, n3_3 ],
[ h1, n3_1, h2, n2_1*n3_1^2, n1_1*n2_1*n3_1, n1_2, n1_3, n2_2, n2_3,
n3_2, n3_3 ] )
gap> S.isHallSystem;
true
gap> S.isHeadSystem;
true
gap> S.isSagGroup;
true
In the next sections the functions which only apply to special ag groups are described.
26.5
MatGroupSagGroup
MatGroupSagGroup( H , i )
MatGroupSagGroup calculates the matrix representation of H on the i-th layer of the Leedham-Green series of H (see 26.1).
See also MatGroupAgGroup.
gap> S := SpecialAgGroup( a4wrs3 );;
gap> S.weights;
[ [ 1, 1, 2 ], [ 1, 1, 3 ], [ 2, 1, 3 ], [ 2, 1, 3 ], [ 2, 2, 3 ],
[ 3, 1, 2 ], [ 3, 1, 2 ], [ 3, 1, 2 ], [ 3, 1, 2 ], [ 3, 1, 2 ],
[ 3, 1, 2 ] ]
580
CHAPTER 26. SPECIAL AG GROUPS
gap> MatGroupSagGroup(S,3);
Group( [ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ],
[ [ Z(3)^0, Z(3)^0 ], [ 0*Z(3), Z(3)^0 ] ] )
26.6
DualMatGroupSagGroup
DualMatGroupSagGroup( H , i )
DualMatGroupSagGroup calculates the dual matrix representation of H on the i-th layer of
the Leedham-Green series of H (see 26.1).
Let V be an F H-module for a field F . Then the dual module to V is defined by V ∗ := {f :
V → F |f is linear }. This module is also an F H-module and the dual matrix representation
is the representation on the dual module.
gap> S := SpecialAgGroup( a4wrs3 );;
gap> DualMatGroupSagGroup(S,3);
Group( [ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ],
[ [ Z(3)^0, 0*Z(3) ], [ Z(3)^0, Z(3)^0 ] ] )
26.7
Ag Group Functions for Special Ag Groups
Since special ag groups are ag groups all functions for ag groups are applicable to special
ag groups. However certain of these functions use special implementations to treat special
ag groups, i.e. there exists functions like SagGroupOps.FunctionName, which are called
by the corresponding general function in case a special ag group given. If you call one of
these general functions with an arbitrary ag group, the general function will not calculate
the special ag group but use the function for ag groups. For the special implementations to
treat special ag groups note the following.
Centre( H )
MinimalGeneratingSet( H )
Intersection( U , L)
EulerianFunction( H ) MaximalSubgroups( H )
ConjugacyClassesMaximalSubgroups( H )
PrefrattiniSubgroup( H )
FrattiniSubgroup( H )
IsNilpotent( H )
These functions are often faster and often use less space for special ag groups.
ElementaryAbelianSeries( H )
This function returns the Leedham-Green series (see 26.1).
IsElementaryAbelianSeries( H )
Returns true.
HallSubgroup( H , primes )
SylowSubgroup( H , p )
26.7. AG GROUP FUNCTIONS FOR SPECIAL AG GROUPS
581
SylowSystem( H )
These functions return the corresponding public subgroups (see 26.1).
Subgroup( H , gens )
AgSubgroup( H , gens, bool )
These functions return an ag group which is not special, except if the group itself is returned.
All domain functions not mentioned here use no special treatments for special ag groups.
Note also that there exists a package to compute formation theoretic subgroups of special
ag groups. This may be used to compute the system normalizer of the public Sylow system,
which is the F -normalizer for the formation of nilpotent groups F . It is also possible to
compute F -normalizers as well as F -covering subgroups and F -residuals of special ag groups
for a number of saturated formations F which are given within the package or for self-defined
saturated formations F .
582
CHAPTER 26. SPECIAL AG GROUPS
Chapter 27
Lists
Lists are the most important way to collect objects and treat them together. A list is
a collection of elements. A list also implies a partial mapping from the integers to the
elements. I.e., there is a first element of a list, a second, a third, and so on.
List constants are written by writing down the elements in order between square brackets
[, ], and separating them with commas ,. An empty list, i.e., a list with no elements, is
written as [].
gap>
[ 1,
gap>
[ [
[ 1, 2, 3
2, 3 ]
[ [], [ 1
], [ 1 ],
];
# a list with three elements
], [ 1, 2 ] ];
[ 1, 2 ] ]
# a list may contain other lists
Usually a list has no holes, i.e., contain an element at every position. However, it is absolutely
legal to have lists with holes. They are created by leaving the entry between the commas
empty. Lists with holes are sometimes convenient when the list represents a mapping from
a finite, but not consecutive, subset of the positive integers. We say that a list that has no
holes is dense.
gap> l := [ , 4, 9,, 25,, 49,,,, 121 ];;
gap> l[3];
9
gap> l[4];
Error, List Element: [4] must have a value
It is most common that a list contains only elements of one type. This is not a must though.
It is absolutely possible to have lists whose elements are of different types. We say that a
list whose elements are all of the same type is homogeneous.
gap> l := [ 1, E(2), Z(3), (1,2,3), [1,2,3], "What a mess" ];;
gap> l[1]; l[3]; l[5][2];
1
Z(3)
2
The first sections describe the functions that test if an object is a list and convert an object
to a list (see 27.1 and 27.2).
583
584
CHAPTER 27. LISTS
The next section describes how one can access elements of a list (see 27.4 and 27.5).
The next sections describe how one can change lists (see 27.6, 27.7, 27.8, 27.9, 27.11).
The next sections describe the operations applicable to lists (see 27.12 and 27.13).
The next sections describe how one can find elements in a list (see 27.14, 27.15, 27.16, 27.19).
The next sections describe the functions that construct new lists, e.g., sublists (see 27.22,
27.23, 27.24, 27.25, 27.26).
The next sections describe the functions deal with the subset of elements of a list that have
a certain property (see 27.27, 27.28, 27.30, 27.32, 27.33, 27.34).
The next sections describe the functions that sort lists (see 27.35, 27.36, 27.38, 27.41).
The next sections describe the functions to compute the product, sum, maximum, and
minimum of the elements in a list (see 27.42, 27.43, 27.45, 27.46, 27.47).
The final section describes the function that takes a random element from a list (see 27.48).
Lists are also used to represent sets, subsets, vectors, and ranges (see 28, 29, 32, and 31).
27.1
IsList
IsList( obj )
IsList returns true if the argument obj , which can be an arbitrary object, is a list and
false otherwise. Will signal an error if obj is an unbound variable.
gap> IsList( [ 1, 3, 5, 7 ] );
true
gap> IsList( 1 );
false
27.2
List
List( obj )
List( list, func )
In its first form List returns the argument obj , which must be a list, a permutation, a string
or a word, converted into a list. If obj is a list, it is simply returned. If obj is a permutation,
List returns a list where the i -th element is the image of i under the permutation obj . If
obj is a word, List returns a list where the i -th element is the i -th generator of the word,
as a word of length 1.
gap>
[ 1,
gap>
[ 2,
List( [1,2,3] );
2, 3 ]
List( (1,2)(3,4,5) );
1, 4, 5, 3 ]
In its second form List returns a new list, where each element is the result of applying the
function func, which must take exactly one argument and handle the elements of list, to the
corresponding element of the list list. The list list must not contain holes.
gap> List( [1,2,3], x->x^2 );
[ 1, 4, 9 ]
gap> List( [1..10], IsPrime );
27.3. APPLYFUNC
585
[ false, true, true, false, true, false, true, false, false, false ]
Note that this function is called map in Lisp and many other similar programming languages.
This name violates the GAP3 rule that verbs are used for functions that change their arguments. According to this rule map would change list, replacing every element with the result
of the application func to this argument.
27.3
ApplyFunc
ApplyFunc( func, arglist )
ApplyFunc invokes the function func as if it had been called with the elements of arglist as
its arguments and returns the value, if any, returned by that invocation.
gap> foo := function(arg1, arg2)
> Print("first ",arg1," second ",arg2,"\n"); end;
function ( arg1, arg2 ) ... end
gap> foo(1,2);
first 1 second 2
gap> ApplyFunc(foo,[1,2]);
first 1 second 2
gap> ApplyFunc(Position,[[1,2,3],2]);
2
27.4
List Elements
list[ pos ]
The above construct evaluates to the pos-th element of the list list. pos must be a positive
integer. List indexing is done with origin 1, i.e., the first element of the list is the element
at position 1.
gap>
gap>
2
gap>
3
gap>
13
l := [ 2, 3, 5, 7, 11, 13 ];;
l[1];
l[2];
l[6];
If list does not evaluate to a list, or pos does not evaluate to a positive integer, or list[pos]
is unbound an error is signalled. As usual you can leave the break loop (see 3.2) with quit;.
On the other hand you can return a result to be used in place of the list element by return
expr ;.
list{ poss }
The above construct evaluates to a new list new whose first element is list[poss[1]], whose
second element is list[poss[2]], and so on. poss must be a dense list of positive integers, it
need, however, not be sorted and may contain duplicate elements. If for any i , list[ poss[i ]
] is unbound, an error is signalled.
gap> l := [ 2, 3, 5, 7, 11, 13, 17, 19 ];;
gap> l{[4..6]};
586
CHAPTER 27. LISTS
[ 7, 11, 13 ]
gap> l{[1,7,1,8]};
[ 2, 17, 2, 19 ]
The result is a new list, that is not identical to any other list. The elements of that list
however are identical to the corresponding elements of the left operand (see 27.9).
It is possible to nest such sublist extractions, as can be seen in the following example.
gap> m := [ [1,2,3], [4,5,6], [7,8,9], [10,11,12] ];;
gap> m{[1,2,3]}{[3,2]};
[ [ 3, 2 ], [ 6, 5 ], [ 9, 8 ] ]
gap> l := m{[1,2,3]};; l{[3,2]};
[ [ 7, 8, 9 ], [ 4, 5, 6 ] ]
Note the difference between the two examples. The latter extracts elements 1, 2, and 3 from
m and then extracts the elements 3 and 2 from this list. The former extracts elements 1, 2,
and 3 from m and then extracts the elements 3 and 2 from each of those element lists.
To be precise. With each selector [pos] or {poss} we associate a level that is defined as
the number of selectors of the form {poss} to its left in the same expression. For example
l[pos1]{poss2}{poss3}[pos4]{poss5}[pos6]
level
0
0
1
1
1
2
Then a selector list[pos] of level level is computed as ListElement(list,pos,level ), where
ListElement is defined as follows
ListElement :=
if level =
return
else
return
fi;
end;
function ( list, pos, level )
0 then
list[pos];
List( list, elm -> ListElement(elm,pos,level-1) );
and a selector list{poss} of level level is computed as ListElements(list,poss,level ), where
ListElements is defined as follows
ListElements := function ( list, poss, level )
if level = 0 then
return list{poss};
else
return List( list, elm -> ListElements(elm,poss,level-1) );
fi;
end;
27.5
Length
Length( list )
Length returns the length of the list list. The length is defined as 0 for the empty list,
and as the largest positive integer index such that list[index ] has an assigned value for
nonempty lists. Note that the length of a list may change if new elements are added to it
or assigned to previously unassigned positions.
27.6. LIST ASSIGNMENT
587
gap> Length( [] );
0
gap> Length( [ 2, 3, 5, 7, 11, 13, 17, 19 ] );
8
gap> Length( [ 1, 2,,, 5 ] );
5
For lists that contain no holes Length, Number (see 27.27), and Size (see 4.10) return the
same value. For lists with holes Length returns the largest index of a bound entry, Number
returns the number of bound entries, and Size signals an error.
27.6
List Assignment
list[ pos ] := object;
The list assignment assigns the object object, which can be of any type, to the list entry at
the position pos, which must be a positive integer, in the list list. That means that accessing
the pos-th element of the list list will return object after this assignment.
gap>
gap>
[ 3,
gap>
[ 3,
gap>
[ 3,
l := [ 1, 2,
l[1] := 3;;
2, 3 ]
l[2] := [ 4,
[ 4, 5, 6 ],
l[ l[1] ] :=
[ 4, 5, 6 ],
3 ];;
l;
5, 6 ];;
3 ]
10;; l;
10 ]
# assign a new object
l;
# object may be of any type
# index may be an expression
If the index pos is larger than the length of the list list (see 27.5), the list is automatically
enlarged to make room for the new element. Note that it is possible to generate lists with
holes that way.
gap>
[ 3,
gap>
[ 3,
l[4] :=
[ 4, 5,
l[ 10 ]
[ 4, 5,
"another entry";; l; # list is enlarged
6 ], 10, "another entry" ]
:= 1;; l;
# now list has a hole
6 ], 10, "another entry",,,,,, 1 ]
The function Add (see 27.7) should be used if you want to add an element to the end of the
list.
Note that assigning to a list changes the list. The ability to change an object is only available
for lists and records (see 27.9).
If list does not evaluate to a list, pos does not evaluate to a positive integer or object is a
call to a function which does not return a value, for example Print (see 3.14), an error is
signalled As usual you can leave the break loop (see 3.2) with quit;. On the other hand
you can continue the assignment by returning a list, an index or an object using return
expr ;.
list{ poss } := objects;
The list assignment assigns the object objects[1], which can be of any type, to the list list
at the position poss[1], the object objects[2] to list[poss[2]], and so on. poss must be
a dense list of positive integers, it need, however, not be sorted and may contain duplicate
elements. objects must be a dense list and must have the same length as poss.
588
CHAPTER 27. LISTS
gap> l := [ 2, 3, 5, 7, 11, 13, 17, 19 ];;
gap> l{[1..4]} := [10..13];; l;
[ 10, 11, 12, 13, 11, 13, 17, 19 ]
gap> l{[1,7,1,10]} := [ 1, 2, 3, 4 ];; l;
[ 3, 11, 12, 13, 11, 13, 2, 19,, 4 ]
It is possible to nest such sublist assignments, as can be seen in the following example.
gap> m := [ [1,2,3], [4,5,6], [7,8,9], [10,11,12] ];;
gap> m{[1,2,3]}{[3,2]} := [ [11,12], [13,14], [15,16] ];; m;
[ [ 1, 12, 11 ], [ 4, 14, 13 ], [ 7, 16, 15 ], [ 10, 11, 12 ] ]
The exact behaviour is defined in the same way as for list extractions (see 27.4). Namely
with each selector [pos] or {poss} we associate a level that is defined as the number of
selectors of the form {poss} to its left in the same expression. For example
l[pos1]{poss2}{poss3}[pos4]{poss5}[pos6]
level
0
0
1
1
1
2
Then a list assignment list[pos] := vals; of level level is computed as ListAssignment(
list, pos, vals, level ), where ListAssignment is defined as follows
ListAssignment := function ( list, pos, vals, level )
local i;
if level = 0 then
list[pos] := vals;
else
for i in [1..Length(list)] do
ListAssignment( list[i], pos, vals[i], level-1 );
od;
fi;
end;
and a list assignment list{poss} := vals of level level is computed as ListAssignments(
list, poss, vals, level ), where ListAssignments is defined as follows
ListAssignments := function ( list, poss, vals, level )
local i;
if level = 0 then
list{poss} := vals;
else
for i in [1..Length(list)] do
ListAssignments( list[i], poss, vals[i], level-1 );
od;
fi;
end;
27.7
Add
Add( list, elm )
Add adds the element elm to the end of the list list, i.e., it is equivalent to the assignment
list[ Length(list) + 1 ] := elm. The list is automatically enlarged to make room for the
new element. Add returns nothing, it is called only for its side effect.
27.8. APPEND
589
Note that adding to a list changes the list. The ability to change an object is only available
for lists and records (see 27.9).
To add more than one element to a list use Append (see 27.8).
gap> l := [ 2, 3, 5 ];;
[ 2, 3, 5, 7 ]
27.8
Add( l, 7 );
l;
Append
Append( list1 , list2 )
Append adds (see 27.7) the elements of the list list2 to the end of the list list1 . list2 may
contain holes, in which case the corresponding entries in list1 will be left unbound. Append
returns nothing, it is called only for its side effect.
gap>
[ 2,
gap>
[ 2,
l := [ 2, 3,
3, 5, 7, 11,
Append( l, [
3, 5, 7, 11,
5 ];; Append( l, [ 7, 11, 13 ] );
13 ]
17,, 23 ] ); l;
13, 17,, 23 ]
l;
Note that appending to a list changes the list. The ability to change an object is only
available for lists and records (see 27.9).
Note that Append changes the first argument, while Concatenation (see 27.22) creates
a new list and leaves its arguments unchanged. As usual the name of the function that
work destructively is a verb, but the name of the function that creates a new object is a
substantive.
27.9
Identical Lists
With the list assignment (see 27.6, 27.7, 27.8) it is possible to change a list. The ability to
change an object is only available for lists and records. This section describes the semantic
consequences of this fact.
You may think that in the following example the second assignment changes the integer,
and that therefore the above sentence, which claimed that only lists and records can be
changed is wrong
i := 3;
i := i + 1;
But in this example not the integer 3 is changed by adding one to it. Instead the variable
i is changed by assigning the value of i+1, which happens to be 4, to i. The same thing
happens in the following example
l := [ 1, 2 ];
l := [ 1, 2, 3 ];
The second assignment does not change the first list, instead it assigns a new list to the
variable l. On the other hand, in the following example the list is changed by the second
assignment.
l := [ 1, 2 ];
l[3] := 3;
590
CHAPTER 27. LISTS
To understand the difference first think of a variable as a name for an object. The important
point is that a list can have several names at the same time. An assignment var := list;
means in this interpretation that var is a name for the object list. At the end of the following
example l2 still has the value [ 1, 2 ] as this list has not been changed and nothing else
has been assigned to it.
l1 := [ 1, 2 ];
l2 := l1;
l1 := [ 1, 2, 3 ];
But after the following example the list for which l2 is a name has been changed and thus
the value of l2 is now [ 1, 2, 3 ].
l1 := [ 1, 2 ];
l2 := l1;
l1[3] := 3;
We shall say that two lists are identical if changing one of them by a list assignment also
changes the other one. This is slightly incorrect, because if two lists are identical, there are
actually only two names for one list. However, the correct usage would be very awkward
and would only add to the confusion. Note that two identical lists must be equal, because
there is only one list with two different names. Thus identity is an equivalence relation that
is a refinement of equality.
Let us now consider under which circumstances two lists are identical.
If you enter a list literal than the list denoted by this literal is a new list that is not identical
to any other list. Thus in the following example l1 and l2 are not identical, though they
are equal of course.
l1 := [ 1, 2 ];
l2 := [ 1, 2 ];
Also in the following example, no lists in the list l are identical.
l := [];
for i in [1..10]
do l[i] := [ 1, 2 ];
od;
If you assign a list to a variable no new list is created. Thus the list value of the variable
on the left hand side and the list on the right hand side of the assignment are identical. So
in the following example l1 and l2 are identical lists.
l1 := [ 1, 2 ];
l2 := l1;
If you pass a list as argument, the old list and the argument of the function are identical.
Also if you return a list from a function, the old list and the value of the function call are
identical. So in the following example l1 and l2 are identical list
l1 := [ 1, 2 ];
f := function ( l )
l2 := f( l1 );
return l;
end;
The functions Copy and ShallowCopy (see 46.11 and 46.12) accept a list and return a new list
that is equal to the old list but that is not identical to the old list. The difference between
Copy and ShallowCopy is that in the case of ShallowCopy the corresponding elements of
27.10. ISIDENTICAL
591
the new and the old lists will be identical, whereas in the case of Copy they will only be
equal. So in the following example l1 and l2 are not identical lists.
l1 := [ 1, 2 ];
l2 := Copy( l1 );
If you change a list it keeps its identity. Thus if two lists are identical and you change one
of them, you also change the other, and they are still identical afterwards. On the other
hand, two lists that are not identical will never become identical if you change one of them.
So in the following example both l1 and l2 are changed, and are still identical.
l1 := [ 1, 2 ];
l2 := l1;
l1[1] := 2;
27.10
IsIdentical
IsIdentical( l , r )
IsIdentical returns true if the objects l and r are identical. Unchangeable objects are
considered identical if the are equal. Changeable objects, i.e., lists and records, are identical
if changing one of them by an assignment also changes the other one, as described in 27.9.
gap> IsIdentical( 1, 1 );
true
gap> IsIdentical( 1, () );
false
gap> l := [ ’h’, ’a’, ’l’, ’l’, ’o’ ];;
gap> l = "hallo";
true
gap> IsIdentical( l, "hallo" );
false
27.11
Enlarging Lists
The previous section (see 27.6) told you (among other things), that it is possible to assign
beyond the logical end of a list, automatically enlarging the list. This section tells you how
this is done.
It would be extremly wasteful to make all lists large enough so that there is room for all
assignments, because some lists may have more than 100000 elements, while most lists have
less than 10 elements.
On the other hand suppose every assignment beyond the end of a list would be done by
allocating new space for the list and copying all entries to the new space. Then creating a
list of 1000 elements by assigning them in order, would take half a million copy operations
and also create a lot of garbage that the garbage collector would have to reclaim.
So the following strategy is used. If a list is created it is created with exactly the correct
size. If a list is enlarged, because of an assignment beyond the end of the list, it is enlarged
by at least length/8 + 4 entries. Therefore the next assignments beyond the end of the list
do not need to enlarge the list. For example creating a list of 1000 elements by assigning
them in order, would now take only 32 enlargements.
592
CHAPTER 27. LISTS
The result of this is of course that the physical length, which is also called the size, of
a list may be different from the logical length, which is usually called simply the length
of the list. Aside from the implications for the performance you need not be aware of the
physical length. In fact all you can ever observe, for example by calling Length is the logical
length.
Suppose that Length would have to take the physical length and then test how many entries
at the end of a list are unassigned, to compute the logical length of the list. That would
take too much time. In order to make Length, and other functions that need to know the
logical length, more efficient, the length of a list is stored along with the list.
A note aside. In the previous version 2.4 of GAP3 a list was indeed enlarged every time an
assignment beyond the end of the list was performed. To deal with the above inefficiency
the following hacks where used. Instead of creating lists in order they were usually created
in reverse order. In situations where this was not possible a dummy assignment to the last
position was performed, for example
l := [];
l[1000] := "dummy";
l[1] := first_value();
for i from 2 to 1000
27.12
do l[i] := next_value(l[i-1]);
od;
Comparisons of Lists
list1 = list2
list1 <> list2
The equality operator = evaluates to true if the two lists list1 and list2 are equal and
false otherwise. The inequality operator <> evaluates to true if the two lists are not equal
and false otherwise. Two lists list1 and list2 are equal if and only if for every index i ,
either both entries list1 [i ] and list2 [i ] are unbound, or both are bound and are equal, i.e.,
list1 [i ] = list2 [i ] is true.
gap> [ 1, 2, 3 ] = [ 1, 2, 3 ];
true
gap> [ , 2, 3 ] = [ 1, 2, ];
false
gap> [ 1, 2, 3 ] = [ 3, 2, 1 ];
false
list1 < list2 , list1 <= list2 list1 > list2 , list1 >= list2
The operators <, <=, > and >= evaluate to true if the list list1 is less than, less than or equal
to, greater than, or greater than or equal to the list list2 and to false otherwise. Lists
are ordered lexicographically, with unbound entries comparing very small. That means the
following. Let i be the smallest positive integer i , such that neither both entries list1 [i ]
and list2 [i ] are unbound, nor both are bound and equal. Then list1 is less than list2 if
either list1 [i ] is unbound (and list2 [i ] is not) or both are bound and list1 [i ] < list2 [i ]
is true.
gap> [ 1, 2, 3, 4 ] < [ 1, 2, 4, 8 ];
true
# list1 [3] < list2 [3]
gap> [ 1, 2, 3 ] < [ 1, 2, 3, 4 ];
27.13. OPERATIONS FOR LISTS
593
true
# list1 [4] is unbound and therefore very small
gap> [ 1, , 3, 4 ] < [ 1, 2, 3 ];
true
# list1 [2] is unbound and therefore very small
You can also compare objects of other types, for example integers or permutations with
lists. Of course those objects are never equal to a list. Records (see 46) are greater than
lists, objects of every other type are smaller than lists.
gap> 123 < [ 1, 2, 3 ];
true
gap> [ 1, 2, 3 ] < rec( a := 123 );
true
27.13
Operations for Lists
list * obj
obj * list
The operator * evaluates to the product of list list by an object obj . The product is a new
list that at each position contains the product of the corresponding element of list by obj .
list may contain holes, in which case the result will contain holes at the same positions.
The elements of list and obj must be objects of the following types; integers (see 10),
rationals (see 12), cyclotomics (see 13), elements of a finite field (see 18), permutations (see
20), matrices (see 34), words in abstract generators (see 22), or words in solvable groups
(see 24).
gap> [ 1, 2, 3 ] * 2;
[ 2, 4, 6 ]
gap> 2 * [ 2, 3,, 5,, 7 ];
[ 4, 6,, 10,, 14 ]
gap> [ (), (2,3), (1,2), (1,2,3), (1,3,2), (1,3) ] * (1,4);
[ (1,4), (1,4)(2,3), (1,2,4), (1,2,3,4), (1,3,2,4), (1,3,4) ]
Many more operators are available for vectors and matrices, which are also represented by
lists (see 32.1, 34.1).
27.14
In
elm in list
The in operator evaluates to true if the object elm is an element of the list list and to
false otherwise. elm is an element of list if there is a positive integer index such that
list[index ]=elm is true. elm may be an object of an arbitrary type and list may be a list
containing elements of any type.
It is much faster to test for membership for sets, because for sets, which are always sorted
(see 28), in can use a binary search, instead of the linear search used for ordinary lists. So
if you have a list for which you want to perform a large number of membership tests you
may consider converting it to a set with the function Set (see 28.2).
gap> 1 in [ 2, 2, 1, 3 ];
true
gap> 1 in [ 4, -1, 0, 3 ];
594
CHAPTER 27. LISTS
false
gap> s := Set([2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32]);;
gap> 17 in s;
false
# uses binary search and only 4 comparisons
gap> 1 in [ "This", "is", "a", "list", "of", "strings" ];
false
gap> [1,2] in [ [0,6], [0,4], [1,3], [1,5], [1,2], [3,4] ];
true
Position (see 27.15) and PositionSorted (see 27.16) allow you to find the position of an
element in a list.
27.15
Position
Position( list, elm )
Position( list, elm, after )
Position returns the position of the element elm, which may be an object of any type, in
the list list. If the element is not in the list the result is false. If the element appears
several times, the first position is returned.
The three argument form begins the search at position after +1, and returns the position of
the next occurence of elm. If there are no more, it returns false.
It is much faster to search for an element in a set, because for sets, which are always sorted
(see 28), Position can use a binary search, instead of the linear search used for ordinary
lists. So if you have a list for which you want to perform a large number of searches you
may consider converting it to a set with the function Set (see 28.2).
gap> Position( [ 2, 2, 1, 3 ], 1 );
3
gap> Position( [ 2, 1, 1, 3 ], 1 );
2
gap> Position( [ 2, 1, 1, 3 ], 1, 2 );
3
gap> Position( [ 2, 1, 1, 3 ], 1, 3 );
false
gap> Position( [ 4, -1, 0, 3 ], 1 );
false
gap> s := Set([2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32]);;
gap> Position( s, 17 );
false
# uses binary search and only 4 comparisons
gap> Position( [ "This", "is", "a", "list", "of", "strings" ], 1 );
false
gap> Position( [ [0,6], [0,4], [1,3], [1,5], [1,2], [3,4] ], [1,2] );
5
The in operator (see 27.14) can be used if you are only interested to know whether the
element is in the list or not. PositionSorted (see 27.16) can be used if the list is sorted.
PositionProperty (see 27.19) allows you to find the position of an element that satisfies a
certain property in a list.
27.16. POSITIONSORTED
27.16
595
PositionSorted
PositionSorted( list, elm )
PositionSorted( list, elm, func )
In the first form PositionSorted returns the position of the element elm, which may be an
object of any type, with respect to the sorted list list.
In the second form PositionSorted returns the position of the element elm, which may
be an object of any type with respect to the list list, which must be sorted with respect to
func. func must be a function of two arguments that returns true if the first argument is
less than the second argument and false otherwise.
PositionSorted returns pos such that list[pos-1]
1
gap>
2
gap>
2
gap>
3
gap>
7
PositionSorted( [1,4,5,5,6,7], 0 );
PositionSorted( [1,4,5,5,6,7], 2 );
PositionSorted( [1,4,5,5,6,7], 4 );
PositionSorted( [1,4,5,5,6,7], 5 );
PositionSorted( [1,4,5,5,6,7], 8 );
Position (see 27.15) is another function that returns the position of an element in a list.
Position accepts unsorted lists, uses linear instead of binary search and returns false if
elm is not in list.
27.17
PositionSet
PositionSet( list, elm )
PositionSet( list, elm, func )
In the first form PositionSet returns the position of the element elm, which may be an
object of any type, with respect to the sorted list list.
In the second form PositionSet returns the position of the element elm, which may be an
object of any type with respect to the list list, which must be sorted with respect to func.
func must be a function of two arguments that returns true if the first argument is less
than the second argument and false otherwise.
PositionSet returns pos such that list[pos-1] PositionSet( [1,4,5,5,6,7], 0 );
false
gap> PositionSet( [1,4,5,5,6,7], 2 );
596
CHAPTER 27. LISTS
false
gap> PositionSet( [1,4,5,5,6,7], 4 );
2
gap> PositionSet( [1,4,5,5,6,7], 5 );
3
gap> PositionSet( [1,4,5,5,6,7], 8 );
false
PositionSet is very similar to PositionSorted (see 27.16) but returns false when elm is
not an element of list.
27.18
Positions
Positions( list, elm )
Returns the list of indices in list where elm occurs, where elm may be an object of any type.
gap> Positions([2,1,3,1],1);
[ 2, 4 ]
gap> Positions([2,1,3,1],4);
[ ]
gap> Positions([2,1,3,1],2);
[ 1 ]
27.19
PositionProperty
PositionProperty( list, func )
PositionProperty returns the position of the first element in the list list for which the
unary function func returns true. list must not contain holes. If func returns false for
all elements of list false is returned. func must return true or false for every element of
list, otherwise an error is signalled.
gap> PositionProperty( [10^7..10^8], IsPrime );
20
gap> PositionProperty( [10^5..10^6],
>
n -> not IsPrime(n) and IsPrimePowerInt(n) );
490
First (see 27.34) allows you to extract the first element of a list that satisfies a certain
property.
27.20
PositionsProperty
PositionsProperty( list, func )
PositionsProperty returns the list of indices i in list for which func(list[i]) returns
true. Here list should be a list without holes and func be a unary function.
gap>
[ 2,
gap>
[ 6,
PositionsProperty([1..9],IsPrime);
3, 5, 7 ]
PositionsProperty([1..9],x->x>5);
7, 8, 9 ]
27.21. POSITIONSUBLIST
27.21
597
PositionSublist
PositionSublist(l ,sub)
Returns the position of the first occurrence of the list sub as a sublist of consecutive elements
in l , or false if there is no such occurrence.
gap> PositionSublist("abcde","cd");
3
gap> PositionSublist([1,0,0,1,0,1],[1,0,1]);
4
27.22
Concatenation
Concatenation( list1 , list2 ..
Concatenation( list )
)
In the first form Concatenation returns the concatenation of the lists list1 , list2 , etc. The
concatenation is the list that begins with the elements of list1 , followed by the elements
of list2 and so on. Each list may also contain holes, in which case the concatenation also
contains holes at the corresponding positions.
gap>
[ 1,
gap>
[ 2,
Concatenation( [ 1, 2, 3 ], [ 4, 5 ] );
2, 3, 4, 5 ]
Concatenation( [2,3,,5,,7], [11,,13,,,,17,,19] );
3,, 5,, 7, 11,, 13,,,, 17,, 19 ]
In the second form list must be a list of lists list1 , list2 , etc, and Concatenation returns
the concatenation of those lists.
gap> Concatenation( [ [1,2,3], [2,3,4], [3,4,5] ] );
[ 1, 2, 3, 2, 3, 4, 3, 4, 5 ]
The result is a new list, that is not identical to any other list. The elements of that list
however are identical to the corresponding elements of the argument lists (see 27.9).
Note that Concatenation creates a new list and leaves it arguments unchanged, while
Append (see 27.8) changes its first argument. As usual the name of the function that
works destructively is a verb, but the name of the function that creates a new object is a
substantive.
Set(Concatenation(set1 ,set2 ..)) (see 28.2) is a way to compute the union of sets, however, Union (see 4.13) is more efficient.
27.23
Flat
Flat( list )
Flat returns the list of all elements that are contained in the list list or its sublists. That
is, Flat first makes a new empty list new . Then it loops over the elements elm of list. If
elm is not a list it is added to new , otherwise Flat appends Flat( elm ) to new .
gap> Flat( [ 1, [ 2, 3 ], [ [ 1, 2 ], 3 ] ] );
[ 1, 2, 3, 1, 2, 3 ]
gap> Flat( [ ] );
[ ]
598
CHAPTER 27. LISTS
27.24
Reversed
Reversed( list )
Reversed returns a new list that contains the elements of the list list, which must not
contain holes, in reverse order. The argument list is unchanged.
gap> Reversed( [ 1, 4, 5, 5, 6, 7 ] );
[ 7, 6, 5, 5, 4, 1 ]
The result is a new list, that is not identical to any other list. The elements of that list
however are identical to the corresponding elements of the argument list (see 27.9).
27.25
Sublist
Sublist( list, inds )
Sublist returns a new list in which the i -th element is the element list[ inds[ i ] ], of
the list list. inds must be a list of positive integers without holes, it need, however, not be
sorted and may contains duplicate elements.
gap> Sublist( [ 2, 3, 5, 7, 11, 13, 17, 19 ], [4..6] );
[ 7, 11, 13 ]
gap> Sublist( [ 2, 3, 5, 7, 11, 13, 17, 19 ], [1,7,1,8] );
[ 2, 17, 2, 19 ]
gap> Sublist( [ 1, , 2, , , 3 ], [ 1..4 ] );
[ 1,, 2 ]
Filtered (see 27.30) allows you to extract elements from a list according to a predicate.
Sublist has been made obsolete by the introduction of the construct list{ inds } (see 27.4),
excepted that in the last case an error is signaled if list[ inds[ i ] ] is unbound for some
i.
27.26
Cartesian
Cartesian( list1 , list2 ..
Cartesian( list )
)
In the first form Cartesian returns the cartesian product of the lists list1 , list2 , etc.
In the second form list must be a list of lists list1 , list2 , etc., and Cartesian returns the
cartesian product of those lists.
The cartesian product is a list cart of lists tup, such that the first element of tup is an
element of list1 , the second element of tup is an element of list2 , and so on. The total
number of elements in cart is the product of the lengths of the argument lists. In particular
cart is empty if and only if at least one of the argument lists is empty. Also cart contains
duplicates if and only if no argument list is empty and at least one contains duplicates.
The last index runs fastest. That means that the first element tup1 of cart contains the first
element from list1 , from list2 and so on. The second element tup2 of cart contains the first
element from list1 , the first from list2 , an so on, but the last element of tup2 is the second
element of the last argument list. This implies that cart is a set if and only if all argument
lists are sets.
27.27. NUMBER
599
gap> Cartesian( [1,2], [3,4], [5,6] );
[ [ 1, 3, 5 ], [ 1, 3, 6 ], [ 1, 4, 5 ], [ 1, 4, 6 ], [ 2, 3, 5 ],
[ 2, 3, 6 ], [ 2, 4, 5 ], [ 2, 4, 6 ] ]
gap> Cartesian( [1,2,2], [1,1,2] );
[ [ 1, 1 ], [ 1, 1 ], [ 1, 2 ], [ 2, 1 ], [ 2, 1 ], [ 2, 2 ],
[ 2, 1 ], [ 2, 1 ], [ 2, 2 ] ]
The function Tuples (see 47.9) computes the k -fold cartesian product of a list.
27.27
Number
Number( list )
Number( list, func )
In the first form Number returns the number of bound entries in the list list.
For lists that contain no holes Number, Length (see 27.5), and Size (see 4.10) return the
same value. For lists with holes Number returns the number of bound entries, Length returns
the largest index of a bound entry, and Size signals an error.
Number returns the number of elements of the list list for which the unary function func
returns true. If an element for which func returns true appears several times in list it will
also be counted several times. func must return either true or false for every element of
list, otherwise an error is signalled.
gap>
4
gap>
5
gap>
8
gap>
4
gap>
>
2
Number( [ 2, 3, 5, 7 ] );
Number( [, 2, 3,, 5,, 7,,,, 11 ] );
Number( [1..20], IsPrime );
Number( [ 1, 3, 4, -4, 4, 7, 10, 6 ], IsPrimePowerInt );
Number( [ 1, 3, 4, -4, 4, 7, 10, 6 ],
n -> IsPrimePowerInt(n) and n mod 2 <> 0 );
Filtered (see 27.30) allows you to extract the elements of a list that have a certain property.
27.28
Collected
Collected( list )
Collected returns a new list new that contains for each different element elm of list a list
of two elements, the first element is elm itself, and the second element is the number of
times elm appears in list. The order of those pairs in new corresponds to the ordering of
the elements elm, so that the result is sorted.
gap> Factors( Factorial( 10 ) );
[ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 5, 5, 7 ]
gap> Collected( last );
[ [ 2, 8 ], [ 3, 4 ], [ 5, 2 ], [ 7, 1 ] ]
gap> Collected( last );
[ [ [ 2, 8 ], 1 ], [ [ 3, 4 ], 1 ], [ [ 5, 2 ], 1 ], [ [ 7, 1 ], 1 ] ]
600
CHAPTER 27. LISTS
27.29
CollectBy
CollectBy(list, f )
list should be a list and f a unary function, or a list of the same length as list. Let v1 , . . . , vn
be the distinct values (sorted) that the function f takes on the elements of list (resp. the
distinct entries of the list f ). The function CollectBy returns a list whose i-th item is the
sublist of the elements of list where f takes the value vi (resp. where the corresponding
element of f is equal to vi ).
gap> CollectBy([1..15],x->x mod 4);
[ [ 4, 8, 12 ], [ 1, 5, 9, 13 ], [ 2, 6, 10, 14 ], [ 3, 7, 11, 15 ] ]
27.30
Filtered
Filtered( list, func )
Filtered returns a new list that contains those elements of the list list for which the unary
function func returns true. The order of the elements in the result is the same as the order
of the corresponding elements of list. If an element, for which func returns true appears
several times in list it will also appear the same number of times in the result. list may
contain holes, they are ignored by Filtered. func must return either true or false for
every element of list, otherwise an error is signalled.
gap>
[ 2,
gap>
[ 3,
gap>
>
[ 3,
Filtered( [1..20], IsPrime );
3, 5, 7, 11, 13, 17, 19 ]
Filtered( [ 1, 3, 4, -4, 4, 7, 10, 6 ], IsPrimePowerInt );
4, 4, 7 ]
Filtered( [ 1, 3, 4, -4, 4, 7, 10, 6 ],
n -> IsPrimePowerInt(n) and n mod 2 <> 0 );
7 ]
The result is a new list, that is not identical to any other list. The elements of that list
however are identical to the corresponding elements of the argument list (see 27.9).
Sublist (see 27.25) allows you to extract elements of a list according to indices given in
another list.
27.31
Zip
Zip(a1 ,...,an,f )
The first arguments a1 ,...,an should be lists of the same length, and the last argument a
function taking n arguments. This functions zips with the function f the lists a1 ,..,an, that
is it returns a list whose i-th entry is f(a1[i],a2[i],..,an[i]).
gap> Zip([1..9],[1..9],function(x,y)return x*y;end);
[ 1, 4, 9, 16, 25, 36, 49, 64, 81 ]
27.32
ForAll
ForAll( list, func )
27.33. FORANY
601
ForAll returns true if the unary function func returns true for all elements of the list list
and false otherwise. list may contain holes. func must return either true or false for
every element of list, otherwise an error is signalled.
gap> ForAll( [1..20], IsPrime );
false
gap> ForAll( [2,3,4,5,8,9], IsPrimePowerInt );
true
gap> ForAll( [2..14], n -> IsPrimePowerInt(n) or n mod 2 = 0 );
true
ForAny (see 27.33) allows you to test if any element of a list satisfies a certain property.
27.33
ForAny
ForAny( list, func )
ForAny returns true if the unary function func returns true for at least one element of the
list list and false otherwise. list may contain holes. func must return either true or false
for every element of list, otherwise ForAny signals an error.
gap> ForAny( [1..20], IsPrime );
true
gap> ForAny( [2,3,4,5,8,9], IsPrimePowerInt );
true
gap> ForAny( [2..14],
>
n -> IsPrimePowerInt(n) and n mod 5 = 0 and not IsPrime(n) );
false
ForAll (see 27.32) allows you to test if all elements of a list satisfies a certain propertie.
27.34
First
First( list, func )
First returns the first element of the list list for which the unary function func returns
true. list may contain holes. func must return either true or false for every element of
list, otherwise an error is signalled. If func returns false for every element of list an error
is signalled.
gap> First( [10^7..10^8], IsPrime );
10000019
gap> First( [10^5..10^6],
>
n -> not IsPrime(n) and IsPrimePowerInt(n) );
100489
PositionProperty (see 27.19) allows you to find the position of the first element in a list
that satisfies a certain property.
27.35
Sort
Sort( list )
Sort( list, func )
602
CHAPTER 27. LISTS
Sort sorts the list list in increasing order. In the first form Sort uses the operator < to
compare the elements. In the second form Sort uses the function func to compare elements.
This function must be a function taking two arguments that returns true if the first is
strictly smaller than the second and false otherwise.
Sort does not return anything, since it changes the argument list. Use ShallowCopy (see
46.12) if you want to keep list. Use Reversed (see 27.24) if you want to get a new list sorted
in decreasing order.
It is possible to sort lists that contain multiple elements which compare equal. In the first
form, it is guaranteed that those elements keep their relative order, but not in the seccond
i.e., Sort is stable in the first form but not in te second.
gap> list := [ 5, 4, 6, 1, 7, 5 ];; Sort( list ); list;
[ 1, 4, 5, 5, 6, 7 ]
gap> list := [ [0,6], [1,2], [1,3], [1,5], [0,4], [3,4] ];;
gap> Sort( list, function(v,w) return v*v < w*w; end ); list;
[ [ 1, 2 ], [ 1, 3 ], [ 0, 4 ], [ 3, 4 ], [ 1, 5 ], [ 0, 6 ] ]
# sorted according to the Euclidian distance from [0,0]
gap> list := [ [0,6], [1,3], [3,4], [1,5], [1,2], [0,4], ];;
gap> Sort( list, function(v,w) return v[1] < w[1]; end ); list;
[ [ 0, 6 ], [ 0, 4 ], [ 1, 3 ], [ 1, 5 ], [ 1, 2 ], [ 3, 4 ] ]
# note the random order of the elements with equal first component
SortParallel (see 27.36) allows you to sort a list and apply the exchanges that are necessary
to another list in parallel. Sortex (see 27.38) sorts a list and returns the sorting permutation.
27.36
SortParallel
SortParallel( list1 , list2 )
SortParallel( list1 , list2 , func )
SortParallel sorts the list list1 in increasing order just as Sort (see 27.35) does. In parallel
it applies the same exchanges that are necessary to sort list1 to the list list2 , which must
of course have at least as many elements as list1 does.
gap>
gap>
gap>
gap>
[ 1,
gap>
[ 7,
list1 := [ 5,
list2 := [ 2,
SortParallel(
list1;
4, 5, 5, 6, 7
list2;
3, 2, 9, 5, 8
4, 6, 1, 7, 5 ];;
3, 5, 7, 8, 9 ];;
list1, list2 );
]
]
# [ 7, 3, 9, 2, 5, 8 ] is also possible
Sortex (see 27.38) sorts a list and returns the sorting permutation.
27.37
SortBy
SortBy(list, fist)
list should be a list and func a unary function. The function SortBy sorts the list list
according to the value that the function func takes on each element of the list.
gap> l:=[1..15];
27.38. SORTEX
603
[ 1 .. 15 ]
gap> SortBy(l,x->x mod 4);
gap> l;
[ 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 ]
27.38
Sortex
Sortex( list )
Sortex sorts the list list and returns the permutation that must be applied to list to obtain
the sorted list.
gap> list1 := [ 5, 4, 6, 1, 7, 5 ];;
gap> list2 := Copy( list1 );;
gap> perm := Sortex( list1 );
(1,3,5,6,4)
gap> list1;
[ 1, 4, 5, 5, 6, 7 ]
gap> Permuted( list2, perm );
[ 1, 4, 5, 5, 6, 7 ]
Permuted (see 27.41) allows you to rearrange a list according to a given permutation.
27.39
SortingPerm
SortingPerm( list )
SortingPerm returns the permutation that must be applied to list to sort it into ascending
order.
gap> list1 := [ 5, 4, 6, 1, 7, 5 ];;
gap> list2 := Copy( list1 );;
gap> perm := SortingPerm( list1 );
(1,3,5,6,4)
gap> list1;
[ 5, 4, 6, 1, 7, 5 ]
gap> Permuted( list2, perm );
[ 1, 4, 5, 5, 6, 7 ]
Sortex( list ) (see 27.38) returns the same permutation as SortingPerm( list ), and also
applies it to list (in place).
27.40
PermListList
PermListList( list1 , list2 )
PermListList returns a permutation that may be applied to list1 to obtain list2 , if there
is one. Otherwise it returns false.
gap> list1 := [ 5, 4, 6, 1, 7, 5 ];;
gap> list2 := [ 4, 1, 7, 5, 5, 6 ];;
gap> perm := PermListList(list1, list2);
(1,2,4)(3,5,6)
gap> Permuted( list2, perm );
[ 5, 4, 6, 1, 7, 5 ]
604
CHAPTER 27. LISTS
27.41
Permuted
Permuted( list, perm )
Permuted returns a new list new that contains the elements of the list list permuted according to the permutation perm. That is new [i ^perm] = list[i ].
gap> Permuted( [ 5, 4, 6, 1, 7, 5 ], (1,3,5,6,4) );
[ 1, 4, 5, 5, 6, 7 ]
Sortex (see 27.38) allows you to compute the permutation that must be applied to a list to
get the sorted list.
27.42
Product
Product( list )
Product( list, func )
In the first form Product returns the product of the elements of the list list, which must
have no holes. If list is empty, the integer 1 is returned.
In the second form Product applies the function func to each element of the list list, which
must have no holes, and multiplies the results. If the list is empty, the integer 1 is returned.
gap> Product( [ 2, 3, 5, 7, 11, 13, 17, 19 ] );
9699690
gap> Product( [1..10], x->x^2 );
13168189440000
gap> Product( [ (1,2), (1,3), (1,4), (2,3), (2,4), (3,4) ] );
(1,4)(2,3)
Sum (see 27.43) computes the sum of the elements of a list.
27.43
Sum
Sum( list )
Sum( list, func )
In the first form Sum returns the sum of the elements of the list list, which must have no
holes. If list is empty 0 is returned.
In the second form Sum applies the function func to each element of the list list, which must
have no holes, and sums the results. If the list is empty 0 is returned.
gap>
77
gap>
385
gap>
[ 9,
Sum( [ 2, 3, 5, 7, 11, 13, 17, 19 ] );
Sum( [1..10], x->x^2 );
Sum( [ [1,2], [3,4], [5,6] ] );
12 ]
Product (see 27.42) computes the product of the elements of a list.
27.44. VALUEPOL
27.44
605
ValuePol
ValuePol( list, x )
list represents the coefficients of a polynomial. The function ValuePol returns the value of
that polynomial at x , using Horner’s scheme. It thus represents the most efficient way to
evaluate the value of a polynomial.
gap> q:=X(Rationals);;q.name:="q";;
gap> ValuePol([1..5],q);
5*q^4 + 4*q^3 + 3*q^2 + 2*q + 1
27.45
Maximum
Maximum( obj1 , obj2 ..
Maximum( list )
)
Maximum returns the maximum of its arguments, i.e., that argument obji for which objk <=
obji for all k. In its second form Maximum takes a list list and returns the maximum of the
elements of this list.
Typically the arguments or elements of the list respectively will be integers, but actually they
can be objects of an arbitrary type. This works because any two objects can be compared
using the < operator.
gap>
700
gap>
700
gap>
[ 2,
27.46
Maximum( -123, 700, 123, 0, -1000 );
Maximum( [ -123, 700, 123, 0, -1000 ] );
Maximum( [ 1, 2 ], [ 0, 15 ], [ 1, 5 ], [ 2, -11 ] );
-11 ]
# lists are compared elementwise
Minimum
Minimum( obj1 , obj2 ..
Minimum( list )
)
Minimum returns the minimum of its arguments, i.e., that argument obji for which obji <=
objk for all k. In its second form Minimum takes a list list and returns the minimum of the
elements of this list.
Typically the arguments or elements of the list respectively will be integers, but actually they
can be objects of an arbitrary type. This works because any two objects can be compared
using the < operator.
gap> Minimum( -123, 700, 123, 0, -1000 );
-1000
gap> Minimum( [ -123, 700, 123, 0, -1000 ] );
-1000
gap> Minimum( [ 1, 2 ], [ 0, 15 ], [ 1, 5 ], [ 2, -11 ] );
[ 0, 15 ]
# lists are compared elementwise
606
CHAPTER 27. LISTS
27.47
Iterated
Iterated( list, f )
Iterated returns the result of the iterated application of the function f , which must take
two arguments, to the elements of list. More precisely Iterated returns the result of the
following application, f (..f ( f ( list[1], list[2] ), list[3] ),..,list[n] ).
gap> Iterated( [ 126, 66, 105 ], Gcd );
3
27.48
RandomList
RandomList( list )
RandomList returns a random element of the list list. The results are equally distributed,
i.e., all elements are equally likely to be selected.
gap>
192
gap>
152
gap>
[ 4,
RandomList( [1..200] );
RandomList( [1..200] );
RandomList( [ [ 1, 2 ], 3, [ 4, 5 ], 6 ] );
5 ]
RandomSeed( n )
RandomSeed seeds the pseudo random number generator RandomList. Thus to reproduce a
computation exactly you can call RandomSeed each time before you start the computation.
When GAP3 is started the pseudo random number generator is seeded with 1.
gap> RandomSeed(1);
96
76
gap> RandomSeed(1);
96
76
RandomList([1..100]);
RandomList([1..100]);
RandomList([1..100]);
RandomList([1..100]);
RandomList is called by all random functions for domains (see 4.16).
Chapter 28
Sets
A very important mathematical concept, maybe the most important of all, are sets. Mathematically a set is an abstract object such that each object is either an element of the set
or it is not. So a set is a collection like a list, and in fact GAP3 uses lists to represent sets.
Note that this of course implies that GAP3 only deals with finite sets.
Unlike a list a set must not contain an element several times. It simply makes no sense to
say that an object is twice an element of a set, because an object is either an element of a
set, or it is not. Therefore the list that is used to represent a set has no duplicates, that is,
no two elements of such a list are equal.
Also unlike a list a set does not impose any ordering on the elements. Again it simply makes
no sense to say that an object is the first or second etc. element of a set, because, again, an
object is either an element of a set, or it is not. Since ordering is not defined for a set we can
put the elements in any order into the list used to represent the set. We put the elements
sorted into the list, because this ordering is very practical. For example if we convert a list
into a set we have to remove duplicates, which is very easy to do after we have sorted the
list, since then equal elements will be next to each other.
In short sets are represented by sorted lists without holes and duplicates in GAP3. Such a
list is in this document called a proper set. Note that we guarantee this representation, so
you may make use of the fact that a set is represented by a sorted list in your functions.
In some contexts (for example see 47), we also want to talk about multisets. A multiset is
like a set, except that an element may appear several times in a multiset. Such multisets
are represented by sorted lists with holes that may have duplicates.
The first section in this chapter describes the functions to test if an object is a set and to
convert objects to sets (see 28.1 and 28.2).
The next section describes the function that tests if two sets are equal (see 28.3).
The next sections describe the destructive functions that compute the standard set operations for sets (see 28.4, 28.5, 28.6, 28.7, and 28.8).
The last section tells you more about sets and their internal representation (see 28.10).
All set theoretic functions, especially Intersection and Union, also accept sets as arguments. Thus all functions described in chapter 4 are applicable to sets (see 28.9).
607
608
CHAPTER 28. SETS
Since sets are just a special case of lists, all the operations and functions for lists, especially
the membership test (see 27.14), can be used for sets just as well (see 27).
28.1
IsSet
IsSet( obj )
IsSet returns true if the object obj is a set and false otherwise. An object is a set if it
is a sorted lists without holes or duplicates. Will cause an error if evaluation of obj is an
unbound variable.
gap> IsSet(
true
gap> IsSet(
true
gap> IsSet(
false
gap> IsSet(
false
gap> IsSet(
false
gap> IsSet(
false
28.2
[] );
[ 2, 3, 5, 7, 11 ] );
[, 2, 3,, 5,, 7,,,, 11 ] );
# this list contains holes
[ 11, 7, 5, 3, 2 ] );
# this list is not sorted
[ 2, 2, 3, 5, 5, 7, 11, 11 ] );
# this list contains duplicates
235711 );
# this argument is not even a list
Set
Set( list )
Set returns a new proper set, which is represented as a sorted list without holes or duplicates,
containing the elements of the list list.
Set returns a new list even if the list list is already a proper set, in this case it is equivalent
to ShallowCopy (see 46.12). Thus the result is a new list that is not identical to any other
list. The elements of the result are however identical to elements of list. If list contains
equal elements, it is not specified to which of those the element of the result is identical (see
27.9).
gap> Set( [3,2,11,7,2,,5] );
[ 2, 3, 5, 7, 11 ]
gap> Set( [] );
[ ]
28.3
IsEqualSet
IsEqualSet( list1 , list2 )
IsEqualSet returns true if the two lists list1 and list2 are equal when viewed as sets,
and false otherwise. list1 and list2 are equal if every element of list1 is also an element of
list2 and if every element of list2 is also an element of list1 .
If both lists are proper sets then they are of course equal if and only if they are also equal as
lists. Thus IsEqualSet( list1 , list2 ) is equivalent to Set( list1 ) = Set( list2 ) (see
28.2), but the former is more efficient.
28.4. ADDSET
609
gap> IsEqualSet( [2,3,5,7,11], [11,7,5,3,2] );
true
gap> IsEqualSet( [2,3,5,7,11], [2,3,5,7,11,13] );
false
28.4
AddSet
AddSet( set, elm )
AddSet adds elm, which may be an elment of an arbitrary type, to the set set, which must
be a proper set, otherwise an error will be signalled. If elm is already an element of the set
set, the set is not changed. Otherwise elm is inserted at the correct position such that set
is again a set afterwards.
gap>
gap>
[ 2,
gap>
[ 2,
gap>
[ 2,
s := [2,3,7,11];;
AddSet( s, 5 ); s;
3, 5, 7, 11 ]
AddSet( s, 13 ); s;
3, 5, 7, 11, 13 ]
AddSet( s, 3 ); s;
3, 5, 7, 11, 13 ]
RemoveSet (see 28.5) is the counterpart of AddSet.
28.5
RemoveSet
RemoveSet( set, elm )
RemoveSet removes the element elm, which may be an object of arbitrary type, from the
set set, which must be a set, otherwise an error will be signalled. If elm is not an element
of set nothing happens. If elm is an element it is removed and all the following elements in
the list are moved one position forward.
gap>
gap>
gap>
[ 2,
gap>
gap>
[ 2,
s := [ 2, 3, 4, 5, 6, 7 ];;
RemoveSet( s, 6 );
s;
3, 4, 5, 7 ]
RemoveSet( s, 10 );
s;
3, 4, 5, 7 ]
AddSet (see 28.4) is the counterpart of RemoveSet.
28.6
UniteSet
UniteSet( set1 , set2 )
UniteSet unites the set set1 with the set set2 . This is equivalent to adding all the elements
in set2 to set1 (see 28.4). set1 must be a proper set, otherwise an error is signalled. set2
may also be list that is not a proper set, in which case UniteSet silently applies Set to it
first (see 28.2). UniteSet returns nothing, it is only called to change set1 .
gap> set := [ 2, 3, 5, 7, 11 ];;
610
CHAPTER 28. SETS
gap>
[ 2,
gap>
[ 2,
UniteSet( set,
3, 4, 5, 7, 8,
UniteSet( set,
3, 4, 5, 7, 8,
[ 4, 8, 9 ] ); set;
9, 11 ]
[ 16, 9, 25, 13, 16 ] );
9, 11, 13, 16, 25 ]
set;
The function UnionSet (see 28.9) is the nondestructive counterpart to the destructive procedure UniteSet.
28.7
IntersectSet
IntersectSet( set1 , set2 )
IntersectSet intersects the set set1 with the set set2 . This is equivalent to removing all
the elements that are not in set2 from set1 (see 28.5). set1 must be a set, otherwise an
error is signalled. set2 may be a list that is not a proper set, in which case IntersectSet
silently applies Set to it first (see 28.2). IntersectSet returns nothing, it is only called to
change set1 .
gap> set := [ 2, 3, 4, 5, 7, 8, 9, 11, 13, 16 ];;
gap> IntersectSet( set, [ 3, 5, 7, 9, 11, 13, 15, 17 ] );
[ 3, 5, 7, 9, 11, 13 ]
gap> IntersectSet( set, [ 9, 4, 6, 8 ] ); set;
[ 9 ]
set;
The function IntersectionSet (see 28.9) is the nondestructive counterpart to the destructive procedure IntersectSet.
28.8
SubtractSet
SubtractSet( set1 , set2 )
SubtractSet subtracts the set set2 from the set set1 . This is equivalent to removing all
the elements in set2 from set1 (see 28.5). set1 must be a proper set, otherwise an error is
signalled. set2 may be a list that is not a proper set, in which case SubtractSet applies
Set to it first (see 28.2). SubtractSet returns nothing, it is only called to change set1 .
gap>
gap>
[ 2,
gap>
[ 2,
set := [ 2, 3, 4,
SubtractSet( set,
3, 4, 5, 7, 8, 9,
SubtractSet( set,
3, 5, 7, 11 ]
5, 6, 7, 8, 9, 10, 11 ];;
[ 6, 10 ] ); set;
11 ]
[ 9, 4, 6, 8 ] ); set;
The function Difference (see 4.14) is the nondestructive counterpart to destructive the
procedure SubtractSet.
28.9
Set Functions for Sets
As was already mentioned in the introduction to this chapter all domain functions also accept
sets as arguments. Thus all functions described in the chapter 4 are applicable to sets. This
section describes those functions where it might be helpful to know the implementation of
those functions for sets.
IsSubset( set1 , set2 )
28.10. MORE ABOUT SETS
611
This is implemented by IsSubsetSet, which you can call directly to save a little bit of time.
Either argument to IsSubsetSet may also be a list that is not a proper set, in which case
IsSubset silently applies Set (see 28.2) to it first.
Union( set1 , set2 )
This is implemented by UnionSet, which you can call directly to save a little bit of time.
Note that UnionSet only accepts two sets, unlike Union, which accepts several sets or a list
of sets. The result of UnionSet is a new set, represented as a sorted list without holes or
duplicates. Each argument to UnionSet may also be a list that is not a proper set, in which
case UnionSet silently applies Set (see 28.2) to this argument. UnionSet is implemented in
terms of its destructive counterpart UniteSet (see 28.6).
Intersection( set1 , set2 )
This is implemented by IntersectionSet, which you can call directly to save a little bit
of time. Note that IntersectionSet only accepts two sets, unlike Intersection, which
accepts several sets or a list of sets. The result of IntersectionSet is a new set, represented
as a sorted list without holes or duplicates. Each argument to IntersectionSet may also be
a list that is not a proper set, in which case IntersectionSet silently applies Set (see 28.2)
to this argument. IntersectionSet is implemented in terms of its destructive counterpart
IntersectSet (see 28.7).
The result of IntersectionSet and UnionSet is always a new list, that is not identical to
any other list. The elements of that list however are identical to the corresponding elements
of set1 . If set1 is not a proper list it is not specified to which of a number of equal elements
in set1 the element in the result is identical (see 27.9).
28.10
More about Sets
In the previous section we defined a proper set as a sorted list without holes or duplicates.
This representation is not only nice to use, it is also a good internal representation supporting
efficient algorithms. For example the in operator can use binary instead of a linear search
since a set is sorted. For another example Union only has to merge the sets.
However, all those set functions also allow lists that are not proper sets, silently making a
copy of it and converting this copy to a set. Suppose all the functions would have to test
their arguments every time, comparing each element with its successor, to see if they are
proper sets. This would chew up most of the performance advantage again. For example
suppose in would have to run over the whole list, to see if it is a proper set, so it could use
the binary search. That would be ridiculous.
To avoid this a list that is a proper set may, but need not, have an internal flag set that
tells those functions that this list is indeed a proper set. Those functions do not have to
check this argument then, and can use the more efficient algorithms. This section tells you
when a proper set obtains this flag, so you can write your functions in such a way that you
make best use of the algorithms.
The results of Set, Difference, Intersection and Union are known to be sets by construction, and thus have the flag set upon creation.
If an argument to IsSet, IsEqualSet, IsSubset, Set, Difference, Intersection or Union
is a proper set, that does not yet have the flag set, those functions will notice that and set
the flag for this set. Note that in will use linear search if the right operand does not have
612
CHAPTER 28. SETS
the flag set, will therefore not detect if it is a proper set and will, unlike the functions above,
never set the flag.
If you change a proper set, that does have this flag set, by assignment, Add or Append the
set will generally lose it flag, even if the change is such that the resulting list is still a proper
set. However if the set has more than 100 elements and the value assigned or added is not
a list and not a record and the resulting list is still a proper set than it will keep the flag.
Note that changing a list that is not a proper set will never set the flag, even if the resulting
list is a proper set. Such a set will obtain the flag only if it is passed to a set function.
Suppose you have built a proper set in such a way that it does not have the flag set, and that
you now want to perform lots of membership tests. Then you should call IsSet with that
set as an argument. If it is indeed a proper set IsSet will set the flag, and the subsequent
in operations will use the more efficient binary search. You can think of the call to IsSet
as a hint to GAP3 that this list is a proper set.
There is no way you can set the flag for an ordinary list without going through the checking
in IsSet. The internal functions depend so much on the fact that a list with this flag set
is indeed sorted and without holes and duplicates that the risk would be too high to allow
setting the flag without such a check.
Chapter 29
Boolean Lists
This chapter describes boolean lists. A boolean list is a list that has no holes and contains
only boolean values, i.e., true and false. In function names we call boolean lists blist for
brevity.
Boolean lists can be used in various ways, but maybe the most important application is
their use for the description of subsets of finite sets. Suppose set is a finite set, represented
as a list. Then a subset sub of set is represented by a boolean list blist of the same length
as set such that blist[i ] is true if set[i ] is in sub and false otherwise.
This package contains functions to switch between the representations of subsets of a finite
set either as sets or as boolean lists (see 29.1, 29.2), to test if a list is a boolean list (see
29.3), and to count the number of true entries in a boolean list (see 29.4).
Next there are functions for the standard set operations for the subsets represented by
boolean lists (see 29.5, 29.6, 29.7, and 29.8). There are also the corresponding destructive
procedures that change their first argument (see 29.9, 29.10, and 29.11). Note that there
is no function to add or delete a single element to a subset represented by a boolean list,
because this can be achieved by assigning true or false to the corresponding position in
the boolean list (see 27.6).
Since boolean lists are just a special case of lists, all the operations and functions for lists,
can be used for boolean lists just as well (see 27). For example Position (see 27.15) can
be used to find the true entries in a boolean list, allowing you to loop over the elements of
the subset represented by the boolean list.
There is also a section about internal details (see 29.12).
29.1
BlistList
BlistList( list, sub )
BlistList returns a new boolean list that describes the list sub as a sublist of the list list,
which must have no holes. That is BlistList returns a boolean list blist of the same length
as list such that blist[i ] is true if list[i ] is in sub and false otherwise.
list need not be a proper set (see 28), even though in this case BlistList is most efficient.
In particular list may contain duplicates. sub need not be a proper sublist of list, i.e., sub
613
614
CHAPTER 29. BOOLEAN LISTS
may contain elements that are not in list. Those elements of course have no influence on
the result of BlistList.
gap> BlistList( [1..10], [2,3,5,7] );
[ false, true, true, false, true, false, true, false, false, false ]
gap> BlistList( [1,2,3,4,5,2,8,6,4,10], [4,8,9,16] );
[ false, false, false, true, false, false, true, false, true, false ]
ListBlist (see 29.2) is the inverse function to BlistList.
29.2
ListBlist
ListBlist( list, blist )
ListBlist returns the sublist sub of the list list, which must have no holes, represented by
the boolean list blist, which must have the same length as list. sub contains the element
list[i ] if blist[i ] is true and does not contain the element if blist[i ] is false. The order
of the elements in sub is the same as the order of the corresponding elements in list.
gap> ListBlist([1..8],[false,true,true,true,true,false,true,true]);
[ 2, 3, 4, 5, 7, 8 ]
gap> ListBlist( [1,2,3,4,5,2,8,6,4,10],
> [false,false,false,true,false,false,true,false,true,false] );
[ 4, 8, 4 ]
BlistList (see 29.1) is the inverse function to ListBlist.
29.3
IsBlist
IsBlist( obj )
IsBlist returns true if obj , which may be an object of arbitrary type, is a boolean list
and false otherwise. A boolean list is a list that has no holes and contains only true and
false.
gap> IsBlist( [ true, true, false, false ] );
true
gap> IsBlist( [] );
true
gap> IsBlist( [false,,true] );
false
# has holes
gap> IsBlist( [1,1,0,0] );
false
# contains not only boolean values
gap> IsBlist( 17 );
false
# is not even a list
29.4
SizeBlist
SizeBlist( blist )
SizeBlist returns the number of entries of the boolean list blist that are true. This is the
size of the subset represented by the boolean list blist.
gap> SizeBlist( [ true, true, false, false ] );
2
29.5. ISSUBSETBLIST
29.5
615
IsSubsetBlist
IsSubsetBlist( blist1 , blist2 )
IsSubsetBlist returns true if the boolean list blist2 is a subset of the boolean list list1 ,
which must have equal length, and false otherwise. blist2 is a subset if blist1 if blist1 [i ]
= blist1 [i ] or blist2 [i ] for all i .
gap> blist1 := [ true, true, false, false ];;
gap> blist2 := [ true, false, true, false ];;
gap> IsSubsetBlist( blist1, blist2 );
false
gap> blist2 := [ true, false, false, false ];;
gap> IsSubsetBlist( blist1, blist2 );
true
29.6
UnionBlist
UnionBlist( blist1 , blist2 ..
UnionBlist( list )
)
In the first form UnionBlist returns the union of the boolean lists blist1 , blist2 , etc., which
must have equal length. The union is a new boolean list such that union[i ] = blist1 [i ]
or blist2 [i ] or ...
In the second form list must be a list of boolean lists blist1 , blist2 , etc., which must have
equal length, and Union returns the union of those boolean list.
gap> blist1 := [ true, true, false, false ];;
gap> blist2 := [ true, false, true, false ];;
gap> UnionBlist( blist1, blist2 );
[ true, true, true, false ]
Note that UnionBlist is implemented in terms of the procedure UniteBlist (see 29.9).
29.7
IntersectionBlist
IntersectionBlist( blist1 , blist2 ..
IntersectionBlist( list )
)
In the first form IntersectionBlist returns the intersection of the boolean lists blist1 ,
blist2 , etc., which must have equal length. The intersection is a new boolean list such
that inter [i ] = blist1 [i ] and blist2 [i ] and ...
In the second form list must be a list of boolean lists blist1 , blist2 , etc., which must have
equal length, and IntersectionBlist returns the intersection of those boolean lists.
gap> blist1 := [ true, true, false, false ];;
gap> blist2 := [ true, false, true, false ];;
gap> IntersectionBlist( blist1, blist2 );
[ true, false, false, false ]
Note that IntersectionBlist is implemented in terms of the procedure IntersectBlist
(see 29.10).
616
CHAPTER 29. BOOLEAN LISTS
29.8
DifferenceBlist
DifferenceBlist( blist1 , blist2 )
DifferenceBlist returns the asymmetric set difference of the two boolean lists blist1 and
blist2 , which must have equal length. The asymmetric set difference is a new boolean
list such that union[i ] = blist1 [i ] and not blist2 [i ].
gap> blist1 := [ true, true, false, false ];;
gap> blist2 := [ true, false, true, false ];;
gap> DifferenceBlist( blist1, blist2 );
[ false, true, false, false ]
Note that DifferenceBlist is implemented in terms of the procedure SubtractBlist (see
29.11).
29.9
UniteBlist
UniteBlist( blist1 , blist2 )
UniteBlist unites the boolean list blist1 with the boolean list blist2 , which must have the
same length. This is equivalent to assigning blist1 [i ] := blist1 [i ] or blist2 [i ] for all i .
UniteBlist returns nothing, it is only called to change blist1 .
gap> blist1 := [ true, true, false, false ];;
gap> blist2 := [ true, false, true, false ];;
gap> UniteBlist( blist1, blist2 );
gap> blist1;
[ true, true, true, false ]
The function UnionBlist (see 29.6) is the nondestructive counterpart to the procedure
UniteBlist.
29.10
IntersectBlist
IntersectBlist( blist1 , blist2 )
IntersectBlist intersects the boolean list blist1 with the boolean list blist2 , which must
have the same length. This is equivalent to assigning blist1 [i ]:= blist1 [i ] and blist2 [i ]
for all i . IntersectBlist returns nothing, it is only called to change blist1 .
gap> blist1 := [ true, true, false, false ];;
gap> blist2 := [ true, false, true, false ];;
gap> IntersectBlist( blist1, blist2 );
gap> blist1;
[ true, false, false, false ]
The function IntersectionBlist (see 29.7) is the nondestructive counterpart to the procedure IntersectBlist.
29.11
SubtractBlist
SubtractBlist( blist1 , blist2 )
29.12. MORE ABOUT BOOLEAN LISTS
617
SubtractBlist subtracts the boolean list blist2 from the boolean list blist1 , which must
have equal length. This is equivalent to assigning blist1 [i ] := blist1 [i ] and not blist2 [i ]
for all i . SubtractBlist returns nothing, it is only called to change blist1 .
gap> blist1 := [ true, true, false, false ];;
gap> blist2 := [ true, false, true, false ];;
gap> SubtractBlist( blist1, blist2 );
gap> blist1;
[ false, true, false, false ]
The function DifferenceBlist (see 29.8) is the nondestructive counterpart to the procedure
SubtractBlist.
29.12
More about Boolean Lists
In the previous section (see 29) we defined a boolean list as a list that has no holes and
contains only true and false. There is a special internal representation for boolean lists
that needs only 1 bit for every entry. This bit is set if the entry is true and reset if the
entry is false. This representation is of course much more compact than the ordinary
representation of lists, which needs 32 bits per entry.
Not every boolean list is represented in this compact representation. It would be too much
work to test every time a list is changed, whether this list has become a boolean list. This
section tells you under which circumstances a boolean list is represented in the compact
representation, so you can write your functions in such a way that you make best use of the
compact representation.
The results of BlistList, UnionBlist, IntersectionBlist and DifferenceBlist are
known to be boolean lists by construction, and thus are represented in the compact representation upon creation.
If an argument of IsBlist, IsSubsetBlist, ListBlist, UnionBlist, IntersectionBlist,
DifferenceBlist, UniteBlist, IntersectBlist and SubtractBlist is a list represented
in the ordinary representation, it is tested to see if it is in fact a boolean list. If it is not,
IsBlist returns false and the other functions signal an error. If it is, the representation
of the list is changed to the compact representation.
If you change a boolean list that is represented in the compact representation by assignment
(see 27.6) or Add (see 27.7) in such a way that the list remains a boolean list it will remain
represented in the compact representation. Note that changing a list that is not represented
in the compact representation, whether it is a boolean list or not, in such a way that the
resulting list becomes a boolean list, will never change the representation of the list.
618
CHAPTER 29. BOOLEAN LISTS
Chapter 30
Strings and Characters
A character is simply an object in GAP3 that represents an arbitrary character from the
character set of the operating system. Character literals can be entered in GAP3 by enclosing
the character in singlequotes ’.
gap> ’a’;
’a’
gap> ’*’;
’*’
A string is simply a dense list of characters. Strings are used mainly in filenames and
error messages. A string literal can either be entered simply as the list of characters or by
writing the characters between doublequotes ". GAP3 will always output strings in the
latter format.
gap> s1 := [’H’,’a’,’l’,’l’,’o’,’ ’,’w’,’o’,’r’,’l’,’d’,’.’];
"Hallo world."
gap> s2 := "Hallo world.";
"Hallo world."
gap> s1 = s2;
true
gap> s3 := "";
""
# the empty string
gap> s3 = [];
true
Note that a string is just a special case of a list. So everything that is possible for lists
(see 27) is also possible for strings. Thus you can access the characters in such a string (see
27.4), test for membership (see 27.14), etc. You can even assign to such a string (see 27.6).
Of course unless you assign a character in such a way that the list stays dense, the resulting
list will no longer be a string.
gap> Length( s2 );
12
gap> s2[2];
’a’
619
620
CHAPTER 30. STRINGS AND CHARACTERS
gap> ’e’ in s2;
false
gap> s2[2] := ’e’;;
"Hello world."
s2;
If a string is displayed as result of an evaluation (see 3.1), it is displayed with enclosing
doublequotes. However, if a string is displayed by Print, PrintTo, or AppendTo (see 3.14,
3.15, 3.16) the enclosing doublequotes are dropped.
gap> s2;
"Hello world."
gap> Print( s2 );
Hello world.gap>
There are a number of special character sequences that can be used between the single
quote of a character literal or between the doublequotes of a string literal to specify characters, which may otherwise be inaccessible. They consist of two characters. The first is a
backslash \. The second may be any character. The meaning is given in the following list
n
newline character. This is the character that, at least on UNIX systems, separates
lines in a text file. Printing of this character in a string has the effect of moving the
cursor down one line and back to the beginning of the line.
"
doublequote character. Inside a string a doublequote must be escaped by the
backslash, because it is otherwise interpreted as end of the string.
’
singlequote character. Inside a character a singlequote must escaped by the
backslash, because it is otherwise interpreted as end of the character.
\
backslash character. Inside a string a backslash must be escaped by another
backslash, because it is otherwise interpreted as first character of an escape sequence.
b
backspace character. Printing this character should have the effect of moving
the cursor back one character. Whether it works or not is system dependent and
should not be relied upon.
r
carriage return character. Printing this character should have the effect of
moving the cursor back to the beginning of the same line. Whether this works or not
is again system dependent.
c
flush character. This character is not printed. Its purpose is to flush the output
queue. Usually GAP3 waits until it sees a newline before it prints a string. If you
want to display a string that does not include this character use \c.
other
For any other character the backslash is simply ignored.
Again, if the line is displayed as result of an evaluation, those escape sequences are displayed
in the same way that they are input. They are displayed in their special way only by Print,
PrintTo, or AppendTo.
gap> "This is one line.\nThis is another line.\n";
"This is one line.\nThis is another line.\n"
gap> Print( last );
This is one line.
This is another line.
It is not allowed to enclose a newline inside the string. You can use the special character
sequence \n to write strings that include newline characters. If, however, a string is too
30.1. STRING
621
long to fit on a single line it is possible to continue it over several lines. In this case the last
character of each line, except the last must be a backslash. Both backslash and newline are
thrown away. Note that the same continuation mechanism is available for identifiers and
integers.
gap> "This is a very long string that does not fit on a line \
gap> and is therefore continued on the next line.";
"This is a very long string that does not fit on a line and is therefo\
re continued on the next line."
# note that the output is also continued, but at a different place
This chapter contains sections describing the function that creates the printable representation of a string (see 30.1), the functions that create new strings (see 30.2, 30.3), the
functions that tests if an object is a string (see 30.5), the string comparisons (see 30.4), and
the function that returns the length of a string (see 27.5).
30.1
String
String( obj )
String( obj , length )
String returns a representation of the obj , which may be an object of arbitrary type, as a
string. This string should approximate as closely as possible the character sequence you see
if you print obj .
If length is given it must be an integer. The absolute value gives the minimal length of the
result. If the string representation of obj takes less than that many characters it is filled
with blanks. If length is positive it is filled on the left, if length is negative it is filled on the
right.
gap> String( 123 );
"123"
gap> String( [1,2,3] );
"[ 1, 2, 3 ]"
gap> String( 123, 10 );
"
123"
gap> String( 123, -10 );
"123
"
gap> String( 123, 2 );
"123"
30.2
ConcatenationString
ConcatenationString( string1 , string2 )
ConcatenationString returns the concatenation of the two strings string1 and string2 .
This is a new string that starts with the characters of string1 and ends with the characters
of string2 .
gap> ConcatenationString( "Hello ", "world.\n" );
"Hello world.\n"
Because strings are now lists, Concatenation (see 27.22) does exactly the right thing, and
the function ConcatenationString is obsolete.
622
CHAPTER 30. STRINGS AND CHARACTERS
30.3
SubString
SubString( string, from, to )
SubString returns the substring of the string string that begins at position from and continues to position to. The characters at these two positions are included. Indexing is done
with origin 1, i.e., the first character is at position 1. from and to must be integers and are
both silently forced into the range 1..Length(string) (see 27.5). If to is less than from the
substring is empty.
gap> SubString( "Hello world.\n", 1, 5 );
"Hello"
gap> SubString( "Hello world.\n", 5, 1 );
""
Because strings are now lists, substrings can also be extracted with string{[from..to]} (see
27.4). SubString forces from and to into the range 1..Length(string), which the above
does not, but apart from that SubString is obsolete.
30.4
Comparisons of Strings
string1 = string2 , string1 <> string2
The equality operator = evaluates to true if the two strings string1 and string2 are equal
and false otherwise. The inequality operator <> returns true if the two strings string1
and string2 are not equal and false otherwise.
gap> "Hello world.\n" = "Hello world.\n";
true
gap> "Hello World.\n" = "Hello world.\n";
false
# string comparison is case sensitive
gap> "Hello world." = "Hello world.\n";
false
# the first string has no newline
gap> "Goodbye world.\n" = "Hello world.\n";
false
gap> [ ’a’, ’b’ ] = "ab";
true
string1 < string2 , string1 <= string2 , string1 > string2 , string1 => string2
The operators <, <=, >, and => evaluate to true if the string string1 is less than, less than
or equal to, greater than, greater than or equal to the string string2 respectively. The
ordering of strings is lexicographically according to the order implied by the underlying,
system dependent, character set.
You can also compare objects of other types, for example integers or permutations with
strings. As strings are dense character lists they compare with other objects as lists do, i.e.,
they are never equal to those objects, records (see 46) are greater than strings, and objects
of every other type are smaller than strings.
gap> "Hello world.\n" < "Hello world.\n";
false
# the strings are equal
gap> "Hello World.\n" < "Hello world.\n";
true
# in ASCII uppercase letters come before lowercase letters
30.5. ISSTRING
623
gap> "Hello world." < "Hello world.\n";
true
# prefixes are always smaller
gap> "Goodbye world.\n" < "Hello world.\n";
true
# G comes before H, in ASCII at least
30.5
IsString
IsString( obj )
IsString returns true if the object obj , which may be an object of arbitrary type, is a
string and false otherwise. Will cause an error if obj is an unbound variable.
gap> IsString( "Hello world.\n" );
true
gap> IsString( "123" );
true
gap> IsString( 123 );
false
gap> IsString( [ ’1’, ’2’, ’3’ ] );
true
gap> IsString( [ ’1’, ’2’, , ’4’ ] );
false
# strings must be dense
gap> IsString( [ ’1’, ’2’, 3 ] );
false
# strings must only contain characters
30.6
Join
Join( list [, delimiter ] )
The function Join is similar to the Perl function of the same name. It first applies the
function String to all elements of the list, then joins the resulting strings, separated by the
given delimiter (if omitted, "," is used as a delimiter)
gap> Join([1..4]);
"1,2,3,4"
gap> Join([1..4],"foo");
"1foo2foo3foo4"
30.7
SPrint
SPrint(s1 ,...,sn)
SPrint(s1 ,...,sn) is a synonym for Join([s1 ,...,sn],""). That is, it first applies the
function String to all arguments, then joins the resulting strings. If s1 ,...,sn have string
methods, the effect of Print(SPrint(s1 ,...,sn)) is the same as directly Print(s1 ,...,sn).
gap> SPrint(1,"a",[3,4]);
"1a[ 3, 4 ]"
30.8
PrintToString
PrintToString(s,s1 ,...,sn)
624
CHAPTER 30. STRINGS AND CHARACTERS
PrintToString(s,s1 ,...,sn) appends to string s the string SPrint(s1 ,...,sn).
gap> s:="a";
"a"
gap> PrintToString(s,[1,2]);
gap> s;
"a[ 1, 2 ]"
30.9
Split
Split( s [, delimiter ] )
This function is similar to the Perl function of the same name. It splits the string s at each
occurrence of the delimiter (a character). If delimiter is omitted, ’,’ is used as a delimiter.
gap> Split("14,2,2,1,");
[ "14", "2", "2", "1", "" ]
30.10
StringDate
StringDate(days)
StringDate([day, month, year ])
This function converts to a readable string a date, which can be a number of days since
1-Jan-1970 or a list [day, month, year ].
gap> StringDate([11,3,1998]);
"11-Mar-1998"
gap> StringDate(2^14);
"10-Nov-2014"
30.11
StringTime
StringTime(msec)
StringTime([hour , min, sec, msec])
This function converts to a readable string atime, which can be a number of milliseconds or
a list [hour , min, sec, msec].
gap> StringTime([1,10,5,13]);
" 1:10:05.013"
gap> StringTime(2^22);
" 1:09:54.304"
30.12
StringPP
StringPP(int)
returns a string representing the prime factor decomposition of the integer int.
gap> StringPP(40320);
"2^7*3^2*5*7"
Chapter 31
Ranges
A range is a dense list of integers, such that the difference between consecutive elements is
a nonzero constant. Ranges can be abbreviated with the syntactic construct [ first, second
.. last ] or, if the difference between consecutive elements is 1, as [ first .. last ].
If first > last, [first,second ..last] is the empty list, which by definition is also a range. If
first = last, [first,second ..last] is a singleton list, which is a range too. Note that last first must be divisible by the increment second - first, otherwise an error is signalled.
Note that a range is just a special case of a list. So everything that is possible for lists (see
27) is also possible for ranges. Thus you can access elements in such a range (see 27.4), test
for membership (see 27.14), etc. You can even assign to such a range (see 27.6). Of course,
unless you assign last + second -first to the entry range[Length(range)+1], the resulting
list will no longer be a range.
Most often ranges are used in connection with the for-loop (see 2.17). Here the construct
for var in [first..last] do statements od replaces the
for var from first to last do statements od, which is more usual in other programming
languages.
Note that a range is at the same time also a set (see 28), because it contains no holes or
duplicates and is sorted, and also a vector (see 32), because it contains no holes and all
elements are integers.
gap> r := [10..20];
[ 10 .. 20 ]
gap> Length( r );
11
gap> r[3];
12
gap> 17 in r;
true
gap> r[12] := 25;; r;
[ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25 ]
gap> r := [1,3..17];
[ 1, 3 .. 17 ]
625
626
CHAPTER 31. RANGES
gap> Length( r );
9
gap> r[4];
7
gap> r := [0,-1..-9];
[ 0, -1 .. -9 ]
gap> r[5];
-4
gap> r := [ 1, 4 .. 32 ];
Error, Range: - must be divisible by
gap> s := [];; for i in [10..20] do Add( s, i^2 ); od;
[ 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400 ]
s;
The first section in this chapter describes the function that tests if a list is a range (see
31.1).
The other section tells you more about the internal representation of ranges (see 31.2).
31.1
IsRange
IsRange( obj )
IsRange returns true if obj , which may be an object of any type, is a range and false
otherwise. A range is a list without holes such that the elements are integers with a constant
increment. Will cause an error if obj is an unassigned variable.
gap> IsRange( [1,2,3] );
true
# this list is a range
gap> IsRange( [7,5,3,1] );
true
# this list is a range
gap> IsRange( [1,2,4,5] );
false
# this list is a set and a vector, but not a range
gap> IsRange( [1,,3,,5,,7] );
false
# this list contains holes
gap> IsRange( 1 );
false
# is not even a list
gap> IsRange( [] );
true
# the empty list is a range by definition
gap> IsRange( [1] );
true
# singleton lists are a range by definition too
31.2
More about Ranges
For some lists the kernel knows that they are in fact ranges. Those lists are represented
internally in a compact way instead of the ordinary way. This is important since this
representation needs only 12 bytes for the entire list while the ordinary representation needs
4length bytes.
Note that a list that is represented in the ordinary way might still be a range. It is just
that GAP3 does not know this. This section tells you under which circumstances a range
is represented in the compact way, so you can write your program in such a way that you
make best use of this compact representation for ranges.
31.2. MORE ABOUT RANGES
Lists created by the syntactic construct [ first, second ..
be ranges and are represented in the compact way.
627
last ] are of course known to
If you call IsRange for a list represented the ordinary way that is indeed a range, IsRange
will note this, change the representation from the ordinary to the compact representation,
and then return true;
If you change a range that is represented in the compact way, by assignment, Add or Append,
the range will be converted to the ordinary representation, even if the change is such that
the resulting list is still a proper range.
Suppose you have built a proper range in such a way that it is represented in the ordinary
way and that you now want to convert it to the compact representation to save space.
Then you should call IsRange with that list as an argument. If it is indeed a proper range,
IsRange will convert it to the compact representation. You can think of the call to IsRange
as a hint to GAP3 that this list is a proper range.
628
CHAPTER 31. RANGES
Chapter 32
Vectors
A important concept in algebra is the vector space over a field F . A vector space V is a
set of vectors, for which an addition u + v and a multiplication by scalars, i.e., elements
from F , sv must be defined. A base of V is a list of vectors, such that every vector in V
can be uniquely written as linear combination of the base vectors. If the base if finite, its
size is called the dimension of V . Using a base it can be shown that V is isomorphic to
the set n-tuples of elements with the componentwise addition and multiplication.
This comment suggests the representation that is actually used in GAP3. A GAP3 vector is
a list without holes whose elements all come from a common field. We call the length of the
list the dimension of the vector. This is a little bit lax, because the dimension is a property
of the vector space, not of the vector, but should seldom cause confusion.
The first possibility for this field are the rationals (see 12). We call a list without holes
whose elements are all rationals a rational vector, which is a bit lax too, but should again
cause no confusion. For example [ 1/2, 0, -1/3, 2 ] is a rational vector of dimension 4.
The second possibility are cyclotomics (see 13). Note that the rationals are the prime field of
cyclotomic fields and therefore rational vectors are just a special case of cyclotomic vectors.
An example of a cyclotomic vector is [ E(3)+E(3)^2, 1, E(15) ].
Third the common field may be a finite field (see 18). Note that it is not enough that
all elements are finite field elements of the same characteristic, the common finite field
containing all elements must be representable in GAP3, i.e., must have at most 216 elements.
An example of such a vector over the finite field GF (34 ) with 81 elements is [ Z(3^4)^3,
Z(3^2)^5, Z(3^4)^11 ].
Finally a list all of whose elements are records is also considered a vector. In that case the
records should all have an operations record with the necessary functions +, -, *, ^. This
allows for vectors over library and/or user defined fields (or rings) such as a polynomial ring
(see 19).
The first section in this chapter describes the operations applicable to vectors (see 32.1).
The next section describes the function that tests if an object is a vector (see 32.2).
The next section describes the function that returns a canonical multiple of a vector (see
32.3).
629
630
CHAPTER 32. VECTORS
The last section tells you more about the internal representation of vectors (see 32.4).
Because vectors are just a special case of lists, all the operations and functions for lists are
applicable to vectors also (see chapter 27). This especially includes accessing elements of
a vector (see 27.4), changing elements of a vector (see 27.6), and comparing vectors (see
27.12).
Vectorspaces are a special category of domains and are described by vectorspace records
(see chapter 9).
Vectors play an important role for matrices (see chapter 34), which are implemented as lists
of vectors.
32.1
Operations for Vectors
vec1 + vec2
In this form the addition operator + evaluates to the sum of the two vectors vec1 and vec2 ,
which must have the same dimension and lie in a common field. The sum is a new vector
where each entry is the sum of the corresponding entries of the vectors. As an exception it
is also possible to add an integer vector to a finite field vector, in which case the integers
are interpreted as scalar * GF .one.
scalar + vec
vec + scalar
In this form + evaluates to the sum of the scalar scalar and the vector vec, which must lie
in a common field. The sum is a new vector where each entry is the sum of the scalar and
the corresponding entry of the vector. As an exception it is also possible to add an integer
scalar to a finite field vector, in which case the integer is interpreted as scalar * GF .one.
gap> [ 1, 2, 3 ] + [ 1/2, 1/3, 1/4 ];
[ 3/2, 7/3, 13/4 ]
gap> [ 1/2, 3/2, 1/2 ] + 1/2;
[ 1, 2, 1 ]
vec1 - vec2
scalar - vec
vec - scalar
The difference operator - returns the componentwise difference of its two operands and is
defined subject to the same restrictions as +.
gap> [ 1, 2, 3 ] - [ 1/2, 1/3, 1/4 ];
[ 1/2, 5/3, 11/4 ]
gap> [ 1/2, 3/2, 1/2 ] - 1/2;
[ 0, 1, 0 ]
vec1 * vec2
In this form the multiplication operator * evaluates to the product of the two vectors vec1
and vec2 , which must have the same dimension and lie in a common field. The product is
the sum of the products of the corresponding entries of the vectors. As an exception it is
also possible to multiply an integer vector to a finite field vector, in which case the integers
are interpreted as scalar * GF .one.
32.2. ISVECTOR
631
scalar * vec
vec * scalar
In this form * evaluates to the product of the scalar scalar and the vector vec, which must
lie in a common field. The product is a new vector where each entry is the product of
the scalar and the corresponding entry of the vector. As an exception it is also possible to
multiply an integer scalar to a finite field vector, in which case the integer is interpreted as
scalar *GF .one.
gap> [ 1, 2, 3 ] * [ 1/2, 1/3, 1/4 ];
23/12
gap> [ 1/2, 3/2, 1/2 ] * 2;
[ 1, 3, 1 ]
Further operations with vectors as operands are defined by the matrix operations (see 34.1).
32.2
IsVector
IsVector( obj )
IsVector returns true if obj , which may be an object of arbitrary type, is a vector and
false else. A vector is a list without holes, whose elements all come from a common field.
gap> IsVector( [ 0, -3, -2, 0, 6 ] );
true
gap> IsVector( [ Z(3^4)^3, Z(3^2)^5, Z(3^4)^13 ] );
true
gap> IsVector( [ 0, Z(2^3)^3, Z(2^3) ] );
false
# integers are not finite field elements
gap> IsVector( [ , 2, 3,, 5,, 7 ] );
false
# list that have holes are not vectors
gap> IsVector( 0 );
false
# not even a list
32.3
NormedVector
NormedVector( vec )
NormedVector returns the scalar multiple of vec such that the first nonzero entry of vec is
the one from the field over which the vector is defined. If vec contains only zeroes a copy of
it is returned.
gap> NormedVector( [
[ 0, 1, 2/3, 0, -2 ]
gap> NormedVector( [
[ 0, 0 ]
gap> NormedVector( [
[ Z(3)^0, Z(3^4)^47,
32.4
0, -3, -2, 0, 6 ] );
0, 0 ] );
Z(3^4)^3, Z(3^2)^5, Z(3^4)^13 ] );
Z(3^2) ]
More about Vectors
In the first section of this chapter we defined a vector as a list without holes whose elements
all come from a common field. This representation is quite nice to use. However, suppose
632
CHAPTER 32. VECTORS
that GAP3 would have to check that a list is a vector every time this vector appears as
operand in a addition or multiplication. This would be quite wasteful.
To avoid this a list that is a vector may, but need not, have an internal flag set that tells
the operations that this list is indeed a vector. Then this operations do not have to check
this operand and can perform the operation right away. This section tells you when a vector
obtains this flag, so you can write your functions in such a way that you make best use of
this feature.
The results of vector operations, i.e., binary operations that involve vectors, are known by
construction to be vectors, and thus have the flag set upon creation.
If the operand of one of the binary operation is a list that does not yet have the flag set,
those operations will check that this operand is indeed a vector and set the flag if it is. If it
is not a vector and not a matrix an error is signalled.
If the argument to IsVector is a list that does not yet have this flag set, IsVector will
test if all elements come from a common field. If they do, IsVector will set the flag. Thus
on the one hand IsVector is a test whether the argument is a vector. On the other hand
IsVector can be used as a hint to GAP3 that a certain list is indeed a vector.
If you change a vector, that does have this flag set, by assignment, Add, or Append, the
vectors will loose its flag, even if the change is such that the resulting list is still a vector.
However if the vector is a vector over a finite field and you assign an element from the same
finite field the vector will keep its flag. Note that changing a list that is not a vector will
never set the flag, even if the resulting list is a vector. Such a vector will obtain the flag
only if it appears as operand in a binary operation, or is passed to IsVector.
Vectors over finite fields have one additional feature. If they are known to be vectors, not
only do they have the flag set, but also are they represented differently. This representation
is much more compact. Instead of storing every element separately and storing for every
element separately in which field it lies, the field is only stored once. This representation
takes up to 10 times less memory.
Chapter 33
Row Spaces
This chapter consists essentially of four parts, according to the four different types of data
structures that are described, after the usual brief discussion of the objects (see 33.1, 33.2,
33.3, 33.4, 33.5).
The first part introduces row spaces, and their operations and functions (see 33.6, 33.7, 33.8,
33.9, 33.10, 33.11, 33.12, 33.13).
The second part introduces bases for row spaces, and their operations and functions (see
33.14, 33.15, 33.16, 33.17, 33.18, 33.19, 33.20, 33.21).
The third part introduces row space cosets, and their operations and functions (see 33.22,
33.23, 33.24).
The fourth part introduces quotient spaces of row spaces, and their operations and functions
(see 33.25, 33.26).
The obligatory last sections describe the details of the implementation of the data structures
(see 33.27, 33.28, 33.29, 33.30).
Note: The current implementation of row spaces provides no homomorphisms of row spaces
(linear maps), and also quotient spaces of quotient spaces are not supported.
33.1
More about Row Spaces
A row space is a vector space (see chapter 9), whose elements are row vectors, that is, lists
of elements in a common field.
Note that for a row space V over the field F necessarily the characteristic of F is the same
as the characteristic of the vectors in V . Furthermore at the moment the field F must
contain the field spanned by all the elements in vectors of V , since in many computations
vectors are normed, that is, divided by their first nonzero entry.
The implementation of functions for these spaces and their elements uses the well-known
linear algebra methods, such as Gaussian elimination, and many functions delegate the
work to functions for matrices, e.g., a basis of a row space can be computed by performing
Gaussian elimination to the matrix formed by the list of generators. Thus in a sense, a
row space in GAP3 is nothing but a GAP3 object that knows about the interpretation of a
matrix as a generating set, and that knows about the functions that do the work.
633
634
CHAPTER 33. ROW SPACES
Row spaces are constructed using 33.6 RowSpace, full row spaces can also be constructed by
F ^ n, for a field F and a positive integer n.
The zero element of a row space V in GAP3 is not necessarily stored in the row space
record. If necessary, it can be computed using Zero( V ).
The generators component may contain zero vectors, so no function should expect a generator to be nonzero.
For the usual concept of substructures and parent structures see 33.5.
See 33.7 and 33.8 for an overview of applicable operators and functions, and 33.27 for details
of the implementation.
33.2
Row Space Bases
Many computations with row spaces require the computation of a basis (which will always
mean a vector space basis in GAP3), such as the computation of the dimension, or efficient
membership test for the row space.
Most of these computations do not rely on special properties of the chosen basis. The
computation of coefficients lists, however, is basis dependent. A natural way to distinguish
these two situations is the following.
For basis independent questions the row space is allowed to compute a suitable basis, and
may store bases. For example the dimension of the space V can be computed this way using
Dimension( V ). In such situations the component V .basis is used. The value of this
component depends on how it was constructed, so no function that accesses this component
should assume special properties of this basis.
On the other hand, the computation of coefficients of a vector v with respect to a basis B of V
depends on this basis, so you have to call Coefficients( B , v ), and not Coefficients(
V , v ).
It should be mentioned that there are two types of row space bases. A basis of the first
type is semi-echelonized (see 33.18 for the definition and examples), its structure allows
to perform efficient calculations of membership test and coefficients.
A basis of the second type is arbitrary, that is, it has no special properties. There are two
ways to construct such a (user-defined) basis that is not necessarily semi-echelonized. The
first is to call RowSpace with the optional argument "basis"; this means that the generators
are known to be linearly independent (see 33.6). The second way is to call Basis with two
arguments (see 33.16). The computation of coefficients with respect to an arbitrary basis
is performed by computing a semi-echelonized basis, delegating the task to this basis, and
then performing the base change.
The functions that are available for row space bases are Coefficients (see 33.14) and
SiftedVector (see 33.15).
The several available row space bases are described in 33.16, 33.17, and 33.18. For details
of the implementation see 33.28.
33.3
Row Space Cosets
Let V be a vector space, and U a subspace of V . The set v + U = {v + u; u ∈ U } is called
a coset of U in V .
33.4. QUOTIENT SPACES
635
In GAP3, cosets are of course domains that can be formed using the ’+’ operator, see 33.22
and 33.23 for an overview of applicable operators and functions, and 33.29 for details of the
implementation.
A coset C = v + U is described by any representative v and the space U . Equal cosets may
have different representatives. A canonical representative of the coset C can be computed
using CanonicalRepresentative( C ), it does only depend on C, especially not on the
basis of U .
Row spaces cosets can be regarded as elements of quotient spaces (see 33.4).
33.4
Quotient Spaces
Let V be a vector space, and U a subspace of V . The set {v + U ; v ∈ V } is again a vector
space, the quotient space (or factor space) of V modulo U .
By definition of row spaces, a quotient space is not a row space. (One reason to describe
quotient spaces here is that for general vector spaces at the moment no factor structures
are supported.)
Quotient spaces in GAP3 are formed from two spaces using the / operator. See the sections
33.25 and 33.26 for an overview of applicable operators and functions, and 33.30 for details
of the implementation.
Bases for Quotient Spaces of Row Spaces
A basis B of a quotient V /U for row spaces V and U is best described by bases of V and U .
If B is a basis without special properties then it will delegate the work to a semi-echelonized
basis. The concept of semi-echelonized bases makes sense also for quotient spaces of row
spaces since for any semi-echelonized basis of U the set S of pivot columns is a subset of the
set of pivot columns of a semi-echelonized basis of V . So the cosets v + U for basis vectors
v with pivot column not in S form a semi-echelonized basis of V /U . The canonical basis
of V /U is the semi-echelonized basis derived in that way from the canonical basis of V (see
33.17).
See 33.26 for details about the bases.
33.5
Subspaces and Parent Spaces
The concept described in this section is essentially the same as the concept of parent groups
and subgroups (see 7.6).
(The section should be moved to chapter 9, but for general vector spaces the concept does
not yet apply.)
Every row space U is either constructed as subspace of an existing space V , for example
using 33.10 Subspace, or it is not.
In the latter case the space is called a parent space, in the former case V is called the
parent of U .
One can only form sums of subspaces of the same parent space, form quotient spaces only
for spaces with same parent, and cosets v + U only for representatives v in the parent of U .
636
CHAPTER 33. ROW SPACES
Parent( V )
returns the parent space of the row space V ,
IsParent( V )
returns true if the row space V is a parent space, and false otherwise.
See 33.11, 33.12 for conversion functions.
33.6
RowSpace
RowSpace( F , generators )
returns the row space that is generated by the vectors generators over the field F . The
elements in generators must be GAP3 vectors.
RowSpace( F , generators, zero )
Whenever the list generators is empty, this call of RowSpace has to be used, with zero the
zero vector of the space.
RowSpace( F , generators, "basis" )
also returns the F -space generated by generators. When the space is constructed in this
way, the vectors generators are assumed to form a basis, and this is used for example when
Dimension is called for the space.
It is not checked that the vectors are really linearly independent.
RowSpace( F , dimension )
F ^ n
return the full row space of dimension n over the field F . The elements of this row space
are all the vectors of length n with entries in F .
gap> v1:=
RowSpace(
gap> v2:=
RowSpace(
gap> v3:=
RowSpace(
gap> v4:=
RowSpace(
gap> v5:=
RowSpace(
gap> v3 =
true
RowSpace( GF(2), [ [ 1, 1
GF(2), [ [ Z(2)^0, Z(2)^0
RowSpace( GF(2), [], [ 0,
GF(2), [ [ 0*Z(2), 0*Z(2)
RowSpace( GF(2), [ [ 1, 1
GF(2), [ [ Z(2)^0, Z(2)^0
RowSpace( GF(2), 2 );
GF(2), [ [ Z(2)^0, 0*Z(2)
GF(2) ^ 2 ;
GF(2), [ [ Z(2)^0, 0*Z(2)
v4;
], [ 0, 1 ] ] * Z(2) );
], [ 0*Z(2), Z(2)^0 ] ] )
0 ] * Z(2) );
] ] )
], [ 0, 1 ] ] * Z(2), "basis" );
], [ 0*Z(2), Z(2)^0 ] ] )
], [ 0*Z(2), Z(2)^0 ] ] )
], [ 0*Z(2), Z(2)^0 ] ] )
Note that the list of generators may contain zero vectors.
33.7
Operations for Row Spaces
Comparisons of Row Spaces
33.8. FUNCTIONS FOR ROW SPACES
637
V = W
returns true if the two row spaces V , W are equal as sets, and false otherwise.
V < W
returns true if the row space V is smaller than the row space W , and false otherwise.
The first criteria of this ordering are the comparison of the fields and the dimensions,
row spaces over the same field and of same dimension are compared by comparison
of the reversed canonical bases (see 33.17).
Arithmetic Operations for Row Spaces
V + W
returns the sum of the row spaces V and W , that is, the row space generated by V
and W . This is computed using the Zassenhaus algorithm.
V / U
returns the quotient space of V modulo its subspace U (see 33.4).
gap> v:= GF(2)^2; v.name:= "v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> s:= Subspace( v, [ [ 1, 1 ] * Z(2) ] );
Subspace( v, [ [ Z(2)^0, Z(2)^0 ] ] )
gap> t:= Subspace( v, [ [ 0, 1 ] * Z(2) ] );
Subspace( v, [ [ 0*Z(2), Z(2)^0 ] ] )
gap> s = t;
false
gap> s < t;
false
gap> t < s;
true
gap> u:= s+t;
Subspace( v, [ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] )
gap> u = v;
true
gap> f:= u / s;
Subspace( v, [ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] ) /
[ [ Z(2)^0, Z(2)^0 ] ]
33.8
Functions for Row Spaces
The following functions are overlaid in the operations record of row spaces.
The set theoretic functions
Closure, Elements, Intersection, Random, Size.
Intersection( V , W )
returns the intersection of the two row spaces V and W that is computed using the
Zassenhaus algorithm.
The vector space specific functions
Base( V )
returns the list of vectors of the canonical basis of the row space V (see 33.17).
638
CHAPTER 33. ROW SPACES
Cosets( V , U )
returns the list of cosets of the subspace U in V , as does Elements( V / U ).
Dimension( V )
returns the dimension of the row space. For this, a basis of the space is computed if
not yet known.
Zero( V )
returns the zero element of the row space V (see 33.1).
33.9
IsRowSpace
IsRowSpace( obj )
returns true if obj , which can be an object of arbitrary type, is a row space and false
otherwise.
gap> v:= GF(2) ^
RowSpace( GF(2),
gap> IsRowSpace(
true
gap> IsRowSpace(
false
33.10
2;
[ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
v );
v / [ v.generators[1] ] );
Subspace
Subspace( V , gens )
returns the subspace of the row space V that is generated by the vectors in the list gens.
gap> v:= GF(3)^2; v.name:= "v";;
RowSpace( GF(3), [ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ] )
gap> s:= Subspace( v, [ [ 1, -1 ] *Z(3)^0 ] );
Subspace( v, [ [ Z(3)^0, Z(3) ] ] )
33.11
AsSubspace
AsSubspace( V ,U )
returns the row space U , viewed as a subspace of the rows space V . For that, V must be a
parent space.
gap> v:= GF(2)^2; v.name:="v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> u:= RowSpace( GF(2), [ [ 1, 1 ] * Z(2) ] );
RowSpace( GF(2), [ [ Z(2)^0, Z(2)^0 ] ] )
gap> w:= AsSubspace( v, u );
Subspace( v, [ [ Z(2)^0, Z(2)^0 ] ] )
gap> w = u;
true
33.12. ASSPACE
33.12
639
AsSpace
AsSpace( U )
returns the subspace U as a parent space.
gap> v:= GF(2)^2; v.name:="v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> u:= Subspace( v, [ [ 1, 1 ] * Z(2) ] );
Subspace( v, [ [ Z(2)^0, Z(2)^0 ] ] )
gap> w:= AsSpace( u );
RowSpace( GF(2), [ [ Z(2)^0, Z(2)^0 ] ] )
gap> w = u;
true
33.13
NormedVectors
NormedVectors( V )
returns the set of those vectors in the row space V for that the first nonzero entry is the
identity of the underlying field.
gap> v:= GF(3)^2;
RowSpace( GF(3), [ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ] )
gap> NormedVectors( v );
[ [ 0*Z(3), Z(3)^0 ], [ Z(3)^0, 0*Z(3) ], [ Z(3)^0, Z(3)^0 ],
[ Z(3)^0, Z(3) ] ]
33.14
Coefficients for Row Space Bases
Coefficients( B , v )
returns the coefficients vector of the vector v with respect to the basis B (see 33.2) of the
vector space V , if v is an element of V . Otherwise false is returned.
gap> v:= GF(3)^2; v.name:= "v";;
RowSpace( GF(3), [ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ] )
gap> b:= Basis( v );
Basis( v, [ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ] )
gap> Coefficients( b, [ Z(3), Z(3) ] );
[ Z(3), Z(3) ]
gap> Coefficients( b, [ Z(3), Z(3)^2 ] );
[ Z(3), Z(3)^0 ]
33.15
SiftedVector
SiftedVector( B , v )
returns the residuum of the vector v with respect to the basis B of the vector space V . The
exact meaning of this depends on the special properties of B .
But in general this residuum is obtained on subtracting appropriate multiples of basis vectors, and v is contained in V if and only if SiftedVector( B , v ) is the zero vector of
V.
640
CHAPTER 33. ROW SPACES
gap> v:= GF(3)^2; v.name:= "v";;
RowSpace( GF(3), [ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ] )
gap> s:= Subspace( v, [ [ 1, -1 ] *Z(3)^0 ] ); s.name:= "s";;
Subspace( v, [ [ Z(3)^0, Z(3) ] ] )
gap> b:= Basis(s);
SemiEchelonBasis( s, [ [ Z(3)^0, Z(3) ] ] )
gap> SiftedVector( b, [ Z(3), 0*Z(3) ] );
[ 0*Z(3), Z(3) ]
33.16
Basis
Basis( V )
Basis( V , vectors )
Basis( V ) returns a basis of the row space V . If the component V .canonicalBasis or
V .semiEchelonBasis was bound before the first call to Basis for V then one of these
bases is returned. Otherwise a semi-echelonized basis (see 33.2) is computed. The basis is
stored in V .basis.
Basis( V , vectors ) returns the basis of V that consists of the vectors in the list vectors.
In the case that V .basis was not bound before the call the basis is stored in this component.
Note that it is not necessarily checked whether vectors is really linearly independent.
gap> v:= GF(2)^2; v.name:= "v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> b:= Basis( v, [ [ 1, 1 ], [ 1, 0 ] ] * Z(2) );
Basis( v, [ [ Z(2)^0, Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] )
gap> Coefficients( b, [ 0, 1 ] * Z(2) );
[ Z(2)^0, Z(2)^0 ]
gap> IsSemiEchelonBasis( b );
false
33.17
CanonicalBasis
CanonicalBasis( V )
returns the canonical basis of the row space V . This is a special semi-echelonized basis
(see 33.18), with the additional properties that for j > i the position of the pivot of row j
is bigger than that of the pivot of row i, and that the pivot columns contain exactly one
nonzero entry.
gap> v:= GF(2)^2; v.name:= "v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> cb:= CanonicalBasis( v );
CanonicalBasis( v )
gap> cb.vectors;
[ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ]
The canonical basis is obtained on applying a full Gaussian elimination to the generators of
V , using 34.19 BaseMat. If the component V .semiEchelonBasis is bound then this basis
is used to compute the canonical basis, otherwise TriangulizeMat is called.
33.18. SEMIECHELONBASIS
33.18
641
SemiEchelonBasis
SemiEchelonBasis( V )
SemiEchelonBasis( V , vectors )
returns a semi-echelonized basis of the row space V . A basis is called semi-echelonized if
the first non-zero element in every row is one, and all entries exactly below these elements
are zero.
If a second argument vectors is given, these vectors are taken as basis vectors. Note that if
the rows of vectors do not form a semi-echelonized basis then an error is signalled.
gap> v:= GF(2)^2; v.name:= "v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> SemiEchelonBasis( v );
SemiEchelonBasis( v, [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> b:= Basis( v, [ [ 1, 1 ], [ 0, 1 ] ] * Z(2) );
Basis( v, [ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] )
gap> IsSemiEchelonBasis( b );
true
gap> b;
SemiEchelonBasis( v, [ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] )
gap> Coefficients( b, [ 0, 1 ] * Z(2) );
[ 0*Z(2), Z(2)^0 ]
gap> Coefficients( b, [ 1, 0 ] * Z(2) );
[ Z(2)^0, Z(2)^0 ]
33.19
IsSemiEchelonBasis
IsSemiEchelonBasis( B )
returns true if B is a semi-echelonized basis (see 33.18), and false otherwise. If B is
semi-echelonized, and this was not yet stored before, after the call the operations record of
B will be SemiEchelonBasisRowSpaceOps.
gap> v:= GF(2)^2; v.name:= "v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> b1:= Basis( v, [ [ 0, 1 ], [ 1, 0 ] ] * Z(2) );
Basis( v, [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] )
gap> IsSemiEchelonBasis( b1 );
true
gap> b1;
SemiEchelonBasis( v, [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] )
gap> b2:= Basis( v, [ [ 0, 1 ], [ 1, 1 ] ] * Z(2) );
Basis( v, [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, Z(2)^0 ] ] )
gap> IsSemiEchelonBasis( b2 );
false
gap> b2;
Basis( v, [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, Z(2)^0 ] ] )
642
CHAPTER 33. ROW SPACES
33.20
NumberVector
NumberVector( B , v )
Pn
Let v = i=1 λi bi where B = (b1 , b2 , . . . , bn ) is a basis of the vector space V over the finite
field F with |F | = q, and the λi are elements of F . Let λ be the integer corresponding to λ
as defined by 39.29 FFList.
Pn
Then NumberVector( B , v ) returns i=1 λi q i−1 .
gap> v:= GF(3)^3;; v.name:= "v";;
gap> b:= CanonicalBasis( v );;
gap> l:= List( [0 .. 6 ], x -> ElementRowSpace( b, x ) );
[ [ 0*Z(3), 0*Z(3), 0*Z(3) ], [ Z(3)^0, 0*Z(3), 0*Z(3) ],
[ Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3) ],
[ Z(3)^0, Z(3)^0, 0*Z(3) ], [ Z(3), Z(3)^0, 0*Z(3) ],
[ 0*Z(3), Z(3), 0*Z(3) ] ]
33.21
ElementRowSpace
ElementRowSpace( B , n )
returns the n-th element of the row space with basis B , with respect to the ordering defined
in 33.20 NumberVector.
gap>
gap>
gap>
gap>
[ 0,
33.22
v:= GF(3)^3;; v.name:= "v";;
b:= CanonicalBasis( v );;
l:= List( [0 .. 6 ], x -> ElementRowSpace( b, x ) );;
List( l, x -> NumberVector( b, x ) );
1, 2, 3, 4, 5, 6 ]
Operations for Row Space Cosets
Comparison of Row Space Cosets
C1 = C2
returns true if the two row space cosets C1 , C2 are equal, and false otherwise.
Note that equal cosets need not have equal representatives (see 33.3).
C1 < C2
returns true if the row space coset C1 is smaller than the row space coset C2 , and
false otherwise. This ordering is defined by comparison of canonical representatives.
Arithmetic Operations for Row Space Cosets
C1 + C2
If C1 and C2 are row space cosets that belong to the same quotient space, the result
is the row space coset that is the sum resp. the difference of these vectors. Otherwise
an error is signalled.
s * C
returns the row space coset that is the product of the scalar s and the row space coset
33.23. FUNCTIONS FOR ROW SPACE COSETS
643
C , where s must be an element of the ground field of the vector space that defines
C.
Membership Test for Row Space Cosets
v in C
returns true if the vector v is an element of the row space coset C , and false otherwise.
gap> v:= GF(2)^2; v.name:= "v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> u:= Subspace( v, [ [ 1, 1 ] * Z(2) ] ); u.name:="u";;
Subspace( v, [ [ Z(2)^0, Z(2)^0 ] ] )
gap> f:= v / u;
v / [ [ Z(2)^0, Z(2)^0 ] ]
gap> elms:= Elements( f );
[ ([ 0*Z(2), 0*Z(2) ]+u), ([ 0*Z(2), Z(2)^0 ]+u) ]
gap> 2 * elms[2];
([ 0*Z(2), 0*Z(2) ]+u)
gap> elms[2] + elms[1];
([ 0*Z(2), Z(2)^0 ]+u)
gap> [ 1, 0 ] * Z(2) in elms[2];
true
gap> elms[1] = elms[2];
false
33.23
Functions for Row Space Cosets
Since row space cosets are domains, all set theoretic functions are applicable to them.
Representative returns the value of the representative component. Note that equal
cosets may have different representatives. Canonical representatives can be computed using
CanonicalRepresentative.
CanonicalRepresentative( C )
returns the canonical representative of the row space coset C , which is defined as the
result of SiftedVector( B , v ) where C = v + U , and B is the canonical basis
of U .
33.24
IsSpaceCoset
IsSpaceCoset( obj )
returns true if obj , which may be an arbitrary object, is a row space coset, and false
otherwise.
gap> v:= GF(2)^2; v.name:= "v";;
RowSpace( GF(2), [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
gap> u:= Subspace( v, [ [ 1, 1 ] * Z(2) ] );
Subspace( v, [ [ Z(2)^0, Z(2)^0 ] ] )
gap> f:= v / u;
v / [ [ Z(2)^0, Z(2)^0 ] ]
644
CHAPTER 33. ROW SPACES
gap> IsSpaceCoset( u );
false
gap> IsSpaceCoset( Random( f ) );
true
33.25
Operations for Quotient Spaces
W1 = W2
returns true if for the two quotient spaces W1 = V1 / U1 and W2 = V2 / U2
the equalities V1 = V2 and U1 = U2 hold, and false otherwise.
W1 < W2
returns true if for the two quotient spaces W1 = V1 / U1 and W2 = V2 / U2
either U1 < U2 or U1 = U2 and V1 < V2 hold, and false otherwise.
33.26
Functions for Quotient Spaces
Computations in quotient spaces usually delegate the work to computations in numerator
and denominator.
The following functions are overlaid in the operations record for quotient spaces.
The set theoretic functions
Closure, Elements, IsSubset, Intersection,
and the vector space functions
Base( V )
returns the vectors of the canonical basis of V ,
Generators( V )
returns a list of cosets that generate V ,
CanonicalBasis( V )
returns the canonical basis of V = W/U , this is derived from the canonical basis of
W.
SemiEchelonBasis( V )
SemiEchelonBasis( V , vectors )
return a semi-echelonized basis of the quotient space V . vectors can be a list of
elements of V , or of representatives.
Basis( V )
Basis( V , vectors )
return a basis of the quotient space V . vectors can be a list of elements of V , or of
representatives.
33.27
Row Space Records
In addition to the record components described in 9.3 the following components must be
present in a row space record.
isRowSpace
is always true,
33.28. ROW SPACE BASIS RECORDS
645
operations
the record RowSpaceOps.
Depending on the calculations in that the row space was involved, it may have lots of
optional components, such as basis, dimension, size.
33.28
Row Space Basis Records
A vector space basis is a record with at least the following components.
isBasis
always true,
vectors
the list of basis vectors,
structure
the underlying vector space,
operations
a record that contains the functions for the basis, at least Coefficients, Print, and
SiftedVector. Of course these functions depend on the special properties of the
basis, so different basis types have different operations record.
Depending on the type of the basis, the basis record additionally contains some components
that are assumed and used by the functions in the operations record.
For arbitrary bases these are semiEchelonBasis and basechange, for semi-echelonized bases
these are the lists heads and ishead. Furthermore, the booleans isSemiEchelonBasis and
isCanonicalBasis may be present.
The operations records for the supported bases are
BasisRowSpaceOps
for arbitrary bases,
CanonicalBasisRowSpaceOps
for the canonical basis of a space,
SemiEchelonBasisRowSpaceOps
for semi-echelonized bases.
33.29
Row Space Coset Records
A row space coset v + U is a record with at least the following components.
isDomain
always true,
isRowSpaceCoset
always true,
isSpaceCoset
always true,
factorDen
the row space U if the coset is an element of V /U for a space V ,
646
CHAPTER 33. ROW SPACES
representative
one element of the coset, note that equal cosets need not have equal representatives
(see 33.3),
operations
the record SpaceCosetRowSpaceOps.
33.30
Quotient Space Records
A quotient space V /U is a record with at least the following components.
isDomain
always true,
isRowSpace
always true,
isFactorSpace
always true,
field
the coefficients field,
factorNum
the row space V (the numerator),
factorDen
the row space U (the denominator),
operations
the record FactorRowSpaceOps.
Chapter 34
Matrices
Matrices are an important tool in algebra. A matrix nicely represents a homomorphism
between two vector spaces with respect to a choice of bases for the vector spaces. Also
matrices represent systems of linear equations.
In GAP3 matrices are represented by list of vectors (see 32). The vectors must all have the
same length, and their elements must lie in a common field. The field may be the field of
rationals (see 12), a cyclotomic field (see 13), a finite field (see 18), or a library and/or user
defined field (or ring) such as a polynomial ring (see 19).
The first section in this chapter describes the operations applicable to matrices (see 34.1).
The next sections describes the function that tests whether an object is a matrix (see 34.2).
The next sections describe the functions that create certain matrices (see 34.3, 34.4, 34.5,
and 34.6). The next sections describe functions that compute certain characteristic values of
matrices (see 34.7, 34.14, 34.15, 34.16, and 34.17). The next sections describe the functions
that are related to the interpretation of a matrix as a system of linear equations (see 34.18,
34.19, 34.20, and 34.21). The last two sections describe the functions that diagonalize an
integer matrix (see 34.22 and 34.23).
Because matrices are just a special case of lists, all operations and functions for lists are
applicable to matrices also (see chapter 27). This especially includes accessing elements of
a matrix (see 27.4), changing elements of a matrix (see 27.6), and comparing matrices (see
27.12).
34.1
Operations for Matrices
mat + scalar
scalar + mat
This forms evaluates to the sum of the matrix mat and the scalar scalar . The elements of
mat and scalar must lie in a common field. The sum is a new matrix where each entry is
the sum of the corresponding entry of mat and scalar .
mat1 + mat2
This form evaluates to the sum of the two matrices mat1 and mat2 , which must have the
same dimensions and whose elements must lie in a common field. The sum is a new matrix
where each entry is the sum of the corresponding entries of mat1 and mat2 .
647
648
CHAPTER 34. MATRICES
mat - scalar
scalar - mat
mat1 - mat2
The definition for the - operator are similar to the above definitions for the + operator,
except that - subtracts of course.
mat * scalar
scalar * mat
This forms evaluate to the product of the matrix mat and the scalar scalar . The elements
of mat and scalar must lie in a common field. The product is a new matrix where each
entry is the product of the corresponding entries of mat and scalar .
vec * mat
This form evaluates to the product of the vector vec and the matrix mat. The length of
vec and the number of rows of mat must be equal. The elements of vec and mat must lie
in a common field. If vec is a vector of length n and mat is a matrix with n rows and m
columns, the product is a new vector of length m. The element at position i is the sum of
vec[l ] * mat[l ][i ] with l running from 1 to n.
mat * vec
This form evaluates to the product of the matrix mat and the vector vec. The number of
columns of mat and the length of vec must be equal. The elements of mat and vec must lie
in a common field. If mat is a matrix with m rows and n columns and vec is a vector of
length n, the product is a new vector of length m. The element at position i is the sum of
mat[i ][l ] * vec[l ] with l running from 1 to n.
mat1 * mat2
This form evaluates to the product of the two matrices mat1 and mat2 . The number of
columns of mat1 and the number of rows of mat2 must be equal. The elements of mat1
and mat2 must lie in a common field. If mat1 is a matrix with m rows and n columns and
mat2 is a matrix with n rows and o columns, the result is a new matrix with m rows and
o columns. The element in row i at position k of the product is the sum of mat1 [i ][l ] *
mat2 [l ][k ] with l running from 1 to n.
mat1 / mat2
scalar / mat
mat / scalar
vec / mat
In general left / right is defined as left * right^-1. Thus in the above forms the right
operand must always be invertable.
mat ^ int
This form evaluates to the int-th power of the matrix mat. mat must be a square matrix,
int must be an integer. If int is negative, mat must be invertible. If int is 0, the result is
the identity matrix, even if mat is not invertible.
mat1 ^ mat2
This form evaluates to the conjugation of the matrix mat1 by the matrix mat2 , i.e., to
mat2 ^-1 * mat1 * mat2 . mat2 must be invertible and mat1 must be such that these
product can be computed.
34.2. ISMAT
649
vec ^ mat
This is in every respect equivalent to vec * mat. This operations reflects the fact that
matrices operate on the vector space by multiplication from the right.
scalar + matlist
matlist + scalar
scalar - matlist
matlist - scalar
scalar * matlist
matlist * scalar
matlist / scalar
A scalar scalar may also be added, subtracted, multiplied with, or divide into a whole list
of matrices matlist. The result is a new list of matrices where each matrix is the result of
performing the operation with the corresponding matrix in matlist.
mat * matlist
matlist * mat
A matrix mat may also be multiplied with a whole list of matrices matlist. The result is a
new list of matrices, where each matrix is the product of mat and the corresponding matrix
in matlist.
matlist / mat
This form evaluates to matlist * mat^-1. mat must of course be invertable.
vec * matlist
This form evaluates to the product of the vector vec and the list of matrices mat. The length
l of vec and matlist must be equal. All matrices in matlist must have the same dimensions.
The elements of vec and the elements of the matrices in matlist must lie in a common field.
The product is the sum of vec[i ] * matlist[i ] with i running from 1 to l .
Comm( mat1 , mat2 )
Comm returns the commutator of the matrices mat1 and mat2 , i.e., mat1 ^-1 * mat2 ^-1
* mat1 * mat2 . mat1 and mat2 must be invertable and such that these product can be
computed.
There is one exception to the rule that the operands or their elements must lie in common
field. It is allowed that one operand is a finite field element, a finite field vector, a finite field
matrix, or a list of finite field matrices, and the other operand is an integer, an integer vector,
an integer matrix, or a list of integer matrices. In this case the integers are interpreted as
int * GF .one, where GF is the finite field (see 18.3).
For all the above operations the result is new, i.e., not identical to any other list (see 27.9).
This is the case even if the result is equal to one of the operands, e.g., if you add zero to a
matrix.
34.2
IsMat
IsMat( obj )
IsMat return true if obj , which can be an object of arbitrary type, is a matrix and false
otherwise. Will cause an error if obj is an unbound variable.
650
CHAPTER 34. MATRICES
gap> IsMat( [ [ 1, 0 ], [ 0, 1 ] ] );
true
# a matrix is a list of vectors
gap> IsMat( [ [ 1, 2, 3, 4, 5 ] ] );
true
gap> IsMat( [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] );
true
gap> IsMat( [ [ Z(2)^0, 0 ], [ 0, Z(2)^0 ] ] );
false
# Z(2)^0 and 0 do not lie in a common field
gap> IsMat( [ 1, 0 ] );
false
# a vector is not a matrix
gap> IsMat( 1 );
false
# neither is a scalar
34.3
IdentityMat
IdentityMat( n )
IdentityMat( n, F )
IdentityMat returns the identity matrix with n rows and n columns over the field F . If no
field is given, IdentityMat returns the identity matrix over the field of rationals. Each call
to IdentityMat returns a new matrix, so it is safe to modify the result.
gap> IdentityMat( 3 );
[ [ 1, 0, 0 ], [ 0, 1, 0 ], [
gap> PrintArray( last );
[ [ 1, 0, 0 ],
[ 0, 1, 0 ],
[ 0, 0, 1 ] ]
gap> PrintArray( IdentityMat(
[ [ Z(2)^0, 0*Z(2), 0*Z(2)
[ 0*Z(2), Z(2)^0, 0*Z(2)
[ 0*Z(2), 0*Z(2), Z(2)^0
34.4
0, 0, 1 ] ]
3, GF(2) ) );
],
],
] ]
NullMat
NullMat( m )
NullMat( m, n )
NullMat( m, n, F )
NullMat returns the null matrix with m rows and n columns over the field F ; if n is omitted,
it is assumed equal to m. If no field is given, NullMat returns the null matrix over the field
of rationals. Each call to NullMat returns a new matrix, so it is safe to modify the result.
gap>
[ [
[
gap>
[ [
[
PrintArray( NullMat( 2, 3 ) );
0, 0, 0 ],
0, 0, 0 ] ]
PrintArray( NullMat( 2, 2, GF(2) ) );
0*Z(2), 0*Z(2) ],
0*Z(2), 0*Z(2) ] ]
34.5. TRANSPOSEDMAT
34.5
651
TransposedMat
TransposedMat( mat )
TransposedMat returns the transposed of the matrix mat. The transposed matrix is a new
matrix trn, such that trn[i ][k ] is mat[k ][i ].
gap> TransposedMat( [ [ 1, 2 ], [ 3, 4 ] ] );
[ [ 1, 3 ], [ 2, 4 ] ]
gap> TransposedMat( [ [ 1..5 ] ] );
[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ]
34.6
KroneckerProduct
KroneckerProduct( mat1 , ..., matn )
KroneckerProduct returns the Kronecker product of the matrices mat1 , ..., matn. If mat1
is a m by n matrix and mat2 is a o by p matrix, the Kronecker product of mat1 by mat2
is a m*o by n*p matrix, such that the entry in row (i1 -1)*o+i2 at position (k1 -1)*p+k2
is mat1 [i1 ][k1 ] * mat2 [i2 ][k2 ].
gap>
gap>
gap>
[ [
[
[
[
34.7
mat1 := [ [ 0, -1, 1 ], [ -2, 0, -2 ] ];;
mat2 := [ [ 1, 1 ], [ 0, 1 ] ];;
PrintArray( KroneckerProduct( mat1, mat2 ) );
0,
0, -1, -1,
1,
1 ],
0,
0,
0, -1,
0,
1 ],
-2, -2,
0,
0, -2, -2 ],
0, -2,
0,
0,
0, -2 ] ]
DimensionsMat
DimensionsMat( mat )
DimensionsMat returns the dimensions of the matrix mat as a list of two integers. The first
entry is the number of rows of mat, the second entry is the number of columns.
gap>
[ 2,
gap>
[ 1,
34.8
DimensionsMat( [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] );
3 ]
DimensionsMat( [ [ 1 .. 5 ] ] );
5 ]
IsDiagonalMat
IsDiagonalMat( mat )
mat must be a matrix. This function returns true if mat is square and all entries mat[i][j]
with i<>j are equal to 0*mat[i][j] and false otherwise.
gap> mat := [ [ 1, 2 ], [ 3, 1 ] ];;
gap> IsDiagonalMat( mat );
false
652
CHAPTER 34. MATRICES
34.9
IsLowerTriangularMat
IsLowerTriangularMat( mat )
mat must be a matrix. This function returns true if all entries mat[i][j] with j>i are
equal to 0*mat[i][j] and false otherwise.
gap> a := [ [ 1, 2 ], [ 3, 1 ] ];;
gap> IsLowerTriangularMat( a );
false
gap> a[1][2] := 0;;
gap> IsLowerTriangularMat( a );
true
34.10
IsUpperTriangularMat
IsUpperTriangularMat( mat )
mat must be a matrix. This function returns true if all entries mat[i][j] with j a := [ [ 1, 2 ], [ 3, 1 ] ];;
gap> IsUpperTriangularMat( a );
false
gap> a[2][1] := 0;;
gap> IsUpperTriangularMat( a );
true
34.11
DiagonalOfMat
DiagonalOfMat( mat )
This function returns the list of diagonal entries of the matrix mat, that is the list of
mat[i][i].
gap> mat := [ [ 1, 2 ], [ 3, 1 ] ];;
gap> DiagonalOfMat( mat );
[ 1, 1 ]
34.12
DiagonalMat
DiagonalMat( mat1 , ...
, matn )
returns the block diagonal direct sum of the matrices mat1 , . . ., matn. Blocks of size 1 × 1
may be given as scalars.
gap> C1 := [ [
>
[
>
[
>
[
gap> C2 := [ [
>
[
>
[
2,
-1,
0,
0,
2,
0,
-1,
-1,
2,
-1,
0,
0,
2,
-1,
0,
0 ],
-1,
0 ],
2, -1 ],
-1,
2 ] ];;
-1 ],
-1 ],
2 ] ];;
34.13. PERMUTATIONMAT
653
gap> PrintArray( DiagonalMat( C1, 3, C2 ) );
[ [
2, -1,
0,
0,
0,
0,
0,
0 ],
[ -1,
2, -1,
0,
0,
0,
0,
0 ],
[
0, -1,
2, -1,
0,
0,
0,
0 ],
[
0,
0, -1,
2,
0,
0,
0,
0 ],
[
0,
0,
0,
0,
3,
0,
0,
0 ],
[
0,
0,
0,
0,
0,
2,
0, -1 ],
[
0,
0,
0,
0,
0,
0,
2, -1 ],
[
0,
0,
0,
0,
0, -1, -1,
2 ] ]
To make a diagonal matrix with a specified diagonal d use ApplyFunc(DiagonalMat, d ).
PermutationMat( perm, dim[, F] ) ( function ) returns a matrix in dimension dim over
the field given by F (i.e. the smallest field containing the element F or F itself if it is a field)
that represents the permutation perm acting by permuting the basis vectors as it permutes
points.
34.13
PermutationMat
PermutationMat( perm, dim [,F ])
returns a matrix in dimension dim over the field F (by default the rationals) that represents
the permutation perm acting by permuting the basis vectors as it permutes points.
gap> PermutationMat((1,2,3),4);
[ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 1, 0, 0, 0 ], [ 0, 0, 0, 1 ] ]
34.14
TraceMat
TraceMat( mat )
TraceMat returns the trace of the square matrix mat. The trace is the sum of all entries on
the diagonal of mat.
gap> TraceMat( [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] );
15
gap> TraceMat( IdentityMat( 4, GF(2) ) );
0*Z(2)
34.15
DeterminantMat
DeterminantMat( mat )
DeterminantMat returns the determinant of the square matrix mat. The determinant is
defined
by
P
Qn
p
p∈Symm(n) sign(p)
i=1 mat[i][i ].
gap> DeterminantMat( [ [ 1, 2 ], [ 3, 4 ] ] );
-2
gap> DeterminantMat( [ [ 0*Z(3), Z(3)^0 ], [ Z(3)^0, Z(3) ] ] );
Z(3)
Note that DeterminantMat does not use the above definition to compute the result. Instead
it performs a Gaussian elimination. For large rational matrices this may take very long,
because the entries may become very large, even if the final result is a small integer.
654
CHAPTER 34. MATRICES
34.16
RankMat
RankMat( mat )
RankMat returns the rank of the matrix mat. The rank is defined as the dimension of the
vector space spanned by the rows of mat. It follows that a n by n matrix is invertible
exactly if its rank is n.
gap> RankMat( [ [ 4, 1, 2 ], [ 3, -1, 4 ], [ -1, -2, 2 ] ] );
2
Note that RankMat performs a Gaussian elimination. For large rational matrices this may
take very long, because the entries may become very large.
34.17
OrderMat
OrderMat( mat )
OrderMat returns the order of the invertible square matrix mat. The order ord is the
smallest positive integer such that mat^ord is the identity.
gap> OrderMat( [ [ 0*Z(2), 0*Z(2), Z(2)^0 ],
>
[ Z(2)^0, Z(2)^0, 0*Z(2) ],
>
[ Z(2)^0, 0*Z(2), 0*Z(2) ] ] );
4
OrderMat first computes ord1 such that the first standard basis vector is mapped by
mat^ord1 onto itself. It does this by applying mat repeatedly to the first standard basis vector. Then it computes mat1 as mat1 ^ord1 . Then it computes ord2 such that the
second standard basis vector is mapped by mat1 ^ord2 onto itself. This process is repeated
until all basis vectors are mapped onto themselves. OrderMat warns you that the order may
be infinite, when it finds that the order must be larger than 1000.
34.18
TriangulizeMat
TriangulizeMat( mat )
TriangulizeMat brings the matrix mat into upper triangular form. Note that mat is
changed. A matrix is in upper triangular form when the first nonzero entry in each row is one
and lies further to the right than the first nonzero entry in the previous row. Furthermore,
above the first nonzero entry in each row all entries are zero. Note that the matrix will
have trailing zero rows if the rank of mat is not maximal. The rows of the resulting matrix
span the same vectorspace than the rows of the original matrix mat. The function returns
the indices of the lines of the orginal matrix corresponding to the non-zero lines of the
triangulized matrix.
gap> m := [ [ 0, -3, -1 ], [ -3, 0, -1 ], [ 2, -2, 0 ] ];;
gap> TriangulizeMat( m ); m;
[ 2, 1 ]
[ [ 1, 0, 1/3 ], [ 0, 1, 1/3 ], [ 0, 0, 0 ] ]
Note that for large rational matrices TriangulizeMat may take very long, because the
entries may become very large during the Gaussian elimination, even if the final result
contains only small integers.
34.19. BASEMAT
34.19
655
BaseMat
BaseMat( mat )
BaseMat returns a standard base for the vector space spanned by the rows of the matrix
mat. The standard base is in upper triangular form. That means that the first nonzero
vector in each row is one and lies further to the right than the first nonzero entry in the
previous row. Furthermore, above the first nonzero entry in each row all entries are zero.
gap> BaseMat( [ [ 0, -3, -1 ], [ -3, 0, -1 ], [ 2, -2, 0 ] ] );
[ [ 1, 0, 1/3 ], [ 0, 1, 1/3 ] ]
Note that for large rational matrices BaseMat may take very long, because the entries may
become very large during the Gaussian elimination, even if the final result contains only
small integers.
34.20
NullspaceMat
NullspaceMat( mat )
NullspaceMat returns a base for the nullspace of the matrix mat. The nullspace is the set
of vectors vec such that vec * mat is the zero vector. The returned base is the standard
base for the nullspace (see 34.19).
gap> NullspaceMat( [ [ 2, -4, 1 ], [ 0, 0, -4 ], [ 1, -2, -1 ] ] );
[ [ 1, 3/4, -2 ] ]
Note that for large rational matrices NullspaceMat may take very long, because the entries
may become very large during the Gaussian elimination, even if the final result only contains
small integers.
34.21
SolutionMat
SolutionMat( mat, vec )
SolutionMat returns one solution of the equation x * mat = vec or false if no such
solution exists.
gap> SolutionMat( [ [ 2,
>
[ 10,
[ 5, 15/4, 0 ]
gap> SolutionMat( [ [ 2,
>
[ 10,
false
-4, 1 ], [ 0, 0, -4 ], [ 1, -2, -1 ] ],
-20, -10 ] );
-4, 1 ], [ 0, 0, -4 ], [ 1, -2, -1 ] ],
20, -10 ] );
Note that for large rational matrices SolutionMat may take very long, because the entries
may become very large during the Gaussian elimination, even if the final result only contains
small integers.
34.22
DiagonalizeMat
DiagonalizeMat( mat )
DiagonalizeMat transforms the integer matrix mat by multiplication with unimodular (i.e.,
determinant +1 or -1) integer matrices from the left and from the right into diagonal form
656
CHAPTER 34. MATRICES
(i.e., only diagonal entries are nonzero). Note that DiagonalizeMat changes mat and returns
nothing. If there are several diagonal matrices to which mat is equivalent, it is not specified
which one is computed, except that all zero entries on the diagonal are collected at the lower
right end (see 34.23).
gap> m := [ [ 0, -1, 1 ], [ -2, 0, -2 ], [ 2, -2, 4 ] ];;
gap> DiagonalizeMat( m ); m;
[ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 0 ] ]
Note that for large integer matrices DiagonalizeMat may take very long, because the entries
may become very large during the computation, even if the final result only contains small
integers.
34.23
ElementaryDivisorsMat
ElementaryDivisorsMat( mat )
ElementaryDivisors returns a list of the elementary divisors, i.e., the unique d with d [i ]
divides d [i +1] and mat is equivalent to a diagonal matrix with the elements d [i ] on the
diagonal (see 34.22).
gap> m := [ [ 0, -1, 1 ], [ -2, 0, -2 ], [ 2, -2, 4 ] ];;
gap> ElementaryDivisorsMat( m );
[ 1, 2, 0 ]
34.24
PrintArray
PrintArray( mat )
PrintArray displays the matrix mat in a pretty way.
gap> m := [[1,2,3,4],[5,6,7,8],[9,10,11,12]];
[ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]
gap> PrintArray( m );
[ [
1,
2,
3,
4 ],
[
5,
6,
7,
8 ],
[
9, 10, 11, 12 ] ]
Chapter 35
Integral matrices and lattices
This is a subset of the functions available in GAP4, ported to GAP3 to be used by CHEVIE.
35.1
NullspaceIntMat
NullspaceIntMat( mat )
If mat is a matrix with integral entries, this function returns a list of vectors that forms a
basis of the integral nullspace of mat, i.e. of those vectors in the nullspace of mat that have
integral entries.
gap> mat:=[[1,2,7],[4,5,6],[7,8,9],[10,11,19],[5,7,12]];;
gap> NullspaceMat(mat);
[ [ 1, 0, 3/4, -1/4, -3/4 ], [ 0, 1, -13/24, 1/8, -7/24 ] ]
gap> NullspaceIntMat(mat);
[ [ 1, 18, -9, 2, -6 ], [ 0, 24, -13, 3, -7 ] ]
35.2
SolutionIntMat
SolutionIntMat( mat, vec )
If mat is a matrix with integral entries and vec a vector with integral entries, this function
returns a vector x with integer entries that is a solution of the equation x *mat=vec. It
returns false if no such vector exists.
gap> mat:=[[1,2,7],[4,5,6],[7,8,9],[10,11,19],[5,7,12]];;
gap> SolutionMat(mat,[95,115,182]);
[ 47/4, -17/2, 67/4, 0, 0 ]
gap> SolutionIntMat(mat,[95,115,182]);
[ 2285, -5854, 4888, -1299, 0 ]
35.3
SolutionNullspaceIntMat
SolutionNullspaceIntMat( mat, vec )
This function returns a list of length two, its first entry being the result of a call to
SolutionIntMat with same arguments, the second the result of NullspaceIntMat applied
657
658
CHAPTER 35. INTEGRAL MATRICES AND LATTICES
to the matrix mat. The calculation is performed faster than if two separate calls would be
used.
gap> mat:=[[1,2,7],[4,5,6],[7,8,9],[10,11,19],[5,7,12]];;
gap> SolutionNullspaceIntMat(mat,[95,115,182]);
[ [ 2285, -5854, 4888, -1299, 0 ],
[ [ 1, 18, -9, 2, -6 ], [ 0, 24, -13, 3, -7 ] ] ]
35.4
BaseIntMat
BaseIntMat( mat )
If mat is a matrix with integral entries, this function returns a list of vectors that forms a
basis of the integral row space of mat, i.e. of the set of integral linear combinations of the
rows of mat.
gap> mat:=[[1,2,7],[4,5,6],[10,11,19]];;
gap> BaseIntMat(mat);
[ [ 1, 2, 7 ], [ 0, 3, 7 ], [ 0, 0, 15 ] ]
35.5
BaseIntersectionIntMats
BaseIntersectionIntMats( m, n )
If m and n are matrices with integral entries, this function returns a list of vectors that
forms a basis of the intersection of the integral row spaces of m and n.
gap> nat:=[[5,7,2],[4,2,5],[7,1,4]];;
gap> BaseIntMat(nat);
[ [ 1, 1, 15 ], [ 0, 2, 55 ], [ 0, 0, 64 ] ]
gap> BaseIntersectionIntMats(mat,nat);
[ [ 1, 5, 509 ], [ 0, 6, 869 ], [ 0, 0, 960 ] ]
35.6
ComplementIntMat
ComplementIntMat( full , sub )
Let full be a list of integer vectors generating an Integral module M and sub a list of vectors
defining a submodule S . This function computes a free basis for M that extends S , that is,
if the dimension of S is n it determines a basis {b1 , . . . , bm } for M , as well as n integers xi
such that xi | xj for i < j and the n vectors si := xi · bi for i = 1, . . . , n form a basis for S .
It returns a record with the following components:
complement
the vectors bn+1 up to bm (they generate a complement to S ).
sub
the vectors si (a basis for S ).
moduli
the factors xi .
gap> m:=IdentityMat(3);;
gap> n:=[[1,2,3],[4,5,6]];;
35.7. TRIANGULIZEDINTEGERMAT
659
gap> ComplementIntMat(m,n);
rec( complement := [ [ 0, 0, 1 ] ], sub := [ [ 1, 2, 3 ], [ 0, 3, 6 ] ],
moduli := [ 1, 3 ] )
35.7
TriangulizedIntegerMat
TriangulizedIntegerMat( mat )
Computes an integral upper triangular form of a matrix with integer entries.
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> TriangulizedIntegerMat(m);
[ [ 1, 15, 28 ], [ 0, 1, 1 ], [ 0, 0, 3 ] ]
35.8
TriangulizedIntegerMatTransform
TriangulizedIntegerMatTransform( mat )
Computes an integral upper triangular form of a matrix with integer entries. It returns
a record with a component normal (a matrix in upper triangular form) and a component
rowtrans that gives the transformations done to the original matrix to bring it into upper
triangular form.
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> n:=TriangulizedIntegerMatTransform(m);
rec( normal := [ [ 1, 15, 28 ], [ 0, 1, 1 ], [ 0, 0, 3 ] ],
rowC := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
rowQ := [ [ 1, 0, 0 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ], rank := 3,
signdet := 1, rowtrans := [ [ 1, 0, 0 ], [ 1, -30, 17 ], [ -3, 97, -55
] ] )
gap> n.rowtrans*m=n.normal;
true
35.9
TriangulizeIntegerMat
TriangulizeIntegerMat( mat )
Changes mat to be in upper triangular form. (The result is the same as that of TriangulizedIntegerMat,
but mat will be modified, thus using less memory.)
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> TriangulizeIntegerMat(m); m;
[ [ 1, 15, 28 ], [ 0, 1, 1 ], [ 0, 0, 3 ] ]
35.10
HermiteNormalFormIntegerMat
HermiteNormalFormIntegerMat( mat )
This operation computes the Hermite normal form of a matrix mat with integer entries.
The Hermite Normal Form (HNF), H of an integer matrix, A is a row equivalent upper
triangular form such that all off-diagonal entries are reduced modulo the diagonal entry of
the column they are in. There exists a unique unimodular matrix Q such that QA = H.
660
CHAPTER 35. INTEGRAL MATRICES AND LATTICES
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> HermiteNormalFormIntegerMat(m);
[ [ 1, 0, 1 ], [ 0, 1, 1 ], [ 0, 0, 3 ] ]
35.11
HermiteNormalFormIntegerMatTransform
HermiteNormalFormIntegerMatTransform( mat )
This operation computes the Hermite normal form of a matrix mat with integer entries. It
returns a record with components normal (a matrix H of the Hermite normal form) and
rowtrans (a unimodular matrix Q) such that Qmat= H
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> n:=HermiteNormalFormIntegerMatTransform(m);
rec( normal := [ [ 1, 0, 1 ], [ 0, 1, 1 ], [ 0, 0, 3 ] ],
rowC := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
rowQ := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ], rank := 3,
signdet := 1,
rowtrans := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ] )
gap> n.rowtrans*m=n.normal;
true
35.12
SmithNormalFormIntegerMat
SmithNormalFormIntegerMat( mat )
This operation computes the Smith normal form of a matrix mat with integer entries. The
Smith Normal Form,S, of an integer matrix A is the unique equivalent diagonal form with
Si dividing Sj for i < j. There exist unimodular integer matrices P, Q such that P AQ = S.
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> SmithNormalFormIntegerMat(m);
[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 3 ] ]
35.13
SmithNormalFormIntegerMatTransforms
SmithNormalFormIntegerMatTransforms( mat )
This operation computes the Smith normal form of a matrix mat with integer entries.
It returns a record with components normal (a matrix S), rowtrans (a matrix P ), and
coltrans (a matrix Q) such that P matQ = S.
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> n:=SmithNormalFormIntegerMatTransforms(m);
rec( normal := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 3 ] ],
rowC := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
rowQ := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ],
colC := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
colQ := [ [ 1, 0, -1 ], [ 0, 1, -1 ], [ 0, 0, 1 ] ], rank := 3,
signdet := 1,
rowtrans := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ],
coltrans := [ [ 1, 0, -1 ], [ 0, 1, -1 ], [ 0, 0, 1 ] ] )
35.14. DIAGONALIZEINTMAT
661
gap> n.rowtrans*m*n.coltrans=n.normal;
true
35.14
DiagonalizeIntMat
DiagonalizeIntMat( mat )
This function changes mat to its SNF. (The result is the same as that of SmithNormalFormIntegerMat,
but mat will be modified, thus using less memory.)
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> DiagonalizeIntMat(m);m;
[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 3 ] ]
35.15
NormalFormIntMat
All the previous routines build on the following “workhorse routine
NormalFormIntMat( mat, options )
This general operation for computation of various Normal Forms is probably the most
efficient.
Options bit values
• 0/1 Triangular Form / Smith Normal Form.
• 2 Reduce off diagonal entries.
• 4 Row Transformations.
• 8 Col Transformations.
• 16 Destructive (the original matrix may be destroyed)
Compute a Triangular, Hermite or Smith form of the n × m integer input matrix A. Optionally, compute n × n and m × m unimodular transforming matrices Q, P which satisfy
QA = H or QAP = S.
Note option is a value ranging from 0 - 15 but not all options make sense (eg reducing
off diagonal entries with SNF option selected already). If an option makes no sense it is
ignored.
Returns a record with component normal containing the computed normal form and optional
components rowtrans and/or coltrans which hold the respective transformation matrix.
Also in the record are components holding the sign of the determinant, signdet, and the
Rank of the matrix, rank.
gap> m:=[[1,15,28],[4,5,6],[7,8,9]];;
gap> NormalFormIntMat(m,0); # Triangular, no transforms
rec( normal := [ [ 1, 15, 28 ], [ 0, 1, 1 ], [ 0, 0, 3 ] ], rank := 3,
signdet := 1 )
gap> NormalFormIntMat(m,6); # Hermite Normal Form with row transforms
rec( normal := [ [ 1, 0, 1 ], [ 0, 1, 1 ], [ 0, 0, 3 ] ],
rowC := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
662
CHAPTER 35. INTEGRAL MATRICES AND LATTICES
rowQ := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ], rank := 3,
signdet := 1,
rowtrans := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ] )
gap> NormalFormIntMat(m,13); # Smith Normal Form with both transforms
rec( normal := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 3 ] ],
rowC := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
rowQ := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ],
colC := [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
colQ := [ [ 1, 0, -1 ], [ 0, 1, -1 ], [ 0, 0, 1 ] ], rank := 3,
signdet := 1,
rowtrans := [ [ -2, 62, -35 ], [ 1, -30, 17 ], [ -3, 97, -55 ] ],
coltrans := [ [ 1, 0, -1 ], [ 0, 1, -1 ], [ 0, 0, 1 ] ] )
gap> last.rowtrans*m*last.coltrans;
[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 3 ] ]
35.16
AbelianInvariantsOfList
AbelianInvariantsOfList( list )
Given a list of positive integers, this routine returns a list of prime powers, such that the
prime power factors of the entries in the list are returned in sorted form.
gap> AbelianInvariantsOfList([4,6,2,12]);
[ 2, 2, 3, 3, 4, 4 ]
35.17
Determinant of an integer matrix
DeterminantIntMat( mat )
Computes the determinant of an integer matrix using the same strategy as NormalFormIntMat.
This method is faster in general for matrices greater than 20 × 20 but quite a lot slower
for smaller matrices. It therefore passes the work to the more general DeterminantMat
(see 34.15) for these smaller matrices.
35.18
Diaconis-Graham normal form
DiaconisGraham( mat, moduli )
Diaconis and Graham (see [DG99]) defined a normal form for generating sets of abelian
groups. Here moduli should be a list of positive integers such that moduli[i+1] divides
moduli[i] for all i, representing the abelian group A = Z/moduli[1] × . . . × Z/moduli[n].
The integral matrix m should have n columns where n=Length(moduli), and each line (with
the i -th element taken mod moduli[i]) represents an element of the group A.
The function returns false if the set of elements of A represented by the lines of m does
not generate A. Otherwise it returns a record r with fields
r.normal
the Diaconis-Graham normal form, a matrix of same shape as m where either
the first n lines are the identity matrix and the remaining lines are 0, or Length(m)=n
and .normal differs from the identity matrix only in the entry .normal[n][n], which
is prime to moduli[n].
35.18. DIACONIS-GRAHAM NORMAL FORM
663
r.rowtrans
a unimodular matrix such that r.normal=List(r.rowtrans*m,v->Zip(v,moduli,
function(x,y)return x mod y;end))
Here is an example:
gap> DiaconisGraham([[3,0],[4,1]],[10,5]);
rec(
rowtrans := [ [ -13, 10 ], [ 4, -3 ] ],
normal := [ [ 1, 0 ], [ 0, 2 ] ] )
664
CHAPTER 35. INTEGRAL MATRICES AND LATTICES
Chapter 36
Matrix Rings
A matrix ring is a ring of square matrices (see chapter 34). In GAP3 you can define matrix
rings of matrices over each of the fields that GAP3 supports, i.e., the rationals, cyclotomic
extensions of the rationals, and finite fields (see chapters 12, 13, and 18).
You define a matrix ring in GAP3 by calling Ring (see 5.2) passing the generating matrices
as arguments.
gap> m1 := [ [ Z(3)^0, Z(3)^0,
Z(3) ],
>
[
Z(3), 0*Z(3),
Z(3) ],
>
[ 0*Z(3),
Z(3), 0*Z(3) ] ];;
gap> m2 := [ [
Z(3),
Z(3), Z(3)^0 ],
>
[
Z(3), 0*Z(3),
Z(3) ],
>
[ Z(3)^0, 0*Z(3),
Z(3) ] ];;
gap> m := Ring( m1, m2 );
Ring( [ [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3), 0*Z(3), Z(3) ],
[ 0*Z(3), Z(3), 0*Z(3) ] ],
[ [ Z(3), Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ],
[ Z(3)^0, 0*Z(3), Z(3) ] ] )
gap> Size( m );
2187
However, currently GAP3 can only compute with finite matrix rings with a multiplicative
neutral element (a one). Also computations with large matrix rings are not done very
efficiently. We hope to improve this situation in the future, but currently you should be
careful not to try too large matrix rings.
Because matrix rings are just a special case of domains all the set theoretic functions such
as Size and Intersection are applicable to matrix rings (see chapter 4 and 36.1).
Also matrix rings are of course rings, so all ring functions such as Units and IsIntegralRing
are applicable to matrix rings (see chapter 5 and 36.2).
36.1
Set Functions for Matrix Rings
All set theoretic functions described in chapter 4 use their default function for matrix rings
currently. This means, for example, that the size of a matrix ring is computed by computing
665
666
CHAPTER 36. MATRIX RINGS
the set of all elements of the matrix ring with an orbit-like algorithm. Thus you should not
try to work with too large matrix rings.
36.2
Ring Functions for Matrix Rings
As already mentioned in the introduction of this chapter matrix rings are after all rings.
All ring functions such as Units and IsIntegralRing are thus applicable to matrix rings.
This section describes how these functions are implemented for matrix rings. Functions not
mentioned here inherit the default group methods described in the respective sections.
IsUnit( R, m )
A matrix is a unit in a matrix ring if its rank is maximal (see 34.16).
Chapter 37
Matrix Groups
A matrix group is a group of invertable square matrices (see chapter 34). In GAP3 you
can define matrix groups of matrices over each of the fields that GAP3 supports, i.e., the
rationals, cyclotomic extensions of the rationals, and finite fields (see chapters 12, 13, and
18).
You define a matrix group in GAP3 by calling Group (see 7.9) passing the generating matrices
as arguments.
gap> m1 := [ [ Z(3)^0, Z(3)^0,
Z(3) ],
>
[
Z(3), 0*Z(3),
Z(3) ],
>
[ 0*Z(3),
Z(3), 0*Z(3) ] ];;
gap> m2 := [ [
Z(3),
Z(3), Z(3)^0 ],
>
[
Z(3), 0*Z(3),
Z(3) ],
>
[ Z(3)^0, 0*Z(3),
Z(3) ] ];;
gap> m := Group( m1, m2 );
Group( [ [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3), 0*Z(3), Z(3) ],
[ 0*Z(3), Z(3), 0*Z(3) ] ],
[ [ Z(3), Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ],
[ Z(3)^0, 0*Z(3), Z(3) ] ] )
However, currently GAP3 can only compute with finite matrix groups. Also computations
with large matrix groups are not done very efficiently. We hope to improve this situation in
the future, but currently you should be careful not to try too large matrix groups.
Because matrix groups are just a special case of domains all the set theoretic functions such
as Size and Intersection are applicable to matrix groups (see chapter 4 and 37.1).
Also matrix groups are of course groups, so all the group functions such as Centralizer
and DerivedSeries are applicable to matrix groups (see chapter 7 and 37.2).
37.1
Set Functions for Matrix Groups
As already mentioned in the introduction of this chapter matrix groups are domains. All set
theoretic functions such as Size and Intersections are thus applicable to matrix groups.
This section describes how these functions are implemented for matrix groups. Functions
667
668
CHAPTER 37. MATRIX GROUPS
not mentioned here either inherit the default group methods described in 7.114 or the default
method mentioned in the respective sections.
To compute with a matrix group m, GAP3 computes the operation of the matrix group on
the underlying vector space (more precisely the union of the orbits of the parent of m on the
standard basis vectors). Then it works with the thus defined permutation group p, which
is of course isomorphic to m, and finally translates the results back into the matrix group.
obj in m
To test if an object obj lies in a matrix group m, GAP3 first tests whether obj is a invertable
square matrix of the same dimensions as the matrices of m. If it is, GAP3 tests whether
obj permutes the vectors in the union of the orbits of m on the standard basis vectors. If it
does, GAP3 takes this permutation and tests whether it lies in p.
Size( m )
To compute the size of the matrix group m, GAP3 computes the size of the isomorphic
permutation group p.
Intersection( m1 , m2 )
To compute the intersection of two subgroups m1 and m2 with a common parent matrix
group m, GAP3 intersects the images of the corresponding permutation subgroups p1 and
p2 of p. Then it translates the generators of the intersection of the permutation subgroups
back to matrices. The intersection of m1 and m2 is the subgroup of m generated by those
matrices. If m1 and m2 do not have a common parent group, or if only one of them is a
matrix group and the other is a set of matrices, the default method is used (see 4.12).
37.2
Group Functions for Matrix Groups
As already mentioned in the introduction of this chapter matrix groups are after all group.
All group functions such as Centralizer and DerivedSeries are thus applicable to matrix
groups. This section describes how these functions are implemented for matrix groups.
Functions not mentioned here either inherit the default group methods described in the
respective sections.
To compute with a matrix group m, GAP3 computes the operation of the matrix group on
the underlying vector space (more precisely, if the vector space is small enough, it enumerates
the space and acts on the whole space. Otherwise it takes the union of the orbits of the
parent of m on the standard basis vectors). Then it works with the thus defined permutation
group p, which is of course isomorphic to m, and finally translates the results back into the
matrix group.
Centralizer( m, u )
Normalizer( m, u )
SylowSubgroup( m, p )
ConjugacyClasses( m )
37.3. MATRIX GROUP RECORDS
669
This functions all work by solving the problem in the permutation group p and translating
the result back.
PermGroup( m )
This function simply returns the permutation group defined above.
Stabilizer( m, v )
The stabilizer of a vector v that lies in the union of the orbits of the parent of m on the
standard basis vectors is computed by finding the stabilizer of the corresponding point in
the permutation group p and translating this back. Other stabilizers are computed with the
default method (see 8.24).
RepresentativeOperation( m, v1 , v2 )
If v1 and v2 are vectors that both lie in the union of the orbits of the parent group of m on
the standard basis vectors, RepresentativeOperation finds a permutation in p that takes
the point corresponding to v1 to the point corresponding to v2 . If no such permutation
exists, it returns false. Otherwise it translates the permutation back to a matrix.
RepresentativeOperation( m, m1 , m2 )
If m1 and m2 are matrices in m, RepresentativeOperation finds a permutation in p that
conjugates the permutation corresponding to m1 to the permutation corresponding to m2 .
If no such permutation exists, it returns false. Otherwise it translates the permutation
back to a matrix.
37.3
Matrix Group Records
A group is represented by a record that contains information about the group. A matrix
group record contains the following components in addition to those described in section
7.118.
isMatGroup
always true.
If a permutation representation for a matrix group m is known it is stored in the following
components.
permGroupP
contains the permutation group representation of m.
permDomain
contains the union of the orbits of the parent of m on the standard basis vectors.
670
CHAPTER 37. MATRIX GROUPS
Chapter 38
Group Libraries
When you start GAP3 it already knows several groups. Currently GAP3 initially knows the
following groups:
• some basic groups, such as cyclic groups or symmetric groups (see 38.1),
• the primitive permutation groups of degree at most 50 (see 38.5),
• the transitive permutation groups of degree at most 15 (see 38.6),
• the solvable groups of size at most 100 (see 38.7),
• the 2-groups of size at most 256 (see 38.8),
• the 3-groups of size at most 729 (see 38.9),
• the irreducible solvable subgroups of GL(n, p) for n > 1 and pn < 256 (see 38.10),
• the finite perfect groups of size at most 106 (excluding 11 sizes) (see 38.11),
• the irreducible maximal finite integral matrix groups of dimension at most 24 (see
38.12),
• the crystallographic groups of dimension at most 4 (see 38.13).
• the groups of order at most 1000 except for 512 and 768 (see 38.14).
Each of the set of groups above is called a library. The whole set of groups that GAP3
knows initially is called the GAP3 collection of group libraries. There is usually no
relation between the groups in the different libraries.
Several of the libraries are accessed in a uniform manner. For each of these libraries there
is a so called selection function that allows you to select the list of groups that satisfy
given criterias from a library. The example function allows you to select one group that
satisfies given criteria from the library. The low-level extraction function allows you to
extract a single group from a library, using a simple indexing scheme. These functions are
described in the sections 38.2, 38.3, and 38.4.
Note that a system administrator may choose to install all, or only a few, or even none
of the libraries. So some of the libraries mentioned below may not be available on your
installation.
671
672
CHAPTER 38. GROUP LIBRARIES
38.1
The Basic Groups Library
CyclicGroup( n )
CyclicGroup( D, n )
In the first form CyclicGroup returns the cyclic group of size n as a permutation group. In
the second form D must be a domain of group elements, e.g., Permutations or AgWords,
and CyclicGroup returns the cyclic group of size n as a group of elements of that type.
gap> c12 := CyclicGroup( 12 );
Group( ( 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12) )
gap> c105 := CyclicGroup( AgWords, 5*3*7 );
Group( c105_1, c105_2, c105_3 )
gap> Order(c105,c105.1); Order(c105,c105.2); Order(c105,c105.3);
105
35
7
AbelianGroup( sizes )
AbelianGroup( D, sizes )
In the first form AbelianGroup returns the abelian group Csizes[1] ∗ Csizes[2] ∗ ... ∗ Csizes[n] ,
where sizes must be a list of positive integers, as a permutation group. In the second form
D must be a domain of group elements, e.g., Permutations or AgWords, and AbelianGroup
returns the abelian group as a group of elements of this type.
gap> g := AbelianGroup( AgWords, [ 2, 3, 7 ] );
Group( a, b, c )
gap> Size( g );
42
gap> IsAbelian( g );
true
The default function GroupElementsOps.AbelianGroup uses the functions CyclicGroup
and DirectProduct (see 7.99) to construct the abelian group.
ElementaryAbelianGroup( n )
ElementaryAbelianGroup( D, n )
In the first form ElementaryAbelianGroup returns the elementary abelian group of size
n as a permutation group. n must be a positive prime power of course. In the second form D must be a domain of group elements, e.g., Permutations or AgWords, and
ElementaryAbelianGroup returns the elementary abelian group as a group of elements of
this type.
gap> ElementaryAbelianGroup( 16 );
Group( (1,2), (3,4), (5,6), (7,8) )
gap> ElementaryAbelianGroup( AgWords, 3 ^ 10 );
Group( m59049_1, m59049_2, m59049_3, m59049_4, m59049_5, m59049_6,
m59049_7, m59049_8, m59049_9, m59049_10 )
The default function GroupElementsOps.ElementaryAbelianGroup uses CyclicGroup and
DirectProduct (see 7.99 to construct the elementary abelian group.
38.1. THE BASIC GROUPS LIBRARY
673
DihedralGroup( n )
DihedralGroup( D, n )
In the first form DihedralGroup returns the dihedral group of size n as a permutation
group. n must be a positive even integer. In the second form D must be a domain of group
elements, e.g., Permutations or AgWords, and DihedralGroup returns the dihedral group
as a group of elements of this type.
gap> DihedralGroup( 12 );
Group( (1,2,3,4,5,6), (2,6)(3,5) )
PolyhedralGroup( p, q )
PolyhedralGroup( D, p, q )
In the first form PolyhedralGroup returns the polyhedral group of size p * q as a permutation group. p and q must be positive integers and there must exist a nontrivial p-th root
of unity modulo every prime factor of q. In the second form D must be a domain of group
elements, e.g., Permutations or Words, and PolyhedralGroup returns the polyhedral group
as a group of elements of this type.
gap> PolyhedralGroup( 3, 13 );
Group( ( 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13), ( 2, 4,10)( 3, 7, 6)
( 5,13,11)( 8, 9,12) )
gap> Size( last );
39
SymmetricGroup( d )
SymmetricGroup( D, d )
In the first form SymmetricGroup returns the symmetric group of degree d as a permutation
group. d must be a positive integer. In the second form D must be a domain of group
elements, e.g., Permutations or Words, and SymmetricGroup returns the symmetric group
as a group of elements of this type.
gap> SymmetricGroup( 8 );
Group( (1,8), (2,8), (3,8), (4,8), (5,8), (6,8), (7,8) )
gap> Size( last );
40320
AlternatingGroup( d )
AlternatingGroup( D, d )
In the first form AlternatingGroup returns the alternating group of degree d as a permutation group. d must be a positive integer. In the second form D must be a domain of
group elements, e.g., Permutations or Words, and AlternatingGroup returns the alternating group as a group of elements of this type.
gap> AlternatingGroup( 8 );
Group( (1,2,8), (2,3,8), (3,4,8), (4,5,8), (5,6,8), (6,7,8) )
gap> Size( last );
20160
674
CHAPTER 38. GROUP LIBRARIES
GeneralLinearGroup( n, q )
GeneralLinearGroup( D, n, q )
In the first form GeneralLinearGroup returns the general linear group GL(n, q) as a matrix
group. In the second form D must be a domain of group elements, e.g., Permutations or
AgWords, and GeneralLinearGroup returns GL(n, q) as a group of elements of that type.
gap> g := GeneralLinearGroup( 2, 4 ); Size( g );
GL(2,4)
180
SpecialLinearGroup( n, q )
SpecialLinearGroup( D, n, q )
In the first form SpecialLinearGroup returns the special linear group SL(n, q) as a matrix
group. In the second form D must be a domain of group elements, e.g., Permutations or
AgWords, and SpecialLinearGroup returns SL(n, q) as a group of elements of that type.
gap> g := SpecialLinearGroup( 3, 4 ); Size( g );
SL(3,4)
60480
SymplecticGroup( n, q )
SymplecticGroup( D, n, q )
In the first form SymplecticGroup returns the symplectic group SP (n, q) as a matrix group.
In the second form D must be a domain of group elements, e.g., Permutations or AgWords,
and SymplecticGroup returns SP (n, q) as a group of elements of that type.
gap> g := SymplecticGroup( 4, 2 ); Size( g );
SP(4,2)
720
GeneralUnitaryGroup( n, q )
GeneralUnitaryGroup( D, n, q )
In the first form GeneralUnitaryGroup returns the general unitary group GU (n, q) as a
matrix group. In the second form D must be a domain of group elements, e.g., Permutations
or AgWords, and GeneralUnitaryGroup returns GU (n, q) as a group of elements of that
type.
gap> g := GeneralUnitaryGroup( 3, 3 ); Size( g );
GU(3,3)
24192
SpecialUnitaryGroup( n, q )
SpecialUnitaryGroup( D, n, q )
In the first form SpecialUnitaryGroup returns the special unitary group SU (n, q) as a
matrix group. In the second form D must be a domain of group elements, e.g., Permutations
or AgWords, and SpecialUnitaryGroup returns SU (n, q) as a group of elements of that type.
38.2. SELECTION FUNCTIONS
675
gap> g := SpecialUnitaryGroup( 3, 3 ); Size( g );
SU(3,3)
6048
MathieuGroup( d )
MathieuGroup returns the Mathieu group of degree d as a permutation group. d is expected
to be 11, 12, 22, 23, or 24.
gap> g := MathieuGroup( 12 ); Size( g );
Group( ( 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11), ( 3, 7,11, 8)
( 4,10, 5, 6), ( 1,12)( 2,11)( 3, 6)( 4, 8)( 5, 9)( 7,10) )
95040
38.2
Selection Functions
AllLibraryGroups( fun1 , val1 , fun2 , val2 , ...
)
For each group library there is a selection function. This function allows you to select all
groups from the library that have a given set of properties.
The name of the selection functions always begins with All and always ends with Groups.
Inbetween is a name that hints at the nature of the group library. For example, the selection
function for the library of all primitive groups of degree at most 50 (see 38.5) is called
AllPrimitiveGroups, and the selection function for the library of all 2-groups of size at
most 256 (see 38.8) is called AllTwoGroups.
These functions take an arbitrary number of pairs of arguments. The first argument in
such a pair is a function that can be applied to the groups in the library, and the second
argument is either a single value that this function must return in order to have this group
included in the selection, or a list of such values.
For example
AllPrimitiveGroups( DegreeOperation,
Size,
IsAbelian,
[10..15],
[1..100],
false
);
should return a list of all primitive groups with degree between 10 and 15 and size less than
100 that are not abelian.
Thus the AllPrimitiveGroups behaves as if it was implemented by a function similar to
the one defined below, where PrimitiveGroupsList is a list of all primitive groups. Note,
in the definition below we assume for simplicity that AllPrimitiveGroups accepts exactly
4 arguments. It is of course obvious how to change this definition so that the function would
accept a variable number of arguments.
AllPrimitiveGroups := function ( fun1, val1, fun2, val2 )
local
groups, g, i;
groups := [];
for i in [ 1 .. Length( PrimitiveGroupsList ) ] do
g := PrimitiveGroupsList[i];
if
fun1(g) = val1 or IsList(val1) and fun1(g) in val1
and fun2(g) = val2 or IsList(val2) and fun2(g) in val2
676
CHAPTER 38. GROUP LIBRARIES
then
Add( groups, g );
fi;
od;
return groups;
end;
Note that the real selection functions are considerably more difficult, to improve the efficiency. Most important, each recognizes a certain set of functions and handles those
properties using an index (see 1.26).
38.3
Example Functions
OneLibraryGroup( fun1 , val1 , fun2 , val2 , ...
)
For each group library there is a example function. This function allows you to find one
group from the library that has a given set of properties.
The name of the example functions always begins with One and always ends with Group.
Inbetween is a name that hints at the nature of the group library. For example, the example
function for the library of all primitive groups of degree at most 50 (see 38.5) is called
OnePrimitiveGroup, and the example function for the library of all 2-groups of size at most
256 (see 38.8) is called OneTwoGroup.
These functions take an arbitrary number of pairs of arguments. The first argument in
such a pair is a function that can be applied to the groups in the library, and the second
argument is either a single value that this function must return in order to have this group
returned by the example function, or a list of such values.
For example
OnePrimitiveGroup( DegreeOperation,
Size,
IsAbelian,
[10..15],
[1..100],
false
);
should return one primitive group with degree between 10 and 15 and size size less than 100
that is not abelian.
Thus the OnePrimitiveGroup behaves as if it was implemented by a function similar to the
one defined below, where PrimitiveGroupsList is a list of all primitive groups. Note, in
the definition below we assume for simplicity that OnePrimitiveGroup accepts exactly 4
arguments. It is of course obvious how to change this definition so that the function would
accept a variable number of arguments.
OnePrimitiveGroup := function ( fun1, val1, fun2, val2 )
local
g, i;
for i in [ 1 .. Length( PrimitiveGroupsList ) ] do
g := PrimitiveGroupsList[i];
if
fun1(g) = val1 or IsList(val1) and fun1(g) in val1
and fun2(g) = val2 or IsList(val2) and fun2(g) in val2
then
return g;
fi;
od;
38.4. EXTRACTION FUNCTIONS
677
return false;
end;
Note that the real example functions are considerably more difficult, to improve the efficiency. Most important, each recognizes a certain set of functions and handles those
properties using an index (see 1.26).
38.4
Extraction Functions
For each group library there is an extraction function. This function allows you to extract
single groups from the library.
The name of the extraction function always ends with Group and begins with a name that
hints at the nature of the library. For example the extraction function for the library of
primitive groups (see 38.5) is called PrimitiveGroup, and the extraction function for the
library of all 2-groups of size at most 256 (see 38.8) is called TwoGroup.
What arguments the extraction function accepts, and how they are interpreted is described
in the sections that describe the individual group libraries.
For example
PrimitiveGroup( 10, 4 );
returns the 4-th primitive group of degree 10.
The reason for the extraction function is as follows. A group library is usually not stored as
a list of groups. Instead a more compact representation for the groups is used. For example
the groups in the library of 2-groups are represented by 4 integers. The extraction function
hides this representation from you, and allows you to access the group library as if it was a
table of groups (two dimensional in the above example).
678
CHAPTER 38. GROUP LIBRARIES
38.5
The Primitive Groups Library
This group library contains all primitive permutation groups of degree at most 50. There are
a total of 406 such groups. Actually to be a little bit more precise, there are 406 inequivalent
primitive operations on at most 50 points. Quite a few of the 406 groups are isomorphic.
AllPrimitiveGroups( fun1 , val1 , fun2 , val2 , ...
)
AllPrimitiveGroups returns a list containing all primitive groups that have the properties
given as arguments. Each property is specified by passing a pair of arguments, the first
being a function, which will be applied to all groups in the library, and the second being a
value or a list of values, that this function must return in order to have this group included
in the list returned by AllPrimitiveGroups.
The first argument must be DegreeOperation and the second argument either a degree or
a list of degrees, otherwise AllPrimitiveGroups will print a warning to the effect that the
library contains only groups with degrees between 1 and 50.
gap> l := AllPrimitiveGroups( Size, 120, IsSimple, false );
#W AllPrimitiveGroups: degree automatically restricted to [1..50]
[ S(5), PGL(2,5), S(5) ]
gap> List( l, g -> g.generators );
[ [ (1,2,3,4,5), (1,2) ], [ (1,2,3,4,5), (2,3,5,4), (1,6)(3,4) ],
[ ( 1, 8)( 2, 5, 6, 3)( 4, 9, 7,10), ( 1, 5, 7)( 2, 9, 4)( 3, 8,10)
] ]
OnePrimitiveGroup( fun1 , val1 , fun2 , val2 , ...
)
OnePrimitiveGroup returns one primitive group that has the properties given as argument.
Each property is specified by passing a pair of arguments, the first being a function, which
will be applied to all groups in the library, and the second being a value or a list of values,
that this function must return in order to have this group returned by OnePrimitiveGroup.
If no such group exists, false is returned.
The first argument must be DegreeOperation and the second argument either a degree or
a list of degrees, otherwise OnePrimitiveGroup will print a warning to the effect that the
library contains only groups with degrees between 1 and 50.
gap> g := OnePrimitiveGroup( DegreeOperation,5, IsSolvable,false );
A(5)
gap> Size( g );
60
AllPrimitiveGroups and OnePrimitiveGroup recognize the following functions and handle
them usually quite efficient. DegreeOperation, Size, Transitivity, and IsSimple. You
should pass those functions first, e.g., it is more efficient to say AllPrimitiveGroups(
Size,120 , IsAbelian,false ) than to say AllPrimitiveGroups( IsAbelian,false,
Size,120 ) (see 1.26).
PrimitiveGroup( deg, nr )
38.5. THE PRIMITIVE GROUPS LIBRARY
679
PrimitiveGroup returns the nr -th primitive group of degree deg. Both deg and nr must
be positive integers. The primitive groups of equal degree are sorted with respect to their
size, so for example PrimitiveGroup( deg, 1 ) is the smallest primitive group of degree
deg, e.g, the cyclic group of size deg, if deg is a prime. Primitive groups of equal degree and
size are in no particular order.
gap> g := PrimitiveGroup( 8, 1 );
AGL(1,8)
gap> g.generators;
[ (1,2,3,4,5,6,7), (1,8)(2,4)(3,7)(5,6) ]
Apart from the usual components described in 7.118, the group records returned by the
above functions have the following components.
transitivity
degree of transitivity of G.
isSharpTransitive
true if G is sharply G.transitivity-fold transitive and false otherwise.
isKPrimitive
true if G is k -fold primitive, and false otherwise.
isOdd
false if G is a subgroup of the alternating group of degree G.degree and true
otherwise.
isFrobeniusGroup
true if G is a Frobenius group and false otherwise.
This library was computed by Charles Sims. The list of primitive permutation groups of
degree at most 20 was published in [Sim70]. The library was brought into GAP3 format by
Martin Schönert. He assumes the responsibility for all mistakes.
680
CHAPTER 38. GROUP LIBRARIES
38.6
The Transitive Groups Library
The transitive groups library contains representatives for all transitive permutation groups
of degree at most 22. Two permutations groups of the same degree are considered to be
equivalent, if there is a renumbering of points, which maps one group into the other one.
In other words, if they lie in the save conjugacy class under operation of the full symmetric
group by conjugation.
There are a total of 4945 such groups up to degree 22.
AllTransitiveGroups( fun1 , val1 , fun2 , val2 , ...
)
AllTransitiveGroups returns a list containing all transitive groups that have the properties
given as arguments. Each property is specified by passing a pair of arguments, the first
being a function, and the second being a value or a list of values. AllTransitiveGroups
will return all groups from the transitive groups library, for which all specified functions
have the specified values.
If the degree is not restricted to 22 at most, AllTransitiveGroups will print a warning.
OneTransitiveGroup( fun1 , val1 , fun2 , val2 , ...
)
OneTransitiveGroup returns one transitive group that has the properties given as argument. Each property is specified by passing a pair of arguments, the first being a function,
and the second being a value or a list of values. OneTransitiveGroup will return one groups
from the transitive groups library, for which all specified functions have the specified values.
If no such group exists, false is returned.
If the degree is not restricted to 22 at most, OneTransitiveGroup will print a warning.
AllTransitiveGroups and OneTransitiveGroup recognize the following functions and get
the corresponding properties from a precomputed list to speed up processing:
DegreeOperation, Size, Transitivity, and IsPrimitive. You do not need to pass those
functions first, as the selection function picks the these properties first.
TransitiveGroup( deg, nr )
TransitiveGroup returns the nr -th transitive group of degree deg. Both deg and nr must be
positive integers. The transitive groups of equal degree are sorted with respect to their size,
so for example TransitiveGroup( deg, 1 ) is the smallest transitive group of degree deg,
e.g, the cyclic group of size deg, if deg is a prime. The ordering of the groups corresponds
to the list in Butler/McKay [BM83].
This library was computed by Gregory Butler, John McKay, Gordon Royle and Alexander
Hulpke. The list of transitive groups up to degree 11 was published in [BM83], the list of
degree 12 was published in [Roy87], degree 14 and 15 were published in [But93].
The library was brought into GAP3 format by Alexander Hulpke, who is responsible for all
mistakes.
gap> TransitiveGroup(10,22);
S(5)[x]2
gap> l:=AllTransitiveGroups(DegreeOperation,12,Size,1440,
38.6. THE TRANSITIVE GROUPS LIBRARY
681
> IsSolvable,false);
[ S(6)[x]2, M_10.2(12) = A_6.E_4(12) = [S_6[1/720]{M_10}S_6]2 ]
gap> List(l,IsSolvable);
[ false, false ]
TransitiveIdentification( G )
Let G be a permutation group, acting transitively on a set of up to 22 points. Then
TransitiveIdentification will return the position of this group in the transitive groups
library. This means, if G operates on m points and TransitiveIdentification returns n,
then G is permutation isomorphic to the group TransitiveGroup(m,n).
gap> TransitiveIdentification(Group((1,2),(1,2,3)));
2
682
CHAPTER 38. GROUP LIBRARIES
38.7
The Solvable Groups Library
GAP3 has a library of the 1045 solvable groups of size between 2 and 100. The groups are
from lists computed by M. Hall and J. K. Senior (size 64, see [HS64]), R. Laue (size 96, see
[Lau82]) and J. Neubüser (other sizes, see [Neu67]).
AllSolvableGroups( fun1 , val1 , fun2 , val2 , ...
)
AllSolvableGroups returns a list containing all solvable groups that have the properties
given as arguments. Each property is specified by passing a pair of arguments, the first
being a function, which will be applied to all the groups in the library, and the second being
a value or a list of values, that this function must return in order to have this group included
in the list returned by AllSolvableGroups.
gap> AllSolvableGroups(Size,24,IsNontrivialDirectProduct,false);
[ 12.2, grp_24_11, D24, Q8+S3, Sl(2,3), S4 ]
OneSolvableGroup( fun1 , val1 , fun2 , val2 , ...
)
OneSolvableGroup returns a solvable group with the specified properties. Each property is
specified by passing a pair of arguments, the first being a function, which will be applied
to all the groups in the library, and the second being a value or a list of values, that this
function must return in order to have this group returned by OneSolvableGroup. If no such
group exists, false is returned.
gap> OneSolvableGroup(Size,100,x->Size(DerivedSubgroup(x)),10);
false
gap> OneSolvableGroup(Size,24,IsNilpotent,false);
S3x2^2
AllSolvableGroups and OneSolvableGroup recognize the following functions and handle
them usually very efficiently:Size, IsAbelian, IsNilpotent, and IsNonTrivialDirectProduct.
SolvableGroup( size, nr )
SolvableGroup returns the nr -th group of size size in the library. SolvableGroup will
signal an error if size is not between 2 and 100, or if nr is larger than the number of solvable
groups of size size. The group is returned as finite polycyclic group (see 25).
gap> SolvableGroup( 32 , 15 );
Q8x4
38.8. THE 2-GROUPS LIBRARY
38.8
683
The 2-Groups Library
The library of 2-groups contains all the 2-groups of size dividing 256. There are a total of
58760 such groups, 1 of size 2, 2 of size 4, 5 of size 8, 14 of size 16, 51 of size 32, 267 of size
64, 2328 of size 128, and 56092 of size 256.
AllTwoGroups( fun1 , val1 , fun2 , val2 , ...
)
AllTwoGroups returns the list of all the 2-groups that have the properties given as arguments. Each property is specified by passing a pair of arguments, the first is a function that
can be applied to each group, the second is either a single value or a list of values that the
function must return in order to select that group.
gap> l := AllTwoGroups( Size, 256, Rank, 3, pClass, 2 );
[ Group( a1, a2, a3, a4, a5, a6, a7, a8 ),
Group( a1, a2, a3, a4, a5, a6, a7, a8 ),
Group( a1, a2, a3, a4, a5, a6, a7, a8 ),
Group( a1, a2, a3, a4, a5, a6, a7, a8 ) ]
gap> List( l, g -> Length( ConjugacyClasses( g ) ) );
[ 112, 88, 88, 88 ]
OneTwoGroup( fun1 , val1 , fun2 , val2 , ...
)
OneTwoGroup returns a single 2-group that has the properties given as arguments. Each
property is specified by passing a pair of arguments, the first is a function that can be
applied to each group, the second is either a single value or a list of values that the function
must return in order to select that group.
gap> g := OneTwoGroup( Size, [64..128], Rank, [2..3], pClass, 5 );
#I size restricted to [ 64, 128 ]
Group( a1, a2, a3, a4, a5, a6 )
gap> Size( g );
64
gap> Rank( g );
2
AllTwoGroups and OneTwoGroup recognize the following functions and handle them usually
very efficiently. Size, Rank for the rank of the Frattini quotient of the group, and pClass
for the exponent-p class of the group. Note that Rank and pClass are dummy functions
that can be used only in this context, i.e., they can not be applied to arbitrary groups.
TwoGroup( size, nr )
TwoGroup returns the nr -th group of size size. The group is returned as a finite polycyclic
group (see 25). TwoGroup will signal an error if size is not a power of 2 between 2 and 256,
or nr is larger than the number of groups of size size.
Within each size the following criteria have been used, in turn, to determine the index
position of a group in the list
1
increasing generator number;
684
CHAPTER 38. GROUP LIBRARIES
2
increasing exponent-2 class;
3
the position of its parent in the list of groups of appropriate size;
4
the list in which the Newman and O’Brien implementation of the p-group generation
algorithm outputs the immediate descendants of a group.
gap> g := TwoGroup( 32, 45 );
Group( a1, a2, a3, a4, a5 )
gap> Rank( g );
4
gap> pClass( g );
2
gap> g.abstractRelators;
[ a1^2*a5^-1, a2^2, a2^-1*a1^-1*a2*a1, a3^2, a3^-1*a1^-1*a3*a1,
a3^-1*a2^-1*a3*a2, a4^2, a4^-1*a1^-1*a4*a1, a4^-1*a2^-1*a4*a2,
a4^-1*a3^-1*a4*a3, a5^2, a5^-1*a1^-1*a5*a1, a5^-1*a2^-1*a5*a2,
a5^-1*a3^-1*a5*a3, a5^-1*a4^-1*a5*a4 ]
Apart from the usual components described in 7.118, the group records returned by the
above functions have the following components.
rank
rank of Frattini quotient of G.
pclass
exponent-p class of G.
abstractGenerators
a list of abstract generators of G (see 22.1).
abstractRelators
a list of relators of G stored as words in the abstract generators.
Descriptions of the algorithms used in constructing the library data may be found in
[O´Br90, O´Br91]. Using these techniques, a library was first prepared in 1987 by M.F. Newman and E.A. O’Brien; a partial description may be found in [NO89].
The library was brought into the GAP3 format by Werner Nickel, Alice Niemeyer, and
E.A. O’Brien.
38.9. THE 3-GROUPS LIBRARY
38.9
685
The 3-Groups Library
The library of 3-groups contains all the 3-groups of size dividing 729. There are a total of
594 such groups, 1 of size 3, 2 of size 9, 5 of size 27, 15 of size 81, 67 of size 243, and 504 of
size 729.
AllThreeGroups( fun1 , val1 , fun2 , val2 , ...
)
AllThreeGroups returns the list of all the 3-groups that have the properties given as arguments. Each property is specified by passing a pair of arguments, the first is a function that
can be applied to each group, the second is either a single value or a list of values that the
function must return in order to select that group.
gap> l := AllThreeGroups( Size, 243, Rank, [2..4], pClass, 3 );;
gap> Length ( l );
33
gap> List( l, g -> Length( ConjugacyClasses( g ) ) );
[ 35, 35, 35, 35, 35, 35, 35, 243, 99, 99, 51, 51, 51, 51, 51, 51,
51, 51, 99, 35, 243, 99, 99, 51, 51, 51, 51, 51, 35, 35, 35, 35, 35
]
OneThreeGroup( fun1 , val1 , fun2 , val2 , ...
)
OneThreeGroup returns a single 3-group that has the properties given as arguments. Each
property is specified by passing a pair of arguments, the first is a function that can be
applied to each group, the second is either a single value or a list of values that the function
must return in order to select that group.
gap> g := OneThreeGroup( Size, 729, Rank, 4, pClass, [3..5] );
Group( a1, a2, a3, a4, a5, a6 )
gap> IsAbelian( g );
true
AllThreeGroups and OneThreeGroup recognize the following functions and handle them
usually very efficiently. Size, Rank for the rank of the Frattini quotient of the group, and
pClass for the exponent-p class of the group. Note that Rank and pClass are dummy
functions that can be used only in this context, i.e., they cannot be applied to arbitrary
groups.
ThreeGroup( size, nr )
ThreeGroup returns the nr -th group of size size. The group is returned as a finite polycyclic
group (see 25). ThreeGroup will signal an error if size is not a power of 3 between 3 and
729, or nr is larger than the number of groups of size size.
Within each size the following criteria have been used, in turn, to determine the index
position of a group in the list
1
increasing generator number;
2
increasing exponent-3 class;
3
the position of its parent in the list of groups of appropriate size;
686
CHAPTER 38. GROUP LIBRARIES
4
the list in which the Newman and O’Brien implementation of the p-group generation
algorithm outputs the immediate descendants of a group.
gap> g := ThreeGroup( 243, 56 );
Group( a1, a2, a3, a4, a5 )
gap> pClass( g );
3
gap> g.abstractRelators;
[ a1^3, a2^3, a2^-1*a1^-1*a2*a1*a4^-1, a3^3, a3^-1*a1^-1*a3*a1,
a3^-1*a2^-1*a3*a2*a5^-1, a4^3, a4^-1*a1^-1*a4*a1*a5^-1,
a4^-1*a2^-1*a4*a2, a4^-1*a3^-1*a4*a3, a5^3, a5^-1*a1^-1*a5*a1,
a5^-1*a2^-1*a5*a2, a5^-1*a3^-1*a5*a3, a5^-1*a4^-1*a5*a4 ]
Apart from the usual components described in 7.118, the group records returned by the
above functions have the following components.
rank
rank of Frattini quotient of G.
pclass
exponent-p class of G.
abstractGenerators
a list of abstract generators of G (see 22.1).
abstractRelators
a list of relators of G stored as words in the abstract generators.
Descriptions of the algorithms used in constructing the library data may be found in
[O´Br90, O´Br91].
The library was generated and brought into GAP3 format by E.A. O’Brien and Colin Rhodes.
David Baldwin, M.F. Newman, and Maris Ozols have contributed in various ways to this
project and to correctly determining these groups. The library design is modelled on and
borrows extensively from the 2-groups library, which was brought into GAP3 format by
Werner Nickel, Alice Niemeyer, and E.A. O’Brien.
38.10. THE IRREDUCIBLE SOLVABLE LINEAR GROUPS LIBRARY
38.10
687
The Irreducible Solvable Linear Groups Library
The IrredSol group library provides access to the irreducible solvable subgroups of GL(n, p),
where n > 1, p is prime and pn < 256. The library contains exactly one member from each
of the 370 conjugacy classes of such subgroups.
By well known theory, this library also doubles as a library of primitive solvable permutation
groups of non-prime degree less than 256. To access the data in this form, you must first
build the matrix group(s) of interest and then call the function
PrimitivePermGroupIrreducibleMatGroup( matgrp )
This function returns a permutation group isomorphic to the semidirect product of an
irreducible matrix group (over a finite field) and its underlying vector space.
AllIrreducibleSolvableGroups( fun1 , val1 , fun2 , val2 , ...
)
AllIrreducibleSolvableGroups returns a list containing all irreducible solvable linear
groups that have the properties given as arguments. Each property is specified by passing a pair of arguments, the first being a function which will be applied to all groups in the
library, and the second being a value or a list of values that this function must return in
order to have this group included in the list returned by AllIrreducibleSolvableGroups.
gap> AllIrreducibleSolvableGroups( Dimension, 2,
>
CharFFE, 3,
>
Size, 8 );
[ Group( [ [ 0*Z(3), Z(3)^0 ], [ Z(3)^0, 0*Z(3) ] ],
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ],
[ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3) ] ] ),
Group( [ [ 0*Z(3), Z(3)^0 ], [ Z(3), 0*Z(3) ] ],
[ [ Z(3)^0, Z(3) ], [ Z(3), Z(3) ] ] ),
Group( [ [ 0*Z(3), Z(3)^0 ], [ Z(3)^0, Z(3) ] ] ) ]
OneIrreducibleSolvableGroup( fun1 , val1 , fun2 , val2 , ...
)
OneIrreducibleSolvableGroup returns one irreducible solvable linear group that has the
properties given as arguments. Each property is specified by passing a pair of arguments,
the first being a function which will be applied to all groups in the library, and the second
being a value or a list of values that this function must return in order to have this group
returned by OneIrreducibleSolvableGroup. If no such group exists, false is returned.
gap> OneIrreducibleSolvableGroup( Dimension, 4,
>
IsLinearlyPrimitive, false );
Group( [ [ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ],
[ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2) ],
[ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ] ],
[ [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ],
[ Z(2)^0, Z(2)^0, 0*Z(2), 0*Z(2) ],
[ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ] ],
[ [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2) ],
688
CHAPTER 38. GROUP LIBRARIES
[ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ],
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ],
[ 0*Z(2), 0*Z(2), Z(2)^0, Z(2)^0 ] ] )
AllIrreducibleSolvableGroups and OneIrreducibleSolvableGroup recognize the following functions and handle them very efficiently (because the information is stored with
the groups and so no computations are needed):Dimension for the linear degree, CharFFE for
the field characteristic, Size, IsLinearlyPrimitive, and MinimalBlockDimension. Note
that the last two are dummy functions that can be used only in this context. Their meaning
is explained at the end of this section.
IrreducibleSolvableGroup( n, p, i )
IrreducibleSolvableGroup returns the i -th irreducible solvable subgroup of GL( n, p
). The irreducible solvable subgroups of GL(n, p) are ordered with respect to the
following criteria
1. increasing size;
2. increasing guardian number.
If two groups have the same size and guardian, they are in no particular order. (See the
library documentation or [Sho92] for the meaning of guardian.)
gap> g := IrreducibleSolvableGroup( 3, 5, 12 );
Group( [ [ 0*Z(5), Z(5)^2, 0*Z(5) ], [ Z(5)^2, 0*Z(5),
[ 0*Z(5), 0*Z(5), Z(5)^2 ] ],
[ [ 0*Z(5), Z(5)^0, 0*Z(5) ], [ 0*Z(5), 0*Z(5), Z(5)^0
[ Z(5)^0, 0*Z(5), 0*Z(5) ] ],
[ [ Z(5)^2, 0*Z(5), 0*Z(5) ], [ 0*Z(5), Z(5)^0, 0*Z(5)
[ 0*Z(5), 0*Z(5), Z(5)^2 ] ],
[ [ Z(5)^0, 0*Z(5), 0*Z(5) ], [ 0*Z(5), Z(5)^2, 0*Z(5)
[ 0*Z(5), 0*Z(5), Z(5)^2 ] ],
[ [ Z(5), 0*Z(5), 0*Z(5) ], [ 0*Z(5), Z(5), 0*Z(5) ],
[ 0*Z(5), 0*Z(5), Z(5) ] ] )
0*Z(5) ],
],
],
],
Apart from the usual components described in 7.118, the group records returned by the
above functions have the following components.
size
size of G.
isLinearlyPrimitive
false if G preserves a direct sum decomposition of the underlying vector space, and
true otherwise.
minimalBlockDimension
not bound if G is linearly primitive; otherwise equals the dimension of the blocks in
an unrefinable system of imprimitivity for G.
This library was computed and brought into GAP3 format by Mark Short. Descriptions of
the algorithms used in computing the library data can be found in [Sho92].
38.11. THE LIBRARY OF FINITE PERFECT GROUPS
38.11
689
The Library of Finite Perfect Groups
The GAP3 library of finite perfect groups provides, up to isomorphism, a list of all perfect
groups whose sizes are less than 106 excluding the following:
• For n = 61440, 122880, 172032, 245760, 344064, 491520, 688128, or 983040, the perfect
groups of size n have not completely been determined yet. The library neither provides
the number of these groups nor the groups themselves.
• For n = 86016, 368640, or 737280, the library does not yet contain the perfect groups
of size n, it only provides their their numbers which are 52, 46, or 54, respectively.
Except for these eleven sizes, the list of altogether 1096 perfect groups in the library is complete. It relies on results of Derek F. Holt and Wilhelm Plesken which are published in their
book Perfect Groups [HP89]. Moreover, they have supplied to us files with presentations
of 488 of the groups. In terms of these, the remaining 607 nontrivial groups in the library
can be described as 276 direct products, 107 central products, and 224 subdirect products.
They are computed automatically by suitable GAP3 functions whenever they are needed.
We are grateful to Derek Holt and Wilhelm Plesken for making their groups available to the
GAP3 community by contributing their files. It should be noted that their book contains a
lot of further information for many of the library groups. So we would like to recommend
it to any GAP3 user who is interested in the groups.
The library has been brought into GAP3 format by Volkmar Felsch.
Like most of the other GAP3 libraries, the library of finite perfect groups provides an extraction function, PerfectGroup. It returns the specified group in form of a finitely presented
group which, in its group record, bears some additional information that allows you to easily
construct an isomorphic permutation group of some appropriate degree by just calling the
PermGroup function.
Further, there is a function NumberPerfectGroups which returns the number of perfect
groups of a given size.
The library does not provide a selection or an example function. There is, however, a
function DisplayInformationPerfectGroups which allows the display of some information
about arbitrary library groups without actually loading the large files with their presentations, and without constructing the groups themselves.
Moereover, there are two functions which allow you to formulate loops over selected library
groups. The first one is the NumberPerfectLibraryGroups function which, for any given
size, returns the number of groups in the library which are of that size.
The second one is the SizeNumbersPerfectGroups function. It allows you to ask for
all library groups which contain certain composition factors. The answer is provided in
form of a list of pairs [size,n] where each such pair characterizes the nth library group
of size size. We will call such a pair [size,n] the size number of the respective perfect
group. As the size numbers are accepted as input arguments by the PerfectGroup and the
DisplayInformationPerfectGroups function, you may use their list to formulate a loop
over the associated groups.
Now we shall give an individual description of each library function.
NumberPerfectGroups( size )
690
CHAPTER 38. GROUP LIBRARIES
NumberPerfectGroups returns the number of non-isomorphic perfect groups of size size for
each positive integer size up to 106 except for the eight sizes listed at the beginning of this
section for which the number is not yet known. For these values as well as for any argument
out of range it returns the value −1.
NumberPerfectLibraryGroups( size )
NumberPerfectLibraryGroups returns the number of perfect groups of size size which are
available in the library of finite perfect groups.
The purpose of the function is to provide a simple way to formulate a loop over all library
groups of a given size.
SizeNumbersPerfectGroups( factor1 , factor2 ...
)
SizeNumbersPerfectGroups returns a list of the size numbers (see above) of all library
groups that contain the specified factors among their composition factors. Each argument
must either be the name of a simple group or an integer expression which is the product
of the sizes of one or more cyclic factors. The function ignores the order in which the
argmuments are given and, in fact, replaces any list of more than one integer expression
among the arguments by their product.
The following text strings are accepted as simple group names.
"A5", "A6", "A7", "A8", "A9" or "A(5)", "A(6)", "A(7)", "A(8)", "A(9)" for the
alternating groups An , 5 ≤ n ≤ 9,
"L2(q)" or "L(2,q)" for P SL(2, q), where q is any prime power with 4 ≤ q ≤ 125,
"L3(q)" or "L(3,q)" for P SL(3, q) with 2 ≤ q ≤ 5,
"U3(q)" or "U(3,q)" for P SU (2, q) with 3 ≤ q ≤ 5,
"U4(2) or "U(4,2)" for P SU (4, 2),
"Sp4(4)" or "S(4,4)" for the symplectic group S(4, 4),
"Sz(8)" for the Suzuki group Sz(8),
"M11", "M12", "M22" or "M(11)", "M(12)", "M(22)" for the Matthieu groups M11 ,
M12 , and M22 , and
"J1", "J2" or "J(1)", "J(2)" for the Janko groups J1 and J2 .
Note that, for most of the groups, the preceding list offers two different names in order to
be consistent with the notation used in [HP89] as well as with the notation used in the
DisplayCompositionSeries command of GAP3. However, as the names are compared as
text strings, you are restricted to the above choice. Even expressions like "L2( 32 )" or
"L2(2^5)" are not accepted.
As the use of the term P SU (n, q) is not unique in the literature, we state that here it denotes
the factor group of SU (n, q) by its centre, where SU (n, q) is the group of all n × n unitary
matrices with entries in GF (q 2 ) and determinant 1.
The purpose of the function is to provide a simple way to formulate a loop over all library
groups which contain certain composition factors.
38.11. THE LIBRARY OF FINITE PERFECT GROUPS
691
DisplayInformationPerfectGroups( size )
DisplayInformationPerfectGroups( size, n )
DisplayInformationPerfectGroups( [ size, n ] )
DisplayInformationPerfectGroups displays some information about the library group G,
say, which is specified by the size number [size,n] or by the two arguments size and n. If,
in the second case, n is omitted, the function will loop over all library groups of size size.
The information provided for G includes the following items:
• a headline containing the size number [size, n] of G in the form size.n (the suffix .n
will be suppressed if, up to isomorphism, G is the only perfect group of size size),
• a message if G is simple or quasisimple, i. e., if the factor group of G by its centre is
simple,
• the “description” of the structure of G as it is given by Holt and Plesken in [HP89]
(see below),
• the size of the centre of G (suppressed, if G is simple),
• the prime decomposition of the size of G,
• orbit sizes for a faithful permutation representation of G which is provided by the
library (see below),
• a reference to each occurrence of G in the tables of section 5.3 of [HP89]. Each of
these references consists of a class number and an internal number (i, j) under which
G is listed in that class. For some groups, there is more than one reference because
these groups belong to more than one of the classes in the book.
Example:
gap> DisplayInformationPerfectGroups( 30720, 3 );
#I Perfect group 30720.3: A5 ( 2^4 E N 2^1 E 2^4 ) A
#I
centre = 1 size = 2^11*3*5 orbit size = 240
#I
Holt-Plesken class 1 (9,3)
gap> DisplayInformationPerfectGroups( 30720, 6 );
#I Perfect group 30720.6: A5 ( 2^4 x 2^4 ) C N 2^1
#I
centre = 2 size = 2^11*3*5 orbit size = 384
#I
Holt-Plesken class 1 (9,6)
gap> DisplayInformationPerfectGroups( Factorial( 8 ) /
#I Perfect group 20160.1: A5 x L3(2) 2^1
#I
centre = 2 size = 2^6*3^2*5*7 orbit sizes = 5 +
#I
Holt-Plesken class 31 (1,1) (occurs also in class
#I Perfect group 20160.2: A5 2^1 x L3(2)
#I
centre = 2 size = 2^6*3^2*5*7 orbit sizes = 7 +
#I
Holt-Plesken class 31 (1,2) (occurs also in class
#I Perfect group 20160.3: ( A5 x L3(2) ) 2^1
#I
centre = 2 size = 2^6*3^2*5*7 orbit size = 192
#I
Holt-Plesken class 31 (1,3)
#I Perfect group 20160.4: simple group A8
#I
size = 2^6*3^2*5*7 orbit size = 8
#I
Holt-Plesken class 26 (0,1)
#I Perfect group 20160.5: simple group L3(4)
#I
size = 2^6*3^2*5*7 orbit size = 21
2 );
16
32)
24
32)
692
CHAPTER 38. GROUP LIBRARIES
#I
Holt-Plesken class 27 (0,1)
For any library group G, the library files do not only provide a presentation, but, in addition,
a list of one or more subgroups
Pr S1 , . . . , Sr of G such that there is a faithful permutation representation of G of degree i=1 G : Si on the set {Si g | 1 ≤ i ≤ r, g ∈ G} of the cosets of the
Si . The respective permutation group is available via the PermGroup function described below. The DisplayInformationPerfectGroups function displays only the available degree.
The message
orbit size = 8
in the above example means that the available permutation representation is transitive and
of degree 8, whereas the message
orbit sizes = 7 + 24
means that a nontransitive permutation representation is available which acts on two orbits
of size 7 and 24 respectively.
The notation used in the “description” of a group is explained in section 5.1.2 of [HP89].
We quote the respective page from there:
‘Within a class Q # p, an isomorphism type of groups will be denoted by an ordered pair
of integers (r, n), where r ≥ 0 and n > 0. More precisely, the isomorphism types in Q # p
of order pr |Q| will be denoted by (r, 1), (r, 2), (r, 3), . . . . Thus Q will always get the size
number (0, 1).
In addition to the symbol (r, n), the groups in Q # p will also be given a more descriptive
name. The purpose of this is to provide a very rough idea of the structure of the group.
The names are derived in the following manner. First of all, the isomorphism classes of
irreducible Fp Q-modules M with |Q||M| ≤ 106 , where Fp is the field of order p, are assigned
symbols. These will either be simply px , where x is the dimension of the module, or, if there
is more than one isomorphism class of irreducible modules having the same dimension, they
0
will be denoted by px , px , etc. The one-dimensional module with trivial Q-action will
therefore be denoted by p1 . These symbols will be listed under the description of Q. The
group name consists essentially of a list of the composition factors working from the top of
the group downwards; hence it always starts with the name of Q itself. (This convention
is the most convenient in our context, but it is different from that adopted in the ATLAS
(Conway et al. 1985), for example, where composition factors are listed in the reverse order.
For example, we denote a group isomorphic to SL(2, 5) by A5 21 rather than 2 · A5 .)
Some other symbols are used in the name, in order to give some idea of the relationship between these composition factors, and splitting properties. We shall now list these additional
symbols.
× between two factors denotes a direct product of Fp Q-modules or groups.
C (for ‘commutator’) between two factors means that the second lies in the commutator
subgroup of the first. Similarly, a segment of the form (f1 ×f2 )Cf3 would mean that
the factors f1 and f2 commute modulo f3 and f3 lies in [f1 , f2 ].
A (for ‘abelian’) between two factors indicates that the second is in the pth power (but
not the commutator subgroup) of the first. ‘A’ may also follow the factors, if bracketed.
E (for ‘elementary abelian’) between two factors indicates that together they generate
an elementary abelian group (modulo subsequent factors), but that the resulting Fp Qmodule extension does not split.
38.11. THE LIBRARY OF FINITE PERFECT GROUPS
693
N (for ‘nonsplit’) before a factor indicates that Q (or possibly its covering group) splits
down as far at this factor but not over the factor itself. So ‘Qf1 N f2 ’ means that the
normal subgroup f1 f2 of the group has no complement but, modulo f2 , f1 , does have
a complement.
Brackets have their obvious meaning. Summarizing, we have
× = dirext product;
C = commutator subgroup;
A = abelian;
E = elementary abelian; and
N = nonsplit.
Here are some examples.
(i) A5 (24 E21 E24 )A means that the pairs 24 E21 and 21 E24 are both elementary abelian
of exponent 4.
(ii) A5 (24 E21 A)C21 means that O2 (G) is of symplectic type 21+5 , with Frattini factor
group of type 24 E21 . The ‘A’ after the 21 indicates that G has a central cyclic
subgroup 21 A21 of order 4.
0
0
0
(iii) L3 (2)((21 E)×(N 23 E23 A)C)23 means that the 23 factor at the bottom lies in the
0
0
0
commutator subgroup of the pair 23 E23 in the middle, but the lower pair 23 A23
1
30
is abelian of exponent 4. There is also a submodule 2 E2 , and the covering group
L3 (2)21 of L3 (2) does not split over the 23 factor. (Since G is perfect, it goes without
saying that the extension L3 (2)21 cannot split itself.)
We must stress that this notation does not always succeed in being precise or even unambiguous, and the reader is free to ignore it if it does not seem helpful.’
If such a group description has been given in the book for G (and, in fact, this is the case
for most of the library groups), it is displayed by the DisplayInformationPerfectGroups
function. Otherwise the function provides a less explicit description of the (in these cases
unique) Holt-Plesken class to which G belongs, together with a serial number if this is
necessary to make it unique.
PerfectGroup( size )
PerfectGroup( size, n )
PerfectGroup( [ size, n ] )
PerfectGroup is the essential extraction function of the library. It returns a finitely presented group, G say, which is isomorphic to the library group specified by the size number
[size,n] or by the two separate arguments size and n. In the second case, you may omit the
parameter n. Then the default value is n = 1.
gap> G := PerfectGroup( 6048 );
PerfectGroup(6048)
gap> G.generators;
[ a, b ]
gap> G.relators;
[ a^2, b^6, a*b*a*b*a*b*a*b*a*b*a*b*a*b,
a*b^2*a*b^2*a*b^2*a*b^-2*a*b^-2*a*b^-2,
694
CHAPTER 38. GROUP LIBRARIES
a*b*a*b^-2*a*b*a*b^-2*a*b*a*b^-2*a*b*a*b^-1*a*b^-1 ]
gap> G.size;
6048
gap> G.description;
"U3(3)"
gap> G.subgroups;
[ Subgroup( PerfectGroup(6048), [ a, b*a*b*a*b*a*b^3 ] ) ]
The generators and relators of G coincide with those given in [HP89].
Note that, besides the components that are usually initialized for any finitely presented
group, the group record of G contains the following components:
size
the size of G,
isPerfect
always true,
description
the description of G as described with the DisplayInformationPerfectGroups function above,
source
some internal information used by the library functions,
subgroups
a list of subgroups S1 , . . . , Sr of G such that G acts faithfully on on the union of the
sets of all cosets of the Si .
The last of these components exists only if G is one of the 488 nontrivial library groups
which are given directly by a presentation on file, i. e., which are not constructed from other
library groups in form of a direct, central, or subdirect product. It will be required by the
following function.
PermGroup( G )
PermGroup returns a permutation group, P say, which is isomorphic to the given group G
which is assumed to be a finitely presented perfect group that has been extracted from the
library of finite perfect groups via the PerfectGroup function.
Let S1 , . . . , Sr be the subgroups listed in the component G.subgroupsP
of the group record
r
of G. Then the resulting group P is the permutation group of degree i=1 G : Si which is
induced by G on the set {Si g | 1 ≤ i ≤ r, g ∈ G} of all cosets of the Si .
Example (continued):
gap> P := PermGroup( G );
PermGroup(PerfectGroup(6048))
gap> P.size;
6048
gap> P.degree;
28
Note that some of the library groups do not have a faithful permutation representation of
small degree. Computations in these groups may be rather time consuming.
38.11. THE LIBRARY OF FINITE PERFECT GROUPS
Example:
gap> P := PermGroup( PerfectGroup( 129024, 2 ) );
PermGroup(PerfectGroup(129024,2))
gap> P.degree;
14336
695
696
38.12
CHAPTER 38. GROUP LIBRARIES
Irreducible Maximal Finite Integral Matrix Groups
A library of irreducible maximal finite integral matrix groups is provided with GAP3. It
contains Q-class representatives for all of these groups of dimension at most 24, and Z-class
representatives for those of dimension at most 11 or of dimension 13, 17, 19, or 23.
The groups provided in this library have been determined by Wilhelm Plesken, partially as
joint work with Michael Pohst, or by members of his institute (Lehrstuhl B für Mathematik,
RWTH Aachen). In particular, the data for the groups of dimensions 2 to 9 have been
taken from the output of computer calculations which they performed in 1979 (see [PP77],
[PP80]). The Z-class representatives of the groups of dimension 10 have been determined
and computed by Bernd Souvignier ([Sou94]), and those of dimensions 11, 13, and 17 have
been recomputed for this library from the circulant Gram matrices given in [Ple85], using
the stand-alone programs for the computation of short vectors and Bravais groups which
have been developed in Plesken’s institute. The Z-class representatives of the groups of
dimensions 19 and 23 had already been determined in [Ple85]. Gabriele Nebe has recomputed
them for us. Her main contribution to this library, however, is that she has determined and
computed the Q-class representatives of the groups of non-prime dimensions between 12 and
24 (see [PN95], [NP95b], [Neb95]).
The library has been brought into GAP3 format by Volkmar Felsch. He has applied several
GAP3 routines to check certain consistency of the data. However, the credit and responsibility for the lists remain with the authors. We are grateful to Wilhelm Plesken, Gabriele
Nebe, and Bernd Souvignier for supplying their results to GAP3.
In the preceding acknowledgement, we used some notations that will also be needed in the
sequel. We first define these.
Any integral matrix group G of dimension n is a subgroup of GLn (Z) as well as of GLn (Q)
and hence lies in some conjugacy class of integral matrix groups under GLn (Z) and also
in some conjugacy class of rational matrix groups under GLn (Q). As usual, we call these
classes the Z-class and the Q-class of G, respectively. Note that any conjugacy class of
subgroups of GLn (Q) contains at least one Z-class of subgroups of GLn (Z) and hence can
be considered as the Q-class of some integral matrix group.
In the context of this library we are only concerned with Z-classes and Q-classes of subgroups of GLn (Z) which are irreducible and maximal finite in GLn (Z) (we will call them
i. m. f. subgroups of GLn (Z)). We can distinguish two types of these groups:
First, there are those i. m. f. subgroups of GLn (Z) which are also maximal finite subgroups
of GLn (Q). Let us denote the set of their Q-classes by Q1 (n). It is clear from the above
remark that Q1 (n) just consists of the Q-classes of i. m. f. subgroups of GLn (Q).
Secondly, there is the set Q2 (n) of the Q-classes of the remaining i. m. f. subgroups of
GLn (Z), i. e., of those which are not maximal finite subgroups of GLn (Q). For any such
group G, say, there is at least one class C ∈ Q1 (n) such that G is conjugate under Q to
a proper subgroup of some group H ∈ C. In fact, the class C is uniquely determined for
any group G occurring in the library (though there seems to be no reason to assume that
this property should hold in general). Hence we may call C the rational i. m. f. class of
G. Finally, we will denote the number of classes in Q1 (n) and Q2 (n) by q1 (n) and q2 (n),
respectively.
As an example, let us consider the case n = 4. There are 6 Z-classes of i. m. f. subgroups
of GL4 (Z) with representative subgroups G1 , . . . , G6 of isomorphsim types G1 ∼
= W (F4 ),
38.12. IRREDUCIBLE MAXIMAL FINITE INTEGRAL MATRIX GROUPS
697
G2 ∼
= D12 o C2 , G3 ∼
= G4 ∼
= C2 × S5 , G5 ∼
= W (B4 ), and G6 ∼
= (D12 YD12 ) : C2 . The corresponding Q-classes, R1 , . . . , R6 , say, are pairwise different except that R3 coincides with R4 .
The groups G1 , G2 , and G3 are i. m. f. subgroups of GL4 (Q), but G5 and G6 are not because
they are conjugate under GL4 (Q) to proper subgroups of G1 and G2 , respectively. So we
have Q1 (4) = {R1 , R2 , R3 }, Q2 (4) = {R5 , R6 }, q1 (4) = 3, and q2 (4) = 2.
The q1 (n) Q-classes of i. m. f. subgroups of GLn (Q) have been determined for each dimension
n ≤ 24. The current GAP3 library provides integral representative groups for all these
classes. Moreover, all Z-classes of i. m. f. subgroups of GLn (Z) are known for n ≤ 11 and for
n ∈ {13, 17, 19, 23}. For these dimensions, the library offers integral representative groups
for all Q-classes in Q1 (n) and Q2 (n) as well as for all Z-classes of i. m. f. subgroups of
GLn (Z).
Any group G of dimension n given in the library is represented as the automorphism group
G = Aut(F, L) = {g ∈ GLn (Z) | Lg = L and gF g tr = F } of a positive definite symmetric
n × n matrix F ∈ Zn×n on an n-dimensional lattice L ∼
= Z1×n (for details see e. g. [PN95]).
GAP3 provides for G a list of matrix generators and the Gram matrix F .
The positive definite quadratic form defined by F defines a norm vF v tr for each vector v ∈ L,
and there is only a finite set of vectors of minimal norm. These vectors are often simply
called the “short vectors”. Their set splits into orbits under G, and G being irreducible acts
faithfully on each of these orbits by multiplication from the right. GAP3 provides for each
of these orbits the orbit size and a representative vector.
Like most of the other GAP3 libraries, the library of i. m. f. integral matrix groups supplies
an extraction function, ImfMatGroup. However, as the library involves only 423 different
groups, there is no need for a selection or an example function. Instead, there are two
functions, ImfInvariants and DisplayImfInvariants, which provide some Z-class invariants that can be extracted from the library without actually constructing the representative
groups themselves. The difference between these two functions is that the latter one displays the resulting data in some easily readable format, whereas the first one returns them
as record components so that you can properly access them.
We shall give an individual description of each of the library functions, but first we would
like to insert a short remark concerning their names: Any self-explaining name of a function
handling irreducible maximal finite integral matrix groups would have to include this term
in full length and hence would grow extremely long. Therefore we have decided to use the
abbreviation Imf instead in order to restrict the names to some reasonable length.
The first three functions can be used to formulate loops over the classes.
ImfNumberQQClasses( dim )
ImfNumberQClasses( dim )
ImfNumberZClasses( dim, q )
ImfNumberQQClasses returns the number q1 (dim) of Q-classes of i. m. f. rational matrix
groups of dimension dim. Valid values of dim are all positive integers up to 24.
Note: In order to enable you to loop just over the classes belonging to Q1 (dim), we have
arranged the list of Q-classes of dimension dim for any dimension dim in the library such
that, whenever the classes of Q2 (dim) are known, too, i. e., in the cases dim ≤ 11 or
dim ∈ {13, 17, 19, 23}, the classes of Q1 (dim) precede those of Q2 (dim) and hence are
numbered from 1 to q1 (dim).
698
CHAPTER 38. GROUP LIBRARIES
ImfNumberQClasses returns the number of Q-classes of groups of dimension dim which
are available in the library. If dim ≤ 11 or dim ∈ {13, 17, 19, 23}, this is the number
q1 (dim) + q2 (dim) of Q-classes of i. m. f. subgroups of GLdim (Z). Otherwise, it is just the
number q1 (dim) of Q-classes of i. m. f. subgroups of GLdim (Q). Valid values of dim are all
positive integers up to 24.
ImfNumberZClasses returns the number of Z-classes in the q th Q-class of i. m. f. integral
matrix groups of dimension dim. Valid values of dim are all positive integers up to 11 and
all primes up to 23.
DisplayImfInvariants( dim, q )
DisplayImfInvariants( dim, q, z )
DisplayImfInvariants displays the following Z-class invariants of the groups in the z th
Z-class in the q th Q-class of i. m. f. integral matrix groups of dimension dim:
• its Z-class number in the form dim.q.z , if dim is at most 11 or a prime, or its Q-class
number in the form dim.q, else,
• a message if the group is solvable,
• the size of the group,
• the isomorphism type of the group,
• the elementary divisors of the associated quadratic form,
• the sizes of the orbits of short vectors (these sizes are the degrees of the faithful permutation representations which you may construct using the PermGroup or
PermGroupImfGroup commands below),
• the norm of the associated short vectors,
• only in case that the group is not an i. m. f. group in GLn (Q): an appropriate message,
including the Q-class number of the corresponding rational i. m. f. class.
If you specify the value 0 for any of the parameters dim, q, or z , the command will loop over
all available dimensions, Q-classes of given dimension, or Z-classes within the given Q-class,
respectively. Otherwise, the values of the arguments must be in range. A value z 6= 1 must
not be specified if the Z-classes are not known for the given dimension, i. e., if dim > 11
and dim 6∈ {13, 17, 19, 23}. The default value of z is 1. This value of z will be accepted
even if the Z-classes are not known. Then it specifies the only representative group which
is available for the q th Q-class. The greatest legal value of dim is 24.
gap> DisplayImfInvariants( 3, 1, 0 );
#I Z-class 3.1.1: Solvable, size = 2^4*3
#I
isomorphism type = C2 wr S3 = C2 x S4 = W(B3)
#I
elementary divisors = 1^3
#I
orbit size = 6, minimal norm = 1
#I Z-class 3.1.2: Solvable, size = 2^4*3
#I
isomorphism type = C2 wr S3 = C2 x S4 = C2 x W(A3)
#I
elementary divisors = 1*4^2
#I
orbit size = 8, minimal norm = 3
#I Z-class 3.1.3: Solvable, size = 2^4*3
#I
isomorphism type = C2 wr S3 = C2 x S4 = C2 x W(A3)
#I
elementary divisors = 1^2*4
38.12. IRREDUCIBLE MAXIMAL FINITE INTEGRAL MATRIX GROUPS
699
#I
orbit size = 12, minimal norm = 2
gap> DisplayImfInvariants( 8, 15, 1 );
#I Z-class 8.15.1: Solvable, size = 2^5*3^4
#I
isomorphism type = C2 x (S3 wr S3)
#I
elementary divisors = 1*3^3*9^3*27
#I
orbit size = 54, minimal norm = 8
#I
not maximal finite in GL(8,Q), rational imf class is 8.5
gap> DisplayImfInvariants( 20, 23 );
#I Q-class 20.23: Size = 2^5*3^2*5*11
#I
isomorphism type = (PSL(2,11) x D12).C2
#I
elementary divisors = 1^18*11^2
#I
orbit size = 3*660 + 2*1980 + 2640 + 3960, minimal norm = 4
Note that the DisplayImfInvariants function uses a kind of shorthand to display the
elementary divisors. E. g., the expression 1*3^3*9^3*27 in the preceding example stands
for the elementary divisors 1, 3, 3, 3, 9, 9, 9, 27. (See also the next example which shows that
the ImfInvariants function provides the elementary divisors in form of an ordinary GAP3
list.)
In the description of the isomorphism types the following notations are used:
AxB
A subd B
AYB
A wr B
A:B
A.B
denotes
denotes
denotes
denotes
denotes
denotes
a direct product of a group A by a group B,
a subdirect product of A by B,
a central product of A by B,
a wreath product of A by B,
a split extension of A by B,
just an extension of A by B (split or nonsplit).
The groups involved are
• the cyclic groups Cn , dihedral groups Dn , and generalized quaternion groups Qn of
order n, denoted by Cn, Dn, and Qn, respectively,
• the alternating groups An and symmetric groups Sn of degree n, denoted by An and
Sn, respectively,
• the linear groups GLn (q), P GLn (q), SLn (q), and P SLn (q), denoted by GL(n,q),
PGL(n,q), SL(n,q), and PSL(n,q), respectively,
• the unitary groups SUn (q) and P SUn (q), denoted by SU(n,q) and PSU(n,q), respectively,
• the symplectic groups Sp(n, q), denoted by Sp(n,q),
• the orthogonal group O8+ (2), denoted by O+(8,2),
• the extraspecial groups 2+1+8 , 3+1+2 , 3+1+4 , and 5+1+2 , denoted by 2+^(1+8), 3+^(1+2),
3+^(1+4), and 5+^(1+2), respectively,
• the Chevalley group G2 (3), denoted by G(2,3),
• the Weyl groups W (An ), W (Bn ), W (Dn ), W (En ), and W (F4 ), denoted by W(An),
W(Bn), W(Dn), W(En), and W(F4), respectively,
• the sporadic simple groups Co1 , Co2 , Co3 , HS, J2 , M12 , M22 , M23 , M24 , and M c,
denoted by Co1, Co2, Co3, HS, J2, M12, M22, M23, M24, and Mc, respectively,
• a point stabilizer of index 11 in M11 , denoted by M10.
700
CHAPTER 38. GROUP LIBRARIES
As mentioned above, the data assembled by the DisplayImfInvariants command are
“cheap data” in the sense that they can be provided by the library without loading any
of its large matrix files or performing any matrix calculations. The following function allows
you to get proper access to these cheap data instead of just displaying them.
ImfInvariants( dim, q )
ImfInvariants( dim, q, z )
ImfInvariants returns a record which provides some Z-class invariants of the groups in the
z th Z-class in the q th Q-class of i. m. f. integral matrix groups of dimension dim. A value
z 6= 1 must not be specified if the Z-classes are not known for the given dimension, i. e., if
dim > 11 and dim 6∈ {13, 17, 19, 23}. The default value of z is 1. This value of z will be
accepted even if the Z-classes are not known. Then it specifies the only representative group
which is available for the q th Q-class. The greatest legal value of dim is 24.
The resulting record contains six or seven components:
size
the size of any representative group G,
isSolvable
is true if G is solvable,
isomorphismType
a text string describing the isomorphism type of G (in the same notation as used by
the DisplayImfInvariants command above),
elementaryDivisors
the elementary divisors of the associated Gram matrix F (in the same format as the
result of the ElementaryDivisorsMat function, see 34.23),
minimalNorm
the norm of the associated short vectors,
sizesOrbitsShortVectors
the sizes of the orbits of short vectors under F ,
maximalQClass
the Q-class number of an i. m. f. group in GLn (Q) that contains G as a subgroup
(only in case that not G itself is an i. m. f. subgroup of GLn (Q)).
Note that four of these data, namely the group size, the solvability, the isomorphism type,
and the corresponding rational i. m. f. class, are not only Z-class invariants, but also Q-class
invariants.
Note further that, though the isomorphism type is a Q-class invariant, you will sometimes
get different descriptions for different Z-classes of the same Q-class (as, e. g., for the classes
3.1.1 and 3.1.2 in the last example above). The purpose of this behaviour is to provide some
more information about the underlying lattices.
gap> ImfInvariants( 8, 15, 1 );
rec(
size := 2592,
isSolvable := true,
isomorphismType := "C2 x (S3 wr S3)",
38.12. IRREDUCIBLE MAXIMAL FINITE INTEGRAL MATRIX GROUPS
701
elementaryDivisors := [ 1, 3, 3, 3, 9, 9, 9, 27 ],
minimalNorm := 8,
sizesOrbitsShortVectors := [ 54 ],
maximalQClass := 5 )
gap> ImfInvariants( 24, 1 ).size;
10409396852733332453861621760000
gap> ImfInvariants( 23, 5, 2 ).sizesOrbitsShortVectors;
[ 552, 53130 ]
gap> for i in [ 1 .. ImfNumberQClasses( 22 ) ] do
>
Print( ImfInvariants( 22, i ).isomorphismType, "\n" ); od;
C2 wr S22 = W(B22)
(C2 x PSU(6,2)).S3
(C2 x S3) wr S11 = (C2 x W(A2)) wr S11
(C2 x S12) wr C2 = (C2 x W(A11)) wr C2
C2 x S3 x S12 = C2 x W(A2) x W(A11)
(C2 x HS).C2
(C2 x Mc).C2
C2 x S23 = C2 x W(A22)
C2 x PSL(2,23)
C2 x PSL(2,23)
C2 x PGL(2,23)
C2 x PGL(2,23)
ImfMatGroup( dim, q )
ImfMatGroup( dim, q, z )
ImfMatGroup is the essential extraction function of this library. It returns a representative
group, G say, of the z th Z-class in the q th Q-class of i. m. f. integral matrix groups of
dimension dim. A value z 6= 1 must not be specified if the Z-classes are not known for the
given dimension, i. e., if dim > 11 and dim 6∈ {13, 17, 19, 23}. The default value of z is 1.
This value of z will be accepted even if the Z-classes are not known. Then it specifies the
only representative group which is available for the q th Q-class. The greatest legal value of
dim is 24.
gap> G := ImfMatGroup( 5, 1, 3 );
ImfMatGroup(5,1,3)
gap> for m in G.generators do PrintArray( m ); od;
[ [ -1,
0,
0,
0,
0 ],
[
0,
1,
0,
0,
0 ],
[
0,
0,
0,
1,
0 ],
[ -1, -1, -1, -1,
2 ],
[ -1,
0,
0,
0,
1 ] ]
[ [ 0, 1, 0, 0, 0 ],
[ 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 1, 0 ],
[ 1, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 1 ] ]
The group record of G contains the usual components of a matrix group record. In addition,
it includes the same six or seven records as the resulting record of the ImfInvariants
702
CHAPTER 38. GROUP LIBRARIES
function described above, namely the components size, isSolvable, isomorphismType,
elementaryDivisors, minimalNorm, and sizesOrbitsShortVectors and, if G is not a
rational i. m. f. group, maximalQClass. Moreover, there are the two components
form
the associated Gram matrix F ,
repsOrbitsShortVectors
representatives of the orbits of short vectors under F .
The last of these components will be required by the PermGroup function below.
Example:
gap> G.size;
3840
gap> G.isomorphismType;
"C2 wr S5 = C2 x W(D5)"
gap> PrintArray( G.form );
[ [ 4, 0, 0, 0, 2 ],
[ 0, 4, 0, 0, 2 ],
[ 0, 0, 4, 0, 2 ],
[ 0, 0, 0, 4, 2 ],
[ 2, 2, 2, 2, 5 ] ]
gap> G.elementaryDivisors;
[ 1, 4, 4, 4, 4 ]
gap> G.minimalNorm;
4
If you want to perform calculations in such a matrix group G you should be aware of the
fact that GAP3 offers much more efficient permutation group routines than matrix group
routines. Hence we recommend that you do your computations, whenever it is possible, in
the isomorphic permutation group that is induced by the action of G on one of the orbits
of the associated short vectors. You may call one of the following functions to get such a
permutation group.
PermGroup( G )
PermGroup returns the permutation group which is induced by the given i. m. f. integral
matrix group G on an orbit of minimal size of G on the set of short vectors (see also
PermGroupImfGroup below).
The permutation representation is computed by first constructing the specified orbit, S
say, of short vectors and then computing the permutations which are induced on S by the
generators of G. We would like to warn you that in case of a large orbit this procedure may
be space and time consuming. Fortunately, there are only five Q-classes in the library for
which the smallest orbit of short vectors is of size greater than 20000, the worst case being
the orbit of size 196560 for the Leech lattice (dim = 24, q = 3).
As mentioned above, PermGroup constructs the required permutation group, P say, as the
image of G under the isomorphism between the matrices in G and their action on S.
Moreover, it constructs the inverse isomorphism from P to G, ϕ say, and returns it in the
group record component P .bijection of P . In fact, ϕ is constructed by determining a Qbase B ⊂ S of Q1×dim in S and, in addition, the associated base change matrix M which
38.12. IRREDUCIBLE MAXIMAL FINITE INTEGRAL MATRIX GROUPS
703
transforms B into the standard base of Z1×dim . Then the image ϕ(p) of any permutation
p ∈ P can be easily computed: If, for 1 ≤ i ≤ dim, bi is the position number in S of the ith
base vector in B, it suffices to look up the vector whose position number in S is the image
of bi under p and to multiply this vector by M to get the ith row of ϕ(p).
You may use ϕ at any time to compute the images in G of permutations in P or to compute
the preimages in P of matrices in G.
The record of P contains, in addition to the usual components of permutation group records,
some special components. The most important of those are:
isomorphismType
a text string describing the isomorphism type of P (in the same notation as used by
the DisplayImfInvariants command above),
matGroup
the associated matrix group G,
bijection
the isomorphism ϕ from P to G,
orbitShortVectors
the orbit S of short vectors (needed for ϕ),
baseVectorPositions
the position numbers of the base vectors in B with respect to S (needed for ϕ),
baseChangeMatrix
the base change matrix M (needed for ϕ).
As an example, let us compute a set R of matrix generators for the solvable residuum of the
group G that we have constructed in the preceding example.
gap> # Perform the computations in an isomorphic permutation group.
gap> P := PermGroup( G );
PermGroup(ImfMatGroup(5,1,3))
gap> P.generators;
[ ( 1, 7, 6)( 2, 9)( 4, 5,10), ( 2, 3, 4, 5)( 6, 9, 8, 7) ]
gap> D := DerivedSubgroup( P );
Subgroup( PermGroup(ImfMatGroup(5,1,3)),
[ ( 1, 2,10, 9)( 3, 8)( 4, 5)( 6, 7),
( 1, 6)( 2, 7, 9, 4)( 3, 8)( 5,10), ( 1, 5,10, 6)( 2, 8, 9, 3) ] )
gap> Size( D );
960
gap> IsPerfect( D );
true
gap> # Now move the results back to the matrix group.
gap> phi := P.bijection;;
gap> R := List( D.generators, p -> Image( phi, p ) );;
gap> for m in R do PrintArray( m ); od;
[ [ -1, -1, -1, -1,
2 ],
[
0, -1,
0,
0,
0 ],
[
0,
0,
0,
1,
0 ],
[
0,
0,
1,
0,
0 ],
704
CHAPTER 38. GROUP LIBRARIES
[
[ [
[
[
[
[
[ [
[
[
[
[
gap>
gap>
true
-1, -1,
0,
0,
0, -1,
0, -1,
0,
1,
0,
0,
-1, -1, -1,
0, -1, -1,
0, -1,
0,
1,
0,
0,
0,
0,
1,
-1, -1, -1,
0, -1,
0,
# The PreImage
PreImage( phi,
0,
1 ] ]
0,
0 ],
0,
0 ],
0,
0 ],
-1,
2 ],
0,
1 ] ]
0,
0 ],
0,
0 ],
0,
0 ],
-1,
2 ],
-1,
1 ] ]
function allows us to use the inverse of phi.
R[1] ) = D.generators[1];
PermGroupImfGroup( G, n )
PermGroupImfGroup returns the permutation group which is induced by the given i. m. f. integral matrix group G on its n th orbit of short vectors. The only difference to the above
PermGroup function is that you can specify the orbit to be used. In fact, as the orbits of short
vectors are sorted by increasing sizes, the function PermGroup( G ) has been implemented
such that it is equivalent to PermGroupImfGroup( G, 1 ).
gap> ImfInvariants( 12, 9 ).sizesOrbitsShortVectors;
[ 120, 300 ]
gap> G := ImfMatGroup( 12, 9 );
ImfMatGroup(12,9)
gap> P1 := PermGroupImfGroup( G, 1 );
PermGroup(ImfMatGroup(12,9))
gap> P1.degree;
120
gap> P2 := PermGroupImfGroup( G, 2 );
PermGroupImfGroup(ImfMatGroup(12,9),2)
gap> P2.degree;
300
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
38.13
705
The Crystallographic Groups Library
GAP3 provides a library of crystallographic groups of dimensions 2, 3, and 4 which covers many of the data that have been listed in the book “Crystallographic groups of fourdimensional space” [BBN+ 78]. It has been brought into GAP3 format by Volkmar Felsch.
How to access the data of the book
Among others, the library offers functions which provide access to the data listed in the
Tables 1, 5, and 6 of [BBN+ 78]:
• The information on the crystal families listed in Table 1 can be reproduced using the
DisplayCrystalFamily function.
• Similarly, the DisplayCrystalSystem function can be used to reproduce the information on the crystal systems provided in Table 1.
• The information given in the Q-class headlines of Table 1 can be displayed by the
DisplayQClass function, whereas the FpGroupQClass function can be used to reproduce the presentations that are listed in Table 1 for the Q-class representatives.
• The information given in the Z-class headlines of Table 1 will be covered by the results
of the DisplayZClass function, and the matrix generators of the Z-class representatives can be constructed by calling the MatGroupZClass function.
• The DisplaySpaceGroupType and the DisplaySpaceGroupGenerators functions can
be used to reproduce all of the information on the space-group types that is provided
in Table 1.
• The normalizers listed in Table 5 can be reproduced by calling the NormalizerZClass
function.
• Finally, the CharTableQClass function will compute the character tables listed in
Table 6, whereas the isomorphism types given in Table 6 may be obtained by calling
the DisplayQClass function.
The display functions mentioned in the above list print their output with different indentation. So, calling them in a suitably nested loop, you may produce a listing in which the
information about the objects of different type will be properly indented as has been done
in Table 1 of [BBN+ 78].
Representation of space groups in GAP3
Probably the most important function in the library is the SpaceGroup function which
provides representatives of the affine classes of space groups. A space group of dimension n
is represented by an (n + 1)-dimensional rational matrix group as follows.
If S is an n-dimensional space group, then each element α ∈ S is an affine mapping α : V → V
of an n-dimensional R-vector space V onto itself. Hence α can be written as the sum of
an appropriate invertible linear mapping ϕ : V → V and a translation by some translation
vector t ∈ V such that, if we write mappings from the left, we have α(v) = ϕ(v) + t for all
v ∈V.
706
CHAPTER 38. GROUP LIBRARIES
If we fix a basis of V and then replace each v ∈ V by the column vector of its coefficients
with respect to that basis (and hence V by the isomorphic column vector space Rn×1 ), we
can describe the linear mapping ϕ involved in α by an n × n matrix Mϕ ∈ GLn (R) which
acts by multiplication from the left on the column vectors in Rn×1 . Hence, if we identify V
with Rn×1 , we have α(v) = Mϕ · v + t for all v ∈ Rn×1 .
v
n×1
Moreover, if we extend each column vector v ∈ R
to a column
of length n + 1
1
by adding
and if we define an (n + 1) × (n + 1) matrix
1 in the last position
an entry
Mϕ t
α(v)
v
, we have
= Mα ·
Mα =
for all v ∈ Rn×1 . This means that we
1
1
0
1
can represent the space group S by the isomorphic group M (S) = {Mα | α ∈ S}. The
submatrices Mϕ occurring in the elements of M (S) form an n × n matrix group P (S), the
“point group” of M (S). In fact, we can choose the basis of Rn×1 such that Mϕ ∈ GLn (Z)
and t ∈ Qn×1 for all Mα ∈ M (S). In particular, the space group representatives that are
normally used by the crystallographers are of this form, and the book [BBN+ 78] uses the
same convention.
Before we describe all available library functions in detail, we have to add three remarks.
Remark 1
The concepts used in this section are defined in chapter 1 (Basic definitions) of [BBN+ 78].
However, note that the definition of the concept of a crystal system given on page 16 of that
book relies on the following statement about Q-classes:
For a Q-class C there is a unique holohedry H such that each f. u. group in C is a
subgroup of some f. u. group in H, but is not a subgroup of any f. u. group belonging
to a holohedry of smaller order.
This statement is correct for dimensions 1, 2, 3, and 4, and hence the definition of “crystal
system” given on page 16 of [BBN+ 78] is known to be unambiguous for these dimensions.
However, there is a counterexample to this statement in seven-dimensional space so that
the definition breaks down for some higher dimensions.
Therefore, the authors of the book have since proposed to replace this definition of “crystal
system” by the following much simpler one, which has been discussed in more detail in
[NPW81]. To formulate it, we use the intersections of Q-classes and Bravais flocks as
introduced on page 17 of [BBN+ 78], and we define the classification of the set of all Zclasses into crystal systems as follows:
Definition: A crystal system (introduced as an equivalence class of Z-classes) consists
of full geometric crystal classes. The Z-classes of two (geometric) crystal classes belong
to the same crystal system if and only if these geometric crystal classes intersect the
same set of Bravais flocks of Z-classes.
¿From this definition of a crystal system of Z-classes one then obtains crystal systems of f. u.
groups, of space-group types, and of space groups in the same manner as with the preceding
definitions in the book.
The new definition is unambiguous for all dimensions. Moreover, it can be checked from the
tables in the book that it defines the same classification as the old one for dimensions 1, 2,
3, and 4.
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
707
It should be noted that the concept of crystal family is well-defined independently of the
dimension if one uses the “more natural” second definition of it at the end of page 17.
Moreover, the first definition of crystal family on page 17 defines the same concept as the
second one if the now proposed definition of crystal system is used.
Remark 2
The second remark just concerns a different terminology in the tables of [BBN+ 78] and in
the current library. In group theory, the number of elements of a finite group usually is
called the “order” of the group. This notation has been used throughout in the book. Here,
however, we will follow the GAP3 conventions and use the term “size” instead.
Remark 3
The third remark concerns a problem in the use of the space groups that should be well
understood.
There is an
to the representation of the space group elements by matrices of
alternative
Mϕ t
as described above. Instead of considering the coefficient vectors as
the form
0
1
columns we may consider them as rows.
Then wecan associate to each affine mapping α ∈ S
Mϕ 0
an (n + 1) × (n + 1) matrix M α =
with M ϕ ∈ GLn (R) and t ∈ R1×n such
t
1
that [α(v), 1] = [v, 1] · M α for all v ∈ R1×n , and we may represent S by the matrix group
M (S) = {M α | α ∈ S}. Again, we can choose the basis of R1×n such that M ϕ ∈ GLn (Z)
and t ∈ Q1×n for all M α ∈ M (S).
From the mathematical point of view, both approaches are equivalent. In particular, M (S)
and M (S) are isomorphic, for instance via the isomorphism τ mapping Mα ∈ M (S) to
(Mαtr )−1 . Unfortunately, however, neither of the two is a good choice for our GAP3 library.
The first convention, using matrices which act on column vectors from the left, is not
consistent with the fact that actions in GAP3 are usually from the right.
On the other hand, if we choose the second convention, we run into a problem with the names
of the space groups as introduced in [BBN+ 78]. Any such name does not just describe the
abstract isomorphism type of the respective space group S, but reflects properties of the
matrix group M (S). In particular, it contains as a leading part the name of the Z-class of the
associated point group P (S). Since the classification of space groups by affine equivalence
is tantamount to their classification by abstract isomorphism, M (S) lies in the same affine
class as M (S) and hence should get the same name as M (S). But the point group P (S)
that occurs in that name is not always Z-equivalent to the point group P (S) of M (S). For
example, the isomorphism τ: M (S) → M (S) defined above maps the Z-class representative
with the parameters [3, 7, 3, 2] (in the notation described below) to the Z-class representative
with the parameters [3, 7, 3, 3]. In other words: The space group names introduced for the
groups M (S) in [BBN+ 78] lead to confusing inconsistencies if assigned to the groups M (S).
In order to avoid this confusion we decided that the first convention is the lesser evil. So
the GAP3 library follows the book, and if you call the SpaceGroup function you will get the
same space group representatives as given there. This does not cause any problems as long
as you do calculations within these groups treating them just as matrix groups of certain
708
CHAPTER 38. GROUP LIBRARIES
isomorphism types. However, if it is necesary to consider the action of a space group as
affine mappings on the natural lattice, you need to use the transposed representation of
the space group. For this purpose the library offers the TransposedSpaceGroup function
which not only transposes the matrices, but also adapts appropriately the associated group
presentation.
Both these functions are described in detail in the following.
The library functions
NrCrystalFamilies( dim )
NrCrystalFamilies returns the number of crystal families in case of dimension dim. It can
be used to formulate loops over the crystal families.
There are 4, 6, and 23 crystal families of dimension 2, 3, and 4, respectively.
gap> n := NrCrystalFamilies( 4 );
23
DisplayCrystalFamily( dim, family )
DisplayCrystalFamily displays for the specified crystal family essentially the same information as is provided for that family in Table 1 of [BBN+ 78], namely
•
•
•
•
•
•
the
the
the
the
the
the
family name,
number of parameters,
common rational decomposition pattern,
common real decomposition pattern,
number of crystal systems in the family, and
number of Bravais flocks in the family.
For details see [BBN+ 78].
gap> DisplayCrystalFamily( 4, 17 );
#I Family XVII: cubic orthogonal; 2 free parameters;
#I Q-decomposition pattern 1+3; R-decomposition pattern 1+3;
#I 2 crystal systems; 6 Bravais flocks
gap> DisplayCrystalFamily( 4, 18 );
#I Family XVIII: octagonal; 2 free parameters;
#I Q-irreducible; R-decomposition pattern 2+2;
#I 1 crystal system; 1 Bravais flock
gap> DisplayCrystalFamily( 4, 21 );
#I Family XXI: di-isohexagonal orthogonal; 1 free parameter;
#I R-irreducible; 2 crystal systems; 2 Bravais flocks
NrCrystalSystems( dim )
NrCrystalSystems returns the number of crystal systems in case of dimension dim. It can
be used to formulate loops over the crystal systems.
There are 4, 7, and 33 crystal systems of dimension 2, 3, and 4, respectively.
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
709
gap> n := NrCrystalSystems( 2 );
4
The following two functions are functions of crystal systems.
Each crystal system is characterized by a pair (dim, system) where dim is the associated
dimension, and system is the number of the crystal system.
DisplayCrystalSystem( dim, system )
DisplayCrystalSystem displays for the specified crystal system essentially the same information as is provided for that system in Table 1 of [BBN+ 78], namely
• the number of Q-classes in the crystal system and
• the identification number, i. e., the tripel (dim, system, q-class) described below, of
the Q-class that is the holohedry of the crystal system.
For details see [BBN+ 78].
gap> for sys in [ 1 .. 4 ] do DisplayCrystalSystem( 2, sys );
#I Crystal system 1: 2 Q-classes; holohedry (2,1,2)
#I Crystal system 2: 2 Q-classes; holohedry (2,2,2)
#I Crystal system 3: 2 Q-classes; holohedry (2,3,2)
#I Crystal system 4: 4 Q-classes; holohedry (2,4,4)
od;
NrQClassesCrystalSystem( dim, system )
NrQClassesCrystalSystem returns the number of Q-classes within the given crystal system.
It can be used to formulate loops over the Q-classes.
The following five functions are functions of Q-classes.
In general, the parameters characterizing a Q-class will form a triple (dim, system, q-class)
where dim is the associated dimension, system is the number of the associated crystal
system, and q-class is the number of the Q-class within the crystal system. However, in
case of dimensions 2 or 3, a Q-class may also be characterized by a pair (dim, IT-number )
where IT-number is the number in the International Tables for Crystallography [Hah83] of
any space-group type lying in (a Z-class of) that Q-class, or just by the Hermann-Mauguin
symbol of any space-group type lying in (a Z-class of) that Q-class.
The Hermann-Mauguin symbols which we use in GAP3 are the short Hermann-Mauguin
symbols defined in the 1983 edition of the International Tables [Hah83], but any occurring indices are expressed by ordinary integers, and bars are replaced by minus signs. For
example, the Hermann-Mauguin symbol P 421 m will be represented by the string "P-421m".
DisplayQClass( dim, system, q-class )
DisplayQClass( dim, IT-number )
DisplayQClass( Hermann-Mauguin-symbol )
DisplayQClass displays for the specified Q-class essentially the same information as is
provided for that Q-class in Table 1 of [BBN+ 78] (except for the defining relations given
there), namely
710
CHAPTER 38. GROUP LIBRARIES
•
•
•
•
•
•
the
the
the
the
the
the
size of the groups in the Q-class,
isomorphism type of the groups in the Q-class,
Hurley pattern,
rational constituents,
number of Z-classes in the Q-class, and
number of space-group types in the Q-class.
For details see [BBN+ 78].
gap> DisplayQClass( "p2" );
#I
Q-class H (2,1,2): size 2; isomorphism type 2.1 = C2;
#I
Q-constituents 2*(2,1,2); cc; 1 Z-class; 1 space group
gap> DisplayQClass( "R-3" );
#I
Q-class (3,5,2): size 6; isomorphism type 6.1 = C6;
#I
Q-constituents (3,1,2)+(3,4,3); ncc; 2 Z-classes; 2 space grps
gap> DisplayQClass( 3, 195 );
#I
Q-class (3,7,1): size 12; isomorphism type 12.5 = A4;
#I
C-irreducible; 3 Z-classes; 5 space grps
gap> DisplayQClass( 4, 27, 4 );
#I
Q-class H (4,27,4): size 20; isomorphism type 20.3 = D10xC2;
#I
Q-irreducible; 1 Z-class; 1 space group
gap> DisplayQClass( 4, 29, 1 );
#I *Q-class (4,29,1): size 18; isomorphism type 18.3 = D6xC3;
#I
R-irreducible; 3 Z-classes; 5 space grps
Note in the preceding examples that, as pointed out above, the term “size” denotes the
order of a representative group of the specified Q-class and, of course, not the (infinite)
class length.
FpGroupQClass( dim, system, q-class )
FpGroupQClass( dim, IT-number )
FpGroupQClass( Hermann-Mauguin-symbol )
FpGroupQClass returns a finitely presented group F , say, which is isomorphic to the groups
in the specified Q-class.
The presentation of that group is the same as the corresponding presentation given in Table
1 of [BBN+ 78] except for the fact that its generators are listed in reverse order. The
reason for this change is that, whenever the group in question is solvable, the resulting
generators form an AG system (as defined in GAP3) if they are numbered “from the top
to the bottom”, and the presentation is a polycyclic power commutator presentation. The
AgGroupQClass function described next will make use of this fact in order to construct an
ag group isomorphic to F .
Note that, for any Z-class in the specified Q-class, the matrix group returned by the
MatGroupZClass function (see below) not only is isomorphic to F , but also its generators
satisfy the defining relators of F .
Besides of the usual components, the group record of F will have an additional component
F .crQClass which saves a list of the parameters that specify the given Q-class.
gap> F := FpGroupQClass( 4, 20, 3 );
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
711
FpGroupQClass( 4, 20, 3 )
gap> F.generators;
[ f.1, f.2 ]
gap> F.relators;
[ f.1^2*f.2^-3, f.2^6, f.2^-1*f.1^-1*f.2*f.1*f.2^-4 ]
gap> F.size;
12
gap> F.crQClass;
[ 4, 20, 3 ]
AgGroupQClass( dim, system, q-class )
AgGroupQClass( dim, IT-number )
AgGroupQClass( Hermann-Mauguin-symbol )
AgGroupQClass returns an ag group A, say, isomorphic to the groups in the specified Qclass, if these groups are solvable, or the value false (together with an appropriate warning),
otherwise.
A is constructed by first establishing a finitely presented group (as it would be returned by
the FpGroupQClass function described above) and then constructing from it an isomorphic
ag group. If the underlying AG system is not yet a PAG system (see sections 24.1 and 25.1),
it will be refined appropriately (and a warning will be displayed).
Besides of the usual components, the group record of A will have an additional component
A.crQClass which saves a list of the parameters that specify the given Q-class.
gap> A := AgGroupQClass( 4, 31, 3
#I Warning: a non-solvable group
false
gap> A := AgGroupQClass( 4, 20, 3
#I Warning: the presentation has
AgGroupQClass( 4, 20, 3 )
gap> A.generators;
[ f.1, f.21, f.22 ]
gap> A.size;
12
gap> A.crQClass;
[ 4, 20, 3 ]
);
can’t be represented as an ag group
);
been extended to get a PAG system
CharTableQClass( dim, system, q-class )
CharTableQClass( dim, IT-number )
CharTableQClass( Hermann-Mauguin-symbol )
CharTableQClass returns the character table T , say, of a representative group of (a Z-class
of) the specified Q-class.
Although the set of characters can be considered as an invariant of the specified Q-class,
the resulting table will depend on the order in which GAP3 sorts the conjugacy classes of
elements and the irreducible characters and hence, in general, will not coincide with the
corresponding table presented in [BBN+ 78].
712
CHAPTER 38. GROUP LIBRARIES
CharTableQClass proceeds as follows. If the groups in the given Q-class are solvable, then
it first calls the AgGroupQClass and RefinedAgSeries functions to get an isomorphic ag
group with a PAG system, and then it calls the CharTable function to compute the character
table of that ag group. In the case of one of the five Q-classes of dimension 4 whose groups
are not solvable, it first calls the FpGroupQClass function to get an isomorphic finitely
presented group, then it constructs a specially chosen faithful permutation representation
of low degree for that group, and finally it determines the character table of the resulting
permutation group again by calling the CharTable function.
In general, the above strategy will be much more efficient than the alternative possibilities of
calling the CharTable function for a finitely presented group provided by the FpGroupQClass
function or for a matrix group provided by the MatGroupZClass function.
gap> T := CharTableQClass( 4, 20, 3 );;
gap> DisplayCharTable( T );
CharTableQClass( 4, 20, 3 )
2
3
X.1
X.2
X.3
X.4
X.5
X.6
2
1
1
1
1
1
2
1
2
.
2
.
1a 3a 6a
2P 1a 3a 3a
3P 1a 1a 2a
5P 1a 3a 6a
2a
1a
2a
2a
4a
2a
4b
4a
4b
2a
4a
4b
1 1 1 1 1 1
1 1 1 1 -1 -1
1 1 -1 -1 A -A
1 1 -1 -1 -A A
2 -1 1 -2 . .
2 -1 -1 2 . .
A = E(4)
= ER(-1) = i
NrZClassesQClass( dim, system, q-class )
NrZClassesQClass( dim, IT-number )
NrZClassesQClass( Hermann-Mauguin-symbol )
NrZClassesQClass returns the number of Z-classes within the given Q-class. It can be used
to formulate loops over the Z-classes.
The following functions are functions of Z-classes.
In general, the parameters characterizing a Z-class will form a quadruple (dim, system,
q-class, z-class) where dim is the associated dimension, system is the number of the associated crystal system, q-class is the number of the associated Q-class within the crystal
system, and z-class is the number of the Z-class within the Q-class. However, in case of
dimensions 2 or 3, a Z-class may also be characterized by a pair (dim, IT-number ) where
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
713
IT-number is the number in the International Tables [Hah83] of any space-group type lying
in that Z-class, or just by the Hermann-Mauguin symbol of any space-group type lying in
that Z-class.
DisplayZClass( dim, system, q-class, z-class )
DisplayZClass( dim, IT-number )
DisplayZClass( Hermann-Mauguin-symbol )
DisplayZClass displays for the specified Z-class essentially the same information as is
provided for that Z-class in Table 1 of [BBN+ 78] (except for the generating matrices of
a class representative group given there), namely
• for dimensions 2 and 3, the Hermann-Mauguin symbol of a representative space-group
type which belongs to that Z-class,
• the Bravais type,
• some decomposability information,
• the number of space-group types belonging to the Z-class,
• the size of the associated cohomology group.
For details see [BBN+ 78].
gap>
#I
#I
gap>
#I
#I
gap>
#I
#I
gap>
#I
#I
DisplayZClass( 2, 3 );
Z-class (2,2,1,1) = Z(pm): Bravais type II/I; fully Z-reducible;
2 space groups; cohomology group size 2
DisplayZClass( "F-43m" );
Z-class (3,7,4,2) = Z(F-43m): Bravais type VI/II; Z-irreducible;
2 space groups; cohomology group size 2
DisplayZClass( 4, 2, 3, 2 );
Z-class B (4,2,3,2): Bravais type II/II; Z-decomposable;
2 space groups; cohomology group size 4
DisplayZClass( 4, 21, 3, 1 );
*Z-class (4,21,3,1): Bravais type XVI/I; Z-reducible;
1 space group; cohomology group size 1
MatGroupZClass( dim, system, q-class, z-class )
MatGroupZClass( dim, IT-number )
MatGroupZClass( Hermann-Mauguin-symbol )
MatGroupZClass returns a dim × dim matrix group M , say, which is a representative of the
specified Z-class. Its generators satisfy the defining relators of the finitely presented group
which may be computed by calling the FpGroupQClass function (see above) for the Q-class
which contains the given Z-class.
The generators of M are the same matrices as those given in Table 1 of [BBN+ 78]. Note,
however, that they will be listed in reverse order to keep them in parallel to the abstract
generators provided by the FpGroupQClass function (see above).
Besides of the usual components, the group record of M will have an additional component M .crZClass which saves a list of the parameters that specify the given Z-class. (In
fact, in order to make the resulting group record consistent with those returned by the
714
CHAPTER 38. GROUP LIBRARIES
NormalizerZClass or ZClassRepsDadeGroup functions described below, it also will have
an additional component M .crConjugator containing just the identity element of M .)
gap> M := MatGroupZClass( 4, 20, 3, 1 );
MatGroupZClass( 4, 20, 3, 1 )
gap> for g in M.generators do
> Print( "\n" ); PrintArray( g ); od; Print( "\n" );
[ [
[
[
[
0,
-1,
0,
0,
1,
0,
0,
0,
0,
0,
-1,
0,
0
0
-1
1
],
],
],
] ]
[ [
[
[
[
-1,
0,
0,
0,
0,
-1,
0,
0,
0,
0,
-1,
1,
0
0
-1
0
],
],
],
] ]
gap> M.size;
12
gap> M.crZClass;
[ 4, 20, 3, 1 ]
NormalizerZClass( dim, system, q-class, z-class )
NormalizerZClass( dim, IT-number )
NormalizerZClass( Hermann-Mauguin-symbol )
NormalizerZClass returns the normalizer N , say, in GL(dim, Z) of the representative dim×
dim matrix group which is constructed by the MatGroupZClass function (see above).
If the size of N is finite, then N again lies in some Z-class. In this case, the group record
of N will contain two additional components N .crZClass and N .crConjugator which
provide the parameters of that Z-class and a matrix g ∈ GL(dim, Z), respectively, such that
N = g −1 Rg, where R is the representative group of that Z-class.
gap> N := NormalizerZClass( 4, 20, 3, 1 );
NormalizerZClass( 4, 20, 3, 1 )
gap> for g in N.generators do
> Print( "\n" ); PrintArray( g ); od; Print( "\n" );
[ [
[
[
[
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
-1,
0
0
0
-1
],
],
],
] ]
[ [
[
[
[
1,
0,
0,
0,
0,
-1,
0,
0,
0,
0,
-1,
1,
0
0
-1
0
],
],
],
] ]
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
[ [
[
[
[
0,
-1,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
0
0
0
1
],
],
],
] ]
[ [
[
[
[
-1,
0,
0,
0,
0,
-1,
0,
0,
0,
0,
-1,
0,
0
0
0
-1
],
],
],
] ]
gap>
96
gap>
[ 4,
gap>
true
N.size;
715
N.crZClass;
20, 22, 1 ]
N.crConjugator = N.identity;
gap> L := NormalizerZClass( 3, 42 );
NormalizerZClass( 3, 3, 2, 4 )
gap> L.size;
16
gap> L.crZClass;
[ 3, 4, 7, 2 ]
gap> L.crConjugator;
[ [ 0, 0, -1 ], [ 1, 0, 0 ], [ 0, -1, -1 ] ]
gap> M := NormalizerZClass( "C2/m" );
Group( [ [ -1, 0, 0 ], [ 0, -1, 0 ], [ 0, 0, -1 ] ],
[ [ 0, -1, 0 ], [ -1, 0, 0 ], [ 0, 0, -1 ] ],
[ [ 1, 0, 1 ], [ 0, 1, 1 ], [ 0, 0, 1 ] ],
[ [ -1, 0, 0 ], [ 0, -1, 0 ], [ -1, -1, 1 ] ],
[ [ 0, 1, -1 ], [ 1, 0, -1 ], [ 0, 0, -1 ] ] )
gap> M.size;
"infinity"
gap> IsBound( M.crZClass );
false
NrSpaceGroupTypesZClass( dim, system, q-class, z-class )
NrSpaceGroupTypesZClass( dim, IT-number )
NrSpaceGroupTypesZClass( Hermann-Mauguin-symbol )
NrSpaceGroupTypes returns the number of space-group types within the given Z-class. It
can be used to formulate loops over the space-group types.
gap> N := NrSpaceGroupTypesZClass( 4, 4, 1, 1 );
13
Some of the Z-classes of dimension d, say, are “maximal” in the sense that the groups in
these classes are maximal finite subgroups of GL(d, Z). Generalizing a term which is being
used for dimension 4, we call the representatives of these maximal Z-classes the “Dade
groups” of dimension d.
716
CHAPTER 38. GROUP LIBRARIES
NrDadeGroups( dim )
NrDadeGroups returns the number of Dade groups of dimension dim. It can be used to
formulate loops over the Dade groups.
There are 2, 4, and 9 Dade groups of dimension 2, 3, and 4, respectively.
gap> NrDadeGroups( 4 );
9
DadeGroup( dim, n )
DadeGroup returns the nth Dade group of dimension dim.
gap> D := DadeGroup( 4, 7 );
MatGroupZClass( 4, 31, 7, 2 )
DadeGroupNumbersZClass( dim, system, q-class, z-class )
DadeGroupNumbersZClass( dim, IT-number )
DadeGroupNumbersZClass( Hermann-Mauguin-symbol )
DadeGroupNumbersZClass returns the set of all those integers ni for which the ni th Dade
group of dimension dim contains a subgroup which, in GL(dim, Z), is conjugate to the
representative group of the given Z-class.
gap> dadeNums := DadeGroupNumbersZClass( 4, 4, 1, 2 );
[ 1, 5, 8 ]
gap> for d in dadeNums do
>
D := DadeGroup( 4, d );
>
Print( D, " of size ", Size( D ), "\n" );
> od;
MatGroupZClass( 4, 20, 22, 1 ) of size 96
MatGroupZClass( 4, 30, 13, 1 ) of size 288
MatGroupZClass( 4, 32, 21, 1 ) of size 384
ZClassRepsDadeGroup( dim, system, q-class, z-class, n )
ZClassRepsDadeGroup( dim, IT-number , n )
ZClassRepsDadeGroup( Hermann-Mauguin-symbol , n )
ZClassRepsDadeGroup determines in the nth Dade group of dimension dim all those conjugacy classes whose groups are, in GL(dim, Z), conjugate to the Z-class representative group
R, say, of the given Z-class. It returns a list of representative groups of these conjugacy
classes.
Let M be any group in the resulting list. Then the group record of M provides two components M .crZClass and M .crConjugator which contain the list of Z-class parameters of
R and a suitable matrix g from GL(dim, Z), respectively, such that M equals g −1 Rg.
gap> DadeGroupNumbersZClass(
[ 1, 2 ]
gap> ZClassRepsDadeGroup( 2,
[ MatGroupZClass( 2, 2, 1, 2
gap> ZClassRepsDadeGroup( 2,
2, 2, 1, 2 );
2, 1, 2, 1 );
)^[ [ 0, 1 ], [ -1, 0 ] ] ]
2, 1, 2, 2 );
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
717
[ MatGroupZClass( 2, 2, 1, 2 )^[ [ 1, -1 ], [ 0, -1 ] ],
MatGroupZClass( 2, 2, 1, 2 )^[ [ 1, 0 ], [ -1, 1 ] ] ]
gap> R := last[2];;
gap> R.crZClass;
[ 2, 2, 1, 2 ]
gap> R.crConjugator;
[ [ 1, 0 ], [ -1, 1 ] ]
The following functions are functions of space-group types.
In general, the parameters characterizing a space-group type will form a quintuple (dim,
system, q-class, z-class, sg-type) where dim is the associated dimension, system is the number of the associated crystal system, q-class is the number of the associated Q-class within
the crystal system, z-class is the number of the Z-class within the Q-class, and sg-type is
the space-group type within the Z-class. However, in case of dimensions 2 or 3, you may
instead specify a Z-class by a pair (dim, IT-number ) or by its Hermann-Mauguin symbol (as described above). Then the function will handle the first space-group type within
that Z-class, i. e., sg-type = 1, that is, the corresponding symmorphic space group (split
extension).
DisplaySpaceGroupType( dim, system, q-class, z-class, sg-type )
DisplaySpaceGroupType( dim, IT-number )
DisplaySpaceGroupType( Hermann-Mauguin-symbol )
DisplaySpaceGroupType displays for the specified space-group type some of the information
which is provided for that space-group type in Table 1 of [BBN+ 78], namely
• the orbit size associated with that space-group type and,
• for dimensions 2 and 3, the IT-number and the Hermann-Mauguin symbol.
For details see [BBN+ 78].
gap>
#I
gap>
#I
gap>
#I
gap>
#I
#I
DisplaySpaceGroupType( 2, 17 );
Space-group type (2,4,4,1,1); IT(17) = p6mm; orbit size 1
DisplaySpaceGroupType( "Pm-3" );
Space-group type (3,7,2,1,1); IT(200) = Pm-3; orbit size 1
DisplaySpaceGroupType( 4, 32, 10, 2, 4 );
*Space-group type (4,32,10,2,4); orbit size 18
DisplaySpaceGroupType( 3, 6, 1, 1, 4 );
*Space-group type (3,6,1,1,4); IT(169) = P61, IT(170) = P65;
orbit size 2; fp-free
DisplaySpaceGroupGenerators( dim, system, q-class, z-class, sg-type )
DisplaySpaceGroupGenerators( dim, IT-number )
DisplaySpaceGroupGenerators( Hermann-Mauguin-symbol )
DisplaySpaceGroupGenerators displays the non-translation generators of a representative
space group of the specified space-group type without actually constructing that matrix
group.
718
CHAPTER 38. GROUP LIBRARIES
In more details: Let n = dim be the given dimension, and let M1 , . . . , Mr be the generators
of the representative n × n matrix group of the given Z-class (this is the group which you
will get if you call the MatGroupZClass function (see above) for that Z-class). Then, for
the given space-group type, the SpaceGroup function described below will construct as
representative of that space-group type an (n + 1) × (n + 1) matrix group which is generated
by the n translations which are induced by the (standard) basis vectors of
the n-dimensional
Mi t i
, where
Euclidian space, and r additional matrices S1 , . . . , Sr of the form Si =
0
1
the n × n submatrices Mi are as defined above, and the ti are n-columns with rational
entries. The DisplaySpaceGroupGenerators function saves time by not constructing the
group, but just displaying the r matrices S1 , . . . , Sr .
gap> DisplaySpaceGroupGenerators( "P61" );
#I The non-translation generators of SpaceGroup( 3, 6, 1, 1, 4 ) are
[ [
[
[
[
-1,
0,
0,
0,
0,
-1,
0,
0,
0,
0,
1,
0,
0
0
1/2
1
],
],
],
] ]
[ [
[
[
[
0,
1,
0,
0,
-1,
-1,
0,
0,
0,
0,
1,
0,
0
0
1/3
1
],
],
],
] ]
SpaceGroup( dim, system, q-class, z-class, sg-type )
SpaceGroup( dim, IT-number )
SpaceGroup( Hermann-Mauguin-symbol )
SpaceGroup returns a (dim + 1) × (dim + 1) matrix group S, say, which is a representative of
the given space-group type (see also the description of the DisplaySpaceGroupGenerators
function above).
gap> S := SpaceGroup( "P61" );
SpaceGroup( 3, 6, 1, 1, 4 )
gap> for s in S.generators do
> Print( "\n" ); PrintArray( s ); od; Print( "\n" );
[ [
[
[
[
-1,
0,
0,
0,
0,
-1,
0,
0,
0,
0,
1,
0,
0
0
1/2
1
],
],
],
] ]
[ [
[
[
[
0,
1,
0,
0,
-1,
-1,
0,
0,
0,
0,
1,
0,
0
0
1/3
1
],
],
],
] ]
0,
1 ],
[ [
1,
0,
38.13. THE CRYSTALLOGRAPHIC GROUPS LIBRARY
[
[
[
0,
0,
0,
1,
0,
0,
0,
1,
0,
0 ],
0 ],
1 ] ]
[ [
[
[
[
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0
1
0
1
],
],
],
] ]
[ [
[
[
[
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0
0
1
1
],
],
],
] ]
719
gap> S.crSpaceGroupType;
[ 3, 6, 1, 1, 4 ]
Besides of the usual components, the resulting group record of S contains an additional
component S.crSpaceGroupType which saves a list of the parameters that specify the given
space-group type.
Moreover, it contains, in form of a finitely presented group, a presentation of S which is
satisfied by the matrix generators. If the factor group of S by its translation normal subgroup
is solvable then this presentation is chosen such that it is a polycyclic power commutator
presentation. The proper way to access this presentation is to call the following function.
FpGroup( S )
FpGroup returns a finitely presented group G, say, which is isomorphic to S , where S is
expected to be a space group. It is chosen such that there is an isomrphism from G to
S which maps each generator of G onto the corresponding generator of S . This means, in
particular, that the matrix generators of S satisfy the relators of G.
gap> G := FpGroup( S );
Group( g1, g2, g3, g4, g5 )
gap> for rel in G.relators do Print( rel, "\n" ); od;
g1^2*g5^-1
g2^3*g5^-1
g2^-1*g1^-1*g2*g1
g3^-1*g1^-1*g3*g1*g3^2
g3^-1*g2^-1*g3*g2*g4*g3^2
g4^-1*g1^-1*g4*g1*g4^2
g4^-1*g2^-1*g4*g2*g4*g3^-1
g4^-1*g3^-1*g4*g3
g5^-1*g1^-1*g5*g1
g5^-1*g2^-1*g5*g2
g5^-1*g3^-1*g5*g3
g5^-1*g4^-1*g5*g4
gap> # Verify that the matrix generators of S satisfy the relators of G.
gap> ForAll( G.relators,
720
CHAPTER 38. GROUP LIBRARIES
> rel -> MappedWord( rel, G.generators, S.generators ) = S.identity );
true
TransposedSpaceGroup(
TransposedSpaceGroup(
TransposedSpaceGroup(
TransposedSpaceGroup(
dim, system, q-class, z-class, sg-type )
dim, IT-number )
Hermann-Mauguin-symbol )
S )
TransposedSpaceGroup returns a matrix group T , say, whose generators are just the transposed generators (in the same order) of the corresponding space group S specified by the
arguments. As for S , you may get a finite presentation for T via the FpGroup function.
The purpose of this function is explicitly discussed in the introduction to this section.
gap> T := TransposedSpaceGroup( S );
TransposedSpaceGroup( 3, 6, 1, 1, 4 )
gap> for m in T.generators do
> Print( "\n" ); PrintArray( m ); od; Print( "\n" );
[ [
[
[
[
-1,
0,
0,
0,
0,
-1,
0,
0,
0,
0,
1,
1/2,
0
0
0
1
],
],
],
] ]
[ [
[
[
[
0,
-1,
0,
0,
1,
-1,
0,
0,
0,
0,
1,
1/3,
0
0
0
1
],
],
],
] ]
[ [
[
[
[
1,
0,
0,
1,
0,
1,
0,
0,
0,
0,
1,
0,
0
0
0
1
],
],
],
] ]
[ [
[
[
[
1,
0,
0,
0,
0,
1,
0,
1,
0,
0,
1,
0,
0
0
0
1
],
],
],
] ]
[ [
[
[
[
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
1,
0
0
0
1
],
],
],
] ]
38.14. THE SMALL GROUPS LIBRARY
38.14
721
The Small Groups Library
This library contains all groups of order at most 1000 except for 512 and 768 up to isomorphism. There are a total of 174366 such groups.
SmallGroup( size, i )
The function SmallGroup( size, i ) returns the ith group of order size in the catalogue.
It will return an AgGroup, if the group is soluble and a PermGroup otherwise.
NumberSmallGroups( size )
The function NumberSmallGroups( size ) returns the number of groups of the order size.
AllSmallGroups( size )
The function AllSmallGroups( size ) returns the list of all groups of the order size.
UnloadSmallGroups( list of sizes )
It is possible to work with the catalogue of groups of small order just using the functions
described above. However, the catalogue is rather large even though the groups are stored
in a very compact description. Thus it might be helpful for a space efficient usage of the
catalogue, to know a little bit about unloading parts of the catalogue by hand.
At the first call of one of the functions described above, the groups of order size are loaded
and stored in a compact description. GAP will not unload them itsself again. Thus if one
calls one of the above functions for a lot of different orders, then all the groups of these orders
are stored. Even though the description of the groups is space efficient, this might use a lot
of space. For example, if one uses the above functions to load the complete catalogue, then
GAP will grow to about 12 MB of workspace.
Thus it might be interesting to unload the groups of some orders again, if they are not used
anymore. This can be done by calling the function UnloadSmallGroups( list of sizes )
If the groups of order size are unloaded by hand, then GAP will of course load them again
at the next call of SmallGroup( size, i ) or one of the other functions described at the
beginning of this section.
IdGroup( G )
Let G be a PermGroup or AgGroup of order at most 1000, but not of order 256, 512 or 768.
Then the function call IdGroup( G ) returns a tuple [size, i] meaning that G is isomorphic
to the i-th group in the catalogue of groups of order size.
Note that this package calls and uses the ANUPQ share library of GAP in a few cases.
722
CHAPTER 38. GROUP LIBRARIES
Chapter 39
Algebras
This chapter introduces the data structures and functions for algebras in GAP3. The word
algebra in this manual means always associative algebra.
At the moment GAP3 supports only finitely presented algebras and matrix algebras. For
details about implementation and special functions for the different types of algebras, see
39.1 and the chapters 40 and 41.
The treatment of algebras is very similar to that of groups. For example, algebras in GAP3
are always finitely generated, since for many questions the generators play an important
role. If you are not familiar with the concepts that are used to handle groups in GAP3 it
might be useful to read the introduction and the overview sections in chapter 7.
Algebras are created using Algebra (see 39.4) or UnitalAlgebra (see 39.5), subalgebras of
a given algebra using Subalgebra (see 39.8) or UnitalSubalgebra (see 39.9). See 39.3, and
the corresponding section 7.6 in the chapter about groups for details about the distinction
between parent algebras and subalgebras.
The first sections of the chapter describe the data structures (see 39.1) and the concepts of
unital algebras (see 39.2) and parent algebras (see 39.3).
The next sections describe the functions for the construction of algebras, and the tests for
algebras (see 39.4, 39.5, 39.6, 39.7, 39.8, 39.9, 39.10, 39.11, 39.12, 39.13, 39.14).
The next sections describe the different types of functions for algebras (see 39.15, 39.16,
39.17, 39.18, 39.19, 39.20, 39.21).
The next sections describe the operation of algebras (see 39.22, 39.23).
The next sections describe algebra homomorphisms (see 39.24, 39.25).
The next sections describe algebra elements (see 39.26, 39.27).
The last section describes the implementation of the data structures (see 39.28).
At the moment there is no implementation for ideals, cosets, and factors of algebras in
GAP3, and the only available algebra homomorphisms are operation homomorphisms.
Also there is no implementation of bases for general algebras, this will be available as soon
as it is for general vector spaces.
723
724
CHAPTER 39. ALGEBRAS
39.1
More about Algebras
Let F be a field. A ring A is called an F -algebra if A is an F -vector space. All algebras in
GAP3 are associative, that is, the multiplication is associative.
An algebra always contains a zero element that can be obtained by subtracting an arbitrary
element from itself. A discussion of identity elements of algebras (and of the consequences
for the implementation in GAP3) can be found in 39.2.
Elements of the field F are not regarded as elements of A. The practical reason (besides
the obvious mathematical one) for this is that even if the identity matrix is contained in
the matrix algebra A it is not possible to write 1 + a for adding the identity matrix to
the algebra element a, since independent of the algebra A the meaning in GAP3 is already
defined as to add 1 to all positions of the matrix a. Thus one has to write One( A ) + a
or a^0 + a instead.
The natural operation domains for algebras are modules (see 39.22, and chapter 42).
39.2
Algebras and Unital Algebras
Not all algebras contain a (left and right) multiplicative neutral identity element, but if
an algebra contains such an identity element it is unique.
If an algebra A contains a multiplicative neutral element then in general it cannot be derived
from an arbitrary element a of A by forming a/a or a0 , since these operations may be not
defined for the algebra A.
More precisely, it may be possible to invert a or raise it to the zero-th power, but A is not
necessarily closed under these operations. For example, if a is a square matrix in GAP3 then
we can form a0 which is the identity matrix of the same size and over the same field as a.
On the other hand, an algebra may have a multiplicative neutral element that is not equal
to the zero-th power of elements (see 39.16).
In many cases, however, the zero-th power of algebra elements is well-defined, with the result
again in the algebra. This holds for example for all finitely presented algebras (see chapter
40) and all those matrix algebras whose generators are the generators of a finite group.
For practical purposes it is useful to distinguish general algebras and unital algebras.
A unital algebra in GAP3 is an algebra U that is known to contain zero-th powers of elements, and all functions may assume this. A not unital algebra A may contain zero-th powers
of elements or not, and no function for A should assume existence or nonexistence of these
elements in A. So it may be possible to view A as a unital algebra using AsUnitalAlgebra(
A ) (see 39.12), and of course it is always possible to view a unital algebra as algebra using
AsAlgebra( U ) (see 39.11).
A can have unital subalgebras, and of course U can have subalgebras that are not unital.
The images of unital algebras under operation homomorphisms are either unital or trivial,
since the identity of the source acts trivially, so its image under the homomorphism is the
identity of the image.
The following example shows the main differences between algebras and unital algebras.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ];;
39.3. PARENT ALGEBRAS AND SUBALGEBRAS
725
gap> alg1:= Algebra( Rationals, [ a ] );
Algebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> id:= a^0;
[ [ 1, 0 ], [ 0, 1 ] ]
gap> id in alg1;
false
gap> alg2:= UnitalAlgebra( Rationals, [ a ] );
UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> id in alg2;
true
gap> alg3:= AsAlgebra( alg2 );
Algebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ], [ [ 1, 0 ], [ 0, 1 ] ]
] )
gap> alg3 = alg2;
true
gap> AsUnitalAlgebra( alg1 );
Error, is not unital
We see that if we want the identity matrix to be contained in an algebra that is not known
to be unital, it might be necessary to add it to the generators. If we would not have the
possibility to define unital algebras, this would lead to the strange situations that a twogenerator algebra means an algebra generated by one nonidentity generator and the identity
matrix, or that an algebra is free on the set X but is generated as algebra by the set X plus
the identity.
39.3
Parent Algebras and Subalgebras
GAP3 distinguishs between parent algebras and subalgebras of parent algebras. The concept
is the same as that for groups (see 7.6), so here it is only sketched.
Each subalgebra belongs to a unique parent algebra, the so-called parent of the subalgebra.
A parent algebra is its own parent.
Parent algebras are constructed by Algebra and UnitalAlgebra, subalgebras are constructed by Subalgebra and UnitalSubalgebra. The parent of the first argument of
Subalgebra will be the parent of the constructed subalgebra.
Those algebra functions that take more than one algebra as argument require that the
arguments have a common parent. Take for instance Centralizer. It takes two arguments,
an algebra A and an algebra B , where either A is a parent algebra, and B is a subalgebra of
this parent algebra, or A and B are subalgebras of a common parent algebra P , and returns
the centralizer of B in A. This is represented as a subalgebra of the common parent of A
and B . Note that a subalgebra of a parent algebra need not be a proper subalgebra.
An exception to this rule is again the set theoretic function Intersection (see 4.12), which
allows to intersect algebras with different parents.
Whenever you have two subalgebras which have different parent algebras but have a common
superalgebra A you can use AsSubalgebra or AsUnitalSubalgebra (see 39.13, 39.14) in
order to construct new subalgebras which have a common parent algebra A.
Note that subalgebras of unital algebras need not be unital (see 39.2).
726
CHAPTER 39. ALGEBRAS
The following sections describe the functions related to this concept (see 39.4, 39.5, 39.6,
39.7, 39.11, 39.12, 39.8, 39.9, 39.13, 39.14, and also 7.7, 7.8).
39.4
Algebra
Algebra( U )
returns a parent algebra A which is isomorphic to the parent algebra or subalgebra U .
Algebra( F , gens )
Algebra( F , gens, zero )
returns a parent algebra over the field F and generated by the algebra elements in the list
gens. The zero element of this algebra may be entered as zero; this is necessary whenever
gens is empty.
gap> a:= [ [ 1 ] ];;
gap> alg:= Algebra( Rationals, [ a ] );
Algebra( Rationals, [ [ [ 1 ] ] ] )
gap> alg.name:= "alg";;
gap> sub:= Subalgebra( alg, [] );
Subalgebra( alg, [ ] )
gap> Algebra( sub );
Algebra( Rationals, [ [ [ 0 ] ] ] )
gap> Algebra( Rationals, [], 0*a );
Algebra( Rationals, [ [ [ 0 ] ] ] )
The algebras returned by Algebra are not unital. For constructing unital algebras, use 39.5
UnitalAlgebra.
39.5
UnitalAlgebra
UnitalAlgebra( U )
returns a unital parent algebra A which is isomorphic to the parent algebra or subalgebra
U . If U is not unital it is checked whether the zero-th power of elements is contained in U ,
and if not an error is signalled.
UnitalAlgebra( F , gens )
UnitalAlgebra( F , gens, zero )
returns a unital parent algebra over the field F and generated by the algebra elements in
the list gens. The zero element of this algebra may be entered as zero; this is necessary
whenever gens is empty.
gap> alg1:= UnitalAlgebra( Rationals, [ NullMat( 2, 2 ) ] );
UnitalAlgebra( Rationals, [ [ [ 0, 0 ], [ 0, 0 ] ] ] )
gap> alg2:= UnitalAlgebra( Rationals, [], NullMat( 2, 2 ) );
UnitalAlgebra( Rationals, [ [ [ 0, 0 ], [ 0, 0 ] ] ] )
gap> alg3:= Algebra( alg1 );
Algebra( Rationals, [ [ [ 0, 0 ], [ 0, 0 ] ], [ [ 1, 0 ], [ 0, 1 ] ]
] )
gap> alg1 = alg3;
true
39.6. ISALGEBRA
727
gap> AsUnitalAlgebra( alg3 );
UnitalAlgebra( Rationals,
[ [ [ 0, 0 ], [ 0, 0 ] ], [ [ 1, 0 ], [ 0, 1 ] ] ] )
The algebras returned by UnitalAlgebra are unital. For constructing algebras that are not
unital, use 39.4 Algebra.
39.6
IsAlgebra
IsAlgebra( obj )
returns true if obj , which can be an object of arbitrary type, is a parent algebra or a
subalgebra and false otherwise. The function will signal an error if obj is an unbound
variable.
gap> IsAlgebra( FreeAlgebra( GF(2), 0 ) );
true
gap> IsAlgebra( 1/2 );
false
39.7
IsUnitalAlgebra
IsUnitalAlgebra( obj )
returns true if obj , which can be an object of arbitrary type, is a unital parent algebra
or a unital subalgebra and false otherwise. The function will signal an error if obj is an
unbound variable.
gap> IsUnitalAlgebra( FreeAlgebra( GF(2), 0 ) );
true
gap> IsUnitalAlgebra( Algebra( Rationals, [ [ [ 1 ] ] ] ) );
false
Note that the function does not check whether obj is an algebra that contains the zero-th
power of elements, but just checks whether obj is an algebra with flag isUnitalAlgebra.
39.8
Subalgebra
Subalgebra( A, gens )
returns the subalgebra of the algebra A generated by the elements in the list gens.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ];;
gap> b:= [ [ 0, 0 ], [ 0, 1 ] ] ;;
gap> alg:= Algebra( Rationals, [ a, b ] );;
gap> alg.name:= "alg";;
gap> s:= Subalgebra( alg, [ a ] );
Subalgebra( alg, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> s = alg;
false
gap> s:= UnitalSubalgebra( alg, [ a ] );
UnitalSubalgebra( alg, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> s = alg;
728
CHAPTER 39. ALGEBRAS
true
Note that Subalgebra, UnitalSubalgebra, AsSubalgebra and AsUnitalSubalgebra are
the only functions in which the name Subalgebra does not refer to the mathematical terms
subalgebra and superalgebra but to the implementation of algebras as subalgebras and
parent algebras.
39.9
UnitalSubalgebra
UnitalSubalgebra( A, gens )
returns the unital subalgebra of the algebra A generated by the elements in the list gens.
If A is not (known to be) unital then first it is checked that A really contains the zero-th
power of elements.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ];;
gap> b:= [ [ 0, 0 ], [ 0, 1 ] ] ;;
gap> alg:= Algebra( Rationals, [ a, b ] );;
gap> alg.name:= "alg";;
gap> s:= Subalgebra( alg, [ a ] );
Subalgebra( alg, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> s = alg;
false
gap> s:= UnitalSubalgebra( alg, [ a ] );
UnitalSubalgebra( alg, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> s = alg;
true
Note that Subalgebra, UnitalSubalgebra, AsSubalgebra and AsUnitalSubalgebra are
the only functions in which the name Subalgebra does not refer to the mathematical terms
subalgebra and superalgebra but to the implementation of algebras as subalgebras and
parent algebras.
39.10
IsSubalgebra
IsSubalgebra( A, U )
returns true if U is a subalgebra of A and false otherwise.
Note that A and U must have a common parent algebra. This function returns true if and
only if the set of elements of U is a subset of the set of elements of A.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ];;
gap> b:= [ [ 0, 0 ], [ 0, 1 ] ] ;;
gap> alg:= Algebra( Rationals, [ a, b ] );;
gap> alg.name:= "alg";;
gap> IsSubalgebra( alg, alg );
true
gap> s:= UnitalSubalgebra( alg, [ a ] );
UnitalSubalgebra( alg, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> IsSubalgebra( alg, s );
true
39.11. ASALGEBRA
39.11
729
AsAlgebra
AsAlgebra( D )
AsAlgebra( F , D )
Let D be a domain. AsAlgebra returns an algebra A over the field F such that the set of
elements of D is the same as the set of elements of A if this is possible. If D is an algebra
the argument F may be omitted, the coefficients field of D is taken as coefficients field of F
in this case.
If D is a list of algebra elements these elements must form a algebra. Otherwise an error is
signalled.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ] * Z(2);;
gap> AsAlgebra( GF(2), [ a, 0*a ] );
Algebra( GF(2), [ [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), 0*Z(2) ] ] ] )
Note that this function returns a parent algebra or a subalgebra of a parent algebra depending on D. In order to convert a subalgebra into a parent algebra you must use Algebra or
UnitalAlgebra (see 39.4, 39.5).
39.12
AsUnitalAlgebra
AsUnitalAlgebra( D )
AsUnitalAlgebra( F , D )
Let D be a domain. AsUnitalAlgebra returns a unital algebra A over the field F such that
the set of elements of D is the same as the set of elements of A if this is possible. If D is an
algebra the argument F may be omitted, the coefficients field of D is taken as coefficients
field of F in this case.
If D is a list of algebra elements these elements must form a unital algebra. Otherwise an
error is signalled.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ] * Z(2);;
gap> AsUnitalAlgebra( GF(2), [ a, a^0, 0*a, a^0-a ] );
UnitalAlgebra( GF(2), [ [ [ 0*Z(2), 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ],
[ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), 0*Z(2) ] ] ] )
Note that this function returns a parent algebra or a subalgebra of a parent algebra depending on D. In order to convert a subalgebra into a parent algebra you must use Algebra or
UnitalAlgebra (see 39.4, 39.5).
39.13
AsSubalgebra
AsSubalgebra( A, U )
Let A be a parent algebra and U be a parent algebra or a subalgebra with a possibly different
parent algebra, such that the generators of U are elements of A. AsSubalgebra returns a
new subalgebra S such that S has parent algebra A and is generated by the generators of
U.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ];;
gap> b:= [ [ 0, 0 ], [ 0, 1 ] ] ;;
730
CHAPTER 39. ALGEBRAS
gap> alg:= Algebra( Rationals,
gap> alg.name:= "alg";;
gap> s:= Algebra( Rationals, [
Algebra( Rationals, [ [ [ 1, 0
gap> AsSubalgebra( alg, s );
Subalgebra( alg, [ [ [ 1, 0 ],
[ a, b ] );;
a ] );
], [ 0, 0 ] ] ] )
[ 0, 0 ] ] ] )
Note that Subalgebra, UnitalSubalgebra, AsSubalgebra and AsUnitalSubalgebra are
the only functions in which the name Subalgebra does not refer to the mathematical terms
subalgebra and superalgebra but to the implementation of algebras as subalgebras and
parent algebras.
39.14
AsUnitalSubalgebra
AsUnitalSubalgebra( A, U )
Let A be a parent algebra and U be a parent algebra or a subalgebra with a possibly
different parent algebra, such that the generators of U are elements of A. AsSubalgebra
returns a new unital subalgebra S such that S has parent algebra A and is generated by
the generators of U . If U or A do not contain the zero-th power of elements an error is
signalled.
gap> a:= [ [ 1, 0 ], [ 0, 0 ] ];;
gap> b:= [ [ 0, 0 ], [ 0, 1 ] ];;
gap> alg:= Algebra( Rationals, [ a, b ] );;
gap> alg.name:= "alg";;
gap> s:= UnitalAlgebra( Rationals, [ a ] );
UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> AsSubalgebra( alg, s );
Subalgebra( alg, [ [ [ 1, 0 ], [ 0, 0 ] ], [ [ 1, 0 ], [ 0, 1 ] ] ] )
gap> AsUnitalSubalgebra( alg, s );
UnitalSubalgebra( alg, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
Note that Subalgebra, UnitalSubalgebra, AsSubalgebra and AsUnitalSubalgebra are
the only functions in which the name Subalgebra does not refer to the mathematical terms
subalgebra and superalgebra but to the implementation of algebras as subalgebras and
parent algebras.
39.15
Operations for Algebras
A ^ n
The operator ^ evaluates to the n-fold direct product of A, viewed as a free A-module.
gap> a:= FreeAlgebra( GF(2), 2 );
UnitalAlgebra( GF(2), [ a.1, a.2 ] )
gap> a^2;
Module( UnitalAlgebra( GF(2), [ a.1, a.2 ] ),
[ [ a.one, a.zero ], [ a.zero, a.one ] ] )
a in A
39.16. ZERO AND ONE FOR ALGEBRAS
731
The operator in evaluates to true if a is an element of A and false otherwise. a must be
an element of the parent algebra of A.
gap> a.1^3 + a.2 in a;
true
gap> 1 in a;
false
39.16
Zero and One for Algebras
Zero( A )
returns the additive neutral element of the algebra A.
One( A )
returns the (right and left) multiplicative neutral element of the algebra A if this
exists, and false otherwise. If A is a unital algebra then this element is obtained on
raising an arbitrary element to the zero-th power (see 39.2).
gap> a:= Algebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] );
Algebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> Zero( a );
[ [ 0, 0 ], [ 0, 0 ] ]
gap> One( a );
[ [ 1, 0 ], [ 0, 0 ] ]
gap> a:= UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] );
UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> Zero( a );
[ [ 0, 0 ], [ 0, 0 ] ]
gap> One( a );
[ [ 1, 0 ], [ 0, 1 ] ]
39.17
Set Theoretic Functions for Algebras
As already mentioned in the introduction of the chapter, algebras are domains. Thus all set
theoretic functions, for example Intersection and Size can be applied to algebras. All set
theoretic functions not mentioned here are not treated specially for algebras.
Elements( A )
computes the elements of the algebra A using a Dimino algorithm. The default
function for algebras computes a vector space basis at the same time.
Intersection( A, H )
returns the intersection of A and H either as set of elements or as an algebra record.
IsSubset( A, H )
If A and H are algebras then IsSubset tests whether the generators of H are elements
of A. Otherwise DomainOps.IsSubset is used.
Random( A )
returns a random element of the algebra A. This requires the computation of a vector
space basis.
See also 41.5, 40.6 for the set theoretic functions for the different types of algebras.
732
CHAPTER 39. ALGEBRAS
39.18
Property Tests for Algebras
The following property tests (cf. 7.45) are available for algebras.
IsAbelian( A )
returns true if the algebra A is abelian and false otherwise. An algebra A is abelian
if and only if for every a, b ∈ A the equation a ∗ b = b ∗ a holds.
IsCentral( A, U )
returns true if the algebra A centralizes the algebra U and false otherwise. An
algebra A centralizes an algebra U if and only if for all a ∈ A and for all u ∈ U the
equation a ∗ u = u ∗ a holds. Note that U need not to be a subalgebra of A but they
must have a common parent algebra.
IsFinite( A )
returns true if the algebra A is finite, and false otherwise.
IsTrivial( A )
returns true if the algebra A consists only of the zero element, and false otherwise.
If A is a unital algebra it is of course never trivial.
All tests expect a parent algebra or subalgebra and return true if the algebra has the
property and false otherwise. Some functions may not terminate if the given algebra has
an infinite set of elements. A warning may be printed in such cases.
gap> IsAbelian( FreeAlgebra( GF(2), 2 ) );
false
gap> a:= UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] );
UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> a.name:= "a";;
gap> s1:= Subalgebra( a, [ One(a) ] );
Subalgebra( a, [ [ [ 1, 0 ], [ 0, 1 ] ] ] )
gap> IsCentral( a, s1 ); IsFinite( s1 );
true
false
gap> s2:= Subalgebra( a, [] );
Subalgebra( a, [ ] )
gap> IsFinite( s2 ); IsTrivial( s2 );
true
true
39.19
Vector Space Functions for Algebras
A finite dimensional F -algebra A is always a finite dimensional F -vector space. Thus in
GAP3, an algebra is a vector space (see 9.2), and vector space functions such as Base and
Dimension are applicable to algebras.
gap> a:= UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] );
UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] )
gap> Dimension( a );
2
gap> Base( a );
39.20. ALGEBRA FUNCTIONS FOR ALGEBRAS
733
[ [ [ 1, 0 ], [ 0, 1 ] ], [ [ 0, 0 ], [ 0, 1 ] ] ]
The vector space structure is used also by the set theoretic functions.
39.20
Algebra Functions for Algebras
The functions desribed in this section compute certain subalgebras of a given algebra, e.g.,
Centre computes the centre of an algebra.
They return algebra records as described in 39.28 for the computed subalgebras. Some
functions may not terminate if the given algebra has an infinite set of elements, while other
functions may signal an error in such cases.
Here the term “subalgebra” is used in a mathematical sense. But in GAP3, every algebra
is either a parent algebra or a subalgebra of a unique parent algebra. If you compute the
centre C of an algebra U with parent algebra A then C is a subalgebra of U but its parent
algebra is A (see 39.3).
Centralizer( A, x )
Centralizer( A, U )
returns the centralizer of an element x in A where x must be an element of the parent
algebra of A, resp. the centralizer of the algebra U in A where both algebras must
have a common parent.
The centralizer of an element x in A is defined as the set C of elements c of A such that
c and x commute.
The centralizer of an algebra U in A is defined as the set C of elements c of A such that
c commutes with every element of U .
gap> a:= MatAlgebra( GF(2), 2 );;
gap> a.name:= "a";;
gap> m:= [ [ 1, 1 ], [ 0, 1 ] ] * Z(2);;
gap> Centralizer( a, m );
UnitalSubalgebra( a, [ [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ],
[ [ 0*Z(2), Z(2)^0 ], [ 0*Z(2), 0*Z(2) ] ] ] )
Centre( A )
returns the centre of A (that is, the centralizer of A in A).
gap> c:= Centre( a );
UnitalSubalgebra( a, [ [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] ] )
Closure( U , a )
Closure( U , S )
Let U be an algebra with parent algebra A and let a be an element of A. Then Closure
returns the closure C of U and a as subalgebra of A. The closure C of U and a is the
subalgebra generated by U and a.
Let U and S be two algebras with a common parent algebra A. Then Closure returns the
subalgebra of A generated by U and S .
gap> Closure( c, m );
UnitalSubalgebra( a, [ [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ],
[ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] ] )
734
39.21
CHAPTER 39. ALGEBRAS
TrivialSubalgebra
TrivialSubalgebra( U )
Let U be an algebra with parent algebra A. Then TrivialSubalgebra returns the trivial
subalgebra T of U , as subalgebra of A.
gap> a:= MatAlgebra( GF(2), 2 );;
gap> a.name:= "a";;
gap> TrivialSubalgebra( a );
Subalgebra( a, [ ] )
39.22
Operation for Algebras
Operation( A, M )
Let A be an F -algebra for a field F , and M an A-module of F -dimension n. With respect
to a chosen F -basis of M , the action of an element of A on M can be described by an n × n
matrix over F . This induces an algebra homomorphism from A onto a matrix algebra AM ,
with action on its natural module equivalent to the action of A on M . The matrix algebra
AM can be computed as Operation( A, M ).
Operation( A, B )
returns the operation of the algebra A on an A-module M with respect to the vector space
basis B of M .
Note that contrary to the situation for groups, the operation domains of algebras are not
lists of elements but domains.
For constructing the algebra homomorphism from A onto AM , and the module homomorphism from M onto the equivalent AM -module, see 39.23 and 42.17, respectively.
gap> a:= UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] );;
gap> m:= Module( a, [ [ 1, 0 ] ] );;
gap> op:= Operation( a, m );
UnitalAlgebra( Rationals, [ [ [ 1 ] ] ] )
gap> mat1:= PermutationMat( (1,2,3), 3, GF(2) );;
gap> mat2:= PermutationMat(
(1,2), 3, GF(2) );;
gap> u:= Algebra( GF(2), [ mat1, mat2 ] );; u.name:= "u";;
gap> nat:= NaturalModule( u );; nat.name:= "nat";;
gap> q:= nat / FixedSubmodule( nat );;
gap> op1:= Operation( u, q );
UnitalAlgebra( GF(2), [ [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, Z(2)^0 ] ],
[ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] ] )
gap> b:= Basis( q, [ [ 0, 1, 1 ], [ 0, 0, 1 ] ] * Z(2) );;
gap> op2:= Operation( u, b );
UnitalAlgebra( GF(2), [ [ [ Z(2)^0, Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ],
[ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] ] )
gap> IsEquivalent( NaturalModule( op1 ), NaturalModule( op2 ) );
true
If the dimension of M is zero then the elements of AM cannot be represented as GAP3
matrices. The result is a null algebra, see 41.9, NullAlgebra.
39.23. OPERATIONHOMOMORPHISM FOR ALGEBRAS
39.23
735
OperationHomomorphism for Algebras
OperationHomomorphism( A, B )
returns the algebra homomorphism (see 39.24) with source A and range B , provided that
B is a matrix algebra that was constructed as operation of A on a suitable module M using
Operation( A, M ), see 39.22.
gap> ophom:= OperationHomomorphism( a, op );
OperationHomomorphism( UnitalAlgebra( Rationals,
[ [ [ 1, 0 ], [ 0, 0 ] ] ] ), UnitalAlgebra( Rationals,
[ [ [ 1 ] ] ] ) )
gap> Image( ophom, a.1 );
[ [ 1 ] ]
gap> Image( ophom, Zero( a ) );
[ [ 0 ] ]
gap> PreImagesRepresentative( ophom, [ [ 2 ] ] );
[ [ 2, 0 ], [ 0, 2 ] ]
39.24
Algebra Homomorphisms
An algebra homomorphism φ is a mapping that maps each element of an algebra A,
called the source of φ, to an element of an algebra B, called the range of φ, such that for
each pair x, y ∈ A we have (xy)φ = xφ y φ and (x + y)φ = xφ + y φ .
An algebra homomorphism of unital algebras is unital if the zero-th power of elements in
the source is mapped to the zero-th power of elements in the range.
At the moment, only operation homomorphisms are supported in GAP3 (see 39.23).
39.25
Mapping Functions for Algebra Homomorphisms
This section describes how the mapping functions defined in chapter 43 are implemented
for algebra homomorphisms. Those functions not mentioned here are implemented by the
default functions described in the respective sections.
Image( hom )
Image( hom, H )
Images( hom, H )
The image of a subalgebra under a algebra homomorphism is computed by computing the
images of a set of generators of the subalgebra, and the result is the subalgebra generated
by those images.
PreImagesRepresentative( hom, elm )
gap> a:= UnitalAlgebra( Rationals, [ [ [ 1, 0 ], [ 0, 0 ] ] ] );;
gap> a.name:= "a";;
gap> m:= Module( a, [ [ 1, 0 ] ] );;
gap> op:= Operation( a, m );
UnitalAlgebra( Rationals, [ [ [ 1 ] ] ] )
736
CHAPTER 39. ALGEBRAS
gap> ophom:= OperationHomomorphism( a, op );
OperationHomomorphism( a, UnitalAlgebra( Rationals, [ [ [ 1 ] ] ] ) )
gap> Image( ophom, a.1 );
[ [ 1 ] ]
gap> Image( ophom, Zero( a ) );
[ [ 0 ] ]
gap> PreImagesRepresentative( ophom, [ [ 2 ] ] );
[ [ 2, 0 ], [ 0, 2 ] ]
39.26
Algebra Elements
This section describes the operations and functions available for algebra elements.
Note that algebra elements may exist independently of an algebra, e.g., you can write down
two matrices and compute their sum and product without ever defining an algebra that
contains them.
Comparisons of Algebra Elements
g = h
evaluates to true if the algebra elements g and h are equal and to false otherwise.
g <> h
evaluates to true if the algebra elements g and h are not equal and to false otherwise.
g
g
g
g
< h
<= h
>= h
> h
The operators <, <=, >= and > evaluate to true if the algebra element g is strictly less
than, less than or equal to, greater than or equal to and strictly greater than the algebra
element h. There is no general ordering on all algebra elements, so g and h should lie in
the same parent algebra. Note that for elements of finitely presented algebra, comparison
means comparison with respect to the underlying free algebra (see 40.9).
Arithmetic Operations for Algebra Elements
a * b
a + b
a - b
The operators *, + and - evaluate to the product, sum and difference of the two algebra
elements a and b. The operands must of course lie in a common parent algebra, otherwise
an error is signalled.
a / c
returns the quotient of the algebra element a by the nonzero element c of the base field of
the algebra.
a ^ i
39.27. ISALGEBRAELEMENT
737
returns the i -th power of an algebra element a and a positive integer i . If i is zero or
negative, perhaps the result is not defined, or not contained in the algebra generated by a.
list + a
a + list
list * a
a * list
In this form the operators + and * return a new list where each entry is the sum resp.
product of a and the corresponding entry of list. Of course addition resp. multiplication
must be defined between a and each entry of list.
39.27
IsAlgebraElement
IsAlgebraElement( obj )
returns true if obj , which may be an object of arbitrary type, is an algebra element, and
false otherwise. The function will signal an error if obj is an unbound variable.
gap> IsAlgebraElement( (1,2) );
false
gap> IsAlgebraElement( NullMat( 2, 2 ) );
true
gap> IsAlgebraElement( FreeAlgebra( Rationals, 1 ).1 );
true
39.28
Algebra Records
Algebras and their subalgebras are represented by records. Once an algebra record is created
you may add record components to it but you must not alter information already present.
Algebra records must always contain the components isDomain and isAlgebra. Subalgebras contain an additional component parent. The components generators, zero and one
are not necessarily contained.
The contents of important record components of an algebra A is described below.
The category components are
isDomain
is true.
isAlgebra
is true.
isUnitalAlgebra
is present (and then true) if A is a unital algebra.
The identification components are
field
is the coefficient field of A.
generators
is a list of algebra generators. Duplicate generators are allowed, also the algebra
738
CHAPTER 39. ALGEBRAS
zero may be among the generators. Note that once created this entry must never be
changed, as most of the other entries depend on generators. If generators is not
bound it can be computed using Generators.
parent
if present this contains the algebra record of the parent algebra of a subalgebra A,
otherwise A itself is a parent algebra.
zero
is the additive neutral element of A, can be computed using Zero.
The component operations contains the operations record of A. This will usually be
one of AlgebraOps, UnitalAlgebraOps, or a record for more specific algebras.
39.29
FFList
FFList( F )
returns for a finite field F a list l of all elements of F in an ordering that is compatible with
the ordering of field elements in the MeatAxe share library (see chapter 69).
The element of F corresponding to the number n is l [ n+1 ], and the canonical number
of the field element z is Position( l , z ) -1.
gap> FFList( GF( 8 ) );
[ 0*Z(2), Z(2)^0, Z(2^3), Z(2^3)^3, Z(2^3)^2, Z(2^3)^6, Z(2^3)^4,
Z(2^3)^5 ]
(This program was originally written by Meinolf Geck.)
Chapter 40
Finitely Presented Algebras
This chapter contains the description of functions dealing with finitely presented algebras.
The first section informs about the data structures (see 40.1), the next sections tell how to
construct free and finitely presented algebras (see 40.2, 40.3), and what functions can be
applied to them (see 40.4, 40.6, 40.5, 40.7), and the final sections introduce functions for
elements of finitely presented algebras (see 40.8, 40.9, 40.10, 40.11).
For a detailed description of operations of finitely presented algebras on modules, see chapter
73.
40.1
More about Finitely Presented Algebras
Free Algebras
Let X be a finite set, and F a field. The free algebra A on X over F can be regarded as
the semigroup ring of the free monoid on X over F . Addition and multiplication of elements
are performed by dealing with sums of words in abstract generators, with coefficients in F .
Free algebras and also their subalgebras in GAP3 are always unital, that is, for an element
a in a subalgebra A of a free algebra always the element a0 lies in A (see 39.2). Thus the
free algebra on the empty set over a field F is defined to consist of all elements f e where f
is in F , and e is the multiplicative neutral element, corresponding to the empty word.
Free algebras are useful when dealing with other algebras, like matrix algebras, since they
allow to handle expressions in terms of the generators. This is just a generalization of
handling words in abstract generators and concrete group elements in parallel, as is done for
example in MappedWord (see 22.12) or functions that construct images and preimages under
homomorphisms. This mechanism is also provided for the records representing matrices in
the MeatAxe share library (see chapter 69).
Finitely Presented Algebras
A finitely presented algebra is defined as quotient A/I of a free algebra A by a two-sided
ideal I in A that is generated by a finite set S of elements in F .
Thus computations with finitely presented algebras are similar to those with finitely presented groups. For example, in general it is impossible to decide whether two elements of
the free algebra A are equal modulo I.
739
740
CHAPTER 40. FINITELY PRESENTED ALGEBRAS
For finitely presented groups a permutation representation on the cosets of a subgroup of
finite index can be computed by the Todd-Coxeter coset enumeration method. An analogue
of this method for finitely presented algebras is Steve Linton’s Vector Enumeration method
that tries to compute a matrix representation of the action on a quotient of a free module
of the algebra. This method is available in GAP3 as a share library (see chapter 73, and the
references there), and this makes finitely presented algebra in GAP3 more than an object
one can only use for the obvious arithmetics with elements of free algebras.
GAP3 only handles the data structures, all the work in done by the standalone program.
Thus all functions for finitely presented algebras, like Size, delegate the work to the
Vector Enumeration program.
Note that (contrary to the situation in finitely presented groups, and several places in
Vector Enumeration) relators are meant to be equal to zero, not to the identity. Two
examples for this. If x^2 - a.one is a relator in the presentation of the algebra a, with x
a generator, then x is an involution. If x^2 is a relator then x is nilpotent. If the generator
x occurs in relators of the form x * v - a.one and w * x - a.one, for v and w elements
of the free algebra, then x is known to be invertible.
The Vector Enumeration package is loaded automatically as soon as it is needed. You can
also load it explicitly using
gap> RequirePackage( "ve" );
Elements of Finitely Presented Algebras
The elements of finitely presented algebras in GAP3 are records that store lists of coefficients
and of words in abstract generators. Note that the elements of the ground field are not
regarded as elements of the algebra, especially the identity and zero element are denoted by
a.one and a.zero, respectively. Functions and operators for elements of finitely presented
algebras are listed in 40.9.
Implementation of Functions for Finitely Presented Algebras
Every question about a finitely presented algebra A that cannot be answered from the presentation directly is delegated to an isomorphic matrix algebra M using the Vector Enumeration
share library. This may be impossible because the dimension of an isomorphic matrix algebra is too large. But for small A it seems to be valuable.
For example, if one asks for the size of A, Vector Enumeration tries to find such a matrix
algebra M , and then GAP3 computes its size. M and the isomorphism between A and M
are stored in the component A.matAlgebraA, so Vector Enumeration is called only once for
A.
40.2
FreeAlgebra
FreeAlgebra( F , rank )
FreeAlgebra( F , rank , name )
FreeAlgebra( F , name1 , name2 , ...
)
return a free algebra with ground field F . In the first two forms an algebra on rank free
generators is returned, their names will be name.1, . . . , name.rank , the default for name
is the string "a".
40.3. FPALGEBRA
741
gap> a:= FreeAlgebra( GF(2), 2 );
UnitalAlgebra( GF(2), [ a.1, a.2 ] )
gap> b:= FreeAlgebra( Rationals, "x", "y" );
UnitalAlgebra( Rationals, [ x, y ] )
gap> x:= b.1;
x
Finitely presented algebras are constructed from free algebras via factoring by a suitable
ideal (see 40.5).
40.3
FpAlgebra
FpAlgebra( A )
returns a finitely presented algebra isomorphic to the algebra A. At the moment this is
implemented only for matrix algebras and finitely presented algebras.
gap> a:= FreeAlgebra( GF(2), 2 );
UnitalAlgebra( GF(2), [ a.1, a.2 ] )
gap> a:= a / [ a.one+a.1^2, a.one+a.2^2, a.one+(a.1*a.2)^3 ];;
gap> a.name:= "a";; s:= Subalgebra( a, [ a.2 ] );;
gap> f:= FpAlgebra( s );
UnitalAlgebra( GF(2), [ a.1 ] )
gap> PrintDefinitionFpAlgebra( f, "f" );
f:= FreeAlgebra( GF(2), "a.1" );
f:= f / [ f.one+f.1^2 ];
FpAlgebra( F , fpgroup )
returns the group algebra of the finitely presented group fpgroup over the field F , this is
the algebra of formal linear combinations of elements of fpgroup, with coefficients in F ; in
this case the number of algebra generators is twice the number of group generators, the first
half corresponding to the group generators, the second half to their inverses.
gap> f:= FreeGroup( 2 );;
gap> s3:= f / [ f.1^2, f.2^2, (f.1*f.2)^3 ];
Group( f.1, f.2 )
gap> a:= FpAlgebra( GF(2), s3 );
UnitalAlgebra( GF(2), [ a.1, a.2, a.3, a.4 ] )
40.4
IsFpAlgebra
IsFpAlgebra( obj )
returns true if obj is a finitely presented algebra, and false otherwise.
gap> IsFpAlgebra( FreeAlgebra( GF(2), 0 ) );
true
gap> IsFpAlgebra( last );
false
742
CHAPTER 40. FINITELY PRESENTED ALGEBRAS
40.5
Operators for Finitely Presented Algebras
A / relators
returns a finitely presented algebra that is the quotient of the free algebra A (see 40.2) by
the two-sided ideal in A spanned by the elements in the list relators.
This is the general method to construct finitely presented algebras in GAP3. For the special
case of group algebras of finitely presented groups see 40.3.
A ^ n
returns a free A-module of dimension n (see chapter 42) for the finitely presented algebra
A.
gap> f:= FreeAlgebra( Rationals, 2 );
UnitalAlgebra( Rationals, [ a.1, a.2 ] )
gap> a:= f / [ f.1^2 - f.one, f.2^2 - f.one, (f.1*f.2)^2 - f.one ];
UnitalAlgebra( Rationals, [ a.1, a.2 ] )
gap> a = f;
false
gap> a^2;
Module( UnitalAlgebra( Rationals, [ a.1, a.2 ] ),
[ [ a.one, a.zero ], [ a.zero, a.one ] ] )
a in A
returns true if a is an element of the finitely presented algebra A, and false otherwise.
Note that the answer may require the computation of an isomorphic matrix algebra if A is
not a parent algebra.
gap> a.1 in a;
true
gap> f.1 in a;
false
gap> 1 in a;
false
40.6
Functions for Finitely Presented Algebras
The following functions are overlaid in the operations record of finitely presented algebras.
The set theoretic functions
Elements, Intersection, IsFinite, IsSubset, Size;
the vector space functions
Base, Coefficients, and Dimension,
Note that at the moment no basis records (see 33.2) for finitely presented algebras are
supported.
and the algebra functions
Closure, IsAbelian, IsTrivial, Operation (see 39.22, 73.1, 73.3), Subalgebra, and
TrivialSubalgebra.
40.7. PRINTDEFINITIONFPALGEBRA
743
Note that these functions try to compute a faithful matrix representation of the algebra
using the Vector Enumeration share library (see chapter 73).
40.7
PrintDefinitionFpAlgebra
PrintDefinitionFpAlgebra( A, name )
prints the assignment of the finitely presented algebra A to the variable name name. Using
the call as an argument of PrintTo (see 3.15), this can be used to save A to a file.
gap> a:= FreeAlgebra( GF(2), "x", "y" );
UnitalAlgebra( GF(2), [ x, y ] )
gap> a:= a / [ a.1^2-a.one, a.2^2-a.one, (a.1*a.2)^3 - a.one ];
UnitalAlgebra( GF(2), [ x, y ] )
gap> PrintDefinitionFpAlgebra( a, "b" );
b:= FreeAlgebra( GF(2), "x", "y" );
b:= b / [ b.one+b.1^2, b.one+b.2^2, b.one+b.1*b.2*b.1*b.2*b.1*b.2 ];
gap> PrintTo( "algebra", PrintDefinitionFpAlgebra( a, "b" ) );
40.8
MappedExpression
MappedExpression( expr , gens1 , gens2 )
For an arithmetic expression expr in terms of gens1 , MappedExpression returns the corresponding expression in terms of gens2 .
gens1 may be a list of abstract generators (in this case the result is the same as the object
returned by 22.12 MappedWord), or of generators of a finitely presented algebra.
gap> a:= FreeAlgebra( Rationals, 2 );;
gap> a:= a / [ a.1^2 - a.one, a.2^2 - a.one, (a.1*a.2)^2 - a.one ];;
gap> matgens:= [ [[0,0,0,1],[0,0,1,0],[0,1,0,0],[1,0,0,0]],
>
[[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]] ];;
gap> permgens:= [ (1,4)(2,3), (1,2)(3,4) ];;
gap> MappedExpression( a.1^2 + a.1, a.generators, matgens );
[ [ 1, 0, 0, 1 ], [ 0, 1, 1, 0 ], [ 0, 1, 1, 0 ], [ 1, 0, 0, 1 ] ]
gap> MappedExpression( a.1 * a.2, a.generators, permgens );
(1,3)(2,4)
Note that this can be done also in terms of (algebra or group) homomorphisms (see 39.24).
MappedExpression may raise elements in gens2 to the zero-th power.
40.9
Elements of Finitely Presented Algebras
Zero and One of Finitely Presented Algebras
A finitely presented algebra A contains a zero element A.zero. If the number of generators
of A is not zero, the multiplicative neutral element of A is A.one, which is the zero-th power
of any nonzero element of A.
Comparisons of Elements of Finitely Presented Algebras
744
CHAPTER 40. FINITELY PRESENTED ALGEBRAS
x = y
x < y
Elements of the same algebra can be compared in order to form sets. Note that probably it
will be necessary to compute an isomorphic matrix representation in order to decide equality
if x and y are not elements of a free algebra.
gap> a:= FreeAlgebra( Rationals, 1 );;
gap> a:= a / [ a.1^2 - a.one ];
UnitalAlgebra( Rationals, [ a.1 ] )
gap> [ a.1^3 = a.1, a.1^3 > a.1, a.1 > a.one, a.zero > a.one ];
[ true, false, false, false ]
Arithmetic Operations for Elements of Finitely Presented Algebras
x
x
x
x
x
+
*
^
/
y
y
y
n
c
The usual arithmetical operations for ring elements apply to elements of finitely presented
algebras. Exponentiation ^ can be used to raise an element x to the n-th power. Division
/ is only defined for denominators in the base field of the algebra.
gap> a:= FreeAlgebra( Rationals, 2 );;
gap> x:= a.1 - a.2;
a.1+-1*a.2
gap> x^2;
a.1^2+-1*a.1*a.2+-1*a.2*a.1+a.2^2
gap> y:= 4 * x - a.1;
3*a.1+-4*a.2
gap> y^2;
9*a.1^2+-12*a.1*a.2+-12*a.2*a.1+16*a.2^2
IsFpAlgebraElement( obj )
returns true if obj is an element of a finitely presented algebra, and false otherwise.
gap> IsFpAlgebraElement( a.zero );
true
gap> IsFpAlgebraElement( a.field.zero );
false
FpAlgebraElement( A, coeff , words )
Elements of finitely presented algebras normally arise from arithmetical operations. It is,
however, possible to construct directly the element of the finitely presented algebra A that
is the sum of the words in the list words, with coefficients given by the list coeff , by calling
FpAlgebraElement( A, coeff , words ). Note that this function does not check whether
some of the words are equal, or whether all coefficients are nonzero. So one should probably
not use it.
40.10. ELEMENTALGEBRA
745
gap> a;
UnitalAlgebra( Rationals, [ a.1, a.2 ] )
gap> FpAlgebraElement( a, [ 1, 1 ], a.generators );
a.1+a.2
gap> FpAlgebraElement( a, [ 1, 1, 1 ], List( [ 1..3 ], i -> a.1^i ) );
a.1+a.1^2+a.1^3
40.10
ElementAlgebra
ElementAlgebra( A, nr )
returns the nr -th element in terms of the generators of the free algebra A over the finite
field F , with respect to the following ordering.
We form the elements as linear combinations with coefficients in the base field of A, with
respect to the basis defined by the ordering of words according to length and lexicographic
order; this sequence starts as follows.
a01 , a1 , a2 , . . . , an , a21 , a1 a2 , a1 a3 , . . . , a1 an , a2 a1 , . . . , a2 an , . . . , a2n , a31 , a21 a2 , . . . , a21 an ,
a1 a2 a1 , . . .
Pk
Let n be the number of generators of A, q the size of F , and nr = i=0 ai q i the q-adic
expression of nr . Then the ai -th element of A.field is the coefficient of the i-th base
element in the required algebra element. The ordering of field elements is the same as that
defined in the MeatAxe package, that is, FFList( F )[ m+1 ] (see 39.29) is the m-th
element of the field F .
gap> a:= FreeAlgebra( GF(2), 2 );;
gap> List( [ 10 .. 20 ], x -> ElementAlgebra( a, x ) );
[ a.1+a.1^2, a.one+a.1+a.1^2, a.2+a.1^2, a.one+a.2+a.1^2,
a.1+a.2+a.1^2, a.one+a.1+a.2+a.1^2, a.1*a.2, a.one+a.1*a.2,
a.1+a.1*a.2, a.one+a.1+a.1*a.2, a.2+a.1*a.2 ]
gap> ElementAlgebra( a, 0 );
a.zero
The function can be applied also if A is an arbitrary finitely presented algebra or a matrix
algebra. In these cases the result is the element of the algebra obtained on replacing the
generators of the corresponding free algebra by the generators of A.
Note that the zero-th power of elements may be needed, which is not necessarily an element
of a matrix algebra.
gap> a:= UnitalAlgebra(
UnitalAlgebra( GF(2), [
[ [ 0*Z(2), Z(2)^0 ],
gap> ElementAlgebra( a,
[ [ 0*Z(2), Z(2)^0 ], [
GF(2), GL(2,2).generators );
[ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ],
[ Z(2)^0, 0*Z(2) ] ] ] )
17 );
Z(2)^0, Z(2)^0 ] ]
The number of an element a can be computed using 40.11.
40.11
NumberAlgebraElement
NumberAlgebraElement( a )
746
CHAPTER 40. FINITELY PRESENTED ALGEBRAS
returns the number n such that the element a of the finitely presented algebra A is the n-th
element of A in the sense of 40.10, that is, a = ElementAlgebra( A, n ).
gap> a:= FreeAlgebra( GF(2), 2 );;
gap> NumberAlgebraElement( ( a.1 + a.one )^4 );
32769
gap> NumberAlgebraElement( a.zero );
0
gap> NumberAlgebraElement( a.one );
1
Note that A.field must be finite.
Chapter 41
Matrix Algebras
This chapter describes the data structures and functions for matrix algebras in GAP3. See
chapter 39 for the description of all those aspects that concern general algebras.
First the objects of interest in this chapter are introduced (see 41.1, 41.2).
The next sections describe functions for matrix algebras, first those that can be applied not
only for matrix algebras (see 41.3, 41.4, 41.5, 41.6, 41.7), and then specific matrix algebra
functions (see 41.8, 41.9, 41.10, 41.11).
41.1
More about Matrix Algebras
A matrix algebra is an algebra (see 39.1) the elements of which are matrices.
There is a canonical isomorphism of a matrix algebra onto a row space (see chapter 33) that
maps a matrix to the concatenation of its rows. This makes all computations with matrix
algebras that use its vector space structure as efficient as the corresponding computation
with a row space. For example the computation of a vector space basis, of coefficients with
respect to such a basis, and of representatives under the action on a vector space by right
multiplication.
If one is interested in matrix algebras as domains themselves then one should think of this
algebra as of a row space that admits a multiplication. For example, the convention for row
spaces that the coefficients field must contain the field of the vector elements also applies to
matrix algebras. And the concept of vector space bases is the same as that for row spaces
(see 41.2).
In the chapter about modules (see chapter 42) it is stated that modules are of interest
mainly as operation domains of algebras. Here we can state that matrix algebras are of
interest mainly because they describe modules. For some of the functions it is not obvious
whether they are functions for modules or for algebras or for the matrices that generate
an algebra. For example, one usually talks about the fingerprint of an A-module M , but
this is in fact computed as the list of nullspace dimensions of generators of a certain matrix
algebra, namely the induced action of A on M as is computed using Operation( A, M )
(see 41.10, 39.22).
747
748
CHAPTER 41. MATRIX ALGEBRAS
41.2
Bases for Matrix Algebras
As stated in section 41.1, the implementation of bases for matrix algebras follows that of row
space bases, see 33.2 for the details. Consequently there are two types of bases, arbitrary
bases and semi-echelonized bases, where the latter type can be defined as follows. Let ϕ be
the vector space homomorphism that maps a matrix in the algebra A to the concatenation
of its rows, and let B = (b1 , b2 , . . . , bn ) be a vector space basis of A, then B is called semiechelonized if and only if the row space basis (ϕ(b1 ), ϕ(b2 ), . . . , ϕ(bn )) is semi-echelonized,
in the sense of 33.2. The canonical basis is defined analogeously.
Due to the multiplicative structure that allows to view a matrix algebra A as an A-module
with action via multiplication from the right, there is additionally the notion of a standard
basis for A, which is essentially described in 42.13. The default way to compute a vector
space basis of a matrix algebra from a set of generating matrices is to compute this standard
basis and a semi-echelonized basis in parallel.
If the matrix algebra A is unital then every semi-echelonized basis and also the standard
basis have One( A ) as first basis vector.
41.3
IsMatAlgebra
IsMatAlgebra( obj )
returns true if obj , which may be an object of arbitrary type, is a matrix algebra and false
otherwise.
gap> IsMatAlgebra( FreeAlgebra( GF(2), 0 ) );
false
gap> IsMatAlgebra( Algebra( Rationals, [[[1]]] ) );
true
41.4
Zero and One for Matrix Algebras
Zero( A )
returns the square zero matrix of the same dimension and characteristic as the elements of A. This matrix is thought only for testing whether a matrix is zero, usually
all its rows will be identical in order to save space. So you should not use this zero
matrix for other purposes; use 34.4 NullMat instead.
One( A )
returns for a unital matrix algebra A the identity matrix of the same dimension
and characteristic as the elements of A; for a not unital matrix algebra A the (left
and right) multiplicative neutral element (if exists) is computed by solving a linear
equation system.
41.5
Functions for Matrix Algebras
Closure, Elements, IsFinite, and Size are the only set theoretic functions that are
overlaid in the operations records for matrix algebras and unital matrix algebras. See 39.17
for an overview of set theoretic functions for general algebras.
41.6. ALGEBRA FUNCTIONS FOR MATRIX ALGEBRAS
749
No vector space functions are overlaid in the operations records for matrix algebras and
unital matrix algebras. The functions for vector space bases are mainly the same as
those for row space bases (see 41.2).
For other functions for matrix algebras, see 41.6.
41.6
Algebra Functions for Matrix Algebras
Centralizer( A, a )
Centralizer( A, S )
returns the element or subalgebra centralizer in the matrix algebra A. Centralizers in
matrix algebras are computed by solving a linear equation system.
Centre( A )
returns the centre of the matrix algebra A, which is computed by solving a linear
equation system.
FpAlgebra( A )
returns a finitely presented algebra that is isomorphic to A. The presentation is computed using the structure constants, thus a vector space basis of A has to be computed.
If A contains no multiplicative neutral element (see 41.4) an error is signalled. (At
the moment the implementation is really simpleminded.)
gap> a:= UnitalAlgebra( Rationals, [[[0,1],[0,0]]] );
UnitalAlgebra( Rationals, [ [ [ 0, 1 ], [ 0, 0 ] ] ] )
gap> FpAlgebra( a );
UnitalAlgebra( Rationals, [ a.1 ] )
gap> last.relators;
[ a.1^2 ]
41.7
RepresentativeOperation for Matrix Algebras
RepresentativeOperation( A, v1 , v2 )
returns the element in the matrix algebra A that maps v1 to v2 via right multiplication if
such an element exists, and false otherwise. v1 and v2 may be vectors or matrices of same
dimension.
gap> a:= MatAlgebra( GF(2), 2 );
UnitalAlgebra( GF(2), [ [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), 0*Z(2) ] ],
[ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] ] )
gap> v1:= [ 1, 0 ] * Z(2);; v2:= [ 1, 1 ] * Z(2);;
gap> RepresentativeOperation( a, v1, v2 );
[ [ Z(2)^0, Z(2)^0 ], [ Z(2)^0, Z(2)^0 ] ]
gap> t:= TrivialSubalgebra( a );;
gap> RepresentativeOperation( t, v1, v2 );
false
41.8
MatAlgebra
MatAlgebra( F , n )
returns the full matrix algebra of n by n matrices over the field F .
750
CHAPTER 41. MATRIX ALGEBRAS
gap> a:= MatAlgebra( GF(2), 2 );
UnitalAlgebra( GF(2), [ [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), 0*Z(2) ] ],
[ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] ] )
gap> Size( a );
16
41.9
NullAlgebra
NullAlgebra( F )
returns a trivial algebra (that is, it contains only the zero element) over the field F . This
occurs in a natural way whenever Operation (see 39.22) constructs a faithful representation
of the zero module.
Here we meet the strange situation that an operation algebra does not consist of matrices,
since in GAP3 a matrix always has a positive number of rows and columns. The element of
a NullAlgebra( F ) is the object EmptyMat that acts (trivially) on empty lists via right
multiplication.
gap> a:= NullAlgebra( GF(2) );
NullAlgebra( GF(2) )
gap> Size( a );
1
gap> Elements( a );
[ EmptyMat ]
gap> [] * EmptyMat;
[ ]
gap> IsAlgebra( a );
true
41.10
Fingerprint
Fingerprint( A )
Fingerprint( A, list )
returns the fingerprint of the matrix algebra A, i.e., a list of nullities of six “standard” words
in A (for 2-generator algebras only) or of the words with numbers in list.
gap>
gap>
gap>
gap>
[ 1,
m1:= PermutationMat( (1,2,3,4,5), 5, GF(2) );;
m2:= PermutationMat( (1,2)
, 5, GF(2) );;
a:= Algebra( GF(2), [ m1, m2 ] );;
Fingerprint( a );
1, 1, 3, 0, 4 ]
Let a and b be the generators of a 2-generator matix algebra. The six standard words used
by Fingerprint are w1 , w2 , . . . , w6 where
w1
w3
w5
= ab + a + b, w2
= a + bw2 ,
w4
= ab + w4 ,
w6
=
=
=
w1 + ab2 ,
b + w3 ,
a + w5
41.11. NATURALMODULE
41.11
751
NaturalModule
NaturalModule( A )
returns the natural module M of the matrix algebra A. If A consists of n by n matrices,
and F is the coefficients field of A then M is an n-dimensional row space over the field F ,
viewed as A-right module (see 42.4).
gap> a:= MatAlgebra( GF(2), 2 );;
gap> a.name:= "a";;
gap> m:= NaturalModule( a );
Module( a, [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
752
CHAPTER 41. MATRIX ALGEBRAS
Chapter 42
Modules
This chapter describes the data structures and functions for modules in GAP3.
After the introduction of the data structures (see 42.1, 42.2, 42.3) the functions for constructing modules and submodules (see 42.4, 42.5, 42.6, 42.7, 42.8) and testing for modules
(see 42.9, 42.10) are described.
The next sections describe operations and functions for modules (see 42.11, 42.12, 42.13,
42.14, 42.16).
The next section describes available module homomorphisms. At the moment only operation
homomorphisms are supported (see 42.17).
The last sections describe the implementation of the data structures (see 42.18, 42.19).
Many examples in this chapter use the natural permutation module for the symmetric group
S3 . If you want to run the examples you must first define this module, as is done using the
following commands.
gap>
gap>
gap>
gap>
gap>
mat1:= PermutationMat( (1,2,3), 3, GF(2) );;
mat2:= PermutationMat(
(1,2), 3, GF(2) );;
a:= UnitalAlgebra( GF(2), [ mat1, mat2 ] );; a.name:= "a";;
nat:= NaturalModule( a );;
nat.name:= "nat";;
There is no possibility to compute the lattice of submodules with the implementations in
GAP3. However, it is possible to use the MeatAxe share library (see chapter 69) to compute
the lattice, and then (perhaps) to carry back interesting parts to GAP3 format using 69.2
GapObject.
42.1
More about Modules
Let R be a ring. An R-module (or, more exactly, an R-right module) is an additive abelian
group on that R acts from the right.
A module is of interest mainly as operation domain of an algebra (see chapter 39). Thus
it is the natural place to store information about the operation of the algebra, for example
753
754
CHAPTER 42. MODULES
whether it is irreducible. But since a module is a domain it has also properties of its own,
independent of the algebra.
According to the different types of algebras in GAP3, namely matrix algebras and finitely
presented algebras, at the moment two types of modules are supported in GAP3, namely row
modules and their quotients for matrix algebras and free modules and their submodules
and quotients for finitely presented algebras. See 42.2 and 42.3 for more information.
For modules, the same concept of parent and substructures holds as for row spaces. That
is, a module is stored either as a submodule of a module, or it is not (see 42.5, 42.7 for the
details).
Also the concept of factor structures and cosets is the same as that for row spaces (see 33.4,
33.3), especially the questions about a factor module is mainly delegated to the numerator
and the denominator, see also 42.11.
42.2
Row Modules
A row module for a matrix algebra A is a row space over a field F on that A acts from
the right via matrix multiplication. All operations, set theoretic functions and vector space
functions for row spaces are applicable to row modules, and the conventions for row spaces
also hold for row modules (see chapter 33). For the notion of a standard basis of a module,
see 42.13.
It should be mentioned, however, that the functions and their results have to be interpreted
in the module context. For example, Generators returns a list of module generators not
vector space generators (see 42.8), and Closure or Sum for modules return a module (namely
the smallest module generated by the arguments).
Quotient modules Q = V /W of row modules are quotients of row spaces V , W that
are both (row) modules for the same matrix algebra A. All operations and functions for
quotient spaces are applicable. The element of such quotient modules are module cosets,
in addition to the operations and functions for row space cosets they can be multiplied by
elements of the acting algebra.
42.3
Free Modules
A free module of dimension n for an algebra A consists of all n-tuples of elements of A,
the action of A is defined as component-wise multiplication from the right. Submodules and
quotient modules are defined in the obvious way.
In GAP3, elements of free modules are stored as lists of algebra elements. Thus there is no
difference to row modules with respect to addition of elements, and operation of the algebra.
However, the applicable functions are different.
At the moment, only free modules for finitely presented algebras are supported in GAP3,
and only very few functions are available for free modules at the moment. Especially the
set theoretic and vector space functions do not work for free modules and their submodules
and quotients.
Free modules were only introduced as operation domains of finitely presented algebras.
A ^ n
42.4. MODULE
755
returns a free module of dimension n for the algebra A.
gap> a:= FreeAlgebra( Rationals, 2 );; a.name:= "a";;
gap> a^2;
Module( a, [ [ a.one, a.zero ], [ a.zero, a.one ] ] )
42.4
Module
Module( R, gens )
Module( R, gens, zero )
Module( R, gens, "basis")
returns the module for the ring R that is generated by the elements in the list gens. If gens
is empty then the zero element zero of the module must be entered.
If the third argument is the string "basis" then the generators gens are assumed to form
a vector space basis.
gap> a:= UnitalAlgebra( GF(2), GL(2,2).generators );;
gap> a.name:="a";;
gap> m1:= Module( a, [ a.1[1] ] );
Module( a, [ [ Z(2)^0, Z(2)^0 ] ] )
gap> Dimension( m1 );
2
gap> Basis( m1 );
SemiEchelonBasis( Module( a, [ [ Z(2)^0, Z(2)^0 ] ] ),
[ [ Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0 ] ] )
gap> m2:= Module( a, a.2, "basis" );;
gap> Basis( m2 );
Basis( Module( a, [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] ),
[ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] )
gap> a.2;
[ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ]
gap> m1 = m2;
true
42.5
Submodule
Submodule( M , gens )
returns the submodule of the parent of the module M that is generated by the elements in
the list gens. If M is a factor module, gens may also consist of representatives instead of
the cosets themselves.
gap> a:= UnitalAlgebra( GF(2), [ mat1, mat2 ] );; a.name:= "a";;
gap> nat:= NaturalModule( a );;
gap> nat.name:= "nat";;
gap> s:= Submodule( nat, [ [ 1, 1, 1 ] * Z(2) ] );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, Z(2)^0 ] ] )
gap> Dimension( s );
1
756
CHAPTER 42. MODULES
42.6
AsModule
AsModule( M )
returns a module that is isomorphic to the module or submodule M .
gap> s:= Submodule( nat, [ [ 1, 1, 1 ] * Z(2) ] );;
gap> s2:= AsModule( s );
Module( a, [ [ Z(2)^0, Z(2)^0, Z(2)^0 ] ] )
gap> s = s2;
true
42.7
AsSubmodule
AsSubmodule( M , U )
returns a submodule of the parent of M that is isomorphic to the module U which can be
a parent module or a submodule with a different parent.
Note that the same ring must act on M and U .
gap> s2:= Module( a, [ [ 1, 1, 1 ] * Z(2) ] );;
gap> s:= AsSubmodule( nat, s2 );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, Z(2)^0 ] ] )
gap> s = s2;
true
42.8
AsSpace for Modules
AsSpace( M )
returns a (quotient of a) row space that is equal to the (quotient of a) row module M .
gap> s:= Submodule( nat, [ [ 1, 1, 0 ] * Z(2) ] );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, 0*Z(2) ] ] )
gap> Dimension( s );
2
gap> AsSpace( s );
RowSpace( GF(2),
[ [ Z(2)^0, Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0, Z(2)^0 ] ] )
gap> q:= nat / s;
nat / [ [ Z(2)^0, Z(2)^0, 0*Z(2) ] ]
gap> AsSpace( q );
RowSpace( GF(2),
[ [ Z(2)^0, 0*Z(2), 0*Z(2) ], [ 0*Z(2), Z(2)^0, 0*Z(2) ],
[ 0*Z(2), 0*Z(2), Z(2)^0 ] ] ) /
[ [ Z(2)^0, Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0, Z(2)^0 ] ]
42.9
IsModule
IsModule( obj )
42.10. ISFREEMODULE
757
returns true if obj , which may be an object of arbitrary type, is a module, and false
otherwise.
gap> IsModule( nat );
true
gap> IsModule( AsSpace( nat ) );
false
42.10
IsFreeModule
IsFreeModule( obj )
returns true if obj , which may be an object of arbitrary type, is a free module, and false
otherwise.
gap> IsFreeModule( nat );
false
gap> IsFreeModule( a^2 );
true
42.11
Operations for Row Modules
Here we mention only those facts about operations that have to be told in addition to those
for row spaces (see 33.7).
Comparisons of Modules
M1 = M2
M1 < M2
Equality and ordering of (quotients of) row modules are defined as equality resp. ordering
of the modules as vector spaces (see 33.7).
This means that equal modules may be inequivalent as modules, and even the acting rings
may be different. For testing equivalence of modules, see 42.14.
gap> s:= Submodule( nat, [ [ 1, 1, 1 ] * Z(2) ] );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, Z(2)^0 ] ] )
gap> s2:= Submodule( nat, [ [ 1, 1, 0 ] * Z(2) ] );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, 0*Z(2) ] ] )
gap> s = s2;
false
gap> s < s2;
true
Arithmetic Operations of Modules
M1 + M2
returns the sum of the two modules M1 and M2 , that is, the smallest module containing both M1 and M2 . Note that the same ring must act on M1 and M2 .
M1 / M2
returns the factor module of the module M1 by its submodule M2 . Note that the
same ring must act on M1 and M2 .
gap> s1:= Submodule( nat, [ [ 1, 1, 1 ] * Z(2) ] );
758
CHAPTER 42. MODULES
Submodule( nat, [ [ Z(2)^0, Z(2)^0, Z(2)^0 ] ] )
gap> q:= nat / s1;
nat / [ [ Z(2)^0, Z(2)^0, Z(2)^0 ] ]
gap> s2:= Submodule( nat, [ [ 1, 1, 0 ] * Z(2) ] );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, 0*Z(2) ] ] )
gap> s3:= s1 + s2;
Submodule( nat,
[ [ Z(2)^0, Z(2)^0, Z(2)^0 ], [ 0*Z(2), 0*Z(2), Z(2)^0 ] ] )
gap> s3 = nat;
true
For forming the sum and quotient of row spaces, see 33.7.
42.12
Functions for Row Modules
As stated in 42.2, row modules behave like row spaces with respect to set theoretic and
vector space functions (see 33.8).
The functions in the following sections use the module structure (see 42.13, 42.14, 42.15,
42.16, 42.17).
42.13
StandardBasis for Row Modules
StandardBasis( M )
StandardBasis( M , seedvectors )
returns the standard basis of the row module M with respect to the seed vectors in the list
seedvectors. If no second argument is given the generators of M are taken.
The standard basis is defined as follows. Take the first seed vector v, apply the generators
of the ring R acting on M in turn, and if the image is linearly independent of the basis
vectors found up to this time, it is added to the basis. When the space becomes stable
under the action of R, proceed with the next seed vector, and so on.
Note that you do not get a basis of the whole module if all seed vectors lie in a proper
submodule.
gap> s:= Submodule( nat, [ [ 1, 1, 0 ] * Z(2) ] );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, 0*Z(2) ] ] )
gap> b:= StandardBasis( s );
StandardBasis( Submodule( nat, [ [ Z(2)^0, Z(2)^0, 0*Z(2) ] ] ) )
gap> b.vectors;
[ [ Z(2)^0, Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0, Z(2)^0 ] ]
gap> StandardBasis( s, [ [ 0, 1, 1 ] * Z(2) ] );
StandardBasis( Submodule( nat, [ [ Z(2)^0, Z(2)^0, 0*Z(2) ] ] ),
[ [ 0*Z(2), Z(2)^0, Z(2)^0 ], [ Z(2)^0, 0*Z(2), Z(2)^0 ] ] )
42.14
IsEquivalent for Row Modules
IsEquivalent( M1 , M2 )
Let M1 and M2 be modules acted on by rings R1 and R2 , respectively, such that mapping
the generators of R1 to the generators of R2 defines a ring homomorphism. Furthermore let
42.15. ISIRREDUCIBLE FOR ROW MODULES
759
at least one of M1 , M2 be irreducible. Then IsEquivalent( M1 , M2 ) returns true if
the actions on M1 and M2 are equivalent, and false otherwise.
gap>
gap>
gap>
gap>
>
true
42.15
rand:= RandomInvertableMat( 3, GF(2) );;
b:= UnitalAlgebra( GF(2), List( a.generators, x -> x^rand ) );;
m:= NaturalModule( b );;
IsEquivalent( nat / FixedSubmodule( nat ),
m / FixedSubmodule( m ) );
IsIrreducible for Row Modules
IsIrreducible( M )
returns true if the (quotient of a) row module M is irreducible, and false otherwise.
gap> IsIrreducible( nat );
false
gap> IsIrreducible( nat / FixedSubmodule( nat ) );
true
42.16
FixedSubmodule
FixedSubmodule( M )
returns the submodule of fixed points in the module M under the action of the generators
of M .ring.
gap> fix:= FixedSubmodule( nat );
Submodule( nat, [ [ Z(2)^0, Z(2)^0, Z(2)^0 ] ] )
gap> Dimension( fix );
1
42.17
Module Homomorphisms
Let M1 and M2 be modules acted on by the rings R1 and R2 (via exponentiation), and ϕ
a ring homomorphism from R1 to R2 . Any linear map ψ = ψϕ from M1 to M2 with the
property that (mr )ψ = (mψ )( rϕ ) is called a module homomorphism.
At the moment only the following type of module homomorphism is available in GAP3.
Suppose you have the module M1 for the algebra R1 . Then you can construct the operation algebra R2 := Operation(R1 , M1 ), and the module for R2 isomorphic to M1 as
M2 := OperationModule(R2 ).
Then OperationHomomorphism(M1 , M2 ) can be used to construct the module homomorphism from M1 to M2 .
gap> s:= Submodule( nat, [ [ 1, 1, 0 ] *Z(2) ] );; s.name:= "s";;
gap> op:= Operation( a, s ); op.name:="op";;
UnitalAlgebra( GF(2), [ [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, Z(2)^0 ] ],
[ [ Z(2)^0, 0*Z(2) ], [ Z(2)^0, Z(2)^0 ] ] ] )
gap> opmod:= OperationModule( op ); opmod.name:= "opmod";;
Module( op, [ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ] )
760
CHAPTER 42. MODULES
gap> modhom:= OperationHomomorphism( s, opmod );
OperationHomomorphism( s, opmod )
gap> b:= Basis( s );
SemiEchelonBasis( s,
[ [ Z(2)^0, Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0, Z(2)^0 ] ] )
Images and preimages of elements under module homomorphisms are computed using Image
and PreImagesRepresentative, respectively. If M1 is a row module this is done by using
the knowledge of images of a basis, if M1 is a (quotient of a) free module then the algebra
homomorphism and images of the generators of M1 are used. The computation of preimages
requires in both cases the knowledge of representatives of preimages of a basis of M2 .
gap> im:= List( b.vectors, x -> Image( modhom, x ) );
[ [ Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0 ] ]
gap> List( im, x -> PreImagesRepresentative( modhom, x ) );
[ [ Z(2)^0, Z(2)^0, 0*Z(2) ], [ 0*Z(2), Z(2)^0, Z(2)^0 ] ]
42.18
Row Module Records
Module records contain at least the components
isDomain
always true,
isModule
always true,
isVectorSpace
always true, since modules are vector spaces,
ring
the ring acting on the module,
field
the coefficients field, is the same as R.field where R is the ring component of the
module,
operations
the operations record of the module.
The following components are optional, but if they are not present then the corresponding
function in the operations record must know how to compute them.
generators
a list of module generators (not necessarily of vector space generators),
zero
the zero element of the module.
basis
a vector space basis of the module (see also 33.2),
Factors of row modules have the same components as quotients of row spaces (see 33.30),
except that of course they have an appropriate operations record.
Additionally factors of row modules have the components isModule, isFactorModule (both
always true). Parent modules also have the ring component, which is the same ring as the
ring component of numerator and denominator.
42.19. MODULE HOMOMORPHISM RECORDS
42.19
761
Module Homomorphism Records
Module homomorphism records have at least the following components.
isGeneralMapping
true,
isMapping
true,
isHomomorphism
true,
domain
Mappings,
source
the source of the homomorphism, a module M1 ,
range
the range of the homomorphism, a module M2 ,
preImage
the module M1 ,
basisImage
a vector space basis of the image of M1 ,
preimagesBasis
a list of preimages of the basis vectors in basisImage
operations
the operations record of the homomorphism.
If the source is a (factor of a) free module then there are also the components
genimages
a list of images of the generators of the source,
alghom
the underlying algebra homomorphism from the ring acting on M1 to the ring acting
on M2 .
If the source is a (factor of a) row module then there are also the components
basisSource
a vector space basis of M1 ,
imagesBasis
a list of images of the basis vectors in basisSource.
762
CHAPTER 42. MODULES
Chapter 43
Mappings
A mapping is an object that maps each element of its source to a value in its range.
Precisely, a mapping is a triple. The source is a set of objects. The range is another
set of objects. The relation is a subset S of the cartesian product of the source with the
range, such that for each element elm of the source there is exactly one element img of the
range, so that the pair (elm, img) lies in S. This img is called the image of elm under the
mapping, and we say that the mapping maps elm to img.
A multi valued mapping is an object that maps each element of its source to a set of
values in its range.
Precisely, a multi valued mapping is a triple. The source is a set of objects. The range
is another set of objects. The relation is a subset S of the cartesian product of the source
with the range. For each element elm of the source the set img such that the pair (elm, img)
lies in S is called the set of images of elm under the mapping, and we say that the mapping
maps elm to this set.
Thus a mapping is a special case of a multi valued mapping where the set of images of each
element of the source contains exactly one element, which is then called the image of the
element under the mapping.
Mappings are created by mapping constructors such as MappingByFunction (see 43.18)
or NaturalHomomorphism (see 7.110).
This chapter contains sections that describe the functions that test whether an object is a
mapping (see 43.1), whether a mapping is single valued (see 43.2), and the various functions
that test if such a mapping has a certain property (see 43.3, 43.4, 43.5, 44.1, 44.2, 44.3,
44.4, 44.3, and 44.6).
Next this chapter contains functions that describe how mappings are compared (see 43.6)
and the operations that are applicable to mappings (see 43.7).
Next this chapter contains sections that describe the functions that deal with the images
and preimages of elements under mappings (see 43.8, 43.9, 43.10, 43.11, 43.12, and 43.13).
Next this chapter contains sections that describe the functions that compute the composition
of two mappings, the power of a mapping, the inverse of a mapping, and the identity mapping
on a certain domain (see 43.14, 43.15, 43.16, and 43.17).
763
764
CHAPTER 43. MAPPINGS
Finally this chapter also contains a section that describes how mappings are represented
internally (see 43.19).
The functions described in this chapter are in the file libname/"mapping.g".
43.1
IsGeneralMapping
IsGeneralMapping( obj )
IsGeneralMapping returns true if the object obj is a mapping (possibly multi valued) and
false otherwise.
gap> g := Group( (1,2,3,4), (2,4), (5,6,7) );; g.name := "g";;
gap> p4 := MappingByFunction( g, g, x -> x^4 );
MappingByFunction( g, g, function ( x )
return x ^ 4;
end )
gap> IsGeneralMapping( p4 );
true
gap> IsGeneralMapping( InverseMapping( p4 ) );
true
# note that the inverse mapping is multi valued
gap> IsGeneralMapping( x -> x^4 );
false
# a function is not a mapping
See 43.18 for the definition of MappingByFunction and 43.16 for InverseMapping.
43.2
IsMapping
IsMapping( map )
IsMapping returns true if the general mapping map is single valued and false otherwise.
Signals an error if map is not a general mapping.
gap> g := Group( (1,2,3,4), (2,4), (5,6,7) );; g.name := "g";;
gap> p4 := MappingByFunction( g, g, x -> x^4 );
MappingByFunction( g, g, function ( x )
return x ^ 4;
end )
gap> IsMapping( p4 );
true
gap> IsMapping( InverseMapping( p4 ) );
false
# note that the inverse mapping is multi valued
gap> p5 := MappingByFunction( g, g, x -> x^5 );
MappingByFunction( g, g, function ( x )
return x ^ 5;
end )
gap> IsMapping( p5 );
true
gap> IsMapping( InverseMapping( p5 ) );
true
# p5 is a bijection
IsMapping first tests if the flag map.isMapping is bound. If the flag is bound, it returns its
value. Otherwise it calls map.operations.IsMapping( map ), remembers the returned
value in map.isMapping, and returns it.
43.3. ISINJECTIVE
765
The default function called this way is MappingOps.IsMapping, which computes the sets of
images of all the elements in the source of map, provided this is finite, and returns true if
all those sets have size one. Look in the index under IsMapping to see for which mappings
this function is overlaid.
43.3
IsInjective
IsInjective( map )
IsInjective returns true if the mapping map is injective and false otherwise. Signals an
error if map is a multi valued mapping.
A mapping map is injective if for each element img of the range there is at most one
element elm of the source that map maps to img.
gap> g := Group( (1,2,3,4), (2,4), (5,6,7) );; g.name := "g";;
gap> p4 := MappingByFunction( g, g, x -> x^4 );
MappingByFunction( g, g, function ( x )
return x ^ 4;
end )
gap> IsInjective( p4 );
false
gap> IsInjective( InverseMapping( p4 ) );
Error,