From 4f732b76fc4dd4287a168014fe44774c7987220a Mon Sep 17 00:00:00 2001 From: Tianrun Yang <117233646+Tianrun-Y@users.noreply.github.com> Date: Fri, 8 Nov 2024 10:29:18 +0000 Subject: [PATCH] Better inverses (#1021) * Stub * Add possibly better method for InversesOfSemigroupElementNC * delete Nambooripad Method for Transformation Semigroup * change inverses to a set * change filter into IsMultiplicativeElementWithOne as it is required for the argument of RightGreensMultiplierNC. * add the AsSet to the test rather than the method * fix consecutive empty lines * fix RightGreensMultiplierNC does not work on fp semigroups where there is no one but the method should work * fix comment * add OneInverseOfSemigroupElement and fix small issues * fix declaration and filter problem * Update gap/attributes/attr.gi Co-authored-by: James Mitchell * Update gap/attributes/attr.gi Co-authored-by: James Mitchell * fix formatting for gaplint * fix issue * Update gap/attributes/attr.gi Co-authored-by: James Mitchell * Update gap/attributes/attr.gi Co-authored-by: James Mitchell * fix issue * Update gap/attributes/attr.gi Co-authored-by: James Mitchell * addnon-no-check version of OneInverse, and a NC version for cannot use froidure pin. * fix small issues in the previous commit * Update gap/attributes/attr.gi Co-authored-by: James Mitchell * add declaration of OneInverseOfSemigroupElement * add documentation of OneInverseOfSemigroupElement * fix formatting for gaplint * fix syntax error * add test for OneInverseOfSemigroupElement * addMultiplicativeNeutralElement as a return * addMultiplicativeNeutralElement as a return for the other one * update documentation for LeftGreensMultiplier * fix filter problem * fix filter problem and also add test * fix test problems * fix gaplint * fix test * add example in documentation * Update doc/attr.xml Co-authored-by: James Mitchell * if there is no inverse * delete merge remnants * add to chapter * fix small issue * fix example format --------- Co-authored-by: James D. Mitchell Co-authored-by: James Mitchell --- doc/attr.xml | 28 ++++++++++++ doc/greens-generic.xml | 2 +- doc/z-chap11.xml | 11 +++++ gap/attributes/attr.gd | 4 ++ gap/attributes/attr.gi | 69 +++++++++++++++++++++++++---- gap/greens/froidure-pin.gi | 46 ++++++++++++------- gap/semigroups/grpperm.gi | 2 +- tst/standard/attributes/attr.tst | 32 ++++++++++++- tst/standard/ideals/ideals.tst | 2 +- tst/standard/semigroups/grpperm.tst | 2 +- tst/standard/semigroups/semirms.tst | 3 +- 11 files changed, 170 insertions(+), 31 deletions(-) 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 f12a48f40..0a59fc015 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 d8278f481..68a1624fb 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(())