From afcba0334b80011565c356cc75d6d53dfa192475 Mon Sep 17 00:00:00 2001 From: Wilf Wilson Date: Fri, 22 Sep 2017 13:34:07 +0100 Subject: [PATCH] attr: methods for MinimalSemigroup/MonoidGenset --- doc/attr.xml | 43 +++++------ gap/attributes/attr.gi | 120 ++++++++++++++++++++++++++++++ tst/standard/attr.tst | 165 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 302 insertions(+), 26 deletions(-) diff --git a/doc/attr.xml b/doc/attr.xml index b17cf97301..1835603e24 100644 --- a/doc/attr.xml +++ b/doc/attr.xml @@ -332,33 +332,21 @@ gap> Length(SmallGeneratingSet(S)); - - A minimal generating set for a semigroup. - - Warning: currently, no methods are installed to compute these - attributes.

- - The attributes MinimalXGeneratingSet return a minimal generating set + The attribute MinimalXGeneratingSet returns a minimal generating set for the semigroup S, with respect to length. The returned value of MinimalXGeneratingSet, where applicable, is a minimal-length list of elements of S with the property that X(MinimalXGeneratingSet(S)) = S; - where X is any of - , - , - , or - .

+ where X is either + , or + .

- For certain types of semigroup, for example monogenic semigroups, a - MinimalXGeneratingSet may be known a priori, or may be deduced as a - by-product of other functions. However, since there are no methods installed - to compute these attributes directly, for most semigroups it is not - currently possible to find a MinimalXGeneratingSet with the - &Semigroups; package.

+ For many types of semigroup, it is not currently possible to find a + MinimalXGeneratingSet with the &Semigroups; package.

See also and . @@ -367,15 +355,18 @@ gap> Length(SmallGeneratingSet(S)); gap> S := MonogenicSemigroup(3, 6);; gap> MinimalSemigroupGeneratingSet(S); [ Transformation( [ 2, 3, 4, 5, 6, 1, 6, 7, 8 ] ) ] -gap> S := Semigroup([ -> PartialPerm([1, 2, 3, 4, 5], [1, 2, 3, 4, 5]), -> PartialPerm([1, 2, 3, 4], [5, 2, 4, 1]), -> PartialPerm([1, 2, 4, 5], [4, 2, 3, 1])]); - -gap> IsMonogenicInverseMonoid(S); +gap> S := FullTransformationMonoid(4);; +gap> MinimalSemigroupGeneratingSet(S); +[ Transformation( [ 1, 4, 2, 3 ] ), Transformation( [ 4, 3, 1, 2 ] ), + Transformation( [ 1, 2, 3, 1 ] ) ] +gap> S := Monoid([ +> PartialPerm([2, 3, 4, 5, 1, 0, 6, 7]), +> PartialPerm([3, 4, 5, 1, 2, 0, 0, 6])]); + +gap> IsMonogenicMonoid(S); true -gap> MinimalInverseMonoidGeneratingSet(S); -[ [3,4,1,5](2) ]]]> +gap> MinimalMonoidGeneratingSet(S); +[ [8,7,6](1,2,3,4,5) ]]]> <#/GAPDoc> diff --git a/gap/attributes/attr.gi b/gap/attributes/attr.gi index a269e475e8..6adeebf990 100644 --- a/gap/attributes/attr.gi +++ b/gap/attributes/attr.gi @@ -960,3 +960,123 @@ function(S) od; return out; end); + +InstallMethod(MinimalSemigroupGeneratingSet, "for a free semigroup", +[IsFreeSemigroup], +GeneratorsOfSemigroup); + +InstallMethod(MinimalSemigroupGeneratingSet, "for a semigroup", +[IsSemigroup], +function(S) + local gens, indecomp, id, T, zero, iso, inv, G, x, D, non_unit_gens, classes, + po, nbs; + + if IsTrivial(S) then + return [Representative(S)]; + elif IsGroupAsSemigroup(S) then + iso := IsomorphismPermGroup(S); + inv := InverseGeneralMapping(iso); + G := Range(iso); + return Images(inv, MinimalGeneratingSet(G)); + elif IsMonogenicSemigroup(S) then + return [Representative(MaximalDClasses(S)[1])]; + fi; + + gens := IrredundantGeneratingSubset(S); + + # A semigroup that has a 2-generating set but is not monogenic has rank 2. + if Length(gens) = 2 then + return gens; + fi; + + # A generating set for a semigroup that has either a one/zero adjoined is + # minimal if and only if it contains that one/zero, and is minimal for the + # semigroup without the one/zero. + if IsMonoidAsSemigroup(S) and IsTrivial(GroupOfUnits(S)) then + id := MultiplicativeNeutralElement(S); + T := Semigroup(Filtered(gens, x -> x <> id)); + return Concatenation([id], MinimalSemigroupGeneratingSet(T)); + elif IsSemigroupWithAdjoinedZero(S) then + zero := MultiplicativeZero(S); + T := Semigroup(Filtered(gens, x -> x <> zero)); + return Concatenation([zero], MinimalSemigroupGeneratingSet(T)); + fi; + + # The indecomposable elements are contains in any generating set. If the + # indecomposable elements (or if not, the indecomposable elements plus a + # single element) generate the semigroup, then you have a minimal generating + # set. + indecomp := IndecomposableElements(S); + if Length(gens) = Length(indecomp) then + return indecomp; + elif not IsEmpty(indecomp) then + x := Difference(gens, Semigroup(indecomp)); + if Length(x) = 1 then + return Concatenation(x, indecomp); + fi; + fi; + + # A generating set for a monoid that consists of a minimal generating set for + # the group of units and exactly one generator in each D-class immediately + # below the group of units is minimal. + if IsMonoidAsSemigroup(S) then + D := DClass(S, MultiplicativeNeutralElement(S)); + non_unit_gens := Filtered(gens, x -> not x in D); + classes := List(non_unit_gens, x -> Position(DClasses(S), DClass(S, x))); + if IsDuplicateFreeList(classes) then + po := Digraph(PartialOrderOfDClasses(S)); + po := DigraphReflexiveTransitiveReduction(po); + nbs := OutNeighboursOfVertex(po, Position(DClasses(S), D)); + if ForAll(classes, x -> x in nbs) then + iso := IsomorphismPermGroup(GroupOfUnits(S)); + inv := InverseGeneralMapping(iso); + G := Range(iso); + return Concatenation(Images(inv, MinimalGeneratingSet(G)), + non_unit_gens); + fi; + fi; + fi; + + # An irredundant generating set of a finite semigroup that contains at most + # one generator per D-class is minimal. + if IsFinite(S) and (IsDTrivial(S) or + Length(Set(gens, x -> DClass(S, x))) = Length(gens)) then + return gens; + fi; + + ErrorNoReturn("Semigroups: MinimalSemigroupGeneratingSet: error,\n", + "no further methods for computing minimal generating sets ", + "are implemented,"); +end); + +InstallMethod(MinimalMonoidGeneratingSet, "for a free monoid", +[IsFreeMonoid], +GeneratorsOfMonoid); + +InstallMethod(MinimalMonoidGeneratingSet, "for a monoid", +[IsMonoid], +function(S) + local one, gens, new; + + one := One(S); + if IsTrivial(S) then + return [one]; + fi; + + gens := MinimalSemigroupGeneratingSet(S); + if not IsTrivial(GroupOfUnits(S)) then + return gens; + fi; + new := Difference(gens, [one]); + if One(new) = one then + # The One of the non-identity generators is the One, so One is not needed. + return new; + fi; + + # This currently applies to only partial perm monoids: sometimes, the One + # of the non-One generators is not the One of the monoid. Therefore the One + # has to be included in the GeneratorsOfMonoid. WARNING: therefore + # GeneratorsOfMonoid may include the One even though, mathematically, it + # shouldn't be needed. For example, see symmetric inverse monoid on 1 pt. + return gens; +end); diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst index 05347bcda7..b55e195e19 100644 --- a/tst/standard/attr.tst +++ b/tst/standard/attr.tst @@ -1737,6 +1737,171 @@ gap> S := MonogenicSemigroup(3, 2);; gap> IndecomposableElements(S) = [S.1]; true +#T# MinimalSemigroupGeneratingSet: for a monogenic semigroup, 1 +gap> S := MonogenicSemigroup(IsTransformationSemigroup, 4, 5); + +gap> MinimalSemigroupGeneratingSet(S); +[ Transformation( [ 2, 3, 4, 5, 1, 5, 6, 7, 8 ] ) ] +gap> x := MinimalSemigroupGeneratingSet(S)[1]; +Transformation( [ 2, 3, 4, 5, 1, 5, 6, 7, 8 ] ) +gap> S := Semigroup(x, x ^ 2); + +gap> x := MinimalSemigroupGeneratingSet(S); +[ Transformation( [ 2, 3, 4, 5, 1, 5, 6, 7, 8 ] ) ] +gap> Length(x); +1 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: for a 2-generated semigroup, 1 +gap> S := SymmetricInverseMonoid(1); + +gap> x := MinimalSemigroupGeneratingSet(S); +[ , ] +gap> Length(x); +2 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: for a semigroup with identity adjoined, 1 +gap> S := Monoid(RectangularBand(IsBipartitionSemigroup, 2, 2)); + +gap> x := MinimalSemigroupGeneratingSet(S);; +gap> Length(x); +3 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: for a semigroup with zero adjoined, 1 +gap> S := ReesZeroMatrixSemigroup(Group(()), [[(), ()]]); + +gap> x := MinimalSemigroupGeneratingSet(S); +[ 0, (1,(),1), (2,(),1) ] +gap> Length(x); +3 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: decomposable elements, 1 +gap> S := Semigroup(ZeroSemigroup(IsPartialPermSemigroup, 4)); + +gap> x := MinimalSemigroupGeneratingSet(S); +[ [1,2], [3,4], [5,6] ] +gap> Length(x); +3 +gap> S = Semigroup(x); +true +gap> S := Semigroup(Elements(S)); + +gap> x := MinimalSemigroupGeneratingSet(S); +[ [1,2], [3,4], [5,6] ] +gap> Length(x); +3 + +#T# MinimalSemigroupGeneratingSet: decomposable elements, 2 +gap> S := Monoid([ +> Transformation([1, 1, 1, 2]), +> Transformation([1, 1, 2, 1]), +> Transformation([1, 1, 2, 2]), +> Transformation([1, 1, 1, 1, 6, 5])]); + +gap> x := MinimalSemigroupGeneratingSet(S); +[ IdentityTransformation, Transformation( [ 1, 1, 1, 1, 6, 5 ] ), + Transformation( [ 1, 1, 1, 2 ] ), Transformation( [ 1, 1, 2, 1 ] ), + Transformation( [ 1, 1, 2, 2 ] ) ] +gap> Length(x); +5 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: for a group as semigroup, 1 +gap> S = Semigroup(x); +true +gap> S := Semigroup([ +> Transformation([1, 3, 2, 1]), +> Transformation([2, 1, 3, 2]), +> Transformation([3, 1, 2, 3])]); + +gap> x := MinimalSemigroupGeneratingSet(S);; +gap> Length(x); +2 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: for a monoid, 1 +gap> S := FullTransformationMonoid(4); + +gap> x := MinimalSemigroupGeneratingSet(S);; +gap> Length(x); +3 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: for a trivial semigroup, 1 +gap> S := FreeSemigroup(1);; +gap> S := S / [[S.1 ^ 2, S.1]]; + +gap> MinimalSemigroupGeneratingSet(S); +[ s1 ] + +#T# MinimalSemigroupGeneratingSet: for a D-trivial semigroup, 1 +gap> n := 3;; +gap> S := UnitriangularBooleanMatMonoid(n); + +gap> x := MinimalSemigroupGeneratingSet(S);; +gap> Length(x); +4 +gap> S = Semigroup(x); +true + +#T# MinimalSemigroupGeneratingSet: not yet implemented, 1 +gap> S := PartitionMonoid(4); + +gap> x := MinimalSemigroupGeneratingSet(S); +Error, Semigroups: MinimalSemigroupGeneratingSet: error, +no further methods for computing minimal generating sets are implemented, + +#T# MinimalMonoidGeneratingSet: for a trivial monoid, 1 +gap> S := FreeMonoid(1);; +gap> S := S / [[S.1, S.1 ^ 0]]; + +gap> MinimalMonoidGeneratingSet(S); +[ ] + +#T# MinimalMonoidGeneratingSet: for a monoid, 1 +gap> S := FullTransformationMonoid(3);; +gap> MinimalMonoidGeneratingSet(S); +[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 3, 1 ] ), + Transformation( [ 1, 2, 1 ] ) ] + +#T# MinimalMonoidGeneratingSet: for a monoid, 2 +gap> S := SymmetricInverseMonoid(2); + +gap> MinimalMonoidGeneratingSet(S); +[ , (1,2) ] +gap> S := AsSemigroup(IsBlockBijectionSemigroup, S); + +gap> MinimalMonoidGeneratingSet(S); +[ , + ] + +#T# MinimalMonoidGeneratingSet: for a monoid, 2 +gap> S := SymmetricInverseMonoid(1); + +gap> MinimalMonoidGeneratingSet(S); +[ , ] +gap> S := AsSemigroup(IsBlockBijectionSemigroup, S);; +gap> MinimalMonoidGeneratingSet(S); +[ ] + +#T# MinimalMonoidGeneratingSet: for a monoid, 3 +gap> x := Bipartition([[1, 3, -1, -2], [2, -3]]);; +gap> S := Monoid(x, x ^ 2); + +gap> MinimalMonoidGeneratingSet(S) = [x]; +true + #T# SEMIGROUPS_UnbindVariables gap> Unbind(D); gap> Unbind(G);