17 Congruences

17.3
Congruence classes

17.3-1 IsCongruenceClass

17.3-2 IsLeftCongruenceClass

17.3-3 IsRightCongruenceClass

17.3-4 CongruenceClassOfElement

17.3-5 CongruenceClasses

17.3-6 NonTrivialEquivalenceClasses

17.3-7 NonTrivialCongruenceClasses

17.3-8 NrEquivalenceClasses

17.3-9 NrCongruenceClasses

17.3-10 EquivalenceRelationLookup

17.3-11 EquivalenceRelationCanonicalLookup

17.3-12 EquivalenceRelationCanonicalPartition

17.3-13 OnLeftCongruenceClasses

17.3-14 OnRightCongruenceClasses

17.3-1 IsCongruenceClass

17.3-2 IsLeftCongruenceClass

17.3-3 IsRightCongruenceClass

17.3-4 CongruenceClassOfElement

17.3-5 CongruenceClasses

17.3-6 NonTrivialEquivalenceClasses

17.3-7 NonTrivialCongruenceClasses

17.3-8 NrEquivalenceClasses

17.3-9 NrCongruenceClasses

17.3-10 EquivalenceRelationLookup

17.3-11 EquivalenceRelationCanonicalLookup

17.3-12 EquivalenceRelationCanonicalPartition

17.3-13 OnLeftCongruenceClasses

17.3-14 OnRightCongruenceClasses

17.4
Finding the congruences of a semigroup

17.4-1 CongruencesOfSemigroup

17.4-2 MinimalCongruencesOfSemigroup

17.4-3 PrincipalCongruencesOfSemigroup

17.4-4 IsCongruencePoset

17.4-5 LatticeOfCongruences

17.4-6 PosetOfPrincipalCongruences

17.4-7 CongruencesOfPoset

17.4-8 UnderlyingSemigroupOfCongruencePoset

17.4-9 PosetOfCongruences

17.4-10 JoinSemilatticeOfCongruences

17.4-11 MinimalCongruences

17.4-1 CongruencesOfSemigroup

17.4-2 MinimalCongruencesOfSemigroup

17.4-3 PrincipalCongruencesOfSemigroup

17.4-4 IsCongruencePoset

17.4-5 LatticeOfCongruences

17.4-6 PosetOfPrincipalCongruences

17.4-7 CongruencesOfPoset

17.4-8 UnderlyingSemigroupOfCongruencePoset

17.4-9 PosetOfCongruences

17.4-10 JoinSemilatticeOfCongruences

17.4-11 MinimalCongruences

Congruences in **Semigroups** can be described in several different ways:

Generating pairs -- the minimal congruence which contains these pairs

Rees congruences -- the congruence specified by a given ideal

Universal congruences -- the unique congruence with only one class

Linked triples -- only for simple or 0-simple semigroups (see below)

Kernel and trace -- only for inverse semigroups

The operation `SemigroupCongruence`

(17.2-1) can be used to create any of these, interpreting the arguments in a smart way. The usual way of specifying a congruence will be by giving a set of generating pairs, but a user with an ideal could instead create a Rees congruence or universal congruence.

If a congruence is specified by generating pairs on a simple, 0-simple, or inverse semigroup, then the congruence may be converted automatically to one of the last two items in the above list, to reduce the complexity of any calculations to be performed. The user need not manually specify, or even be aware of, the congruence's linked triple or kernel and trace.

We can also create left congruences and right congruences, using the `LeftSemigroupCongruence`

(17.2-2) and `RightSemigroupCongruence`

(17.2-3) functions.

Please note that congruence objects made in **GAP** before loading the **Semigroups** package may not behave correctly after **Semigroups** is loaded. If **Semigroups** is loaded at the beginning of the session, or before any congruence work is done, then the objects should behave correctly.

`‣ IsSemigroupCongruence` ( obj ) | ( property ) |

A semigroup congruence `cong`

is an equivalence relation on a semigroup `S`

which respects left and right multiplication.

That is, if \((a,b)\) is a pair in `cong`

, and \(x\) is an element of `S`

, then \((ax,bx)\) and \((xa,xb)\) are both in `cong`

.

The simplest way of creating a congruence in **Semigroups** is by a set of *generating pairs*. See `SemigroupCongruence`

(17.2-1).

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> cong := SemigroupCongruence(S, [pair1, pair2]); <semigroup congruence over <simple transformation semigroup of degree 5 with 4 generators> with linked triple (2,4,1)> gap> IsSemigroupCongruence(cong); true

`‣ IsLeftSemigroupCongruence` ( obj ) | ( property ) |

A left semigroup congruence `cong`

is an equivalence relation on a semigroup `S`

which respects left multiplication.

That is, if \((a,b)\) is a pair in `cong`

, and \(x\) is an element of `S`

, then \((xa,xb)\) is also in `cong`

.

The simplest way of creating a left congruence in **Semigroups** is by a set of *generating pairs*. See `LeftSemigroupCongruence`

(17.2-2).

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> cong := LeftSemigroupCongruence(S, [pair1, pair2]); <left semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs> gap> IsLeftSemigroupCongruence(cong); true

`‣ IsRightSemigroupCongruence` ( obj ) | ( property ) |

A right semigroup congruence `cong`

is an equivalence relation on a semigroup `S`

which respects right multiplication.

That is, if \((a,b)\) is a pair in `cong`

, and \(x\) is an element of `S`

, then \((ax,bx)\) is also in `cong`

.

The simplest way of creating a right congruence in **Semigroups** is by a set of *generating pairs*. See `RightSemigroupCongruence`

(17.2-3).

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> RightSemigroupCongruence(S, [pair1, pair2]); <right semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs> gap> IsRightSemigroupCongruence(cong); true

`‣ SemigroupCongruence` ( S, pairs ) | ( function ) |

Returns: A semigroup congruence.

This function returns a semigroup congruence over the semigroup `S`.

If `pairs` is a list of lists of size 2 with elements from `S`, then this function will return the semigroup congruence defined by these generating pairs. The individual pairs may instead be given as separate arguments.

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> SemigroupCongruence(S, [pair1, pair2]); <semigroup congruence over <simple transformation semigroup of degree 5 with 4 generators> with linked triple (2,4,1)> gap> SemigroupCongruence(S, pair1, pair2); <semigroup congruence over <simple transformation semigroup of degree 5 with 4 generators> with linked triple (2,4,1)>

`‣ LeftSemigroupCongruence` ( S, pairs ) | ( function ) |

Returns: A left semigroup congruence.

This function returns a left semigroup congruence over the semigroup `S`.

If `pairs` is a list of lists of size 2 with elements from `S`, then this function will return the least left semigroup congruence on `S` which contains these generating pairs. The individual pairs may instead be given as separate arguments.

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> LeftSemigroupCongruence(S, [pair1, pair2]); <left semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs> gap> LeftSemigroupCongruence(S, pair1, pair2); <left semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs>

`‣ RightSemigroupCongruence` ( S, pairs ) | ( function ) |

Returns: A right semigroup congruence.

This function returns a right semigroup congruence over the semigroup `S`.

If `pairs` is a list of lists of size 2 with elements from `S`, then this function will return the least right semigroup congruence on `S` which contains these generating pairs. The individual pairs may instead be given as separate arguments.

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> RightSemigroupCongruence(S, [pair1, pair2]); <right semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs> gap> RightSemigroupCongruence(S, pair1, pair2); <right semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs>

`‣ GeneratingPairsOfSemigroupCongruence` ( cong ) | ( attribute ) |

`‣ GeneratingPairsOfLeftSemigroupCongruence` ( cong ) | ( attribute ) |

`‣ GeneratingPairsOfRightSemigroupCongruence` ( cong ) | ( attribute ) |

Returns: A list of lists.

If `cong` is a semigroup congruence, then `GeneratingPairsOfSemigroupCongruence`

returns a list of pairs of elements from `Range(`

that `cong`)*generates* the congruence; i.e. `cong` is the least congruence on the semigroup which contains all the pairs in the list.

If `cong` is a left or right semigroup congruence, then `GeneratingPairsOfLeft/RightSemigroupCongruence`

will instead give a list of pairs which generate it as a left or right congruence. Note that, although a congruence is also a left and right congruence, its generating pairs as a left or right congruence may differ from its generating pairs as a two-sided congruence.

A congruence can be defined using a set of generating pairs: see `SemigroupCongruence`

(17.2-1), `LeftSemigroupCongruence`

(17.2-2), and `RightSemigroupCongruence`

(17.2-3).

gap> S := Semigroup([Transformation([3, 3, 2, 3]), > Transformation([3, 4, 4, 1])]);; gap> pairs := > [[Transformation([1, 1, 1, 1]), Transformation([2, 2, 2, 3])], > [Transformation([2, 2, 3, 2]), Transformation([3, 3, 2, 3])]];; gap> cong := SemigroupCongruence(S, pairs);; gap> GeneratingPairsOfSemigroupCongruence(cong); [ [ Transformation( [ 1, 1, 1, 1 ] ), Transformation( [ 2, 2, 2, 3 ] ) ], [ Transformation( [ 2, 2, 3, 2 ] ), Transformation( [ 3, 3, 2, 3 ] ) ] ]

`‣ IsCongruenceClass` ( obj ) | ( category ) |

This category contains any object which is an equivalence class of a semigroup congruence (see `IsSemigroupCongruence`

(17.1-1)). An object will only be in this category if the relation is known to be a semigroup congruence when the congruence class is created.

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> cong := SemigroupCongruence(S, [Transformation([1, 2, 1]), > Transformation([2, 1, 2])]);; gap> class := EquivalenceClassOfElement(cong, > Transformation([3, 1, 1])); <congruence class of Transformation( [ 3, 1, 1 ] )> gap> IsCongruenceClass(class); true

`‣ IsLeftCongruenceClass` ( obj ) | ( category ) |

This category contains any object which is an equivalence class of a left semigroup congruence (see `IsLeftSemigroupCongruence`

(17.1-2)). An object will only be in this category if the relation is known to be a left semigroup congruence when the class is created.

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> pairs := [Transformation([1, 2, 1]), > Transformation([2, 1, 2])];; gap> cong := LeftSemigroupCongruence(S, pairs);; gap> class := EquivalenceClassOfElement(cong, > Transformation([3, 1, 1])); <left congruence class of Transformation( [ 3, 1, 1 ] )> gap> IsLeftCongruenceClass(class); true

`‣ IsRightCongruenceClass` ( obj ) | ( category ) |

This category contains any object which is an equivalence class of a right semigroup congruence (see `IsRightSemigroupCongruence`

(17.1-3)). An object will only be in this category if the relation is known to be a right semigroup congruence when the class is created.

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> pairs := [Transformation([1, 2, 1]), > Transformation([2, 1, 2])];; gap> cong := RightSemigroupCongruence(S, pairs);; gap> class := EquivalenceClassOfElement(cong, > Transformation([3, 1, 1])); <right congruence class of Transformation( [ 3, 1, 1 ] )> gap> IsRightCongruenceClass(class); true

`‣ CongruenceClassOfElement` ( cong, elm ) | ( operation ) |

`‣ LeftCongruenceClassOfElement` ( cong, elm ) | ( operation ) |

`‣ RightCongruenceClassOfElement` ( cong, elm ) | ( operation ) |

Returns: An equivalence class.

These operations act as a synonym of `EquivalenceClassOfElement`

in the case that the argument `cong` is a congruence, left congruence, or right congruence (respectively) of a semigroup.

See `IsLeftSemigroupCongruence`

(17.1-2), `IsRightSemigroupCongruence`

(17.1-3), and `IsSemigroupCongruence`

(17.1-1).

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong := CongruencesOfSemigroup(S)[3];; gap> elm := ReesZeroMatrixSemigroupElement(S, 1, (1, 3, 2), 1);; gap> CongruenceClassOfElement(cong, elm); <congruence class of (1,(1,3,2),1)>

`‣ CongruenceClasses` ( cong ) | ( operation ) |

`‣ LeftCongruenceClasses` ( cong ) | ( operation ) |

`‣ RightCongruenceClasses` ( cong ) | ( operation ) |

Returns: A list of equivalence classes.

These operations act as a synonym of `EquivalenceClasses`

in the case that the argument `cong` is a congruence, left congruence, or right congruence (respectively) of a semigroup.

See `IsLeftSemigroupCongruence`

(17.1-2), `IsRightSemigroupCongruence`

(17.1-3), and `IsSemigroupCongruence`

(17.1-1).

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> pair := [Transformation([1, 2, 1]), Transformation([2, 1, 2])];; gap> cong := SemigroupCongruence(S, pair);; gap> classes := CongruenceClasses(cong);; gap> Set(classes); [ <congruence class of Transformation( [ 3, 3, 3 ] )>, <congruence class of Transformation( [ 2, 1, 2 ] )>, <congruence class of Transformation( [ 1, 2, 2 ] )>, <congruence class of IdentityTransformation>, <congruence class of Transformation( [ 3, 1, 3 ] )>, <congruence class of Transformation( [ 3, 1, 1 ] )> ]

`‣ NonTrivialEquivalenceClasses` ( eq ) | ( attribute ) |

Returns: A list of equivalence classes.

If `eq` is an equivalence relation, then this attribute returns a list of all equivalence classes of `eq` which contain more than one element.

gap> S := Monoid([Transformation([1, 2, 2]), > Transformation([3, 1, 3])]);; gap> cong := SemigroupCongruence(S, [Transformation([1, 2, 1]), > Transformation([2, 1, 2])]);; gap> classes := NonTrivialEquivalenceClasses(cong);; gap> Set(classes); [ <congruence class of Transformation( [ 3, 3, 3 ] )>, <congruence class of Transformation( [ 2, 1, 2 ] )>, <congruence class of Transformation( [ 1, 2, 2 ] )>, <congruence class of Transformation( [ 3, 1, 3 ] )>, <congruence class of Transformation( [ 3, 1, 1 ] )> ]

`‣ NonTrivialCongruenceClasses` ( cong ) | ( operation ) |

`‣ NonTrivialLeftCongruenceClasses` ( cong ) | ( operation ) |

`‣ NonTrivialRightCongruenceClasses` ( cong ) | ( operation ) |

Returns: A list of equivalence classes.

These operations act as a synonym of `NonTrivialEquivalenceClasses`

in the case that the argument `cong` is a congruence, left congruence, or right congruence (respectively) of a semigroup.

See `IsLeftSemigroupCongruence`

(17.1-2), `IsRightSemigroupCongruence`

(17.1-3), and `IsSemigroupCongruence`

(17.1-1).

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> cong := RightSemigroupCongruence(S, [Transformation([1, 2, 1]), > Transformation([2, 1, 2])]);; gap> classes := NonTrivialRightCongruenceClasses(cong);; gap> Set(classes); [ <right congruence class of Transformation( [ 2, 1, 2 ] )>, <right congruence class of Transformation( [ 3, 1, 3 ] )> ]

`‣ NrEquivalenceClasses` ( eq ) | ( attribute ) |

Returns: A positive integer.

If `eq` is an equivalence relation, then this attribute describes the number of equivalence classes it has.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong := CongruencesOfSemigroup(S)[3];; gap> NrEquivalenceClasses(cong); 9

`‣ NrCongruenceClasses` ( cong ) | ( operation ) |

`‣ NrLeftCongruenceClasses` ( cong ) | ( operation ) |

`‣ NrRightCongruenceClasses` ( cong ) | ( operation ) |

Returns: A list of equivalence classes.

These operations act as a synonym of `NrEquivalenceClasses`

in the case that the argument `cong` is a congruence, left congruence, or right congruence (respectively) of a semigroup.

`IsLeftSemigroupCongruence`

(17.1-2), `IsRightSemigroupCongruence`

(17.1-3), and `IsSemigroupCongruence`

(17.1-1).

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> pair := [Transformation([1, 2, 1]), Transformation([2, 1, 2])];; gap> cong := SemigroupCongruence(S, pair);; gap> NrCongruenceClasses(cong); 6 gap> cong := RightSemigroupCongruence(S, pair);; gap> NrRightCongruenceClasses(cong); 10

`‣ EquivalenceRelationLookup` ( cong ) | ( attribute ) |

Returns: A list.

This attribute describes the (left, right or two-sided) semigroup congruence `cong` as a list of positive integers with length the size of the finite semigroup over which `cong` is defined.

Each position in the list corresponds to an element of the semigroup (in a consistent canonical order) and the integer at that position is a unique identifier for that element's congruence class under `cong`. Two elements of the semigroup on which the congruence is defined are related in the congruence if and only if they have the same number at their respective positions in the lookup.

Note that the order in which numbers appear in the list is non-deterministic, and two congruence objects which describe the same equivalence relation might therefore have different lookups. Note also that the maximum value of the list may not be the number of classes of `cong`, and that any integer might not be included. However, see `EquivalenceRelationCanonicalLookup`

(17.3-11).

See also `EquivalenceRelationPartition`

(Reference: EquivalenceRelationPartition).

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> cong := SemigroupCongruence(S, > [Transformation([1, 2, 1]), Transformation([2, 1, 2])]);; gap> lookup := EquivalenceRelationLookup(cong);; gap> lookup[3] = lookup[8]; true gap> lookup[2] = lookup[9]; false

`‣ EquivalenceRelationCanonicalLookup` ( cong ) | ( attribute ) |

Returns: A list.

This attribute describes the semigroup congruence `cong` as a list of positive integers with length the size of the finite semigroup over which `cong` is defined.

Each position in the list corresponds to an element of the semigroup (in a consistent canonical order) and the integer at that position is a unique identifier for that element's congruence class under `cong`. The value of `EquivalenceRelationCanonicalLookup`

has the property that the first appearance of the value `i`

is strictly later than the first appearance of `i-1`

, and that all entries in the list will be from the range `[1 .. NrEquivalenceClasses(`

. As such, two congruences on a given semigroup are equal if and only if their canonical lookups are equal.`cong`)]

Two elements of the semigroup on which the congruence is defined are related in the congruence if and only if they have the same number at their respective positions in the lookup.

See also `EquivalenceRelationLookup`

(17.3-10) and `EquivalenceRelationPartition`

(Reference: EquivalenceRelationPartition).

gap> S := Monoid([ > Transformation([1, 2, 2]), Transformation([3, 1, 3])]);; gap> cong := SemigroupCongruence(S, > [Transformation([1, 2, 1]), Transformation([2, 1, 2])]);; gap> EquivalenceRelationCanonicalLookup(cong); [ 1, 2, 3, 4, 5, 6, 2, 3, 6, 4, 5, 6 ]

`‣ EquivalenceRelationCanonicalPartition` ( cong ) | ( attribute ) |

Returns: A list of lists.

This attribute returns a list of lists of elements of the underlying set of the semigroup congruence `cong`. These lists are precisely the nontrivial equivalence classes of `cong`. The order in which the classes appear is deterministic, and the order of the elements inside each class is also deterministic. Hence, two congruence objects have the same `EquivalenceRelationCanonicalPartition`

if and only if they describe the same relation.

See also `EquivalenceRelationPartition`

(Reference: EquivalenceRelationPartition), a similar attribute which does not have canonical ordering, but which is likely to be faster.

gap> S := Semigroup(Transformation([1, 4, 3, 3]), > Transformation([2, 4, 3, 3]));; gap> cong := SemigroupCongruence(S, [Transformation([1, 4, 3, 3]), > Transformation([1, 3, 3, 3])]);; gap> EquivalenceRelationCanonicalPartition(cong); [ [ Transformation( [ 1, 3, 3, 3 ] ), Transformation( [ 1, 4, 3, 3 ] ) ], [ Transformation( [ 3, 3, 3, 3 ] ), Transformation( [ 4, 3, 3, 3 ] ) ] ]

`‣ OnLeftCongruenceClasses` ( class, elm ) | ( operation ) |

Returns: A left congruence class.

If `class` is an equivalence class of the left semigroup congruence `cong`

on the semigroup `S`

, and `elm` is an element of `S`

, then this operation returns the equivalence class of `cong`

containing the element

, where `elm` * x`x`

is any element of `class`. The result is well-defined by the definition of a left congruence.

See `IsLeftSemigroupCongruence`

(17.1-2) and `IsLeftCongruenceClass`

(17.3-2).

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> cong := LeftSemigroupCongruence(S, [pair1, pair2]); <left semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs> gap> x := Transformation([3, 4, 3, 4, 3]);; gap> class := LeftCongruenceClassOfElement(cong, x); <left congruence class of Transformation( [ 3, 4, 3, 4, 3 ] )> gap> elm := Transformation([1, 2, 2, 1, 2]);; gap> OnLeftCongruenceClasses(class, elm); <left congruence class of Transformation( [ 3, 4, 4, 3, 4 ] )>

`‣ OnRightCongruenceClasses` ( class, elm ) | ( operation ) |

Returns: A right congruence class.

If `class` is an equivalence class of the right semigroup congruence `cong`

on the semigroup `S`

, and `elm` is an element of `S`

, then this operation returns the equivalence class of `cong`

containing the element `x * `

, where `elm``x`

is any element of `class`. The result is well-defined by the definition of a right congruence.

See `IsRightSemigroupCongruence`

(17.1-3) and `IsRightCongruenceClass`

(17.3-3).

gap> S := Semigroup([ > Transformation([2, 1, 1, 2, 1]), > Transformation([3, 4, 3, 4, 4]), > Transformation([3, 4, 3, 4, 3]), > Transformation([4, 3, 3, 4, 4])]);; gap> pair1 := [Transformation([3, 4, 3, 4, 3]), > Transformation([1, 2, 1, 2, 1])];; gap> pair2 := [Transformation([4, 3, 4, 3, 4]), > Transformation([3, 4, 3, 4, 3])];; gap> cong := RightSemigroupCongruence(S, [pair1, pair2]); <right semigroup congruence over <transformation semigroup of degree 5 with 4 generators> with 2 generating pairs> gap> x := Transformation([3, 4, 3, 4, 3]);; gap> class := RightCongruenceClassOfElement(cong, x); <right congruence class of Transformation( [ 3, 4, 3, 4, 3 ] )> gap> elm := Transformation([1, 2, 2, 1, 2]);; gap> OnRightCongruenceClasses(class, elm); <right congruence class of Transformation( [ 2, 1, 2, 1, 2 ] )>

`‣ CongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ LeftCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ RightCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ CongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

`‣ LeftCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

`‣ RightCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

Returns: The congruences of a semigroup.

This attribute gives a list of the left, right, or 2-sided congruences of the semigroup `S`.

If `restriction` is specified and is a collection of elements from `S`, then the result will only include congruences generated by pairs of elements from `restriction`. Otherwise, all congruences will be calculated.

See also `LatticeOfCongruences`

(17.4-5).

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> congs := CongruencesOfSemigroup(S);; gap> Length(congs); 4 gap> Set(congs, NrCongruenceClasses); [ 1, 5, 9, 25 ] gap> pos := Position(congs, UniversalSemigroupCongruence(S));; gap> congs[pos]; <universal semigroup congruence over <Rees 0-matrix semigroup 2x2 over Sym( [ 1 .. 3 ] )>>

`‣ MinimalCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ MinimalLeftCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ MinimalRightCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ MinimalCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

`‣ MinimalLeftCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

`‣ MinimalRightCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

Returns: The congruences of a semigroup.

If `S` is a semigroup, then the attribute `MinimalCongruencesOfSemigroup`

gives a list of all the congruences on `S` which are *minimal*. A congruence is minimal iff it is non-trivial and contains no other congruences as subrelations (apart from the trivial congruence).

`MinimalLeftCongruencesOfSemigroup`

and `MinimalRightCongruencesOfSemigroup`

do the same thing, but for left congruences and right congruences respectively. Note that any congruence is also a left congruence, but that a minimal congruence may not be a minimal left congruence.

If `restriction` is specified and is a collection of elements from `S`, then the result will only include congruences generated by pairs of elements from `restriction`. Otherwise, all congruences will be calculated.

See also `CongruencesOfSemigroup`

(17.4-1) and `PrincipalCongruencesOfSemigroup`

(17.4-3).

gap> S := Semigroup(Transformation([1, 3, 2]), > Transformation([3, 1, 3]));; gap> min := MinimalCongruencesOfSemigroup(S); [ <semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs> ] gap> minl := MinimalLeftCongruencesOfSemigroup(S); [ <left semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs>, <left semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs>, <left semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs> ]

`‣ PrincipalCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ PrincipalLeftCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ PrincipalRightCongruencesOfSemigroup` ( S ) | ( attribute ) |

`‣ PrincipalCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

`‣ PrincipalLeftCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

`‣ PrincipalRightCongruencesOfSemigroup` ( S, restriction ) | ( operation ) |

Returns: A list.

If `S` is a semigroup, then the attribute `PrincipalCongruencesOfSemigroup`

gives a list of all the congruences on `S` which are *principal*. A congruence is principal if and only if it is non-trivial and can be defined by a single generating pair.

`PrincipalLeftCongruencesOfSemigroup`

and `PrincipalRightCongruencesOfSemigroup`

do the same thing, but for left congruences and right congruences respectively. Note that any congruence is a left congruence and a right congruence, but that a principal congruence may not be a principal left congruence or a principal right congruence.

If `restriction` is specified and is a collection of elements from `S`, then the result will only include congruences generated by pairs of elements from `restriction`. Otherwise, all congruences will be calculated.

See also `CongruencesOfSemigroup`

(17.4-1) and `MinimalCongruencesOfSemigroup`

(17.4-2).

gap> S := Semigroup(Transformation([1, 3, 2]), > Transformation([3, 1, 3]));; gap> congs := PrincipalCongruencesOfSemigroup(S); [ <semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs>, <semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs>, <semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs>, <semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs>, <semigroup congruence over <transformation semigroup of size 13, degree 3 with 2 generators> with 1 generating pairs> ]

`‣ IsCongruencePoset` ( poset ) | ( category ) |

Returns: `true`

or `false`

.

This category contains all congruence posets. A *congruence poset* is a partially ordered set of congruences over a specific semigroup, where the ordering is defined by containment according to `IsSubrelation`

(17.5-1): given two congruences `cong1`

and `cong2`

, we say that `cong1`

< `cong2`

if and only if `cong1`

is a subrelation (a refinement) of `cong2`

. The congruences in a congruence poset can be left, right, or two-sided.

A congruence poset is a digraph (see `IsDigraph`

(Digraphs: IsDigraph)) with a vertex for each congruence, and an edge from vertex `i`

to vertex `j`

if and only if the congruence numbered `i`

is a subrelation of the congruence numbered `j`

. The list of congruences can be obtained using `CongruencesOfPoset`

(17.4-7).

Congruence posets can be created using `PosetOfCongruences`

(17.4-9), `JoinSemilatticeOfCongruences`

(17.4-10), and `LatticeOfCongruences`

(17.4-5).

gap> S := SymmetricInverseMonoid(2);; gap> poset := LatticeOfCongruences(S); <poset of 4 congruences over <symmetric inverse monoid of degree 2>> gap> IsCongruencePoset(poset); true gap> IsDigraph(poset); true gap> OutNeighbours(poset); [ [ 1 .. 4 ], [ 2, 3, 4 ], [ 3 ], [ 3, 4 ] ] gap> T := FullTransformationMonoid(3);; gap> congs := PrincipalCongruencesOfSemigroup(T);; gap> poset := JoinSemilatticeOfCongruences(congs, > JoinSemigroupCongruences); <poset of 6 congruences over <full transformation monoid of degree 3>> gap> IsCongruencePoset(poset); true gap> Size(poset); 6

`‣ LatticeOfCongruences` ( S ) | ( attribute ) |

`‣ LatticeOfLeftCongruences` ( S ) | ( attribute ) |

`‣ LatticeOfRightCongruences` ( S ) | ( attribute ) |

`‣ LatticeOfCongruences` ( S, restriction ) | ( operation ) |

`‣ LatticeOfLeftCongruences` ( S, restriction ) | ( operation ) |

`‣ LatticeOfRightCongruences` ( S, restriction ) | ( operation ) |

Returns: A list of lists.

If `S` is a semigroup, then `LatticeOfCongruences`

gives a congruence poset object containing all the congruences of `S` and information about how they are contained in each other. See `IsCongruencePoset`

(17.4-4) for more details.

`LatticeOfLeftCongruences`

and `LatticeOfRightCongruences`

do the same thing for left and right congruences respectively.

`restriction` is specified and is a collection of elements from `S`, then the result will only include congruences generated by pairs of elements from `restriction`. Otherwise, all congruences will be calculated.

See `CongruencesOfSemigroup`

(17.4-1).

gap> S := OrderEndomorphisms(2);; gap> LatticeOfCongruences(S); <poset of 3 congruences over <regular transformation monoid of size 3, degree 2 with 2 generators>> gap> LatticeOfLeftCongruences(S); <poset of 3 congruences over <regular transformation monoid of size 3, degree 2 with 2 generators>> gap> LatticeOfRightCongruences(S); <poset of 5 congruences over <regular transformation monoid of size 3, degree 2 with 2 generators>> gap> OutNeighbours(LatticeOfRightCongruences(S)); [ [ 1 .. 5 ], [ 2, 5 ], [ 3, 5 ], [ 4, 5 ], [ 5 ] ] gap> S := FullTransformationMonoid(4);; gap> restriction := [Transformation([1, 1, 1, 1]), > Transformation([1, 1, 1, 2]), > Transformation([1, 1, 1, 3])];; gap> latt := LatticeOfCongruences(S, restriction); <poset of 2 congruences over <full transformation monoid of degree 4>>

`‣ PosetOfPrincipalCongruences` ( S ) | ( attribute ) |

`‣ PosetOfPrincipalLeftCongruences` ( S ) | ( attribute ) |

`‣ PosetOfPrincipalRightCongruences` ( S ) | ( attribute ) |

`‣ PosetOfPrincipalCongruences` ( S, restriction ) | ( operation ) |

`‣ PosetOfPrincipalLeftCongruences` ( S, restriction ) | ( operation ) |

`‣ PosetOfPrincipalRightCongruences` ( S, restriction ) | ( operation ) |

Returns: A congruence poset.

If `S` is a semigroup, then `PosetOfPrincipalCongruences`

returns a congruence poset object which contains all the principal congruences of `S`, ordered by containment according to `IsSubrelation`

(17.5-1). A congruence is *principal* if it can be defined by a single generating pair. `PosetOfPrincipalLeftCongruences`

and `PosetOfPrincipalRightCongruences`

do the same thing for left and right congruences respectively.

If `restriction` is specified and is a collection of elements from `S`, then the result will only include principal congruences generated by pairs of elements from `restriction`. Otherwise, all principal congruences will be calculated.

See also `LatticeOfCongruences`

(17.4-5) and `PrincipalCongruencesOfSemigroup`

(17.4-3).

gap> S := Semigroup([Transformation([1, 3, 1]), > Transformation([2, 3, 3])]);; gap> PosetOfPrincipalLeftCongruences(S); <poset of 12 congruences over <transformation semigroup of size 11, degree 3 with 2 generators>> gap> PosetOfPrincipalCongruences(S); <poset of 3 congruences over <transformation semigroup of size 11, degree 3 with 2 generators>> gap> restriction := [Transformation([3, 2, 3]), > Transformation([3, 1, 3]), > Transformation([2, 2, 2])];; gap> poset := PosetOfPrincipalRightCongruences(S, restriction); <poset of 3 congruences over <transformation semigroup of size 11, degree 3 with 2 generators>>

`‣ CongruencesOfPoset` ( poset ) | ( attribute ) |

Returns: A list.

If `poset` is a congruence poset object, then this attribute returns a list of all the congruence objects in the poset (these may be left, right, or two-sided). The order of this list corresponds to the order of the entries in the poset.

See also `LatticeOfCongruences`

(17.4-5) and `CongruencesOfSemigroup`

(17.4-1).

gap> S := OrderEndomorphisms(2);; gap> latt := LatticeOfRightCongruences(S); <poset of 5 congruences over <regular transformation monoid of size 3, degree 2 with 2 generators>> gap> CongruencesOfPoset(latt); [ <right semigroup congruence over <regular transformation monoid of size 3, degree 2 with 2 generators> with 0 generating pairs>, <right semigroup congruence over <regular transformation monoid of size 3, degree 2 with 2 generators> with 1 generating pairs>, <right semigroup congruence over <regular transformation monoid of size 3, degree 2 with 2 generators> with 1 generating pairs>, <right semigroup congruence over <regular transformation monoid of size 3, degree 2 with 2 generators> with 1 generating pairs>, <right semigroup congruence over <regular transformation monoid of size 3, degree 2 with 2 generators> with 2 generating pairs> ]

`‣ UnderlyingSemigroupOfCongruencePoset` ( poset ) | ( attribute ) |

Returns: A semigroup.

If `poset` is a congruence poset object, then this attribute returns the semigroup on which all its congruences are defined.

gap> S := OrderEndomorphisms(2); <regular transformation monoid of degree 2 with 2 generators> gap> latt := LatticeOfRightCongruences(S); <poset of 5 congruences over <regular transformation monoid of size 3, degree 2 with 2 generators>> gap> UnderlyingSemigroupOfCongruencePoset(latt) = S; true

`‣ PosetOfCongruences` ( coll ) | ( operation ) |

Returns: A congruence poset.

If `coll` is a list or collection of semigroup congruences (which may be left, right, or two-sided) then this operation returns the congruence poset formed by these congruences partially ordered by containment.

This operation does not create any new congruences or take any joins. However, see `JoinSemilatticeOfCongruences`

(17.4-10). See also `IsCongruencePoset`

(17.4-4) and `LatticeOfCongruences`

(17.4-5).

gap> S := OrderEndomorphisms(2);; gap> pair1 := [Transformation([1, 1]), IdentityTransformation];; gap> pair2 := [IdentityTransformation, Transformation([2, 2])];; gap> coll := [RightSemigroupCongruence(S, pair1), > RightSemigroupCongruence(S, pair2), > RightSemigroupCongruence(S, [])];; gap> poset := PosetOfCongruences(coll); <poset of 3 congruences over <regular transformation monoid of degree 2 with 2 generators>> gap> OutNeighbours(poset); [ [ 1 ], [ 2 ], [ 1, 2, 3 ] ]

`‣ JoinSemilatticeOfCongruences` ( coll, join_func ) | ( operation ) |

`‣ JoinSemilatticeOfCongruences` ( poset, join_func ) | ( operation ) |

Returns: A congruence poset.

If `coll` is a list or collection of semigroup congruences (which may be left, right, or two-sided) and `join_func` is a function for taking the join of two of the congruences (such as `JoinSemigroupCongruences`

(17.5-4)) then this operation returns the congruence poset formed by these congruences partially ordered by containment, along with all their joins.

Alternatively, a congruence poset `poset` can be specified; in this case, the congruences contained in `poset` will be used in place of `coll`, and information already known about their containments will be used.

See also `IsCongruencePoset`

(17.4-4) and `PosetOfCongruences`

(17.4-9).

gap> S := SymmetricInverseMonoid(2);; gap> pair1 := [PartialPerm([1], [1]), PartialPerm([2], [1])];; gap> pair2 := [PartialPerm([1], [1]), PartialPerm([1, 2], [1, 2])];; gap> pair3 := [PartialPerm([1, 2], [1, 2]), > PartialPerm([1, 2], [2, 1])];; gap> coll := [RightSemigroupCongruence(S, pair1), > RightSemigroupCongruence(S, pair2), > RightSemigroupCongruence(S, pair3)];; gap> JoinSemilatticeOfCongruences(coll, JoinRightSemigroupCongruences); <poset of 4 congruences over <symmetric inverse monoid of degree 2>>

`‣ MinimalCongruences` ( coll ) | ( attribute ) |

`‣ MinimalCongruences` ( poset ) | ( attribute ) |

Returns: A list.

If `coll` is a list or collection of semigroup congruences (which may be left, right, or two-sided) then this attribute returns a list of all the congruences from `coll` which do not contain any of the others as subrelations.

Alternatively, a congruence poset `poset` can be specified; in this case, the congruences contained in `poset` will be used in place of `coll`, and information already known about their containments will be used.

This function should not be confused with `MinimalCongruencesOfSemigroup`

(17.4-2). See also `IsCongruencePoset`

(17.4-4) and `PosetOfCongruences`

(17.4-9).

gap> S := SymmetricInverseMonoid(2);; gap> pair1 := [PartialPerm([1], [1]), PartialPerm([2], [1])];; gap> pair2 := [PartialPerm([1], [1]), PartialPerm([1, 2], [1, 2])];; gap> pair3 := [PartialPerm([1, 2], [1, 2]), > PartialPerm([1, 2], [2, 1])];; gap> coll := [RightSemigroupCongruence(S, pair1), > RightSemigroupCongruence(S, pair2), > RightSemigroupCongruence(S, pair3)];; gap> MinimalCongruences(coll); [ <right semigroup congruence over <symmetric inverse monoid of degree\ 2> with 1 generating pairs>, <right semigroup congruence over <symmetric inverse monoid of degree\ 2> with 1 generating pairs> ] gap> poset := LatticeOfCongruences(S); <poset of 4 congruences over <symmetric inverse monoid of degree 2>> gap> MinimalCongruences(poset); [ <semigroup congruence over <symmetric inverse monoid of degree 2> wi\ th 0 generating pairs> ]

`‣ IsSubrelation` ( cong1, cong2 ) | ( operation ) |

Returns: True or false.

If `cong1` and `cong2` are congruences over the same semigroup, then this operation returns whether `cong2` is a refinement of `cong1`, i.e. whether every pair in `cong2` is contained in `cong1`.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong1 := SemigroupCongruence(S, [RMSElement(S, 1, (1, 2, 3), 1), > RMSElement(S, 1, (), 1)]);; gap> cong2 := SemigroupCongruence(S, []);; gap> IsSubrelation(cong1, cong2); true gap> IsSubrelation(cong2, cong1); false

`‣ IsSuperrelation` ( cong1, cong2 ) | ( operation ) |

Returns: True or false.

If `cong1` and `cong2` are congruences over the same semigroup, then this operation returns whether `cong1` is a refinement of `cong2`, i.e. whether every pair in `cong1` is contained in `cong2`.

See `IsSubrelation`

(17.5-1).

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong1 := SemigroupCongruence(S, [RMSElement(S, 1, (1, 2, 3), 1), > RMSElement(S, 1, (), 1)]);; gap> cong2 := SemigroupCongruence(S, []);; gap> IsSuperrelation(cong1, cong2); false gap> IsSuperrelation(cong2, cong1); true

`‣ MeetSemigroupCongruences` ( c1, c2 ) | ( operation ) |

Returns: A semigroup congruence.

This operation returns the *meet* of the two semigroup congruences `c1` and `c2` -- that is, the largest semigroup congruence contained in both `c1` and `c2`.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong1 := SemigroupCongruence(S, [RMSElement(S, 1, (1, 2, 3), 1), > RMSElement(S, 1, (), 1)]);; gap> cong2 := SemigroupCongruence(S, []);; gap> MeetSemigroupCongruences(cong1, cong2); <semigroup congruence over <Rees 0-matrix semigroup 2x2 over Sym( [ 1 .. 3 ] )> with linked triple (1,2,2)>

`‣ JoinSemigroupCongruences` ( c1, c2 ) | ( operation ) |

`‣ JoinLeftSemigroupCongruences` ( c1, c2 ) | ( operation ) |

`‣ JoinRightSemigroupCongruences` ( c1, c2 ) | ( operation ) |

Returns: A semigroup congruence.

This operation returns the *join* of the two semigroup congruences `c1` and `c2` -- that is, the smallest semigroup congruence containing all the relations in both `c1` and `c2`.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong1 := SemigroupCongruence(S, [RMSElement(S, 1, (1, 2, 3), 1), > RMSElement(S, 1, (), 1)]);; gap> cong2 := SemigroupCongruence(S, []);; gap> JoinSemigroupCongruences(cong1, cong2); <semigroup congruence over <Rees 0-matrix semigroup 2x2 over Sym( [ 1 .. 3 ] )> with linked triple (3,2,2)>

This section describes the implementation of congruences of simple and 0-simple semigroups in the **Semigroups** package, and the functions associated with them. This code and this part of the manual were written by Michael Torpey. Most of the theorems used in this chapter are from Section 3.5 of [How95].

By the Rees Theorem, any 0-simple semigroup \(S\) is isomorphic to a *Rees 0-matrix semigroup* (see Reference: Rees Matrix Semigroups) over a group, with a regular sandwich matrix. That is,

\[S \cong \mathcal{M} ^ 0[G; I, \Lambda; P], \]

where \(G\) is a group, \(\Lambda\) and \(I\) are non-empty sets, and \(P\) is regular in the sense that it has no rows or columns consisting solely of zeroes.

The congruences of a Rees 0-matrix semigroup are in 1-1 correspondence with the *linked triple*, which is a triple of the form `[N, S, T]`

where:

`N`

is a normal subgroup of the underlying group`G`

,`S`

is an equivalence relation on the columns of`P`

,`T`

is an equivalence relation on the rows of`P`

,

satisfying the following conditions:

a pair of

`S`

-related columns must contain zeroes in precisely the same rows,a pair of

`T`

-related rows must contain zeroes in precisely the same columns,if

`i`

and`j`

are`S`

-related,`k`

and`l`

are`T`

-related and the matrix entries \(p_{k, i}, p_{k, j}, p_{l, i}, p_{l, j} \neq 0\), then \(q_{k, l, i, j} \in N\), where\[q_{k, l, i, j} = p_{k, i} p_{l, i} ^ {-1} p_{l, j} p_{k, j} ^ {-1}.\]

By Theorem 3.5.9 in [How95], for any finite 0-simple Rees 0-matrix semigroup, there is a bijection between its non-universal congruences and its linked triples. In this way, we can internally represent any congruence of such a semigroup by storing its associated linked triple instead of a set of generating pairs, and thus perform many calculations on it more efficiently.

If a congruence is defined by a linked triple `(N, S, T)`

, then a single class of that congruence can be defined by a triple `(Nx, i / S, k / S)`

, where `Nx`

is a right coset of `N`

, `i / S`

is the equivalence class of `i`

in `S`

, and `k / S`

is the equivalence class of `k`

in `T`

. Thus we can internally represent any class of such a congruence as a triple simply consisting of a right coset and two positive integers.

An analogous condition exists for finite simple Rees matrix semigroups without zero.

`‣ IsRMSCongruenceByLinkedTriple` ( obj ) | ( category ) |

`‣ IsRZMSCongruenceByLinkedTriple` ( obj ) | ( category ) |

Returns: `true`

or `false`

.

These categories describe a type of semigroup congruence over a Rees matrix or 0-matrix semigroup. Externally, an object of this type may be used in the same way as any other object in the category `IsSemigroupCongruence`

(Reference: IsSemigroupCongruence) but it is represented internally by its *linked triple*, and certain functions may take advantage of this information to reduce computation times.

An object of this type may be constructed with `RMSCongruenceByLinkedTriple`

or `RZMSCongruenceByLinkedTriple`

, or this representation may be selected automatically by `SemigroupCongruence`

(17.2-1).

gap> G := Group([(1, 4, 5), (1, 5, 3, 4)]);; gap> mat := [[0, 0, (1, 4, 5), 0, 0, (1, 4, 3, 5)], > [0, (), 0, 0, (3, 5), 0], > [(), 0, 0, (3, 5), 0, 0]];; gap> S := ReesZeroMatrixSemigroup(G, mat);; gap> N := Group([(1, 4)(3, 5), (1, 5)(3, 4)]);; gap> colBlocks := [[1], [2, 5], [3, 6], [4]];; gap> rowBlocks := [[1], [2], [3]];; gap> cong := RZMSCongruenceByLinkedTriple(S, N, colBlocks, rowBlocks);; gap> IsRZMSCongruenceByLinkedTriple(cong); true

`‣ RMSCongruenceByLinkedTriple` ( S, N, colBlocks, rowBlocks ) | ( function ) |

`‣ RZMSCongruenceByLinkedTriple` ( S, N, colBlocks, rowBlocks ) | ( function ) |

Returns: A Rees matrix or 0-matrix semigroup congruence by linked triple.

This function returns a semigroup congruence over the Rees matrix or 0-matrix semigroup `S` corresponding to the linked triple (`N`, `colBlocks`, `rowBlocks`). The argument `N` should be a normal subgroup of the underlying semigroup of `S`; `colBlocks` should be a partition of the columns of the matrix of `S`; and `rowBlocks` should be a partition of the rows of the matrix of `S`. For example, if the matrix has 5 rows, then a possibility for `rowBlocks` might be `[[1, 3], [2, 5], [4]]`

.

If the arguments describe a valid linked triple on `S`, then an object in the category `IsRZMSCongruenceByLinkedTriple`

is returned. This object can be used like any other semigroup congruence in **GAP**.

If the arguments describe a triple which is not *linked* in the sense described above, then this function returns an error.

gap> G := Group([(1, 4, 5), (1, 5, 3, 4)]);; gap> mat := [[0, 0, (1, 4, 5), 0, 0, (1, 4, 3, 5)], > [0, (), 0, 0, (3, 5), 0], > [(), 0, 0, (3, 5), 0, 0]];; gap> S := ReesZeroMatrixSemigroup(G, mat);; gap> N := Group([(1, 4)(3, 5), (1, 5)(3, 4)]);; gap> colBlocks := [[1], [2, 5], [3, 6], [4]];; gap> rowBlocks := [[1], [2], [3]];; gap> cong := RZMSCongruenceByLinkedTriple(S, N, colBlocks, rowBlocks);;

`‣ IsRMSCongruenceClassByLinkedTriple` ( obj ) | ( category ) |

`‣ IsRZMSCongruenceClassByLinkedTriple` ( obj ) | ( category ) |

Returns: `true`

or `false`

.

These categories contain the congruence classes of a semigroup congruence of the categories `IsRMSCongruenceByLinkedTriple`

(17.6-1) and `IsRZMSCongruenceByLinkedTriple`

(17.6-1) respectively.

An object of one of these types may be used in the same way as any other object in the category `IsCongruenceClass`

(17.3-1), but the class is represented internally by information related to the congruence's *linked triple*, and certain functions may take advantage of this information to reduce computation times.

gap> G := Group([(1, 4, 5), (1, 5, 3, 4)]);; gap> mat := [[0, 0, (1, 4, 5), 0, 0, (1, 4, 3, 5)], > [0, (), 0, 0, (3, 5), 0], > [(), 0, 0, (3, 5), 0, 0]];; gap> S := ReesZeroMatrixSemigroup(G, mat);; gap> N := Group([(1, 4)(3, 5), (1, 5)(3, 4)]);; gap> colBlocks := [[1], [2, 5], [3, 6], [4]];; gap> rowBlocks := [[1], [2], [3]];; gap> cong := RZMSCongruenceByLinkedTriple(S, N, colBlocks, rowBlocks);; gap> classes := CongruenceClasses(cong);; gap> IsRZMSCongruenceClassByLinkedTriple(classes[1]); true

`‣ RMSCongruenceClassByLinkedTriple` ( cong, nCoset, colClass, rowClass ) | ( operation ) |

`‣ RZMSCongruenceClassByLinkedTriple` ( cong, nCoset, colClass, rowClass ) | ( operation ) |

Returns: A Rees matrix or 0-matrix semigroup congruence class by linked triple.

This operation returns one congruence class of the congruence `cong`, as defined by the other three parameters.

The argument `cong` must be a Rees matrix or 0-matrix semigroup congruence by linked triple. If the linked triple consists of the three parameters `N`

, `colBlocks`

and `rowBlocks`

, then `nCoset` must be a right coset of `N`

, `colClass` must be a positive integer corresponding to a position in the list `colBlocks`

, and `rowClass` must be a positive integer corresponding to a position in the list `rowBlocks`

.

If the arguments are valid, an `IsRMSCongruenceClassByLinkedTriple`

or `IsRZMSCongruenceClassByLinkedTriple`

object is returned, which can be used like any other equivalence class in **GAP**. Otherwise, an error is returned.

gap> G := Group([(1, 4, 5), (1, 5, 3, 4)]);; gap> mat := [[0, 0, (1, 4, 5), 0, 0, (1, 4, 3, 5)], > [0, (), 0, 0, (3, 5), 0], > [(), 0, 0, (3, 5), 0, 0]];; gap> S := ReesZeroMatrixSemigroup(G, mat);; gap> N := Group([(1, 4)(3, 5), (1, 5)(3, 4)]);; gap> colBlocks := [[1], [2, 5], [3, 6], [4]];; gap> rowBlocks := [[1], [2], [3]];; gap> cong := RZMSCongruenceByLinkedTriple(S, N, colBlocks, rowBlocks);; gap> class := RZMSCongruenceClassByLinkedTriple(cong, > RightCoset(N, (1, 5)), 2, 3); <congruence class of (2,(3,4),3)>

`‣ IsLinkedTriple` ( S, N, colBlocks, rowBlocks ) | ( operation ) |

Returns: `true`

or `false`

.

This operation returns true if and only if the arguments (`N`, `colBlocks`, `rowBlocks`) describe a linked triple of the Rees matrix or 0-matrix semigroup `S`, as described above.

gap> G := Group([(1, 4, 5), (1, 5, 3, 4)]);; gap> mat := [[0, 0, (1, 4, 5), 0, 0, (1, 4, 3, 5)], > [0, (), 0, 0, (3, 5), 0], > [(), 0, 0, (3, 5), 0, 0]];; gap> S := ReesZeroMatrixSemigroup(G, mat);; gap> N := Group([(1, 4)(3, 5), (1, 5)(3, 4)]);; gap> colBlocks := [[1], [2, 5], [3, 6], [4]];; gap> rowBlocks := [[1], [2], [3]];; gap> IsLinkedTriple(S, N, colBlocks, rowBlocks); true

`‣ CanonicalRepresentative` ( class ) | ( attribute ) |

Returns: A congruence class.

This attribute gives a canonical representative for the semigroup congruence class `class`. This representative can be used to identify a class uniquely.

At present this only works for simple and 0-simple semigroups.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong := CongruencesOfSemigroup(S)[3];; gap> class := CongruenceClasses(cong)[3];; gap> CanonicalRepresentative(class); (1,(1,2,3),2)

`‣ AsSemigroupCongruenceByGeneratingPairs` ( cong ) | ( operation ) |

Returns: A semigroup congruence.

This operation takes `cong`, a semigroup congruence, and returns the same congruence relation, but described by **GAP**'s default method of defining semigroup congruences: a set of generating pairs for the congruence.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> cong := CongruencesOfSemigroup(S)[3];; gap> AsSemigroupCongruenceByGeneratingPairs(cong); <semigroup congruence over <Rees 0-matrix semigroup 2x2 over Sym( [ 1 .. 3 ] )> with 1 generating pairs>

`‣ AsRMSCongruenceByLinkedTriple` ( cong ) | ( operation ) |

`‣ AsRZMSCongruenceByLinkedTriple` ( cong ) | ( operation ) |

Returns: A Rees matrix or 0-matrix semigroup congruence by linked triple.

This operation takes a semigroup congruence `cong` over a finite simple or 0-simple Rees 0-matrix semigroup, and returns that congruence relation in a new form: as either a congruence by linked triple, or a universal congruence.

If the congruence is not defined over an appropriate type of semigroup, then this function returns an error.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> x := ReesZeroMatrixSemigroupElement(S, 1, (1, 3, 2), 1);; gap> y := ReesZeroMatrixSemigroupElement(S, 1, (), 1);; gap> cong := SemigroupCongruenceByGeneratingPairs(S, [[x, y]]);; gap> AsRZMSCongruenceByLinkedTriple(cong); <semigroup congruence over <Rees 0-matrix semigroup 2x2 over Sym( [ 1 .. 3 ] )> with linked triple (3,2,2)>

This section describes the implementation of congruences of inverse semigroups in the **Semigroups** package, and the functions associated with them. This code and this part of the manual were written by Michael Torpey. Most of the theorems used in this chapter are from Section 5.3 of [How95].

The congruences of an inverse semigroup are in 1-1 correspondence with its *congruence pairs*. A congruence pair is a pair `(N, t)`

such that:

`N`

is a normal subsemigroup of`S`

-- that is, a self-conjugate subsemigroup which contains all the idempotents of`S`

,`t`

is a normal congruence on`E`

, the subsemigroup of all idempotents in`S`

-- that is, a congruence on`E`

such that if \((e, f)\) is a pair in`t`

, then the pair \((a ^ {-1} e a, a ^ {-1} f a)\) is also in`t`

,

satisfying the following conditions:

If \(ae \in N\) and \((e, a ^ {-1} a) \in t\), then \(a \in N\),

If \(a \in N\), then \((aa ^ {-1} , a ^ {-1} a) \in t\).

By Theorem 5.3.3 in [How95], for any inverse semigroup, there is a bijection between its congruences and its congruence pairs. In this way, we can internally represent any congruence of such a semigroup by storing its associated congruence pair instead of a set of generating pairs, and thus perform many calculations on it more efficiently.

If we have a congruence `C`

with congruence pair `(N, t)`

, it turns out that `N`

is its *kernel* (that is, the set of all elements congruent to an idempotent) and that `t`

is its *trace* (that is, the restriction of `C`

to the idempotents). Hence, we refer to a congruence stored in this format as a "congruence by kernel and trace".

See `cong_by_ker_trace_threshold`

in Section 6.3 for details on when this method is used.

`‣ IsInverseSemigroupCongruenceByKernelTrace` ( cong ) | ( category ) |

Returns: `true`

or `false`

.

This category contains any inverse semigroup congruence `cong` which is represented internally by its kernel and trace. The `SemigroupCongruence`

(17.2-1) function may create an object of this category if its first argument `S` is an inverse semigroup and has sufficiently large size. It can be treated like any other semigroup congruence object.

See [How95] Section 5.3 for more details. See also `InverseSemigroupCongruenceByKernelTrace`

(17.7-2).

gap> S := InverseSemigroup([ > PartialPerm([4, 3, 1, 2]), > PartialPerm([1, 4, 2, 0, 3])], > rec(cong_by_ker_trace_threshold := 0));; gap> cong := SemigroupCongruence(S, []); <semigroup congruence over <inverse partial perm semigroup of size 351, rank 5 with 2 generators> with congruence pair (24,24)> gap> IsInverseSemigroupCongruenceByKernelTrace(cong); true

`‣ InverseSemigroupCongruenceByKernelTrace` ( S, kernel, traceBlocks ) | ( function ) |

Returns: An inverse semigroup congruence by kernel and trace.

If `S` is an inverse semigroup, `kernel` is a subsemigroup of `S`, `traceBlocks` is a list of lists describing a congruence on the idempotents of `S`, and \((\textit{kernel}, \textit{trace})\) describes a valid congruence pair for `S` (see [How95] Section 5.3) then this function returns the semigroup congruence defined by that congruence pair.

See also `KernelOfSemigroupCongruence`

(17.7-4) and `TraceOfSemigroupCongruence`

(17.7-5).

gap> S := InverseSemigroup([ > PartialPerm([2, 3]), PartialPerm([2, 0, 3])]);; gap> kernel := InverseSemigroup([ > PartialPerm([1, 0, 3]), PartialPerm([0, 2, 3]), > PartialPerm([1, 2]), PartialPerm([3]), > PartialPerm([2])]);; gap> trace := [ > [PartialPerm([0, 2, 3])], > [PartialPerm([1, 2])], > [PartialPerm([1, 0, 3])], > [PartialPerm([0, 0, 3]), PartialPerm([0, 2]), > PartialPerm([1]), PartialPerm([], [])]];; gap> cong := InverseSemigroupCongruenceByKernelTrace(S, kernel, trace); <semigroup congruence over <inverse partial perm semigroup of rank 3 with 2 generators> with congruence pair (13,4)>

`‣ AsInverseSemigroupCongruenceByKernelTrace` ( cong ) | ( attribute ) |

Returns: An inverse semigroup congruence by kernel and trace.

If `cong` is a semigroup congruence over an inverse semigroup, then this attribute returns an object which describes the same congruence, but with an internal representation defined by that congruence's kernel and trace.

See [How95] section 5.3 for more details.

gap> I := InverseSemigroup([ > PartialPerm([2, 3]), PartialPerm([2, 0, 3])]);; gap> cong := SemigroupCongruenceByGeneratingPairs(I, > [[PartialPerm([0, 1, 3]), PartialPerm([0, 1])], > [PartialPerm([]), PartialPerm([1, 2])]]); <semigroup congruence over <inverse partial perm semigroup of rank 3 with 2 generators> with 2 generating pairs> gap> cong2 := AsInverseSemigroupCongruenceByKernelTrace(cong); <semigroup congruence over <inverse partial perm semigroup of rank 3 with 2 generators> with congruence pair (19,1)>

`‣ KernelOfSemigroupCongruence` ( cong ) | ( attribute ) |

Returns: An inverse semigroup.

If `cong` is a congruence over a semigroup with inverse op, then this attribute returns the *kernel* of that congruence; that is, the inverse subsemigroup consisting of all elements which are related to an idempotent by `cong`.

gap> I := InverseSemigroup([ > PartialPerm([2, 3]), PartialPerm([2, 0, 3])]);; gap> cong := SemigroupCongruence(I, > [[PartialPerm([0, 1, 3]), PartialPerm([0, 1])], > [PartialPerm([]), PartialPerm([1, 2])]]); <semigroup congruence over <inverse partial perm semigroup of size 19, rank 3 with 2 generators> with 2 generating pairs> gap> KernelOfSemigroupCongruence(cong); <inverse partial perm semigroup of rank 3 with 5 generators>

`‣ TraceOfSemigroupCongruence` ( cong ) | ( attribute ) |

Returns: A list of lists.

If `cong` is an inverse semigroup congruence by kernel and trace, then this attribute returns the restriction of `cong` to the idempotents of the semigroup. This is in block form: each idempotent will appear in precisely one list, and two idempotents will be in the same list if and only if they are related by `cong`.

gap> I := InverseSemigroup([ > PartialPerm([2, 3]), PartialPerm([2, 0, 3])]);; gap> cong := SemigroupCongruence(I, > [[PartialPerm([0, 1, 3]), PartialPerm([0, 1])], > [PartialPerm([]), PartialPerm([1, 2])]]); <semigroup congruence over <inverse partial perm semigroup of size 19, rank 3 with 2 generators> with 2 generating pairs> gap> TraceOfSemigroupCongruence(cong); [ [ <empty partial perm>, <identity partial perm on [ 1 ]>, <identity partial perm on [ 2 ]>, <identity partial perm on [ 1, 2 ]>, <identity partial perm on [ 3 ]>, <identity partial perm on [ 2, 3 ]>, <identity partial perm on [ 1, 3 ]> ] ]

`‣ IsInverseSemigroupCongruenceClassByKernelTrace` ( obj ) | ( category ) |

Returns: `true`

or `false`

.

This category contains any congruence class which belongs to a congruence which is represented internally by its kernel and trace. See `InverseSemigroupCongruenceByKernelTrace`

(17.7-2).

See [How95] Section 5.3 for more details.

gap> I := InverseSemigroup([ > PartialPerm([2, 3]), PartialPerm([2, 0, 3])], > rec(cong_by_ker_trace_threshold := 0));; gap> cong := SemigroupCongruence(I, > [[PartialPerm([0, 1, 3]), PartialPerm([0, 1])], > [PartialPerm([]), PartialPerm([1, 2])]]);; gap> class := CongruenceClassOfElement(cong, > PartialPerm([1, 2], [2, 3]));; gap> IsInverseSemigroupCongruenceClassByKernelTrace(class); true

`‣ MinimumGroupCongruence` ( S ) | ( attribute ) |

Returns: An inverse semigroup congruence by kernel and trace.

If `S` is an inverse semigroup, then this function returns the least congruence on `S` whose quotient is a group.

gap> S := InverseSemigroup([ > PartialPerm([5, 2, 0, 0, 1, 4]), > PartialPerm([1, 4, 6, 3, 5, 0, 2])]);; gap> cong := MinimumGroupCongruence(S); <semigroup congruence over <inverse partial perm semigroup of rank 7 with 2 generators> with congruence pair (59,1)> gap> IsGroupAsSemigroup(S / cong); true

A Rees congruence is defined by a semigroup ideal. It is a congruence on a semigroup `S`

which has one congruence class equal to a semigroup ideal `I`

of `S`

, and every other congruence class being a singleton.

`‣ SemigroupIdealOfReesCongruence` ( cong ) | ( attribute ) |

Returns: A semigroup ideal.

If `cong` is a rees congruence (see `IsReesCongruence`

(Reference: IsReesCongruence)) then this attribute returns the two-sided ideal that was used to define it, i.e.~the ideal of elements in the only non-trivial congruence class of `cong`.

gap> S := Semigroup([ > Transformation([2, 3, 4, 3, 1, 1]), > Transformation([6, 4, 4, 4, 6, 1])]);; gap> I := SemigroupIdeal(S, > Transformation([4, 4, 4, 4, 4, 2]), > Transformation([3, 3, 3, 3, 3, 2]));; gap> cong := ReesCongruenceOfSemigroupIdeal(I);; gap> SemigroupIdealOfReesCongruence(cong); <non-regular transformation semigroup ideal of degree 6 with 2 generators>

`‣ IsReesCongruenceClass` ( obj ) | ( category ) |

Returns: `true`

or `false`

.

This category describes a congruence class of a Rees congruence. A congruence class of a Rees congruence either contains all the elements of an ideal, or is a singleton (see `IsReesCongruence`

(Reference: IsReesCongruence)).

An object of this type may be used in the same way as any other congruence class object.

gap> S := Semigroup( > Transformation([2, 3, 4, 3, 1, 1]), > Transformation([6, 4, 4, 4, 6, 1]));; gap> I := SemigroupIdeal(S, > Transformation([4, 4, 4, 4, 4, 2]), > Transformation([3, 3, 3, 3, 3, 2]));; gap> cong := ReesCongruenceOfSemigroupIdeal(I);; gap> classes := CongruenceClasses(cong);; gap> IsReesCongruenceClass(classes[1]); true

The linked triples of a completely 0-simple Rees 0-matrix semigroup describe only its non-universal congruences. In any one of these, the zero element of the semigroup is related only to itself. However, for any semigroup \(S\) the universal relation \(S \times S\) is a congruence; called the *universal congruence*. The universal congruence on a semigroup has its own unique representation.

Since many things we want to calculate about congruences are trivial in the case of the universal congruence, this package contains a category specifically designed for it, `IsUniversalSemigroupCongruence`

. We also define `IsUniversalSemigroupCongruenceClass`

, which represents the single congruence class of the universal congruence.

`‣ IsUniversalSemigroupCongruence` ( obj ) | ( property ) |

Returns: `true`

or `false`

.

This property describes a type of semigroup congruence, which must refer to the *universal semigroup congruence* \(S \times S\). Externally, an object of this type may be used in the same way as any other object in the category `IsSemigroupCongruence`

(Reference: IsSemigroupCongruence).

An object of this type may be constructed with `UniversalSemigroupCongruence`

or this representation may be selected automatically as an alternative to an `IsRZMSCongruenceByLinkedTriple`

object (since the universal congruence cannot be represented by a linked triple).

gap> S := Semigroup([Transformation([3, 2, 3])]);; gap> U := UniversalSemigroupCongruence(S);; gap> IsUniversalSemigroupCongruence(U); true

`‣ IsUniversalSemigroupCongruenceClass` ( obj ) | ( category ) |

Returns: `true`

or `false`

.

This category describes a class of the universal semigroup congruence (see `IsUniversalSemigroupCongruence`

(17.9-1)). A universal semigroup congruence by definition has precisely one congruence class, which contains all of the elements of the semigroup in question.

gap> S := Semigroup([Transformation([3, 2, 3])]);; gap> U := UniversalSemigroupCongruence(S);; gap> classes := CongruenceClasses(U);; gap> IsUniversalSemigroupCongruenceClass(classes[1]); true

`‣ UniversalSemigroupCongruence` ( S ) | ( operation ) |

Returns: A universal semigroup congruence.

This operation returns the universal semigroup congruence for the semigroup `S`. It can be used in the same way as any other semigroup congruence object.

gap> S := ReesZeroMatrixSemigroup(SymmetricGroup(3), > [[(), (1, 3, 2)], [(1, 2), 0]]);; gap> UniversalSemigroupCongruence(S); <universal semigroup congruence over <Rees 0-matrix semigroup 2x2 over Sym( [ 1 .. 3 ] )>>

generated by GAPDoc2HTML