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
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..abd48b2d9 100644
--- a/gap/semigroups/semicons.gi
+++ b/gap/semigroups/semicons.gi
@@ -967,6 +967,61 @@ for _IsXSemigroup in ["IsTransformationSemigroup",
od;
Unbind(_IsXSemigroup);
+InstallMethod(PowerSemigroup, "for a semigroup",
+[IsSemigroup and IsFinite],
+function(S)
+ local n, N, subs, x, 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 := {sub, subindex} -> Union(List(sub,
+ i -> precompute[i][subindex]));
+
+ 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();;