Semigroups and monoids defined by generators
This section provides information about how to use the Semigroups package for
GAP to compute with a semigroup or monoid defined by a collection of
generators. We assume some basic familiarity with the GAP programming language,
see the GAP: First Steps section for a basic overview if you do
not yet feel comfortable with GAP.
All code examples in this section assume that the Semigroups package
is loaded. To do so, simply add
If Semigroups fails to load
If you encounter an error when loading the Semigroups package,
it may be due to the kernel module (the C++ component powering Semigroups)
not being compiled. Execute the command
SetInfoLevel(InfoPackageLoading, 4); and attempt to load the package
again. If you see an error similar to the following:
gap> SetInfoLevel(InfoPackageLoading, 4);
gap> LoadPackage("Semigroups");
#I Semigroups: entering LoadPackage
#I Semigroups: PackageAvailabilityInfo for version 5.5.4
#I Semigroups: the kernel module is not compiled,
#I the package cannot be loaded.
#I Semigroups: PackageAvailabilityInfo: the AvailabilityTest function returned false
#I Semigroups: PackageAvailabilityInfo: no installed version fits
#I Semigroups: return from LoadPackage, package is not available
fail
Kinds of elements
Any GAP object equipped with an associative multiplication can in principle
be used to construct a semigroup in GAP. However, there are certain kinds of
semigroups for which there exist the algorithms that are several orders
of magnitude faster than those applicable in the general case.
In particular, the Semigroups package implements efficient algorithms for
the so called
acting semigroups1
and has an efficient implementation of the
Froidure-Pin algorithm2
which can be applied to subsemigroups of certain semigroups.
In this section we give a brief description of the main types of
elements which can be efficiently computed with via the Semigroups package.
See Chapter 6
of the Semigroups package documentation for more details.
Transformations
Recall that a transformation of
degree \(n\) is a function \(f: \{1, \ldots, n\} \rightarrow \{1, \ldots, n\}\).
In GAP we can construct a transformation using the
Transformation
function.
One way of constructing a transformation \(t\) is to provide
a list A such that the \(i\)-th entry A[i] is the image of the point \(i\)
under the transformation \(t\). So, for example
t := Transformation([1, 3, 3, 4]); defines the transformation
\(t\)
such that \(t(1) = 1, t(2) = t(3) = 3\) and \(t(4) = 4\). We can
multiply transformations using the usual multiplication operator *.
Furthermore, we can obtain the image \(t(x)\) of a point
\(x \in \{1, \ldots, 4\}\) under \(t\) via the power syntax x ^ t.
Note
The code examples in this section will consist of two tabs: one labelled "GAP REPL" showcasing the output in an example GAP REPL session, and another labelled "GAP script" which contains the same code without the GAP REPL output, for easier copy-pasting into a GAP session.
gap> a := Transformation([1, 3, 3, 4]);
Transformation( [ 1, 3, 3 ] )
gap> b := Transformation([2, 3, 4, 1]);
Transformation( [ 2, 3, 4, 1 ] )
gap> a * b;
Transformation( [ 2, 4, 4, 1 ] )
gap> b * a;
Transformation( [ 3, 3, 4, 1 ] )
gap> 2 ^ a;
3
gap> 3 ^ b;
4
gap> 2 ^ (a * b);
4
gap> 2 ^ (b * a);
3
As we discussed in the Help system section, to
learn more about any GAP function you can use the help operator ? in the GAP
REPL, e.g.
gap> ?Transformation
53.2-1 Transformation
‣ Transformation( list ) ─────────────────────────────────────────── operation
‣ Transformation( list, func ) ───────────────────────────────────── operation
‣ TransformationList( list ) ─────────────────────────────────────── operation
Returns: A transformation.
TransformationList returns the transformation f such that i ^ f = list[i] if i
is between 1 and the length of list and i ^ f = i if i is larger than the
length of list. An error will occur in TransformationList if list is not
dense, if list contains an element which is not a positive integer, or if list
contains an integer not in [ 1 .. Length( list ) ].
TransformationList is the analogue in the context of transformations of
PermList (42.5-2). Transformation is a synonym of TransformationList when the
argument is a list.
When the arguments are a list of positive integers list and a function func,
Transformation returns the transformation f such that list[i] ^ f = func(
list[i] ) if i is in the range [ 1 .. Length( list ) ] and f fixes all other
points.
───────────────────────────────── Example ──────────────────────────────────
gap> SetUserPreference( "NotationForTransformations", "input" );
gap> f := Transformation( [ 11, 10, 2, 11, 4, 4, 7, 6, 9, 10, 1, 11 ] );
Transformation( [ 11, 10, 2, 11, 4, 4, 7, 6, 9, 10, 1, 11 ] )
gap> f := TransformationList( [ 2, 3, 3, 1 ] );
Transformation( [ 2, 3, 3, 1 ] )
gap> SetUserPreference( "NotationForTransformations", "fr" );
gap> f := Transformation( [ 10, 11 ], x -> x ^ 2 );
<transformation: 1,2,3,4,5,6,7,8,9,100,121>
gap> SetUserPreference( "NotationForTransformations", "input" );
──────────────────────────────────────────────────────────────────────────────
This can be especially helpful for understanding the functions we will use going forward. In particular, the documentation shows us another way of constructing a transformation using a list and a function.
Properties of transformations such as their degree, image, kernel and
rank are implemented by the
DegreeOfTransformation,
ImageSetOfTransformation,
KernelOfTransformation,
and RankOfTransformation
functions respectively.
Note
Mathematically, all transformations in GAP belong to
the infinite transformation monoid \(\mathcal{T}_\mathbb{N}\) of transformations
\(f: \mathbb{N} \rightarrow \mathbb{N}\). GAP simply treats all points
after the largest moved point of a transformation \(t\) as fixed.
This means that we can multiply two transformations acting
on a different number of points, so e.g.
Transformation([2, 1]) * Transformation([3, 3, 4, 5]);
is valid. Similarly, 10 ^ (Transformation([2, 1])); is
valid and returns 10.
The degree of a transformation \(t\), as returned by
the DegreeOfTransformation
function in GAP, is simply the largest moved point of \(t\), i.e.
the largest value \(n \in \mathbb{N}\) such that \(t(n) \neq n\).
Note
GAP does not have a distinguished type for partial transformations
of degree \(n\),
i.e. partial functions with domain and codomain in \(\{1, \ldots, n\}\).
However, for any fixed \(n\), the semigroup of all partial transformations
of degree \(n\) is isomorphic to the semigroup of all total transformations
of degree \(n+1\), which is what the Semigroups package utilizes.
See the documentation of the
PartialTransformationMonoid
for more details.
Info
See Chapter 53 of the GAP reference manual for more details about transformations.
Partial permutations
Recall that a partial permutation of degree \(n\) is a partial function
\(f: \{1, \ldots, n\} \rightarrow \{1, \ldots, n\}\) which is a bijection
when restricted to its domain, i.e. the set of points on which it is defined.
We can construct a partial permutation using the
PartialPerm
function in GAP by supplying two lists defining the domain and image of
the partial permutation. Partial permutations can be multiplied using *,
and the image of a point under a partial permutation can be obtained
using the ^ operator. Note that points not in the domain get mapped to 0.
Partial permutations in GAP are displayed in disjoint cycle and chain notation. Recall that a cycle of a partial permutation \(p\) is a sequence of points \(x_1, \ldots, x_k\) such that
- \(x_1 \in \text{dom}(p)\),
- \(p(x_i) = p(x_{i+1})\) for all \(i \in \{1, \ldots, k - 1\}\) and
- \(p(x_k) = x_1\).
A chain of \(p\) is a sequence of points \(x_1, \ldots, x_k\) such that
- \(x_1 \in \text{dom}(p) \setminus \text{im}(p)\),
- \(p(x_i) = p(x_{i+1})\) for all \(i \in \{1, \ldots, k - 1\}\) and
- \(p(x_k) \in \text{im}(p)\setminus \text{dom}(p)\).
Just as permutations can be written in disjoint cycle notation, partial
permutations can be written in disjoint cycle and chain notation.
Cycles are displayed using round brackets () and chains using square
brackets [].
See Section 54.6
of the reference manual for more details.
Warning
A Set
in GAP is a strictly sorted list of elements. GAP expects the
domain of PartialPerm to be a set, so in particular, this means
that giving the elements of the domain of a PartialPerm out of
order will result in a GAP error:
gap> PartialPerm([1, 2, 20, 5], [2, 3, 4, 50]); # 5 and 20 need to be swapped
Error, usage: the 1st argument must be a set of positive integers and the 2nd
argument must be a duplicate-free list of positive integers of equal length
to the first
*[1] ErrorNoReturn( "usage: the 1st argument must be a set of positive ",
"integers and the 2nd argument must be a duplicate-free ",
"list of positive integers of equal length to the first" );
@ /Users/rcirpons/Desktop/Source/gap/lib/pperm.gi:527
<function "PartialPerm">( <arguments> )
called from read-eval loop at *stdin*:44
type 'quit;' to quit to outer loop
brk>
The image must not contain duplicates (as otherwise the element would not be a partial bijection), but otherwise there is no restriction on the order of elements.
Properties of transformations such as their
degree, codegree, domain, image, and rank are implemented by the
DegreeOfPartialPerm,
CodegreeOfPartialPerm,
DomainOfPartialPerm,
ImageSetOfPartialPerm and
RankOfPartialPerm
functions respectively.
Note
Similar to transformations, all partial permutation in GAP belong to the infinite symmetric inverse monoid \(\mathcal{I}_\mathbb{N}\) of partial bijections \(f: \mathbb{N} \rightarrow \mathbb{N}\). Hence it is always possible to multiply any pair of partial permutations.
Info
See Chapter 54 of the GAP reference manual for more details about partial permutations.
Bipartitions
Recall that a bipartition of degree \(n\) is a
partition of the set \(\{1, \ldots, n\} \cup \{-n, \ldots, -1\}\).
The parts of a bipartition \(b\) are called blocks.
Bipartitions in GAP can be specified using the
Bipartition
function by specifying the blocks of the bipartition.
Bipartitions can be multiplied using the * operator
(see Chapter 3
of the Semigroups manual for a definition of bipartition multiplication).
Furthermore, bipartitions admit an involution
Star,
which swaps all the points \(i\) with \(-i\) in the partition.
gap> a := Bipartition([[1, -1, -2], [2, 5], [3, 4, -3], [-4, -5]]);
<bipartition: [ 1, -1, -2 ], [ 2, 5 ], [ 3, 4, -3 ], [ -4, -5 ]>
gap> b := Bipartition([[1, -4], [2], [3, -1], [4], [5, -3], [-2], [-5]]);
<bipartition: [ 1, -4 ], [ 2 ], [ 3, -1 ], [ 4 ], [ 5, -3 ], [ -2 ], [ -5 ]>
gap> a * b;
<bipartition: [ 1, -4 ], [ 2, 5 ], [ 3, 4, -1 ], [ -2 ], [ -3 ], [ -5 ]>
gap> b * a;
<bipartition: [ 1, 5, -3 ], [ 2 ], [ 3, -1, -2 ], [ 4 ], [ -4, -5 ]>
gap> Star(a);
<bipartition: [ 1, 2, -1 ], [ 3, -3, -4 ], [ 4, 5 ], [ -2, -5 ]>
The TikzString
function can be used to produce code visualizing the presentation using
the Latex package tikz. Provided you have a Latex
installation on your computer, the
Splash
function can be used to display the image this code generates.
gap> TikzString(a);
"%latex\n\\documentclass{minimal}\n\\usepackage{tikz}\n\n\\begin{document}\n\\be\
gin{tikzpicture}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2)cir\
cle(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n \\fill(1, \
0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n \\fill(2, 0)circle(.1\
25);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 0.125) .. \
controls (1, 0.59999999999999998) and (2, 0.59999999999999998) .. (2, 0.125);\n \
\\draw(1, 2)--(1, 0);\n\n %block number 2\n %vertices and labels\n \\fill(2,\
2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n \\fill(5, 2)circle(\
.125);\n \\draw(4.9500000000000002, 2.2) node [above] {$5$};\n\n %lines\n \\d\
raw(2, 1.875) .. controls (2, 1.2) and (5, 1.2) .. (5, 1.875);\n\n %block numbe\
r 3\n %vertices and labels\n \\fill(3, 2)circle(.125);\n \\draw(2.95000000000\
00002, 2.2) node [above] {$3$};\n \\fill(4, 2)circle(.125);\n \\draw(3.9500000\
000000002, 2.2) node [above] {$4$};\n \\fill(3, 0)circle(.125);\n \\draw(3, -0\
.2) node [below] {$-3$};\n\n %lines\n \\draw(3, 1.875) .. controls (3, 1.39999\
99999999999) and (4, 1.3999999999999999) .. (4, 1.875);\n \\draw(3, 2)--(3, 0);\
\n\n %block number 4\n %vertices and labels\n \\fill(4, 0)circle(.125);\n \\\
draw(4, -0.2) node [below] {$-4$};\n \\fill(5, 0)circle(.125);\n \\draw(5, -0.\
2) node [below] {$-5$};\n\n %lines\n \\draw(4, 0.125) .. controls (4, 0.599999\
99999999998) and (5, 0.59999999999999998) .. (5, 0.125);\n\\end{tikzpicture}\n\n\
\\end{document}"
gap> Splash(TikzString(a));
gap> Splash(TikzString(b));
A visualization of the bipartition a.
Result of the Splash(TikzString(a)) call.
A visualization of the bipartition b.
Result of the Splash(TikzString(b)) call.
Properties of bipartitions such as their degree, domain, codomain and
rank are implemented by the
DegreeOfBipartition,
DomainOfBipartition,
CodomainOfBipartition and
RankOfBipartition
functions respectively.
gap> c := Bipartition([[1, -1, -2], [2, 5], [3, 4, -3], [-4, -5], [6, -6]]);
<bipartition: [ 1, -1, -2 ], [ 2, 5 ], [ 3, 4, -3 ], [ 6, -6 ], [ -4, -5 ]>
gap> DegreeOfBipartition(c);
6
gap> DomainOfBipartition(c);
[ 1, 3, 4, 6 ]
gap> CodomainOfBipartition(c);
[ -1, -2, -3, -6 ]
gap> RankOfBipartition(c);
3
Warning
Unlike transformation and partial permutations,
bipartitions of distinct degrees cannot be multiplied
together, and attempting to do so at the moment will cause
erroneous output.
This issue will be resolved in a future release of the Semigroups
package, a fix was implemented in
Pull request #1185.
Info
See Chapter 3
of the Semigroups manual for more details about bipartitions.
Matrices over semirings
Recall that a semiring is a set \(S\) equipped with two binary operations \(+, \cdot: S\times S\rightarrow S\) such that \((S, +)\) is a commutative monoid, \((S, \cdot)\) is a monoid, and \(S\) satisfies three additional axioms:
- For all \(x \in S\), \(0_S \cdot x = x \cdot 0_S = 0_S\), where \(0_S\) is the additive identity of \(S\),
- For all \(x, y, z\in S\), \(x \cdot (y + z) = x \cdot y + x \cdot z\) and
- For all \(x, y, z\in S\), \((x + y) \cdot z = x \cdot z + y \cdot z\).
The set of \(n\times n\) matrices with entries in \(S\) forms a semigroup under matrix multiplication, i.e. if \(A\) and \(B\) are two \(n\times n\) matrices, then \((A \cdot B)_{i, j} = \sum_{k = 1}^n A_{i, k} \cdot B_{k, j}\).
The semigroups package currently supports efficient manipulation of \(n \times n\) matrices over the following semirings:
- The integers \(\mathbb{Z}\) under the usual addition and multiplication.
- The finite fields \(\mathbb{F}_{p^d}\) where \(p\) is a prime and \(d\) is a positive integer.
- The boolean semiring \(\mathbb{B} = \{\texttt{true}, \texttt{false}\}\) with addition given by the boolean \(\texttt{or}\) function and multiplication by the boolean \(\texttt{and}\) function;
- The max-plus semiring \(\mathbb{Z} \cup \{-\infty\}\) with operations \(\max\) and \(+\);
- The min-plus semiring \(\mathbb{Z} \cup \{+\infty\}\) with operations \(\min\) and \(+\);
- The tropical max-plus and tropical min-plus semirings, which are analogues of the max-plus and min-plus semirings, where the underlying set is replaced with \(\{-\infty, 0, \ldots, t\}\) and \(\{0, \ldots, t, \infty\}\), respectively.
- The semiring \(\mathbb{N}_{t, p} = \{0, \ldots t+p\}\) with addition and multiplication modulo the relation \(t = t + p\).
In general, an \(n\times n\) matrix \(A\) is represented in GAP as a
list of lists A such that A[i] is the \(i\)-th row of \(A\) and A[i][j] is
the \(i\)-th row and \(j\)-th column entry of \(A\).
Matrices can be multiplied using the * operator, provided they have the
same dimensions and same underlying semiring. The * operator
can also be used to multiply a matrix by a scalar from the underlying
semiring.
The ^ -1 operator
can be used to find the inverse of a matrix. If A is invertible over the
semiring, then A^-1 will return the inverse of A, and otherwise
A^-1 will return fail.
The transpose of a matrix can be found using the
TransposedMat
function.
Matrices can be
pretty-printed using the Display
function.
In order to make sure a matrix over the correct semiring is constructed, we must use the correct constructor function. We now briefly cover each type of matrix along with its constructors in turn.
Integers
One can construct an integer matrix \(A\) using the
Matrix
function by specifying the semiring Integers as the first argument and
the list of lists representing A as the second argument.
gap> A := Matrix(Integers, [
> [1, 2, 3],
> [4, 3, -1],
> [1, 0, -3]]);
<3x3-matrix over Integers>
gap> B := Matrix(Integers, [
> [1, -1, 0],
> [0, 0, 1],
> [1, 0, 1]]);
<3x3-matrix over Integers>
gap> C := Matrix(Integers, [
> [0, 0, 0],
> [0, 1, -1],
> [1, 0, 1]]);
<3x3-matrix over Integers>
gap> A * B;
<3x3-matrix over Integers>
gap> B * A;
<3x3-matrix over Integers>
gap> Display(A * B);
<3x3-matrix over Integers:
[[ 4, -1, 5 ]
[ 3, -4, 2 ]
[ -2, -1, -3 ]
]>
gap> Display(B * A);
<3x3-matrix over Integers:
[[ -3, -1, 4 ]
[ 1, 0, -3 ]
[ 2, 2, 0 ]
]>
gap> Display(A * 2);
<3x3-matrix over Integers:
[[ 2, 4, 6 ]
[ 8, 6, -2 ]
[ 2, 0, -6 ]
]>
gap> Display(3 * A);
<3x3-matrix over Integers:
[[ 3, 6, 9 ]
[ 12, 9, -3 ]
[ 3, 0, -9 ]
]>
gap> Display(TransposedMat(A));
<immutable 3x3-matrix over Integers:
[[ 1, 4, 1 ]
[ 2, 3, 0 ]
[ 3, -1, -3 ]
]>
gap> Display(B ^ -1);
<3x3-matrix over Integers:
[[ 0, -1, 1 ]
[ -1, -1, 1 ]
[ 0, 1, 0 ]
]>
gap> C^-1;
fail
A := Matrix(Integers, [
[1, 2, 3],
[4, 3, -1],
[1, 0, -3]]);
B := Matrix(Integers, [
[1, -1, 0],
[0, 0, 1],
[1, 0, 1]]);
C := Matrix(Integers, [
[0, 0, 0],
[0, 1, -1],
[1, 0, 1]]);
A * B;
B * A;
Display(A * B);
Display(B * A);
Display(A * 2);
Display(3 * A);
Display(TransposedMat(A));
Display(B ^ -1);
C^-1;
Warning
If an integer matrix is invertible over the rationals, but not the integers,
then the inversion operator ^ -1 will throw an error instead of
returning fail at the moment, e.g.
gap> A := Matrix(Integers, [
> [1, 2, 3],
> [4, 3, -1],
> [1, 0, -3]]);
<3x3-matrix over Integers>
gap> A^-1;
Error, the elements in <list> must lie in <basedomain>
*[1] Error( "the elements in <list> must lie in <basedomain>" );
@ /Users/rcirpons/Desktop/Source/gap/lib/matobjplist.gi:90
[2] MakeIsPlistVectorRep( v![1], list, true )
@ /Users/rcirpons/Desktop/Source/gap/lib/matobjplist.gi:319
[3] Vector( list[i], t )
@ /Users/rcirpons/Desktop/Source/gap/lib/matobjplist.gi:687
[4] Matrix( n, Length( n ), M )
@ /Users/rcirpons/Desktop/Source/gap/lib/matobjplist.gi:1215
<function "InverseSameMutability [ IsPlistMatrixRep ]">( <arguments> )
called from read-eval loop at *stdin*:160
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk> quit;
A is invertible over the rationals
but not the integers.
This issue will be resolved in a future version of GAP,
once Pull request #6342
gets merged.
The order of an integer matrix \(A\) is
the smallest positive positive integer \(n\) such that \(A^n\) is the
identity matrix, if such an integer exists and \(\infty\) otherwise.
We can compute the order using the
Order
function and we can check if the order is finite using the
IsTorsion
function. Note that only the order of an invertible matrix can be computed,
and the Order function will throw an error if a non-invertible matrix is given
as input.
gap> D := Matrix(Integers, [
> [0, 0, -1, 0],
> [0, -1, 0, 0],
> [4, 4, 2, -1],
> [1, 1, 0, 3]]);;
gap> Order(D);
infinity
gap> IsTorsion(D);
false
gap> F := Matrix(Integers, [
> [0, 0, -1],
> [0, 1, 0],
> [1, 0, 0]]);;
gap> Order(F);
4
gap> IsTorsion(F);
true
gap> G := Matrix(Integers, [
> [0, 0, 0],
> [0, 1, -1],
> [1, 0, 1]]);
gap> Order(G);
Error, Order: <mat> must be invertible
*[1] Error( "Order: <mat> must be invertible" );
@ /Users/rcirpons/Desktop/Source/gap/lib/matrix.gi:1169
[2] Order( Unpack( mat ) )
@ /Users/rcirpons/Desktop/Source/gap/pkg/Semigroups/gap/elements/maxplusmat.g\
i:759
<function "Order for an integer matrix obj">( <arguments> )
called from read-eval loop at *stdin*:172
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk> quit;
Warning
Certain single letter variables such as
E,
X and
Z
are defined as functions in GAP, and therefore cannot
be modified. Hence attempting to assign to either E, X or Z
will result in an error. This is why we skip E in the example above.
Finite fields
Recall that a field is a semiring which is additionally a
commutative group under addition and whose
non-zero elements form a commutative group under multiplication.
A finite field is a field with finitely many elements, and a
\(q\) element field exists precisely when \(q = p^d\) for some prime \(p\)
and positive integer \(d\). Furthermore all fields with \(q\) elements are
isomorphic, and we denote the finite field of order \(q\) by \(\mathbb{F}_q\).
In GAP the finite field of order \(q\) can be constructed via the
GF
function.
The
Z
function returns the generator Z(p^d) of the multiplicative group of
the finite field GF(p^d). As such Z(p^d)^0 is the multiplicative identity
of GF(p^d).
To construct a matrix \(A\) over a finite field, we use the
Matrix
function again, specifying the appropriate finite field
GF(p^d) as the first argument and
a list of lists of elements of GF(p^d)
representing A as the second argument.
gap> A := Matrix(GF(3), Z(3)^0 * [[0, 1, 2], [0, 0, 1], [1, 1, 1]]);
[ [ 0*Z(3), Z(3)^0, Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ],
[ Z(3)^0, Z(3)^0, Z(3)^0 ] ]
gap> B := Matrix(GF(3), Z(3)^0 * [[0, 2, 2], [1, 0, 1], [2, 0, 2]]);
[ [ 0*Z(3), Z(3), Z(3) ], [ Z(3)^0, 0*Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ] ]
gap> A^-1;
[ [ Z(3), Z(3)^0, Z(3)^0 ], [ Z(3)^0, Z(3)^0, 0*Z(3) ],
[ 0*Z(3), Z(3)^0, 0*Z(3) ] ]
gap> Display(TransposedMat(A));
. . 1
1 . 1
2 1 1
gap> Display(A^-1);
2 1 1
1 1 .
. 1 .
gap> B^-1;
fail
gap> Display(A * B);
2 . 2
2 . 2
. 2 2
gap> Display(B * A);
2 2 1
1 2 .
2 1 .
gap> C := Matrix(GF(3^3), Z(3^3)^0 * [[0, Z(3^3)^2 + 2 * Z(3^3) + 2, 1], [1, 1, 1], [2, 0, 2]]);
[ [ 0*Z(3), Z(3^3)^7, Z(3)^0 ], [ Z(3)^0, Z(3)^0, Z(3)^0 ],
[ Z(3), 0*Z(3), Z(3) ] ]
gap> Display(C);
z = Z(27)
. z^7 1
1 . 1
2 . 2
gap> Display(C^-1);
z = Z(27)
2 z^7 z^18
. 1 1
1 z^20 z^20
gap> Display(C * C);
z = Z(27)
z^18 z^7 z^18
. z^4 1
1 z^20 .
A := Matrix(GF(3), Z(3)^0 * [[0, 1, 2], [0, 0, 1], [1, 1, 1]]);
B := Matrix(GF(3), Z(3)^0 * [[0, 2, 2], [1, 0, 1], [2, 0, 2]]);
A^-1;
Display(TransposedMat(A));
Display(A^-1);
B^-1;
Display(A * B);
Display(B * A);
C := Matrix(GF(3^3), Z(3^3)^0 * [[0, Z(3^3)^2 + 2 * Z(3^3) + 2, 1], [1, 1, 1], [2, 0, 2]]);
Display(C);
Display(C^-1);
Display(C * C);
Warning
At the moment, passing an integer matrix whose entries are not elements
of GF(p^d) as the second argument will cause the conversion to a matrix
over a semiring to silently fail, e.g.
gap> A := Matrix(GF(2), [[1, 1, 1], [0, 1, 1], [0, 0, 1]]);
[ [ 1, 1, 1 ], [ 0, 1, 1 ], [ 0, 0, 1 ] ]
gap> A^-1;
[ [ 1, -1, 0 ], [ 0, 1, -1 ], [ 0, 0, 1 ] ]
gap> A[1][1] in GF(2);
false
Z(p^d)^0 to prevent this from happening, i.e.
This issue will be fixed in a future release of GAP.
Boolean matrices
One can construct a boolean matrix \(A\) using the
BooleanMat
functions by providing the list of lists representing A.
We allow either matrices that contain entries false and true or 0 and 1.
The entries false and true get mapped to 0 and 1 respectively.
gap> A := BooleanMat([[true, true, false], [false, false, false], [true, false, true]]);
Matrix(IsBooleanMat, [[1, 1, 0], [0, 0, 0], [1, 0, 1]])
gap> B := BooleanMat([[1, 1, 0], [0, 1, 0], [0, 0, 1]]);
Matrix(IsBooleanMat, [[1, 1, 0], [0, 1, 0], [0, 0, 1]])
gap> A * B;
Matrix(IsBooleanMat, [[1, 1, 0], [0, 0, 0], [1, 1, 1]])
gap> B * A;
Matrix(IsBooleanMat, [[1, 1, 0], [0, 0, 0], [1, 0, 1]])
gap> Display(A);
1 1 0
0 0 0
1 0 1
gap> Display(B);
1 1 0
0 1 0
0 0 1
A boolean matrix \(A\) of dimension \(n\) can equivalently be viewed as a binary
relation \(R\) of the set \(\{1, \ldots, n\}\), where \((i, j) \in R\) if and only
if \(A_{i, j} = 1\). The Semigroups package implements
functions for checking if a boolean matrix, when viewed as a binary relation
in this manner, is reflexive, symmetric, antisymmetric or transitive via the
functions
IsReflexiveBooleanMat,
IsSymmetricBooleanMat,
IsAntiSymmetricBooleanMat and
IsTransitiveBooleanMat
respectively.
gap> C := BooleanMat([
> [1, 1, 1, 0],
> [1, 1, 1, 1],
> [1, 1, 1, 1],
> [0, 1, 1, 1]]);
Matrix(IsBooleanMat, [[1, 1, 1, 0], [1, 1, 1, 1], [1, 1, 1, 1], [0, 1, 1, 1]])
gap> IsReflexiveBooleanMat(C);
true
gap> IsSymmetricBooleanMat(C);
true
gap> IsAntiSymmetricBooleanMat(C);
false
gap> IsTransitiveBooleanMat(C);
false
Max-plus, min-plus and tropical semirings and the \(\mathbb{N}_{t, p}\) semiring
To construct a matrix \(A\) over a max-plus, min-plus, tropical max-plus,
tropical min-plus or \(\mathbb{N}_{t, p}\) semiring, we use the
Matrix
function and specify, respectively,
IsMaxPlusSemiringas the first argument and a list of listsArepresenting the matrix \(A\) as the second argument. The element \(-\infty\) is expressed by the GAP variable-infinity.IsMinPlusSemiringas the first argument and a list of listsArepresenting the matrix \(A\) as the second argument. The element \(\infty\) is expressed by the GAP variableinfinity.IsTropicalMaxPlusSemiringas the first argument, a list of listsArepresenting the matrix \(A\) as the second argument, and the parameter \(t\) as the third argument.IsTropicalMinPlusSemiringas the first argument, a list of listsArepresenting the matrix \(A\) as the second argument, and the parameter \(t\) as the third argument.IsNTPMatrixas the first argument, a list of listsArepresenting the matrix \(A\) as the second argument, and the parameters \(t\) and \(p\) as the third and fourth argument.
gap> Display(Matrix(IsMaxPlusMatrix, [[4, 0, -2], [1, -3, 0], [5, -1, -4]]));
4 0 -2
1 -3 0
5 -1 -4
gap> Display(Matrix(IsMinPlusMatrix, [[-1, infinity], [1, -1]]));
-1 ∞
1 -1
gap> Display(Matrix(IsTropicalMaxPlusMatrix, [[3, 2, 4], [3, 1, 1], [-infinity, 1, 1]], 9));
3 2 4
3 1 1
-∞ 1 1
gap> Display(Matrix(IsTropicalMinPlusMatrix, [[1, 1, 1], [0, 3, 0], [1, 1, 3]], 9));
1 1 1
0 3 0
1 1 3
gap> Display(Matrix(IsNTPMatrix, [[0, 0, 0], [2, 0, 1], [2, 2, 2]], 2, 1));
0 0 0
2 0 1
2 2 2
Display(Matrix(IsMaxPlusMatrix, [[4, 0, -2], [1, -3, 0], [5, -1, -4]]));
Display(Matrix(IsMinPlusMatrix, [[-1, infinity], [1, -1]]));
Display(Matrix(IsTropicalMaxPlusMatrix, [[3, 2, 4], [3, 1, 1], [-infinity, 1, 1]], 9));
Display(Matrix(IsTropicalMinPlusMatrix, [[1, 1, 1], [0, 3, 0], [1, 1, 3]], 9));
Display(Matrix(IsNTPMatrix, [[0, 0, 0], [2, 0, 1], [2, 2, 2]], 2, 1));
Some standard matrices and matrix properties
GAP provides implementations of some standard matrix constructions, such as the
- identity matrix via
IdentityMat, - zero matrix via
NullMat, - diagonal matrices via
DiagonalMat, - permutation matrices via
PermutationMat.
We can wrap these in the appropriate constructor from above to construct respectively the identity, zero, a diagonal and a permutation matrix over the appropriate semiring:
gap> Display(Matrix(Integers, IdentityMat(5)));
<5x5-matrix over Integers:
[[ 1, 0, 0, 0, 0 ]
[ 0, 1, 0, 0, 0 ]
[ 0, 0, 1, 0, 0 ]
[ 0, 0, 0, 1, 0 ]
[ 0, 0, 0, 0, 1 ]
]>
gap> Display(BooleanMat(NullMat(6, 6)));
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> Display(Matrix(GF(16), DiagonalMat([Z(16), Z(16)^0, Z(16)^3 + Z(16), 0*Z(16)])));
z = Z(16)
z^1 . . .
. 1 . .
. . z^9 .
. . . .
gap> Display(Matrix(IsMaxPlusMatrix, PermutationMat((1, 3, 2)(5, 4), 6)));
0 0 1 0 0 0
1 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 1 0
0 0 0 1 0 0
0 0 0 0 0 1
One can also compute properties of matrices such as the determinant, trace, rank
and eigenvalues, to name a few,
using the
DeterminantMatrix
TraceMatrix,
RankMatrix and
Eigenvalues
functions, though not all semirings support all of these functions.
gap> A := Matrix(Integers, [[1, 2, 3], [4, 3, -1], [1, 0, -3]]);
<3x3-matrix over Integers>
gap> B := Matrix(GF(3^3), Z(3^3)^0 * [[0, Z(3^3)^2 + 2 * Z(3^3) + 2, 1], [1, 1, 1], [2, 0, 2]]);
[ [ 0*Z(3), Z(3^3)^7, Z(3)^0 ], [ Z(3)^0, Z(3)^0, Z(3)^0 ],
[ Z(3), 0*Z(3), Z(3) ] ]
gap> DeterminantMatrix(A);
4
gap> TraceMatrix(A);
1
gap> RankMatrix(B);
3
gap> # We need to also specify a field over which to find eigenvalues over
gap> Eigenvalues(GF(3^3), B);
[ Z(3^3)^11 ]
Info
See Chapter 5
of the Semigroups manual for more details about matrices over semirings,
as well as Chapter 24
of the GAP reference manual for more details about general methods for
matrices. Note, however that not all methods may be implemented for
semigroups over a semiring.
Constructing semigroups
In this section we briefly outline different methods for constructing
semigroups using GAP and the Semigroups package. We will occasionally
use some functions to showcase properties of these semigroups, such as
Size, Elements, IsRegularSemigroup and so on. These functions will
be explained in more detail in the Analyzing semigroups
section later on.
Built-in semigroups and monoids
GAP and the Semigroups package provide a range of built-in standard semigroups,
such as the
- full transformation semigroup \(\mathcal{T}_n\) consisting of all degree \(n\)
transformations via the
FullTransformationSemigroupfunction. - symmetric inverse semigroup \(\mathcal{I}_n\) consisting of all degree \(n\)
partial permutation via the
SymmetricInverseSemigroupfunction. - partition monoid \(\mathcal{P}_n\) consisting of all degree \(n\) bipartitions
via the
PartitionMonoidfunction. - full matrix monoid of dimension \(n\) over the finite field \(\mathbb{F}_q\)
consisting of all \(n\times n\) matrices with entries in \(\mathbb{F}_q\)
via the
FullMatrixMonoidfunction. - full boolean matrix monoid of dimension \(n\) consisting of all
\(n\times n\) boolean matrices via the
FullBooleanMatMonoid.
Here we showcase how to construct each semigroup, and then use the
Size and IsRegularSemigroup functions to determine its size and
whether or not the semigroup is regular:
gap> T := FullTransformationSemigroup(5);
<full transformation monoid of degree 5>
gap> Size(T);
3125
gap> IsRegularSemigroup(T);
true
gap> I := SymmetricInverseSemigroup(6);
<symmetric inverse monoid of degree 6>
gap> Size(I);
13327
gap> IsRegularSemigroup(I);
true
gap> P := PartitionMonoid(4);
<regular bipartition *-monoid of size 4140, degree 4 with 4 generators>
gap> Size(P);
4140
gap> IsRegularSemigroup(P);
true
gap> MF := FullMatrixMonoid(4, 3^2);
<general linear monoid 4x4 over GF(3^2)>
gap> Size(MF);
1853020188851841
gap> IsRegularSemigroup(MF);
true
gap> MB := FullBooleanMatMonoid(4);
<monoid of 4x4 boolean matrices with 7 generators>
gap> Size(MB);
65536
gap> IsRegularSemigroup(MB);
false
T := FullTransformationSemigroup(5);
Size(T);
IsRegularSemigroup(T);
I := SymmetricInverseSemigroup(6);
Size(I);
IsRegularSemigroup(I);
P := PartitionMonoid(4);
Size(P);
IsRegularSemigroup(P);
MF := FullMatrixMonoid(4, 3^2);
Size(MF);
IsRegularSemigroup(MF);
MB := FullBooleanMatMonoid(4);
Size(MB);
IsRegularSemigroup(MB);
Info
See Chapter 7
of the Semigroups manual for a list of many more standard semigroups
and monoids implemented by the Semigroups package.
Finitely generated subsemigroups and submonoids
If A is a list of semigroup generators then we can construct the semigroup
generated by A using the Semigroup
function:
gap> a := Transformation([9, 5, 10, 8, 1, 4, 1, 4, 5, 2]);;
gap> b := Transformation([8, 8, 6, 5, 8, 9, 1, 3, 6, 6]);;
gap> c := Transformation([2, 8, 5, 4, 10, 4, 5, 4, 10, 10]);;
gap> T := Semigroup([a, b, c]);
<transformation semigroup of degree 10 with 3 generators>
gap> Size(T);
5965
gap> IsRegularSemigroup(T);
false
gap> d := Bipartition([
> [ 1, 2, 4, -5 ], [ 3, -7 ], [ 5, 9, 10, -10 ], [ 6 ],
> [ 7, -2, -3, -8, -9 ], [ 8 ], [ -1 ], [ -4 ], [ -6 ]]);
<bipartition: [ 1, 2, 4, -5 ], [ 3, -7 ], [ 5, 9, 10, -10 ], [ 6 ],
[ 7, -2, -3, -8, -9 ], [ 8 ], [ -1 ], [ -4 ], [ -6 ]>
gap> e := Bipartition([
> [ 1, 3, 10, -4, -5, -7, -9 ], [ 2, 4, 5, 7, -1, -3, -8 ],
> [ 6, 8, 9, -2 ], [ -6 ], [ -10 ]]);
<bipartition: [ 1, 3, 10, -4, -5, -7, -9 ], [ 2, 4, 5, 7, -1, -3, -8 ],
[ 6, 8, 9, -2 ], [ -6 ], [ -10 ]>
gap> f := Bipartition([
> [ 1, 2, 4, 9, 10, -7 ], [ 3, 6, 7, 8, -1, -2, -8 ],
> [ 5, -3, -4, -5, -6, -9, -10 ]]);
<block bijection: [ 1, 2, 4, 9, 10, -7 ], [ 3, 6, 7, 8, -1, -2, -8 ],
[ 5, -3, -4, -5, -6, -9, -10 ]>
gap> g := Bipartition([
> [ 1, 2, -1, -8 ], [ 3, 7, -3, -7, -10 ], [ 4, 5, 9, -5, -6 ],
> [ 6, 8, -2 ], [ 10 ], [ -4, -9 ]]);
<bipartition: [ 1, 2, -1, -8 ], [ 3, 7, -3, -7, -10 ], [ 4, 5, 9, -5, -6 ],
[ 6, 8, -2 ], [ 10 ], [ -4, -9 ]>
gap> S := Semigroup([d, e, f, g]);
<bipartition semigroup of degree 10 with 4 generators>
gap> Size(S);
24
gap> IsRegularSemigroup(S);
false
a := Transformation([9, 5, 10, 8, 1, 4, 1, 4, 5, 2]);;
b := Transformation([8, 8, 6, 5, 8, 9, 1, 3, 6, 6]);;
c := Transformation([2, 8, 5, 4, 10, 4, 5, 4, 10, 10]);;
T := Semigroup([a, b, c]);
Size(T);
IsRegularSemigroup(T);
d := Bipartition([
[ 1, 2, 4, -5 ], [ 3, -7 ], [ 5, 9, 10, -10 ], [ 6 ],
[ 7, -2, -3, -8, -9 ], [ 8 ], [ -1 ], [ -4 ], [ -6 ]]);
e := Bipartition([
[ 1, 3, 10, -4, -5, -7, -9 ], [ 2, 4, 5, 7, -1, -3, -8 ],
[ 6, 8, 9, -2 ], [ -6 ], [ -10 ]]);
f := Bipartition([
[ 1, 2, 4, 9, 10, -7 ], [ 3, 6, 7, 8, -1, -2, -8 ],
[ 5, -3, -4, -5, -6, -9, -10 ]]);
g := Bipartition([
[ 1, 2, -1, -8 ], [ 3, 7, -3, -7, -10 ], [ 4, 5, 9, -5, -6 ],
[ 6, 8, -2 ], [ 10 ], [ -4, -9 ]]);
S := Semigroup([d, e, f, g]);
Size(S);
IsRegularSemigroup(S);
As mention at the start of the Kinds of elements
section, in theory any collection of elements with associative multiplication
can be used to construct a finitely generated semigroup using the Semigroup
function. However, using the kinds of elements described in the
Kinds of elements section is guaranteed to utilize
the fast algorithms implemented in Semigroups. For an extreme example
consider:
gap> gens := [
> Transformation([10, 10, 6, 9, 3, 6, 6, 8, 3, 4]),
> Transformation([10, 10, 6, 9, 3, 6, 6, 8, 3, 4]),
> Transformation([6, 8, 8, 4, 7, 1, 2, 9, 9, 3]),
> Transformation([6, 8, 8, 4, 7, 1, 2, 9, 9, 3]),
> Transformation([9, 9, 1, 3, 4, 10, 5, 6, 3, 3]),
> Transformation([9, 9, 1, 3, 4, 10, 5, 6, 3, 3]),
> Transformation([7, 1, 2, 9, 3, 10, 3, 2, 5, 6])];;
gap> S := Semigroup(gens);
<transformation semigroup of degree 10 with 7 generators>
gap> Size(S);
3063073
gap> time; # The time function outputs the time it took to run the last command in ms
4451
gens := [
Transformation([10, 10, 6, 9, 3, 6, 6, 8, 3, 4]),
Transformation([10, 10, 6, 9, 3, 6, 6, 8, 3, 4]),
Transformation([6, 8, 8, 4, 7, 1, 2, 9, 9, 3]),
Transformation([6, 8, 8, 4, 7, 1, 2, 9, 9, 3]),
Transformation([9, 9, 1, 3, 4, 10, 5, 6, 3, 3]),
Transformation([9, 9, 1, 3, 4, 10, 5, 6, 3, 3]),
Transformation([7, 1, 2, 9, 3, 10, 3, 2, 5, 6])];;
S := Semigroup(gens);
Size(S);
time; # The time function outputs the time it took to run the last command in ms
We are able to enumerate a semigroup of 3 million elements in 4.5 seconds. Of
course the runtime will depend on the machine and so on, but the point is that
this computation takes seconds instead of days with Semigroups.
Trying to run the computation without the Semigroups package loaded
will cause the Size computation to run significantly longer (we have not
been able to run it to completion without the Semigroups package loaded).
In certain cases, we may even be able to determine that a semigroup is
infinite using the Semigroups package:
However, one must be careful, since it is general undecidable if a matrix semigroup is finite or not. Modifying the example just slightly we obtain an infinite semigroup whose size calculation does not terminate:
gap> C := Matrix(Integers, [[1, 1], [0, 1]]);
<2x2-matrix over Integers>
gap> D := Matrix(Integers, [[0, 1], [-1, 0]]);
<2x2-matrix over Integers>
gap> S := Semigroup([C, D]);
<semigroup of 2x2 integer matrices with 2 generators>
gap> # The following computation will run forever, uncomment the next line
gap> # at your own risk:
gap> # Size(S);
gap> # Pressing Ctrl+C twice in your console in rapid succession
gap> # should kill the computation
To create a monoid defined by a finite generated set instead of a semigroup,
we can use the Monoid function:
gap> a := Transformation([9, 5, 10, 8, 1, 4, 1, 4, 5, 2]);;
gap> b := Transformation([8, 8, 6, 5, 8, 9, 1, 3, 6, 6]);;
gap> c := Transformation([2, 8, 5, 4, 10, 4, 5, 4, 10, 10]);;
gap> T := Monoid([a, b, c]);
<transformation semigroup of degree 10 with 3 generators>
gap> Size(T);
5966
gap> IsRegularSemigroup(T);
false
gap> d := Bipartition([
> [ 1, 2, 4, -5 ], [ 3, -7 ], [ 5, 9, 10, -10 ], [ 6 ],
> [ 7, -2, -3, -8, -9 ], [ 8 ], [ -1 ], [ -4 ], [ -6 ]]);
<bipartition: [ 1, 2, 4, -5 ], [ 3, -7 ], [ 5, 9, 10, -10 ], [ 6 ],
[ 7, -2, -3, -8, -9 ], [ 8 ], [ -1 ], [ -4 ], [ -6 ]>
gap> e := Bipartition([
> [ 1, 3, 10, -4, -5, -7, -9 ], [ 2, 4, 5, 7, -1, -3, -8 ],
> [ 6, 8, 9, -2 ], [ -6 ], [ -10 ]]);
<bipartition: [ 1, 3, 10, -4, -5, -7, -9 ], [ 2, 4, 5, 7, -1, -3, -8 ],
[ 6, 8, 9, -2 ], [ -6 ], [ -10 ]>
gap> f := Bipartition([
> [ 1, 2, 4, 9, 10, -7 ], [ 3, 6, 7, 8, -1, -2, -8 ],
> [ 5, -3, -4, -5, -6, -9, -10 ]]);
<block bijection: [ 1, 2, 4, 9, 10, -7 ], [ 3, 6, 7, 8, -1, -2, -8 ],
[ 5, -3, -4, -5, -6, -9, -10 ]>
gap> g := Bipartition([
> [ 1, 2, -1, -8 ], [ 3, 7, -3, -7, -10 ], [ 4, 5, 9, -5, -6 ],
> [ 6, 8, -2 ], [ 10 ], [ -4, -9 ]]);
<bipartition: [ 1, 2, -1, -8 ], [ 3, 7, -3, -7, -10 ], [ 4, 5, 9, -5, -6 ],
[ 6, 8, -2 ], [ 10 ], [ -4, -9 ]>
gap> S := Monoid([d, e, f, g]);
<bipartition semigroup of degree 10 with 4 generators>
gap> Size(S);
25
gap> IsRegularSemigroup(S);
false
a := Transformation([9, 5, 10, 8, 1, 4, 1, 4, 5, 2]);;
b := Transformation([8, 8, 6, 5, 8, 9, 1, 3, 6, 6]);;
c := Transformation([2, 8, 5, 4, 10, 4, 5, 4, 10, 10]);;
T := Monoid([a, b, c]);
Size(T);
IsRegularSemigroup(T);
d := Bipartition([
[ 1, 2, 4, -5 ], [ 3, -7 ], [ 5, 9, 10, -10 ], [ 6 ],
[ 7, -2, -3, -8, -9 ], [ 8 ], [ -1 ], [ -4 ], [ -6 ]]);
e := Bipartition([
[ 1, 3, 10, -4, -5, -7, -9 ], [ 2, 4, 5, 7, -1, -3, -8 ],
[ 6, 8, 9, -2 ], [ -6 ], [ -10 ]]);
f := Bipartition([
[ 1, 2, 4, 9, 10, -7 ], [ 3, 6, 7, 8, -1, -2, -8 ],
[ 5, -3, -4, -5, -6, -9, -10 ]]);
g := Bipartition([
[ 1, 2, -1, -8 ], [ 3, 7, -3, -7, -10 ], [ 4, 5, 9, -5, -6 ],
[ 6, 8, -2 ], [ 10 ], [ -4, -9 ]]);
S := Monoid([d, e, f, g]);
Size(S);
IsRegularSemigroup(S);
Warning
In GAP monoids are implemented as algebras with two operations: a binary
multiplication and a nullary identity. Hence, while every Monoid is a
Semigroup in GAP, not every Semigroup that is mathematically a monoid
is a Monoid in the GAP sense.
So, if a semigroup
constructed with the Semigroup function happens to be a monoid, it will
not be recognized by GAP as a monoid. For example we could construct the
symmetric group with the Semigroup function and check if it is a monoid
using the IsMonoid
function:
gap> S := Semigroup([(1, 2), (1, 2, 3)]);
<semigroup with 2 generators>
gap> Elements(M);
[ (), (2,3), (1,2), (1,2,3), (1,3,2), (1,3) ]
gap> IsMonoid(S);
false
There are two solutions to this:
- We can construct the semigroup using the
Monoidfunction instead: The resulting monoid has all the same elements, but it is additionally recognized as a monoid. - We can use the
AsMonoidfunction to convert the semigroup to a monoid:
Info
See Chapter 6
of the Semigroups manual for more info on how the Semigroups package
handles finitely generated subsemigroups as well as
Section 51.1
and
Section 51.2
of the GAP reference manual for more information on semigroups
and monoids in GAP.
Multiplication tables
A multiplication table is an \(n\times n\) table \(A\) whose entries are integers
\(\{1, \ldots, n\}\). The table \(A\) defines a semigroup with elements
\(\{1, \ldots, n\}\) and the product of \(i, j\in \{1, \ldots, n\}\) is given by
the \((i, j)\)-th entry of \(A\). In GAP a multiplication table can be specified by
a list of lists whose entries are integers. We can construct a semigroup
from such a multiplication table using the
SemigroupByMultiplicationTable
function. If the given multiplication table does not define a semigroup, i.e. it is not
associative, then the function returns fail instead.
The
MonoidByMultiplicationTable function
can be used to construct a monoid from a multiplication table instead.
gap> table1 := [
> [2, 2, 4, 4],
> [3, 2, 3, 3],
> [3, 1, 1, 3],
> [4, 4, 1, 3]];
[ [ 2, 2, 4, 4 ], [ 3, 2, 3, 3 ], [ 3, 1, 1, 3 ], [ 4, 4, 1, 3 ] ]
gap> SemigroupByMultiplicationTable(table1);
fail
gap> table2 := [
> [1, 2, 1, 2],
> [1, 2, 1, 2],
> [3, 4, 3, 4],
> [3, 4, 3, 4]];
[ [ 1, 2, 1, 2 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 3, 4, 3, 4 ] ]
gap> SemigroupByMultiplicationTable(table2);
<semigroup of size 4, with 4 generators>
gap> table3 := [
> [1, 1, 4, 4],
> [1, 2, 3, 4],
> [1, 3, 2, 4],
> [1, 4, 1, 4]];
[ [ 1, 1, 4, 4 ], [ 1, 2, 3, 4 ], [ 1, 3, 2, 4 ], [ 1, 4, 1, 4 ] ]
gap> SemigroupByMultiplicationTable(table3);
<semigroup of size 4, with 4 generators>
gap> MonoidByMultiplicationTable(table2);
fail
gap> MonoidByMultiplicationTable(table3);
<monoid of size 4, with 4 generators>
table1 := [
[2, 2, 4, 4],
[3, 2, 3, 3],
[3, 1, 1, 3],
[4, 4, 1, 3]];
SemigroupByMultiplicationTable(table1);
table2 := [
[1, 2, 1, 2],
[1, 2, 1, 2],
[3, 4, 3, 4],
[3, 4, 3, 4]];
SemigroupByMultiplicationTable(table2);
table3 := [
[1, 1, 4, 4],
[1, 2, 3, 4],
[1, 3, 2, 4],
[1, 4, 1, 4]];
SemigroupByMultiplicationTable(table3);
MonoidByMultiplicationTable(table2);
MonoidByMultiplicationTable(table3);
Dually, the
MultiplicationTable
function can be used to find the multiplication table of any given semigroup
or monoid:
gap> T := FullTransformationSemigroup(2);
<full transformation monoid of degree 2>
gap> Display(MultiplicationTable(T));
[ [ 1, 1, 4, 4 ],
[ 1, 2, 3, 4 ],
[ 1, 3, 2, 4 ],
[ 1, 4, 1, 4 ] ]
gap> S := Monoid([Transformation([1, 1, 1]), Transformation([1, 2, 3])]);
<commutative transformation monoid of degree 3 with 1 generator>
gap> Display(MultiplicationTable(S));
[ [ 1, 1 ],
[ 1, 2 ] ]
Warning
Multiplication tables are a very inefficient way of defining a semigroup. Indeed, to define a semigroup \(S\) using a multiplication table we need to give a table of \(|S|^2\) entries. However, if a generating set \(A\) for \(S\) is known, we can construct a transformation representation for \(S\) by taking only those rows in the multiplication table that correspond to the generators in \(A\). This allows us to construct a transformation semigroup \(S^\prime\) that is isomorphic to \(S\), and we only need specify \(|A|\cdot |S|\) many entries.
For example, if \(S\) is a 3-generated semigroup of size 1000, specifying a multiplication table requires a 1000000 entry table, whereas an isomorphic transformation semigroup can be specified with just 3 transformations of degree 1000, for a total of 3000 entries. Furthermore, algorithms for transformation semigroups are generally much faster.
The small semigroups library
The Smallsemi
package contains a database of all semigroups of order up to \(8\) up to
isomorphism and anti-isomorphism.
To use the Smallsemi package we need to load it first, just as
we did with the Semigroups package.
We can get the \(n\)-th semigroup of order \(m\) using the
SmallSemigroup
function with arguments m and n.
gap> LoadPackage("Smallsemi");
------------------------------------------------------------------------------------
Smallsemi - A library of small semigroups
by Andreas Distler & James Mitchell
For contents, type: ?Smallsemi:
Loading Smallsemi 0.7.2 ...
------------------------------------------------------------------------------------
true
gap> Display(MultiplicationTable(S1));
[ [ 1, 1, 1, 1 ],
[ 1, 1, 1, 1 ],
[ 1, 1, 1, 1 ],
[ 1, 1, 1, 1 ] ]
gap> S2 := SmallSemigroup(4, 2);
<small semigroup of size 4>
gap> Display(MultiplicationTable(S2));
[ [ 1, 1, 1, 1 ],
[ 1, 1, 1, 1 ],
[ 1, 1, 1, 1 ],
[ 1, 1, 2, 1 ] ]
gap> S3 := SmallSemigroup(8, 1000);
<small semigroup of size 8>
gap> Display(MultiplicationTable(S3));
[ [ 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, 2 ],
[ 1, 1, 1, 1, 1, 1, 1, 2 ],
[ 1, 1, 1, 1, 2, 1, 1, 1 ],
[ 1, 1, 1, 2, 3, 1, 1, 2 ],
[ 1, 1, 2, 2, 2, 1, 6, 1 ] ]
Info
See the Smallsemi
package documentation for more information about the small semigroups
library.
Analyzing semigroups
Now that we can construct semigroups in GAP, we consider methods of analyzing them.
Finiteness and enumeration
We already saw that the
Size
function can be used to determine the order of a semigroup or monoid.
The IsFinite
function can be used to test if a given semigroup is finite or infinite.
The elements of a semigroup can be computed using the
Elements function.
The idempotents, i.e. elements \(x\) such that \(x^2 = x\), can be found using
the Idempotents
function.
gap> S := Semigroup([Transformation([1, 1]), Transformation([2, 2]), Transformation([5, 4, 3, 2, 1])]);
<transformation semigroup of degree 5 with 3 generators>
gap> IsFinite(S);
true
gap> Size(S);
18
gap> Elements(S);
[ Transformation( [ 1, 1, 3, 4, 4 ] ), Transformation( [ 1, 1 ] ),
Transformation( [ 1, 1, 3, 5, 5 ] ), Transformation( [ 1, 2, 3, 4, 4 ] ),
IdentityTransformation, Transformation( [ 1, 2, 3, 5, 5 ] ),
Transformation( [ 2, 2, 3, 4, 4 ] ), Transformation( [ 2, 2 ] ),
Transformation( [ 2, 2, 3, 5, 5 ] ), Transformation( [ 4, 4, 3, 1, 1 ] ),
Transformation( [ 4, 4, 3, 2, 1 ] ), Transformation( [ 4, 4, 3, 2, 2 ] ),
Transformation( [ 5, 4, 3, 1, 1 ] ), Transformation( [ 5, 4, 3, 2, 1 ] ),
Transformation( [ 5, 4, 3, 2, 2 ] ), Transformation( [ 5, 5, 3, 1, 1 ] ),
Transformation( [ 5, 5, 3, 2, 1 ] ), Transformation( [ 5, 5, 3, 2, 2 ] ) ]
gap> Idempotents(S);
[ Transformation( [ 1, 1 ] ), Transformation( [ 2, 2 ] ), IdentityTransformation,
Transformation( [ 1, 2, 3, 5, 5 ] ), Transformation( [ 1, 2, 3, 4, 4 ] ),
Transformation( [ 1, 1, 3, 5, 5 ] ), Transformation( [ 2, 2, 3, 5, 5 ] ),
Transformation( [ 1, 1, 3, 4, 4 ] ), Transformation( [ 2, 2, 3, 4, 4 ] ) ]
gap> T := Semigroup([Matrix(Integers, [[1, 1], [1, 0]]), Matrix(Integers, [[1, 0], [0, 0]])]);
<semigroup of 2x2 integer matrices with 2 generators>
gap> IsFinite(T);
false
Warning
It is in general undecidable if a given finitely generated semigroup
is finite. Hence the functions Size, IsFinite and Idempotents
may run forever on semigroups that are infinite,
as we saw in the
Finitely generated subsemigroups and submonoids
section. However, the
functions Size, IsFinite, Elements and Idempotents are guaranteed
to terminate when the underlying semigroup is finite.
Cayley graphs
Recall that the right Cayley graph of a semigroup \(S\) generated
by \(A\) is the directed graph \(G\) with vertex set \(V(G) = S\) and
edge set \(E(G) = \{(x, a, y)\in S \times A \times S : x\cdot a = y \}\).
The left Cayley graph is defined analogously replacing the condition
\(x\cdot a = y\) with \(a\cdot x = y\).
We can think of these as directed graphs whose edges are colored by elements
in \(A\).
The RightCayleyDigraph and LeftCayleyDigraph functions
can be used to compute, respectively, the right and left Cayley graphs of
a semigroup S. The output of these functions is a directed graph
represented as a
Digraph
object.
gap> S := Semigroup([Transformation([1, 1]), Transformation([2, 2]), Transformation([5, 4, 3, 2, 1])]);
<transformation semigroup of degree 5 with 3 generators>
gap> RightCayleyDigraph(S);
<immutable digraph with 18 vertices, 54 edges>
gap> LeftCayleyDigraph(S);
<immutable multidigraph with 18 vertices, 54 edges>
There are two ways of visualizing these graphs using the
Semigroups package:
-
We can visualize these graphs without the edge coloring using the
DotRightCayleyDigraphandDotLeftCayleyDigraphfunctions, which producegraphvizcode describing the right and left Cayley graphs, respectively. If you havegraphvizinstalled on your computer, you can render the resulting graphs using theSplashfunction:gap> S := Semigroup([Transformation([1, 1]), Transformation([2, 2]), Transformation([5, 4, 3, 2, 1])]); <transformation semigroup of degree 5 with 3 generators> gap> DotRightCayleyDigraph(S); "//dot\ndigraph hgn{\nnode [shape=circle]\n1 [label=\"a\"]\n2 [label=\"b\"]\n3 [label\ =\"c\"]\n4 [label=\"ac\"]\n5 [label=\"bc\"]\n6 [label=\"ca\"]\n7 [label=\"cb\"]\n8 [l\ abel=\"c ^ 2\"]\n9 [label=\"aca\"]\n10 [label=\"acb\"]\n11 [label=\"bca\"]\n12 [label\ =\"bcb\"]\n13 [label=\"cac\"]\n14 [label=\"cbc\"]\n15 [label=\"acac\"]\n16 [label=\"a\ cbc\"]\n17 [label=\"bcac\"]\n18 [label=\"bcbc\"]\n1 -> 1\n1 -> 2\n1 -> 4\n2 -> 1\n2 -\ > 2\n2 -> 5\n3 -> 6\n3 -> 7\n3 -> 8\n4 -> 9\n4 -> 10\n4 -> 1\n5 -> 11\n5 -> 12\n5 -> \ 2\n6 -> 6\n6 -> 7\n6 -> 13\n7 -> 6\n7 -> 7\n7 -> 14\n8 -> 1\n8 -> 2\n8 -> 3\n9 -> 9\n\ 9 -> 10\n9 -> 15\n10 -> 9\n10 -> 10\n10 -> 16\n11 -> 11\n11 -> 12\n11 -> 17\n12 -> 11\ \n12 -> 12\n12 -> 18\n13 -> 15\n13 -> 17\n13 -> 6\n14 -> 16\n14 -> 18\n14 -> 7\n15 ->\ 15\n15 -> 17\n15 -> 9\n16 -> 16\n16 -> 18\n16 -> 10\n17 -> 15\n17 -> 17\n17 -> 11\n1\ 8 -> 16\n18 -> 18\n18 -> 12\n}\n" gap> Splash(DotLeftCayleyDigraph(S));A visualization of the left Cayley digraph of \(S\). Result of the
Splash(DotLeftDigraph(S))call. -
We can visualize these graphs with edge coloring using the
DotEdgeColoredDigraphfunction, applied to the right or left Cayley digraph, and a list describing the edge colors. TheSplashfunction can be used to render this output.gap> S := Semigroup([Transformation([1, 1]), Transformation([2, 2]), Transformation([5, 4, 3, 2, 1])]); <transformation semigroup of degree 5 with 3 generators> gap> # We need to specify the edge colors at each vertex of the graph gap> # The following function creates a list of lists, which indicates gap> # that the outgoing edges at each vertex of the Cayley graph gap> # should be colored red, green and blue, respectively. gap> colors := List([1 .. Size(S)], x -> ["red", "green", "blue"]);; gap> DotEdgeColoredDigraph(LeftCayleyDigraph(S), colors); "//dot\ndigraph hgn{\nnode [shape=circle]\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\ \n14\n15\n16\n17\n18\n1 -> 1[color=red]\n1 -> 1[color=green]\n1 -> 6[color=blue]\n2 -\ > 2[color=red]\n2 -> 2[color=green]\n2 -> 7[color=blue]\n3 -> 4[color=red]\n3 -> 5[co\ lor=green]\n3 -> 8[color=blue]\n4 -> 4[color=red]\n4 -> 4[color=green]\n4 -> 13[color\ =blue]\n5 -> 5[color=red]\n5 -> 5[color=green]\n5 -> 14[color=blue]\n6 -> 9[color=red\ ]\n6 -> 11[color=green]\n6 -> 1[color=blue]\n7 -> 10[color=red]\n7 -> 12[color=green]\ \n7 -> 2[color=blue]\n8 -> 1[color=red]\n8 -> 2[color=green]\n8 -> 3[color=blue]\n9 -\ > 9[color=red]\n9 -> 9[color=green]\n9 -> 15[color=blue]\n10 -> 10[color=red]\n10 -> \ 10[color=green]\n10 -> 17[color=blue]\n11 -> 11[color=red]\n11 -> 11[color=green]\n11\ -> 16[color=blue]\n12 -> 12[color=red]\n12 -> 12[color=green]\n12 -> 18[color=blue]\ \n13 -> 15[color=red]\n13 -> 17[color=green]\n13 -> 4[color=blue]\n14 -> 16[color=red\ ]\n14 -> 18[color=green]\n14 -> 5[color=blue]\n15 -> 15[color=red]\n15 -> 15[color=gr\ een]\n15 -> 9[color=blue]\n16 -> 16[color=red]\n16 -> 16[color=green]\n16 -> 11[color\ =blue]\n17 -> 17[color=red]\n17 -> 17[color=green]\n17 -> 10[color=blue]\n18 -> 18[co\ lor=red]\n18 -> 18[color=green]\n18 -> 12[color=blue]\n}\n" gap> Splash(DotEdgeColoredDigraph(LeftCayleyDigraph(S), colors));S := Semigroup([Transformation([1, 1]), Transformation([2, 2]), Transformation([5, 4, 3, 2, 1])]); # We need to specify the edge colors at each vertex of the graph # The following function creates a list of lists, which indicates # that the outgoing edges at each vertex of the Cayley graph # should be colored red, green and blue, respectively. colors := List([1 .. Size(S)], x -> ["red", "green", "blue"]);; DotEdgeColoredDigraph(LeftCayleyDigraph(S), colors); Splash(DotEdgeColoredDigraph(LeftCayleyDigraph(S), colors));A colorful visualization of the left Cayley digraph of \(S\). Result of the
Splash(DotEdgeColoredDigraph(LeftCayleyDigraph(S), colors))call.
Info
See Chapter 16
of the Semigroups manual for more information about visualizing semigroups
and their Cayley graphs, as well as
Chapter 9
of the Digraphs package manual.
Properties of semigroups
Recall that an element \(x \in S\) is regular if there exists some \(y\in S\) such that \(xyx = x\) and \(yxy = y\). We say that the element \(y\) is an inverse of \(x\) in this case. A semigroup is regular if every element is regular. A semigroup is inverse if every element has precisely one inverse. A semigroup is a band if the equation \(x^2 = x\) holds for all \(x\in S\). A semigroup is commutative if the equation \(xy = yx\) holds for all \(x, y \in S\). A semigroup is simple if it does not contain a non-trivial two-sided ideal.
We can
- check if an element \(x\in S\) is regular with the
IsRegularSemigroupElementfunction; - find all inverses of an element with the
InversesOfSemigroupElementfunction; - check if a semigroup is regular with the
IsRegularSemigroupfunction; - check if a semigroup is inverse with the
IsInverseSemigroupfunction; - check if a semigroup is a band with the
IsBandfunction; - check if a semigroup is commutative with the
IsCommmutativeSemigroupfunction; - check if a semigroup is simple with the
IsSimpleSemigroupfunction.
gap> S := Semigroup([
> Transformation([3, 1, 4, 2, 5, 2, 1, 6, 1]),
> Transformation([5, 7, 8, 8, 7, 5, 9, 1, 9]),
> Transformation([7, 6, 2, 8, 4, 7, 5, 8, 3])]);
<transformation semigroup of degree 9 with 3 generators>
gap> x := Transformation([3, 1, 4, 2, 5, 2, 1, 6, 1]);;
gap> InversesOfSemigroupElement(S, x);
[ ]
gap> IsRegularSemigroupElement(S, x);
false
gap> y := Transformation([1, 9, 7, 5, 5, 1, 9, 5, 1]);;
gap> InversesOfSemigroupElement(S, y);
[ Transformation( [ 1, 5, 1, 2, 5, 1, 3, 2, 2 ] ),
Transformation( [ 1, 2, 3, 5, 5, 1, 3, 5, 2 ] ),
Transformation( [ 1, 5, 1, 1, 5, 1, 3, 1, 2 ] ) ]
gap> IsRegularSemigroupElement(S, y);
true
gap> IsRegularSemigroup(S);
false
gap> T := Semigroup([
> Transformation([1, 2, 4, 5, 6, 3, 7, 8]),
> Transformation([3, 3, 4, 5, 6, 2, 7, 8]),
> Transformation([1, 2, 5, 3, 6, 8, 4, 4])]);;
gap> IsInverseSemigroup(T);
true
gap> U := Semigroup([
> Transformation([1, 1, 1, 4, 4, 4, 7, 7, 7, 1]),
> Transformation([2, 2, 2, 5, 5, 5, 8, 8, 8, 2]),
> Transformation([3, 3, 3, 6, 6, 6, 9, 9, 9, 3]),
> Transformation([1, 1, 1, 4, 4, 4, 7, 7, 7, 4]),
> Transformation([1, 1, 1, 4, 4, 4, 7, 7, 7, 7])]);;
gap> IsBand(U);
true
gap> V := Semigroup([
> Transformation([2, 4, 5, 3, 7, 8, 6, 9, 1]),
> Transformation([3, 5, 6, 7, 8, 1, 9, 2, 4])]);;
gap> IsCommutativeSemigroup(V);
true
gap> W := Semigroup([
> Transformation([2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 2]),
> Transformation([1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 3]),
> Transformation([1, 7, 3, 9, 5, 11, 7, 1, 9, 3, 11, 5, 5]),
> Transformation([7, 7, 9, 9, 11, 11, 1, 1, 3, 3, 5, 5, 7])]);;
gap> IsSimpleSemigroup(W);
true
S := Semigroup([
Transformation([3, 1, 4, 2, 5, 2, 1, 6, 1]),
Transformation([5, 7, 8, 8, 7, 5, 9, 1, 9]),
Transformation([7, 6, 2, 8, 4, 7, 5, 8, 3])]);
x := Transformation([3, 1, 4, 2, 5, 2, 1, 6, 1]);;
InversesOfSemigroupElement(S, x);
IsRegularSemigroupElement(S, x);
y := Transformation([1, 9, 7, 5, 5, 1, 9, 5, 1]);;
InversesOfSemigroupElement(S, y);
IsRegularSemigroupElement(S, y);
IsRegularSemigroup(S);
T := Semigroup([
Transformation([1, 2, 4, 5, 6, 3, 7, 8]),
Transformation([3, 3, 4, 5, 6, 2, 7, 8]),
Transformation([1, 2, 5, 3, 6, 8, 4, 4])]);;
IsInverseSemigroup(T);
U := Semigroup([
Transformation([1, 1, 1, 4, 4, 4, 7, 7, 7, 1]),
Transformation([2, 2, 2, 5, 5, 5, 8, 8, 8, 2]),
Transformation([3, 3, 3, 6, 6, 6, 9, 9, 9, 3]),
Transformation([1, 1, 1, 4, 4, 4, 7, 7, 7, 4]),
Transformation([1, 1, 1, 4, 4, 4, 7, 7, 7, 7])]);;
IsBand(U);
V := Semigroup([
Transformation([2, 4, 5, 3, 7, 8, 6, 9, 1]),
Transformation([3, 5, 6, 7, 8, 1, 9, 2, 4])]);;
IsCommutativeSemigroup(V);
W := Semigroup([
Transformation([2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 2]),
Transformation([1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 3]),
Transformation([1, 7, 3, 9, 5, 11, 7, 1, 9, 3, 11, 5, 5]),
Transformation([7, 7, 9, 9, 11, 11, 1, 1, 3, 3, 5, 5, 7])]);;
IsSimpleSemigroup(W);
Info
See Chapter 12
of the Semigroups manual for a comprehensive list of semigroup
properties that can be checked by the Semigroups package, as well as
Section 51.4
of the GAP reference manual.
Green's relations and egg-box diagrams
Recall that the Green's \(\mathscr{R}, \mathscr{L}\) and \(\mathscr{J}\) relations are equivalence relations on a semigroup \(S\) defined by
- \(x \mathscr{R} y\) if and only if \(x S = y S\),
- \(x \mathscr{L} y\) if and only if \(S x = S y\),
- \(x \mathscr{J} y\) if and only if \(S x S = S y S\).
The Green's \(\mathscr{H}\) and \(\mathscr{D}\) relations are defined as the intersection and composition of the \(\mathscr{R}\) and \(\mathscr{L}\) relations, respectively. For a finite semigroup, the \(\mathscr{D}\) and \(\mathscr{J}\) relations coincide.
We can obtain the \(\mathscr{R}, \mathscr{L}, \mathscr{D}\) or
\(\mathscr{H}\)-equivalence class of an element of a semigroup using
the
RClass,
LClass,
DClass and
HClass functions, respectively.
gap> S := Semigroup([Transformation([1, 1]), Transformation([2, 2]), Transformation([5, 4, 3, 2, 1])]);
<transformation semigroup of degree 5 with 3 generators>
gap> RClass(S, Transformation([1, 1]));
<Green's R-class: Transformation( [ 1, 1 ] )>
gap> Elements(RClass(S, Transformation([1, 1])));
[ Transformation( [ 1, 1 ] ), Transformation( [ 2, 2 ] ),
Transformation( [ 4, 4, 3, 2, 1 ] ), Transformation( [ 5, 5, 3, 2, 1 ] ) ]
gap> Elements(LClass(S, Transformation([1, 1])));
[ Transformation( [ 1, 1 ] ), Transformation( [ 5, 4, 3, 1, 1 ] ) ]
gap> Elements(DClass(S, Transformation([1, 1])));
[ Transformation( [ 1, 1 ] ), Transformation( [ 1, 2, 3, 4, 4 ] ),
Transformation( [ 1, 2, 3, 5, 5 ] ), Transformation( [ 2, 2 ] ),
Transformation( [ 4, 4, 3, 2, 1 ] ), Transformation( [ 5, 4, 3, 1, 1 ] ),
Transformation( [ 5, 4, 3, 2, 2 ] ), Transformation( [ 5, 5, 3, 2, 1 ] ) ]
gap> Elements(HClass(S, Transformation([1, 1])));
[ Transformation( [ 1, 1 ] ) ]
S := Semigroup([Transformation([1, 1]), Transformation([2, 2]), Transformation([5, 4, 3, 2, 1])]);
RClass(S, Transformation([1, 1]));
Elements(RClass(S, Transformation([1, 1])));
Elements(LClass(S, Transformation([1, 1])));
Elements(DClass(S, Transformation([1, 1])));
Elements(HClass(S, Transformation([1, 1])));
Recall that the egg-box diagram of a semigroup is a visual representation
of its Green's relations. In GAP we can display them using the Splash and
DotString
functions:
The resulting egg-box diagram for \(\mathcal{T}_3\) can be seen on the right. The large boxes labelled 1, 2 and 3 in the diagram correspond to Green's \(\mathscr{D}\)-classes of \(\mathcal{T}_3\), the lines between them denote inclusion in the ordering on \(\mathscr{D}\)-classes induced by the Green's \(\mathscr{J}\)-relation.
The rows of the boxes representing the \(\mathscr{D}\)-classes correspond to
Green's \(\mathscr{L}\)-classes, the columns to Green's \(\mathscr{R}\)-classes.
Finally, the cells of the boxes representing the \(\mathscr{D}\)-classes
are the \(\mathscr{H}\)-classes of \(\mathcal{T}_3\). Cells shaded in gray
denote the group \(\mathscr{H}\)-classes, and they contain the
StructureDescription of these groups,
this is a consequence of the rec(maximal := true) argument.
So, by visual inspection we can deduce that \(\mathcal{T}_3\) has 3 Green's \(\mathscr{D}\)-classes, furthermore, each \(\mathscr{D}\)-class contains a group \(\mathscr{H}\)-class, and is therefore a regular \(\mathscr{D}\)-class. Hence we can conclude that \(\mathcal{T}_3\) is regular, just by visual inspection of the egg-box diagram.
The egg-box diagram of \(\mathcal{T}_3\).
Info
See Chapter 10
of the Semigroups manual for a deeper look at Green's relation related
functionality.
Isomorphisms
We can check if two semigroups \(S\) and \(T\) are isomorphic using the
IsomorphismSemigroups
function. The function will return an isomorphism, if one exists,
and return fail if the semigroups are not isomorphic.
gap> S := Semigroup([Transformation([1, 1]), Transformation([2, 2])]);
<transformation semigroup of degree 2 with 2 generators>
gap> T := Semigroup([Transformation([1, 3, 3]), Transformation([1, 2, 2])]);
<transformation semigroup of degree 3 with 2 generators>
gap> IsomorphismSemigroups(S, T); # Isomorphism found
CompositionMapping( MappingByFunction( <Rees matrix semigroup 1x2 over Group(())>,
<simple transformation semigroup of degree 3 with 2 generators>
, function( object ) ... end, function( object ) ... end ), CompositionMapping(
((), GroupHomomorphismByImages( Group( [ () ] ), Group( [ () ] ), [ ], [ ] ),
[ (), (), () ]), MappingByFunction( <simple transformation semigroup of degree 2
with 2 generators>, <Rees matrix semigroup 1x2 over Group(())>
, function( object ) ... end, function( object ) ... end ) ) )
gap> IsomorphismSemigroups(S, FullTransformationMonoid(10)); # No isomorphism
fail
Warning
If either S or T is an infinite semigroup, then
IsomorphismSemigroups may never terminate as the
isomorphism problem for infinite finitely generated semigroups is
undecidable.
Info
See Chapter 14
of the Semigroups manual for more information about
semigroup isomorphisms and homomorphisms.
Lattices of congruences
Given a semigroup \(S\) one can construct the congruence lattice
of \(S\) using the LatticeOfCongruences
function.
gap> P := PartitionMonoid(2);
<regular bipartition *-monoid of size 15, degree 2 with 3 generators>
gap> latt := LatticeOfCongruences(S);
<lattice of 11 two-sided congruences over <regular transformation semigroup
of size 71, degree 5 with 3 generators>>
gap> CongruencesOfPoset(latt);
[ <2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 0 generating pairs>,
<universal semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators>>, <2-sided semigroup congruence over
<regular bipartition *-monoid of size 15, degree 2 with 3 generators> with
1 generating pairs>, <2-sided semigroup congruence over <regular bipartition *-
monoid of size 15, degree 2 with 3 generators> with 1 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 1 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 1 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 1 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 1 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 1 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 1 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 2 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 2 generating pairs>,
<2-sided semigroup congruence over <regular bipartition *-monoid of size 15,
degree 2 with 3 generators> with 2 generating pairs> ]
Analogous functions exist for computing the left and right congruence lattices of \(S\) as well.
We can use the DotString
function to visualize a congruence lattice.
The congruence lattice of \(\mathcal{P}_2\).
Result of Splash(DotString(latt));.