diff --git a/doc/ideals.xml b/doc/ideals.xml
index a553724bc..12357c91b 100644
--- a/doc/ideals.xml
+++ b/doc/ideals.xml
@@ -98,6 +98,56 @@ gap> I := SemigroupIdeal(S, I, Idempotents(S));
<#/GAPDoc>
+<#GAPDoc Label="LeftSemigroupIdeal">
+
+
+
+ A left ideal of a semigroup.
+
+
+ If obj1, obj2, .. . are (any combination) of elements of the
+ semigroup S or collections of elements of S (including
+ subsemigroups and ideals of S), then LeftSemigroupIdeal returns the
+ left ideal of the semigroup S generated by the union of
+ obj1, obj2, .. ..
+
+ The of the ideal returned by this
+ function is S.
+
+ S := SymmetricInverseMonoid(10);
+
+gap> I := LeftSemigroupIdeal(S, PartialPerm([1, 2]));
+]]>
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="RightSemigroupIdeal">
+
+
+
+ A Right ideal of a semigroup.
+
+
+ If obj1, obj2, .. . are (any combination) of elements of the
+ semigroup S or collections of elements of S (including
+ subsemigroups and ideals of S), then RightSemigroupIdeal returns the
+ Right ideal of the semigroup S generated by the union of
+ obj1, obj2, .. ..
+
+ The of the ideal returned by this
+ function is S.
+
+ S := SymmetricInverseMonoid(10);
+
+gap> I := RightSemigroupIdeal(S, PartialPerm([1, 2]));
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="SupersemigroupOfIdeal">
diff --git a/doc/semicons.xml b/doc/semicons.xml
index a5d10da52..07f2d8f78 100644
--- a/doc/semicons.xml
+++ b/doc/semicons.xml
@@ -147,6 +147,61 @@ true]]>
<#/GAPDoc>
+<#GAPDoc Label="FreeSemilattice">
+
+
+
+ A free semilattice with n generators.
+
+
+ If n is a positive integer, then this function returns a free
+ semilattice with n generators in the representation given by the
+ filter filt.
+
+ The optional argument filt may be one of the following:
+
+ - IsTransformationSemigroup
+ (the default, if filt is not specified),
+ - IsTransformationMonoid,
+ - IsPartialPermSemigroup,
+ - IsPartialPermMonoid,
+ - IsFpSemigroup,
+ - IsFpMonoid,
+ - IsBipartitionSemigroup,
+ - IsBipartitionMonoid,
+ - IsPBRSemigroup,
+ - IsPBRMonoid,
+ - IsBooleanMatSemigroup,
+ - IsBooleanMatMonoid,
+ - IsNTPMatrixSemigroup,
+ - IsNTPMatrixMonoid,
+ - IsMaxPlusMatrixSemigroup,
+ - IsMaxPlusMatrixMonoid,
+ - IsMinPlusMatrixSemigroup,
+ - IsMinPlusMatrixMonoid,
+ - IsTropicalMaxPlusMatrixSemigroup,
+ - IsTropicalMaxPlusMatrixMonoid,
+ - IsTropicalMinPlusMatrixSemigroup,
+ - IsTropicalMinPlusMatrixMonoid,
+ - IsProjectiveMaxPlusMatrixSemigroup,
+ - IsProjectiveMaxPlusMatrixMonoid,
+ - IsIntegerMatrixSemigroup.
+ - IsIntegerMatrixMonoid.
+
+
+ S := FreeSemilattice(IsTransformationSemigroup, 5);
+
+gap> T := FreeSemilattice(IsPartialPermSemigroup, 3);
+
+gap> U := FreeSemilattice(IsBooleanMatSemigroup, 4);
+
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="ZeroSemigroup">
diff --git a/doc/z-chap07.xml b/doc/z-chap07.xml
index 8616e149b..ce2b680f9 100644
--- a/doc/z-chap07.xml
+++ b/doc/z-chap07.xml
@@ -155,6 +155,7 @@
<#Include Label = "TrivialSemigroup">
<#Include Label = "MonogenicSemigroup">
<#Include Label = "RectangularBand">
+ <#Include Label = "FreeSemilattice">
<#Include Label = "ZeroSemigroup">
<#Include Label = "LeftZeroSemigroup">
<#Include Label = "BrandtSemigroup">
diff --git a/doc/z-chap09.xml b/doc/z-chap09.xml
index d289760e3..f31bba0b1 100644
--- a/doc/z-chap09.xml
+++ b/doc/z-chap09.xml
@@ -29,6 +29,8 @@
<#Include Label = "SemigroupIdeal">
+ <#Include Label = "LeftSemigroupIdeal">
+ <#Include Label = "RightSemigroupIdeal">
<#Include Label = "Ideals">
diff --git a/gap/ideals/froidure-pin.gd b/gap/ideals/froidure-pin.gd
index b06e73058..37b974239 100644
--- a/gap/ideals/froidure-pin.gd
+++ b/gap/ideals/froidure-pin.gd
@@ -9,3 +9,5 @@
##
DeclareAttribute("PositionsInSupersemigroup", IsSemigroupIdeal);
+DeclareAttribute("PositionsInSupersemigroup", IsLeftSemigroupIdeal);
+DeclareAttribute("PositionsInSupersemigroup", IsRightSemigroupIdeal);
diff --git a/gap/ideals/froidure-pin.gi b/gap/ideals/froidure-pin.gi
index 5a3c59e6a..39edc5bbd 100644
--- a/gap/ideals/froidure-pin.gi
+++ b/gap/ideals/froidure-pin.gi
@@ -39,6 +39,48 @@ function(I)
return result;
end);
+InstallMethod(PositionsInSupersemigroup,
+"for a left semigroup ideal with known generators",
+[IsLeftSemigroupIdeal and HasGeneratorsOfSemigroupIdeal and
+ CanUseFroidurePin],
+function(I)
+ local S, L, result, pos, x;
+ S := SupersemigroupOfIdeal(I);
+ L := LeftCayleyDigraph(S);
+
+ result := [];
+ for x in GeneratorsOfSemigroupIdeal(I) do
+ pos := PositionCanonical(S, x);
+ if not pos in result then
+ AddSet(result, pos);
+ UniteSet(result, VerticesReachableFrom(L, pos));
+ fi;
+ od;
+
+ return result;
+end);
+
+InstallMethod(PositionsInSupersemigroup,
+"for a right semigroup ideal with known generators",
+[IsRightSemigroupIdeal and HasGeneratorsOfSemigroupIdeal and
+ CanUseFroidurePin],
+function(I)
+ local S, R, result, pos, x;
+ S := SupersemigroupOfIdeal(I);
+ R := RightCayleyDigraph(S);
+
+ result := [];
+ for x in GeneratorsOfSemigroupIdeal(I) do
+ pos := PositionCanonical(S, x);
+ if not pos in result then
+ AddSet(result, pos);
+ UniteSet(result, VerticesReachableFrom(R, pos));
+ fi;
+ od;
+
+ return result;
+end);
+
InstallMethod(GeneratorsOfInverseSemigroup,
"for an inverse semigroup ideal with inverse op and generators",
[IsSemigroupIdeal and IsInverseSemigroup
diff --git a/gap/ideals/ideals.gd b/gap/ideals/ideals.gd
index 3d6a12cb6..d8c40e134 100644
--- a/gap/ideals/ideals.gd
+++ b/gap/ideals/ideals.gd
@@ -7,15 +7,21 @@
##
#############################################################################
-DeclareSynonymAttr("GeneratorsOfSemigroupIdeal", GeneratorsOfMagmaIdeal);
+DeclareSynonymAttr("GeneratorsOfSemigroupIdeal",
+ GeneratorsOfMagmaIdeal);
+DeclareSynonymAttr("GeneratorsOfLeftSemigroupIdeal",
+ GeneratorsOfLeftMagmaIdeal);
+DeclareSynonymAttr("GeneratorsOfRightSemigroupIdeal",
+ GeneratorsOfRightMagmaIdeal);
+
DeclareGlobalFunction("SemigroupIdeal");
+DeclareGlobalFunction("LeftSemigroupIdeal");
+DeclareGlobalFunction("RightSemigroupIdeal");
DeclareOperation("SemigroupIdealByGenerators",
[IsSemigroup, IsListOrCollection]);
-
DeclareOperation("SemigroupIdealByGenerators",
[IsSemigroup, IsListOrCollection, IsRecord]);
-
DeclareOperation("SemigroupIdealByGeneratorsNC",
[IsSemigroup, IsListOrCollection, IsRecord]);
diff --git a/gap/ideals/ideals.gi b/gap/ideals/ideals.gi
index 7b47706e5..af2db6950 100644
--- a/gap/ideals/ideals.gi
+++ b/gap/ideals/ideals.gi
@@ -187,8 +187,7 @@ InstallMethod(Representative, "for a semigroup ideal",
# a convenience, similar to the functions , , etc
-InstallGlobalFunction(SemigroupIdeal,
-function(arg...)
+SEMIGROUPS.AnySemigroupIdealInputParsing := function(arg...)
local out, i;
if Length(arg) <= 1 then
@@ -197,11 +196,11 @@ function(arg...)
ErrorNoReturn("the 1st argument is not a semigroup");
elif Length(arg) = 2 and IsMatrix(arg[2]) then
# special case for matrices, because they may look like lists
- return SemigroupIdealByGenerators(arg[1], [arg[2]]);
+ return [arg[1], [arg[2]]];
elif Length(arg) = 2 and IsList(arg[2]) and 0 < Length(arg[2]) then
# list of generators
- return SemigroupIdealByGenerators(arg[1], arg[2]);
+ return [arg[1], arg[2]];
elif (IsMultiplicativeElement(arg[2])
and IsGeneratorsOfSemigroup([arg[2]]))
or (IsListOrCollection(arg[2])
@@ -212,7 +211,7 @@ function(arg...)
for i in [2 .. Length(arg)] do
# so that we can pass the options record
if i = Length(arg) and IsRecord(arg[i]) then
- return SemigroupIdealByGenerators(arg[1], out, arg[i]);
+ return [arg[1], out, arg[i]];
elif IsMultiplicativeElement(arg[i]) and
IsGeneratorsOfSemigroup([arg[i]]) then
Add(out, arg[i]);
@@ -232,36 +231,68 @@ function(arg...)
"nor semigroups");
fi;
od;
- return SemigroupIdealByGenerators(arg[1], out);
+ return [arg[1], out];
fi;
ErrorNoReturn("invalid arguments");
+end;
+
+InstallGlobalFunction(SemigroupIdeal,
+function(arg...)
+ local parsed;
+ parsed := CallFuncList(SEMIGROUPS.AnySemigroupIdealInputParsing, arg);
+ if Length(parsed) = 3 then
+ return SEMIGROUPS.AnySemigroupIdealByGenerators4(parsed[1],
+ IsMagmaIdeal, parsed[2], parsed[3]);
+ else
+ return SEMIGROUPS.AnySemigroupIdealByGenerators3(parsed[1],
+ IsMagmaIdeal, parsed[2]);
+ fi;
end);
-InstallMethod(SemigroupIdealByGenerators,
-"for a semigroup and list or collections",
-[IsSemigroup, IsListOrCollection],
-{S, gens} -> SemigroupIdealByGenerators(S, gens, SEMIGROUPS.OptionsRec(S)));
+InstallGlobalFunction(LeftSemigroupIdeal,
+function(arg...)
+ local parsed;
+ parsed := CallFuncList(SEMIGROUPS.AnySemigroupIdealInputParsing, arg);
+ if Length(parsed) = 3 then
+ return SEMIGROUPS.AnySemigroupIdealByGenerators4(parsed[1],
+ IsLeftMagmaIdeal, parsed[2], parsed[3]);
+ else
+ return SEMIGROUPS.AnySemigroupIdealByGenerators3(parsed[1],
+ IsLeftMagmaIdeal, parsed[2]);
+ fi;
+end);
-InstallMethod(SemigroupIdealByGenerators,
-"for semigroup, list or collection, and record",
-[IsSemigroup, IsListOrCollection, IsRecord],
-function(S, gens, opts)
+InstallGlobalFunction(RightSemigroupIdeal,
+function(arg...)
+ local parsed;
+ parsed := CallFuncList(SEMIGROUPS.AnySemigroupIdealInputParsing, arg);
+ if Length(parsed) = 3 then
+ return SEMIGROUPS.AnySemigroupIdealByGenerators4(parsed[1],
+ IsRightMagmaIdeal, parsed[2], parsed[3]);
+ else
+ return SEMIGROUPS.AnySemigroupIdealByGenerators3(parsed[1],
+ IsRightMagmaIdeal, parsed[2]);
+ fi;
+end);
+
+SEMIGROUPS.AnySemigroupIdealByGenerators3 := {S, filter, gens} ->
+ SEMIGROUPS.AnySemigroupIdealByGenerators4(S,
+ filter, gens, SEMIGROUPS.OptionsRec(S));
+
+SEMIGROUPS.AnySemigroupIdealByGenerators4 := function(S, filter, gens, opts)
if not ForAll(gens, x -> x in S) then
ErrorNoReturn("the 2nd argument (a mult. elt. coll.) do not all ",
"belong to the semigroup");
fi;
- return SemigroupIdealByGeneratorsNC(S, gens, opts);
-end);
+ return SEMIGROUPS.AnySemigroupIdealByGeneratorsNC(S, filter, gens, opts);
+end;
-InstallMethod(SemigroupIdealByGeneratorsNC,
-"for a semigroup, list or collections, and record",
-[IsSemigroup, IsListOrCollection, IsRecord],
-function(S, gens, opts)
+SEMIGROUPS.AnySemigroupIdealByGeneratorsNC := function(S, filter, gens, opts)
local filts, I;
opts := SEMIGROUPS.ProcessOptionsRec(SEMIGROUPS.DefaultOptionsRec, opts);
gens := AsList(gens);
- filts := IsMagmaIdeal and IsAttributeStoringRep;
+ filts := filter and IsAttributeStoringRep;
if opts.acting
and (IsActingSemigroup(S) or IsGeneratorsOfActingSemigroup(gens)) then
@@ -313,7 +344,16 @@ function(S, gens, opts)
fi;
SetParent(I, S);
- SetGeneratorsOfMagmaIdeal(I, gens);
+ if "IsLeftActedOnBySuperset" in NamesFilter(filter) and
+ "IsRightActedOnBySuperset" in NamesFilter(filter) then
+ SetGeneratorsOfMagmaIdeal(I, gens);
+ elif "IsLeftActedOnBySuperset" in NamesFilter(filter) then
+ SetGeneratorsOfLeftMagmaIdeal(I, gens);
+ elif "IsRightActedOnBySuperset" in NamesFilter(filter) then
+ SetGeneratorsOfRightMagmaIdeal(I, gens);
+ else
+ # PANIC
+ fi;
if not IsActingSemigroup(I) then
# to keep the craziness in the library happy!
@@ -326,6 +366,26 @@ function(S, gens, opts)
fi;
return I;
+end;
+
+InstallMethod(SemigroupIdealByGenerators,
+"for a semigroup and list or collections",
+[IsSemigroup, IsListOrCollection],
+{S, gens} -> SemigroupIdealByGenerators(S, gens, SEMIGROUPS.OptionsRec(S)));
+
+InstallMethod(SemigroupIdealByGenerators,
+"for semigroup, list or collection, and record",
+[IsSemigroup, IsListOrCollection, IsRecord],
+function(S, gens, opts)
+ return SEMIGROUPS.AnySemigroupIdealByGenerators4(S, IsMagmaIdeal, gens, opts);
+end);
+
+InstallMethod(SemigroupIdealByGeneratorsNC,
+"for a semigroup, list or collections, and record",
+[IsSemigroup, IsListOrCollection, IsRecord],
+function(S, gens, opts)
+ return SEMIGROUPS.AnySemigroupIdealByGeneratorsNC(S,
+ IsMagmaIdeal, gens, opts);
end);
InstallMethod(MinimalIdealGeneratingSet,
diff --git a/gap/semigroups/semicons.gd b/gap/semigroups/semicons.gd
index 6a5c16d77..10089096e 100644
--- a/gap/semigroups/semicons.gd
+++ b/gap/semigroups/semicons.gd
@@ -12,6 +12,8 @@ DeclareGlobalFunction("TrivialSemigroup");
DeclareConstructor("TrivialSemigroupCons", [IsSemigroup, IsInt]);
DeclareGlobalFunction("RectangularBand");
DeclareConstructor("RectangularBandCons", [IsSemigroup, IsPosInt, IsPosInt]);
+DeclareGlobalFunction("FreeSemilattice");
+DeclareConstructor("FreeSemilatticeCons", [IsSemigroup, IsPosInt]);
DeclareGlobalFunction("MonogenicSemigroup");
DeclareConstructor("MonogenicSemigroupCons", [IsSemigroup, IsPosInt, IsPosInt]);
DeclareGlobalFunction("ZeroSemigroup");
diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi
index 0c83701a1..a9bbddaf2 100644
--- a/gap/semigroups/semicons.gi
+++ b/gap/semigroups/semicons.gi
@@ -406,6 +406,181 @@ for _IsXSemigroup in ["IsBooleanMatSemigroup",
od;
Unbind(_IsXSemigroup);
+# Free semilattice: main method
+
+InstallGlobalFunction(FreeSemilattice,
+function(arg...)
+ local filter, n, S;
+
+ if Length(arg) = 1 then
+ filter := IsTransformationSemigroup;
+ n := arg[1];
+ elif Length(arg) = 2 then
+ filter := arg[1];
+ n := arg[2];
+ else
+ ErrorNoReturn("expected 2 arguments found ", Length(arg));
+ fi;
+
+ if not IsPosInt(n) or not IsOperation(filter) then
+ ErrorNoReturn("the arguments must be a positive integer or a filter ",
+ "and a positive integer");
+ fi;
+
+ S := FreeSemilatticeCons(filter, n);
+
+ if "IsMagmaWithOne" in NamesFilter(filter) then
+ SetSize(S, 2 ^ n);
+ else
+ SetSize(S, 2 ^ n - 1);
+ fi;
+
+ SetIsSemilattice(S, true);
+
+ return S;
+end);
+
+# Free semilattice: constructors
+
+InstallMethod(FreeSemilatticeCons,
+"for IsFpSemigroup and a pos int",
+[IsFpSemigroup, IsPosInt],
+function(_, n)
+ local F, gen, l, i, j, commR, idemR;
+ F := FreeSemigroup(n);
+ gen := GeneratorsOfSemigroup(F);
+ l := Length(gen);
+
+ commR := [];
+ for i in [1 .. l - 1] do
+ for j in [i + 1 .. l] do
+ Add(commR, [gen[i] * gen[j], gen[j] * gen[i]]);
+ od;
+ od;
+
+ idemR := List(gen, x -> [x * x, x]);
+ return F / Concatenation(commR, idemR);
+end);
+
+InstallMethod(FreeSemilatticeCons,
+"for IsFpSemigroup and a pos int",
+[IsFpMonoid, IsPosInt],
+function(_, n)
+ local F, gen, l, i, j, commR, idemR;
+ F := FreeMonoid(n);
+ gen := GeneratorsOfSemigroup(F);
+ l := Length(gen);
+
+ commR := [];
+ for i in [1 .. l - 1] do
+ for j in [i + 1 .. l] do
+ Add(commR, [gen[i] * gen[j], gen[j] * gen[i]]);
+ od;
+ od;
+
+ idemR := List(gen, x -> [x * x, x]);
+ return F / Concatenation(commR, idemR);
+end);
+
+InstallMethod(FreeSemilatticeCons,
+"for IsTransformationSemigroup and a pos int",
+[IsTransformationSemigroup, IsPosInt],
+function(_, n)
+ local gen, i, L;
+ gen := [];
+ for i in [1 .. n] do
+ L := [1 .. n + 1];
+ L[i] := n + 1;
+ Add(gen, Transformation(L));
+ od;
+ return Semigroup(gen);
+end);
+
+InstallMethod(FreeSemilatticeCons,
+"for IsTransformationSemigroup and a pos int",
+[IsTransformationMonoid, IsPosInt],
+function(_, n)
+ local gen, i, L;
+ gen := [];
+ for i in [1 .. n] do
+ L := [1 .. n + 1];
+ L[i] := n + 1;
+ Add(gen, Transformation(L));
+ od;
+ return Monoid(gen);
+end);
+
+InstallMethod(FreeSemilatticeCons,
+"for IsPartialPermSemigroup and a pos int",
+[IsPartialPermSemigroup, IsPosInt],
+function(_, n)
+ local gen, i, L;
+ gen := [];
+ for i in [1 .. n] do
+ L := [1 .. n];
+ Remove(L, i);
+ Add(gen, PartialPerm(L, L));
+ od;
+ return Semigroup(gen);
+end);
+
+InstallMethod(FreeSemilatticeCons,
+"for IsPartialPermSemigroup and a pos int",
+[IsPartialPermMonoid, IsPosInt],
+function(_, n)
+ local gen, i, L;
+ gen := [];
+ for i in [1 .. n] do
+ L := [1 .. n];
+ Remove(L, i);
+ Add(gen, PartialPerm(L, L));
+ od;
+ return Monoid(gen);
+end);
+
+# Free semilattice: other constructors
+
+for _IsXSemigroup in ["IsBipartitionSemigroup",
+ "IsPBRSemigroup",
+ "IsBooleanMatSemigroup",
+ "IsNTPMatrixSemigroup",
+ "IsMaxPlusMatrixSemigroup",
+ "IsMinPlusMatrixSemigroup",
+ "IsTropicalMaxPlusMatrixSemigroup",
+ "IsTropicalMinPlusMatrixSemigroup",
+ "IsProjectiveMaxPlusMatrixSemigroup",
+ "IsIntegerMatrixSemigroup"] do
+ InstallMethod(FreeSemilatticeCons,
+ Concatenation("for ", _IsXSemigroup, ", and pos int"),
+ [ValueGlobal(_IsXSemigroup), IsPosInt],
+ function(filter, n)
+ return AsSemigroup(filter,
+ FreeSemilatticeCons(IsTransformationSemigroup, n));
+ end);
+od;
+
+for _IsXMonoid in ["IsBipartitionMonoid",
+ "IsPBRMonoid",
+ "IsBooleanMatMonoid",
+ "IsNTPMatrixMonoid",
+ "IsMaxPlusMatrixMonoid",
+ "IsMinPlusMatrixMonoid",
+ "IsTropicalMaxPlusMatrixMonoid",
+ "IsTropicalMinPlusMatrixMonoid",
+ "IsProjectiveMaxPlusMatrixMonoid",
+ "IsIntegerMatrixMonoid"] do
+ InstallMethod(FreeSemilatticeCons,
+ Concatenation("for ", _IsXMonoid, ", and pos int"),
+ [ValueGlobal(_IsXMonoid), IsPosInt],
+ function(filter, n)
+ return AsMonoid(filter,
+ FreeSemilatticeCons(IsTransformationMonoid, n));
+ end);
+od;
+
+Unbind(_IsXSemigroup);
+Unbind(_IsXMonoid);
+
# Zero semigroup: main method
InstallGlobalFunction(ZeroSemigroup,
diff --git a/tst/standard/ideals/ideals.tst b/tst/standard/ideals/ideals.tst
index 1914760b0..8209f3468 100644
--- a/tst/standard/ideals/ideals.tst
+++ b/tst/standard/ideals/ideals.tst
@@ -20,8 +20,8 @@ gap> SEMIGROUPS.StartTest();
# Test SupersemigroupOfIdeal
gap> S := RegularBooleanMatMonoid(3);;
-gap> I := SemigroupIdeal(S,
-> Matrix(IsBooleanMat,
+gap> I := SemigroupIdeal(S,
+> Matrix(IsBooleanMat,
> [[1, 1, 1], [1, 0, 1], [1, 1, 1]]));
gap> J := MinimalIdeal(I);
@@ -35,8 +35,8 @@ true
# Test PrintString
gap> S := RegularBooleanMatMonoid(3);;
-gap> I := SemigroupIdeal(S,
-> Matrix(IsBooleanMat,
+gap> I := SemigroupIdeal(S,
+> Matrix(IsBooleanMat,
> [[1, 1, 1], [1, 0, 1], [1, 1, 1]]));
gap> PrintString(I);
@@ -133,34 +133,54 @@ false
gap> S = MinimalIdeal(S);
false
-# Test SemigroupIdeal (the function)
+# Test SEMIGROUPS.AnySemigroupIdealInputParsing
+gap> SEMIGROUPS.AnySemigroupIdealInputParsing();
+Error, there must be 2 or more arguments
+gap> SEMIGROUPS.AnySemigroupIdealInputParsing(6330);
+Error, there must be 2 or more arguments
+gap> S := RegularBooleanMatMonoid(2);;
+gap> SEMIGROUPS.AnySemigroupIdealInputParsing(S);
+Error, there must be 2 or more arguments
+gap> SEMIGROUPS.AnySemigroupIdealInputParsing(S, [S.1, S.2]);
+[ ,
+ [ Matrix(IsBooleanMat, [[0, 1], [1, 0]]),
+ Matrix(IsBooleanMat, [[1, 0], [0, 0]]) ] ]
+gap> SEMIGROUPS.AnySemigroupIdealInputParsing(S, NullDigraph(2));
+Error, invalid arguments
+gap> I := SemigroupIdeal(S, []);
+Error, the 2nd argument is not a combination of generators, lists of generator\
+s, nor semigroups
+
+# Test SemigroupIdeal, LeftSemigroupIdeal, RightSemigroupIdeal (the function)
gap> SemigroupIdeal("a");
Error, there must be 2 or more arguments
-gap> S := RegularBooleanMatMonoid(1);;
-gap> SemigroupIdeal(S);
+gap> LeftSemigroupIdeal("314159265358979");
+Error, there must be 2 or more arguments
+gap> RightSemigroupIdeal(5);
Error, there must be 2 or more arguments
gap> S := Semigroup([[Z(2)]]);
gap> SemigroupIdeal(S, S.1);
+gap> LeftSemigroupIdeal(S, S.1);
+
+gap> RightSemigroupIdeal(S, S.1);
+
gap> S := RegularBooleanMatMonoid(2);;
gap> I := SemigroupIdeal(S, [S.1, S.2]);
gap> J := SemigroupIdeal(S, I, S.3);
+gap> I := LeftSemigroupIdeal(S, [S.1, S.2]);
+
+gap> I := RightSemigroupIdeal(S, [S.1, S.2]);
+
gap> I := SemigroupIdeal(S, [S.1, S.2], rec());
gap> I := SemigroupIdeal(S, MaximalDClasses(S)[1]);
-gap> I := SemigroupIdeal(S, []);
-Error, the 2nd argument is not a combination of generators, lists of generator\
-s, nor semigroups
-gap> SemigroupIdeal();
-Error, there must be 2 or more arguments
-gap> SemigroupIdeal(S, NullDigraph(2));
-Error, invalid arguments
-# Test SemigroupIdealByGenerators
+# Test SEMIGROUPS.AnySemigroupIdealByGenerators4
gap> S := RegularBooleanMatMonoid(1);;
gap> T := RegularBooleanMatMonoid(2);;
gap> SemigroupIdeal(S, T.1);
@@ -200,7 +220,7 @@ gap> I := SemigroupIdeal(S, S.1);
gap> MinimalIdealGeneratingSet(I);
[ Transformation( [ 2, 3, 1 ] ) ]
gap> S := RegularBooleanMatMonoid(3);;
-gap> I := SemigroupIdeal(S,
+gap> I := SemigroupIdeal(S,
> Matrix(IsBooleanMat, [[1, 1, 1], [1, 1, 0], [1, 0, 1]]),
> Matrix(IsBooleanMat, [[1, 1, 1], [1, 1, 0], [0, 0, 1]]),
> Matrix(IsBooleanMat, [[1, 0, 0], [0, 1, 1], [1, 0, 1]]),
@@ -218,7 +238,7 @@ gap> MinimalIdealGeneratingSet(I);
# Test InversesOfSemigroupElementNC
gap> S := RegularBooleanMatMonoid(3);;
-gap> I := SemigroupIdeal(S,
+gap> I := SemigroupIdeal(S,
> Matrix(IsBooleanMat, [[1, 1, 1], [1, 1, 0], [1, 0, 1]]),
> Matrix(IsBooleanMat, [[1, 1, 1], [1, 1, 0], [0, 0, 1]]),
> Matrix(IsBooleanMat, [[1, 0, 0], [0, 1, 1], [1, 0, 1]]),
@@ -256,8 +276,8 @@ gap> I := SemigroupIdeal(T, z);;
gap> IsCommutativeSemigroup(I);
true
gap> S := RegularBooleanMatMonoid(3);;
-gap> I := SemigroupIdeal(S,
-> [Matrix(IsBooleanMat, [[0, 1, 0], [1, 0, 1], [1, 1, 0]]),
+gap> I := SemigroupIdeal(S,
+> [Matrix(IsBooleanMat, [[0, 1, 0], [1, 0, 1], [1, 1, 0]]),
> Matrix(IsBooleanMat, [[1, 0, 0], [1, 1, 0], [1, 0, 1]])]);;
gap> IsCommutativeSemigroup(I);
false
@@ -327,7 +347,7 @@ gap> ideals := Ideals(S);;
gap> Size(ideals);
1
gap> S := Semigroup([
-> Bipartition([[1, 2, -1, -4], [3, -5], [4], [5, -2], [-3]]),
+> Bipartition([[1, 2, -1, -4], [3, -5], [4], [5, -2], [-3]]),
> Bipartition([[1, 2, 4, -3, -5], [3, -4], [5, -1, -2]]),
> Bipartition([[1, 2, 5, -3, -4], [3, 4, -1, -2], [-5]])]);;
gap> ideals := Ideals(S);;
diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst
index 3b5f3f24a..34986b2d0 100644
--- a/tst/standard/semigroups/semicons.tst
+++ b/tst/standard/semigroups/semicons.tst
@@ -497,6 +497,47 @@ gap> S := RectangularBand(IsReesMatrixSemigroup, 5, 5);
gap> S := RectangularBand(IsReesMatrixSemigroup, 10, 11);
+# constructions: FreeSemilattice: errors
+gap> S := FreeSemilattice(0);
+Error, the arguments must be a positive integer or a filter and a positive int\
+eger
+gap> S := FreeSemilattice(IsPartialPermSemigroup, 0);
+Error, the arguments must be a positive integer or a filter and a positive int\
+eger
+gap> S := FreeSemilattice(IsPermGroup, 1, 1);
+Error, expected 2 arguments found 3
+gap> S := FreeSemilattice(IsPartialPermSemigroup, true);
+Error, the arguments must be a positive integer or a filter and a positive int\
+eger
+
+# constructions: FreeSemilattice: known properties and attributes, 17
+gap> S := FreeSemilattice(17);;
+gap> HasSize(S);
+true
+gap> Size(S) = 2 ^ 17 - 1;
+true
+
+# constructions: FreeSemilattice: default
+gap> S := FreeSemilattice(1);
+
+gap> S := FreeSemilattice(2);
+
+gap> S := FreeSemilattice(5);
+
+gap> S := FreeSemilattice(21);
+
+
+# constructions: FreeSemilattice: transformation semigroup
+gap> S := FreeSemilattice(IsTransformationSemigroup, 1);
+
+gap> S := FreeSemilattice(IsTransformationSemigroup, 2);
+
+gap> S := FreeSemilattice(IsTransformationSemigroup, 5);
+
+gap> S := FreeSemilattice(IsTransformationSemigroup, 11);
+
+
# constructions: ZeroSemigroup: errors
gap> S := ZeroSemigroup(0);
Error, the arguments must be a positive integer or a filter and a positive int\