From 4bd642f74d3ab7188c7fb142878afc9445072efa Mon Sep 17 00:00:00 2001 From: William-Kenyon <115789274+William-Kenyon@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:25:08 +0100 Subject: [PATCH 1/3] Fixes #1092, adding construction of power semigroups --- gap/semigroups/semicons.gd | 1 + gap/semigroups/semicons.gi | 56 ++++++++++++++++++++++++++++ tst/standard/semigroups/semicons.tst | 21 +++++++++++ 3 files changed, 78 insertions(+) diff --git a/gap/semigroups/semicons.gd b/gap/semigroups/semicons.gd index 10089096e..d6a288a8a 100644 --- a/gap/semigroups/semicons.gd +++ b/gap/semigroups/semicons.gd @@ -22,6 +22,7 @@ DeclareGlobalFunction("LeftZeroSemigroup"); DeclareGlobalFunction("RightZeroSemigroup"); DeclareConstructor("BrandtSemigroupCons", [IsSemigroup, IsGroup, IsPosInt]); DeclareGlobalFunction("BrandtSemigroup"); +DeclareOperation("PowerSemigroup", [IsSemigroup and IsFinite]); DeclareCategory("IsSSSE", IsAssociativeElement); DeclareCategoryCollections("IsSSSE"); diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index f8e3c5fd1..1cf369e84 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -967,6 +967,62 @@ for _IsXSemigroup in ["IsTransformationSemigroup", od; Unbind(_IsXSemigroup); +InstallMethod(PowerSemigroup, "for a semigroup", +[IsSemigroup and IsFinite], +function(S) + local n, N, subs, x, powers, getindex, multtable, precompute, subsproduct, + table, result; + + n := Size(S); + if n > 12 then + Info(InfoWarning, 1, + "PowerSemigroup: the argument has ", n, " elements, so the result ", + "will have 2^", n, " - 1 elements and its multiplication table ", + "may exceed memory limits, "); + fi; + + N := (2 ^ n) - 1; + + # want subsets in binary-code order, not lexicographical, so easier to index + # e.g. {1, 2, 3} -> {1}, {2}, {1, 2}, {3}..., i.e. 001, 010, 011, 100... + subs := [[]]; + for x in [1 .. n] do + Append(subs, List(subs, s -> Concatenation(s, [x]))); + od; + Remove(subs, 1); + + getindex := s -> Sum(s, j -> 2 ^ (j - 1)); + + multtable := MultiplicationTable(S); + + # precompute[i][j] is the product: (element i of S) times (subset j of S) + precompute := List([1 .. n], + i -> List(subs, sub -> Set(sub, j -> multtable[i][j]))); + + # the product of two subsets X, Y is equivalent to + # (x_1 * Y) union (x_2 * Y) union (x_3 * Y)... + # so is just a union of the precomputed values above + subsproduct := function(sub, subindex) + return Union(List(sub, i -> precompute[i][subindex])); + end; + + table := List(subs, + sub -> List([1 .. N], + subindex -> getindex(subsproduct(sub, subindex)))); + + if IsMonoidAsSemigroup(S) then + result := MonoidByMultiplicationTable(table); + else + result := SemigroupByMultiplicationTable(table); + fi; + + if IsCommutative(S) then + SetIsCommutative(result, true); + fi; + + return result; +end); + InstallMethod(StrongSemilatticeOfSemigroups, "for a digraph, a list, and a list", [IsDigraph, IsList, IsList], diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst index 34986b2d0..86dec2e06 100644 --- a/tst/standard/semigroups/semicons.tst +++ b/tst/standard/semigroups/semicons.tst @@ -972,6 +972,27 @@ gap> S := BrandtSemigroup(IsIntegerMatrixSemigroup, DihedralGroup(4), 3); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `BrandtSemigroupCons' on 3 arguments +# constructions: power semigroups +gap> PowerSemigroup(FreeSemigroup(1)); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `PowerSemigroup' on 1 arguments +gap> S := PowerSemigroup(TrivialSemigroup());; +gap> IsTrivial(S); +true +gap> S := PowerSemigroup(CyclicGroup(2));; +gap> HasIsCommutative(S); +true +gap> IsMonoid(S); +true +gap> S1 := SemigroupByMultiplicationTable([[1, 2, 3], [2, 1, 3], [3, 3, 3]]);; +gap> IsomorphismSemigroups(S, S1) <> fail; +true +gap> S := PowerSemigroup(LeftZeroSemigroup(2));; +gap> HasIsCommutative(S); +false +gap> IsMonoid(S); +false + # constructions: strong semilattices of semigroups: trivial argument checks gap> D := CompleteDigraph(2);; gap> S1 := TrivialSemigroup();; From 8dda90bfd4c661337298456ea7b366a1b41971e0 Mon Sep 17 00:00:00 2001 From: William-Kenyon <115789274+William-Kenyon@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:25:31 +0100 Subject: [PATCH 2/3] Documentation for PowerSemigroups --- doc/semicons.xml | 30 ++++++++++++++++++++++++++++++ doc/z-chap08.xml | 12 ++++++++++++ 2 files changed, 42 insertions(+) diff --git a/doc/semicons.xml b/doc/semicons.xml index 8221b93ff..a24635c28 100644 --- a/doc/semicons.xml +++ b/doc/semicons.xml @@ -355,6 +355,36 @@ true]]> <#/GAPDoc> +<#GAPDoc Label="PowerSemigroup"> + + + + A semigroup or monoid. + + + The power semigroup \mathcal{P}(S) over the finite semigroup + S consists of the set of all non-empty subsets of S, along + with the binary operation of setwise multiplication, defined by + (X, Y) \mapsto \{xy : x \in X, y \in Y\} +

+ If S is a monoid, then PowerSemigroup returns a monoid. +

+ Power semigroups grow exponentially; for a semigroup S of size + n, the corresponding power semigroup has size 2^{n}-1, so + its multiplication table may exhaust memory. + + S := SemigroupByMultiplicationTable([[1, 2], [2, 1]]);; +gap> S1 := PowerSemigroup(S);; +gap> MultiplicationTable(S1); +[ [ 1, 2, 3 ], [ 2, 1, 3 ], [ 3, 3, 3 ] ] +gap> IsMonoid(S1); +true +]]> + + +<#/GAPDoc> + <#GAPDoc Label="StrongSemilatticeOfSemigroups"> diff --git a/doc/z-chap08.xml b/doc/z-chap08.xml index 6f498f35c..dc69a227b 100644 --- a/doc/z-chap08.xml +++ b/doc/z-chap08.xml @@ -37,6 +37,18 @@ +

+ Power semigroups + The power semigroup of a semigroup S is the semigroup + consisting of the power set of S excluding the empty set, along with + the binary operation of setwise multiplication, defined by + (X, Y) \mapsto \{xy : x \in X, y \in Y\}. + <#Include Label = "PowerSemigroup"> +
+ + + +
Strong semilattices of semigroups From 7c3321354abee67c0c56be0d588fa307c2c16b39 Mon Sep 17 00:00:00 2001 From: William-Kenyon <115789274+William-Kenyon@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:47:16 +0100 Subject: [PATCH 3/3] Fix gaplint errors --- gap/semigroups/semicons.gi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 1cf369e84..abd48b2d9 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -970,7 +970,7 @@ Unbind(_IsXSemigroup); InstallMethod(PowerSemigroup, "for a semigroup", [IsSemigroup and IsFinite], function(S) - local n, N, subs, x, powers, getindex, multtable, precompute, subsproduct, + local n, N, subs, x, getindex, multtable, precompute, subsproduct, table, result; n := Size(S); @@ -1002,9 +1002,8 @@ function(S) # the product of two subsets X, Y is equivalent to # (x_1 * Y) union (x_2 * Y) union (x_3 * Y)... # so is just a union of the precomputed values above - subsproduct := function(sub, subindex) - return Union(List(sub, i -> precompute[i][subindex])); - end; + subsproduct := {sub, subindex} -> Union(List(sub, + i -> precompute[i][subindex])); table := List(subs, sub -> List([1 .. N],