diff --git a/doc/attr.xml b/doc/attr.xml
index f576823cc..422ed0347 100644
--- a/doc/attr.xml
+++ b/doc/attr.xml
@@ -1205,6 +1205,34 @@ gap> GeneratorsSmallest(T);
<#/GAPDoc>
+<#GAPDoc Label="OneInverseOfSemigroupElement">
+
+
+ One inverse of an element of a semigroup.
+
+ OneInverseOfSemigroupElement returns one inverse of the element
+ x in the semigroup S and returns fail if this
+ element has no inverse in S.
+ x in the semigroup S.
+ S := FullTransformationMonoid(4);
+
+gap> s := Transformation([2, 3, 1, 1]);
+Transformation( [ 2, 3, 1, 1 ] )
+gap> OneInverseOfSemigroupElement(S, s);
+Transformation( [ 3, 1, 2, 2 ] )
+gap> e := IdentityTransformation;
+IdentityTransformation
+gap> OneInverseOfSemigroupElement(S, e);
+IdentityTransformation
+gap> F := FreeSemigroup(1);
+
+gap> OneInverseOfSemigroupElement(F, F.1);
+Error, the semigroup is not finite]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="IndecomposableElements">
diff --git a/doc/greens-generic.xml b/doc/greens-generic.xml
index 3809fbac7..a13f50794 100644
--- a/doc/greens-generic.xml
+++ b/doc/greens-generic.xml
@@ -1066,7 +1066,7 @@ gap> List(DClasses(S), SchutzenbergerGroup);
element s is of the same type as the elements of S but may
or may not be an element of S. In particular, if S is not a
monoid and a = b, then
- One(GeneratorsOfSemigroup(S)) may be returned. Even if a <>
+ One(GeneratorsOfSemigroup(S)) or an adjoined identity may be returned. Even if a <>
b, then it is not guaranteed that the returned element s
will belong to S. It is guaranteed that the left action of s on
the elements of the &L;-class of a is the same as the left action of
diff --git a/doc/z-chap11.xml b/doc/z-chap11.xml
index 0d95c97a5..6d41bd471 100644
--- a/doc/z-chap11.xml
+++ b/doc/z-chap11.xml
@@ -58,6 +58,17 @@
+
+
+
+ Operations for elements in a semigroup
+
+ <#Include Label = "OneInverseOfSemigroupElement">
+
+
+
+
+
diff --git a/gap/attributes/attr.gd b/gap/attributes/attr.gd
index bf54289b1..06a89023a 100644
--- a/gap/attributes/attr.gd
+++ b/gap/attributes/attr.gd
@@ -67,6 +67,10 @@ DeclareAttribute("UnderlyingSemigroupOfSemigroupWithAdjoinedZero",
DeclareOperation("InversesOfSemigroupElementNC",
[IsSemigroup, IsMultiplicativeElement]);
+DeclareOperation("OneInverseOfSemigroupElementNC",
+ [IsSemigroup, IsMultiplicativeElement]);
+DeclareOperation("OneInverseOfSemigroupElement",
+ [IsSemigroup, IsMultiplicativeElement]);
DeclareAttribute("IndecomposableElements", IsSemigroup);
DeclareAttribute("NambooripadLeqRegularSemigroup", IsSemigroup);
diff --git a/gap/attributes/attr.gi b/gap/attributes/attr.gi
index c0c58fe04..096abd016 100644
--- a/gap/attributes/attr.gi
+++ b/gap/attributes/attr.gi
@@ -759,7 +759,7 @@ end);
InstallMethod(InversesOfSemigroupElementNC,
"for a group as semigroup and a multiplicative element",
-[IsGroupAsSemigroup, IsMultiplicativeElement],
+[IsGroupAsSemigroup and CanUseFroidurePin, IsMultiplicativeElement],
function(G, x)
local i, iso, inv;
if IsMultiplicativeElementWithInverse(x) then
@@ -774,26 +774,79 @@ function(G, x)
end);
InstallMethod(InversesOfSemigroupElementNC,
-"for a semigroup and a multiplicative element",
-[IsSemigroup, IsMultiplicativeElement],
+"for a semigroup that can use froidure-pin and a multiplicative element",
+[CanUseFroidurePin, IsMultiplicativeElement],
+function(S, a)
+ local R, L, inverses, e, f, s;
+ R := RClass(S, a);
+ L := LClass(S, a);
+ inverses := EmptyPlist(NrIdempotents(R) * NrIdempotents(L));
+
+ for e in Idempotents(R) do
+ s := RightGreensMultiplierNC(S, a, e) * e;
+ for f in Idempotents(L) do
+ Add(inverses, f * s);
+ od;
+ od;
+ return inverses;
+end);
+
+InstallMethod(InversesOfSemigroupElement,
+"for a semigroup that can use froidure-pin and a multiplicative element",
+[CanUseFroidurePin, IsMultiplicativeElement], # to beat the library method
function(S, x)
if not IsFinite(S) then
TryNextMethod();
+ elif not x in S then
+ ErrorNoReturn("the 2nd argument (a mult. element) must belong to the 1st ",
+ "argument (a semigroup)");
fi;
- return Filtered(EnumeratorSorted(S), y -> x * y * x = x and y * x * y = y);
+ return InversesOfSemigroupElementNC(S, x);
end);
-InstallMethod(InversesOfSemigroupElement,
+InstallMethod(OneInverseOfSemigroupElementNC,
"for a semigroup and a multiplicative element",
-[IsSemigroup, IsMultiplicativeElement], 1, # to beat the library method
+[IsSemigroup, IsMultiplicativeElement],
+function(S, x)
+ if not IsFinite(S) then
+ TryNextMethod();
+ fi;
+ return First(EnumeratorSorted(S),
+ y -> x * y * x = x and y * x * y = y);
+end);
+
+InstallMethod(OneInverseOfSemigroupElementNC,
+"for CanUseFroidurePin and a multiplicative element",
+[CanUseFroidurePin, IsMultiplicativeElement],
+function(S, a)
+ local R, L, e, f, s;
+ R := RClass(S, a);
+ L := LClass(S, a);
+ e := Idempotents(R);
+ if IsEmpty(e) then
+ return fail;
+ fi;
+ e := e[1];
+ f := Idempotents(L);
+ if IsEmpty(f) then
+ return fail;
+ fi;
+ f := f[1];
+ s := RightGreensMultiplierNC(S, a, e);
+ return f * s * e;
+end);
+
+InstallMethod(OneInverseOfSemigroupElement,
+"for a semigroup and a multiplicative element",
+[IsSemigroup, IsMultiplicativeElement],
function(S, x)
if not IsFinite(S) then
- TryNextMethod();
+ ErrorNoReturn("the semigroup is not finite");
elif not x in S then
ErrorNoReturn("the 2nd argument (a mult. element) must belong to the 1st ",
"argument (a semigroup)");
fi;
- return InversesOfSemigroupElementNC(S, x);
+ return OneInverseOfSemigroupElementNC(S, x);
end);
InstallMethod(UnderlyingSemigroupOfSemigroupWithAdjoinedZero,
diff --git a/gap/greens/froidure-pin.gi b/gap/greens/froidure-pin.gi
index 7151d6353..49cbba441 100644
--- a/gap/greens/froidure-pin.gi
+++ b/gap/greens/froidure-pin.gi
@@ -606,39 +606,53 @@ function(S)
end);
InstallMethod(LeftGreensMultiplierNC,
-"for a semigroup that can use Froidure-Pin and L-related elements with one",
+"for a semigroup that can use Froidure-Pin and L-related elements",
[IsSemigroup and CanUseFroidurePin,
- IsMultiplicativeElementWithOne,
- IsMultiplicativeElementWithOne],
+ IsMultiplicativeElement,
+ IsMultiplicativeElement],
function(S, a, b)
- local gens, D, path;
+ local gens, D, path, a1, b1;
gens := GeneratorsOfSemigroup(S);
D := LeftCayleyDigraph(S);
- a := PositionCanonical(S, a);
- b := PositionCanonical(S, b);
- path := NextIterator(IteratorOfPaths(D, a, b));
+ a1 := PositionCanonical(S, a);
+ b1 := PositionCanonical(S, b);
+ path := NextIterator(IteratorOfPaths(D, a1, b1));
if path = fail then
# This can occur when, for example, a = b and S is not a monoid.
- return One(gens);
+ if IsMultiplicativeElementWithOne(a)
+ and IsMultiplicativeElementWithOne(b) then
+ return One(gens);
+ elif MultiplicativeNeutralElement(S) <> fail then
+ return MultiplicativeNeutralElement(S);
+ else
+ return SEMIGROUPS.UniversalFakeOne;
+ fi;
fi;
return EvaluateWord(gens, Reversed(path[2]));
end);
InstallMethod(RightGreensMultiplierNC,
-"for a semigroup that can use Froidure-Pin and R-related elements with one",
+"for a semigroup that can use Froidure-Pin and R-related elements",
[IsSemigroup and CanUseFroidurePin,
- IsMultiplicativeElementWithOne,
- IsMultiplicativeElementWithOne],
+ IsMultiplicativeElement,
+ IsMultiplicativeElement],
function(S, a, b)
- local gens, D, path;
+ local gens, D, path, a1, b1;
gens := GeneratorsOfSemigroup(S);
D := RightCayleyDigraph(S);
- a := PositionCanonical(S, a);
- b := PositionCanonical(S, b);
- path := NextIterator(IteratorOfPaths(D, a, b));
+ a1 := PositionCanonical(S, a);
+ b1 := PositionCanonical(S, b);
+ path := NextIterator(IteratorOfPaths(D, a1, b1));
if path = fail then
# This can occur when, for example, a = b and S is not a monoid.
- return One(gens);
+ if IsMultiplicativeElementWithOne(a)
+ and IsMultiplicativeElementWithOne(b) then
+ return One(gens);
+ elif MultiplicativeNeutralElement(S) <> fail then
+ return MultiplicativeNeutralElement(S);
+ else
+ return SEMIGROUPS.UniversalFakeOne;
+ fi;
fi;
return EvaluateWord(gens, path[2]);
end);
diff --git a/gap/semigroups/grpperm.gi b/gap/semigroups/grpperm.gi
index fd1df6e5e..693043243 100644
--- a/gap/semigroups/grpperm.gi
+++ b/gap/semigroups/grpperm.gi
@@ -53,7 +53,7 @@ end);
# fall back method, same method for ideals
-InstallMethod(IsomorphismPermGroup, "for a semigroup", [IsSemigroup],
+InstallMethod(IsomorphismPermGroup, "for a semigroup", [CanUseFroidurePin],
function(S)
local cay, deg, G, gen1, gen2, next, pos, iso, inv, i;
if not IsFinite(S) then
diff --git a/tst/standard/attributes/attr.tst b/tst/standard/attributes/attr.tst
index 669060462..2445ddef0 100644
--- a/tst/standard/attributes/attr.tst
+++ b/tst/standard/attributes/attr.tst
@@ -1474,9 +1474,39 @@ gap> InversesOfSemigroupElement(S, IdentityTransformation);
Error, usage: the 2nd argument must be an element of the 1st,
gap> InversesOfSemigroupElementNC(S, S.1);
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
-Error, no 2nd choice method found for `InversesOfSemigroupElementNC' on 2 argu\
+Error, no 1st choice method found for `InversesOfSemigroupElementNC' on 2 argu\
ments
+# attr: OneInverseOfSemigroupElement, for a semigroup
+gap> S := Semigroup([
+> Matrix(IsMaxPlusMatrix, [[-2, 2, 0], [-1, 0, 0], [1, -3, 1]]),
+> Matrix(IsMaxPlusMatrix, [[- infinity, 0, 0], [0, 1, 0], [1, -1, 0]])]);;
+gap> OneInverseOfSemigroupElement(S, S.1);
+Error, the semigroup is not finite
+gap> S := Semigroup(Transformation([2, 3, 1, 3, 3]));;
+gap> OneInverseOfSemigroupElement(S, Transformation([1, 3, 2]));
+Error, the 2nd argument (a mult. element) must belong to the 1st argument (a s\
+emigroup)
+gap> S := Semigroup([Matrix(IsBooleanMat, [[0, 0, 1], [0, 1, 1], [1, 0, 0]]),
+> Matrix(IsBooleanMat, [[1, 0, 0], [1, 0, 1], [1, 1, 1]])]);;
+gap> OneInverseOfSemigroupElement(S, S.1);
+fail
+gap> OneInverseOfSemigroupElement(S, S.1 * S.2 * S.1);
+Matrix(IsBooleanMat, [[1, 1, 1], [1, 1, 1], [0, 0, 1]])
+
+# OneInverseOfSemigroupElement, for a semigroup that cannot use Froidure-Pin
+gap> S := Semigroup(SEMIGROUPS.UniversalFakeOne);;
+gap> OneInverseOfSemigroupElement(S, S.1);
+
+
+# OneInverseOfSemigroupElement, for an infinite semigroup, 1
+gap> S := FreeSemigroup(1);
+
+gap> OneInverseOfSemigroupElementNC(S, S.1);
+Error, no method found! For debugging hints type ?Recovery from NoMethodFound
+Error, no 2nd choice method found for `OneInverseOfSemigroupElementNC' on 2 ar\
+guments
+
# attr: IdempotentGeneratedSubsemigroup, 2
gap> S := FullTransformationMonoid(3);;
gap> I := IdempotentGeneratedSubsemigroup(S);;
diff --git a/tst/standard/ideals/ideals.tst b/tst/standard/ideals/ideals.tst
index 1914760b0..b60679144 100644
--- a/tst/standard/ideals/ideals.tst
+++ b/tst/standard/ideals/ideals.tst
@@ -230,7 +230,7 @@ gap> I := SemigroupIdeal(S,
> Matrix(IsBooleanMat, [[1, 0, 1], [0, 0, 0], [0, 1, 0]]),
> Matrix(IsBooleanMat, [[0, 1, 1], [0, 1, 1], [1, 0, 1]]));;
gap> x := Matrix(IsBooleanMat, [[1, 0, 1], [0, 1, 0], [1, 0, 1]]);;
-gap> InversesOfSemigroupElement(I, x);
+gap> AsSet(InversesOfSemigroupElement(I, x));
[ Matrix(IsBooleanMat, [[0, 0, 0], [0, 1, 0], [0, 0, 1]]),
Matrix(IsBooleanMat, [[0, 0, 0], [0, 1, 0], [1, 0, 0]]),
Matrix(IsBooleanMat, [[0, 0, 0], [0, 1, 0], [1, 0, 1]]),
diff --git a/tst/standard/semigroups/grpperm.tst b/tst/standard/semigroups/grpperm.tst
index 556876861..8b4151589 100644
--- a/tst/standard/semigroups/grpperm.tst
+++ b/tst/standard/semigroups/grpperm.tst
@@ -397,7 +397,7 @@ Group([ (1,3)(2,5)(4,6), (1,4,5)(2,6,3) ])
# IsomorphismPermGroup, infinite 1 / 1
gap> IsomorphismPermGroup(FreeMonoid(3));
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
-Error, no 3rd choice method found for `IsomorphismPermGroup' on 1 arguments
+Error, no 2nd choice method found for `IsomorphismPermGroup' on 1 arguments
# IsomorphismPermGroup, for a block bijection semigroup
gap> S := Semigroup(Bipartition([[1, 2, -3, -4], [3, 4, -1, -2]]));;
diff --git a/tst/standard/semigroups/semirms.tst b/tst/standard/semigroups/semirms.tst
index 24859c3a8..a2c5dd19a 100644
--- a/tst/standard/semigroups/semirms.tst
+++ b/tst/standard/semigroups/semirms.tst
@@ -2629,8 +2629,7 @@ gap> R := ReesZeroMatrixSemigroup(SymmetricGroup(4),
> [(), (2, 4, 3), (1, 2)]]);
gap> IsomorphismPermGroup(R);
-Error, the underlying semigroup of the argument (a subsemigroup of a Rees 0-m\
-atrix semigroup) does not satisfy IsGroupAsSemigroup
+Error, the argument (a semigroup) does not satisfy IsGroupAsSemigroup
gap> S := Semigroup(MultiplicativeZero(R));;
gap> IsomorphismPermGroup(S);
-> Group(())