diff --git a/doc/congsemigraph.xml b/doc/congsemigraph.xml index 2a8bab25e..2d918c4ad 100644 --- a/doc/congsemigraph.xml +++ b/doc/congsemigraph.xml @@ -114,6 +114,38 @@ gap> AsCongruenceByWangPair(cong); <#/GAPDoc> +<#GAPDoc Label="TraceOfCongruenceByWangPair"> + + + The trace of congruence by Wang pair. + + This operation takes cong, a finite graph inverse semigroup + congruence represented by a Wang pair

, and returns an object + representing the trace of cong. + D := Digraph([[2, 3], [3], [4], []]); + +gap> S := GraphInverseSemigroup(D); + +gap> cong := CongruenceByWangPair(S, [4], [2]); + +gap> tr := TraceOfCongruenceByWangPair(cong); + +gap> a := S.2 * S.4 * S.4 ^ -1 * S.2 ^ -1; +e_2e_4e_4^-1e_2^-1 +gap> ImagesElm(tr, a); +[ 0, v_4, e_4e_4^-1, e_2e_4e_4^-1e_2^-1, e_3e_4e_4^-1e_3^-1, e_1e_3e_4e_4^-1e_3^-1e_1^-1 ] +gap> b := S.8; +v_4 +gap> CongruenceTestMembershipNC(tr, a, b); +true +gap> EquivalenceRelationPartition(tr); +[ [ 0, v_4, e_4e_4^-1, e_2e_4e_4^-1e_2^-1, e_3e_4e_4^-1e_3^-1, e_1e_3e_4e_4^-1e_3^-1e_1^-1 ], [ v_2, e_3e_3^-1 ], [ e_1e_1^-1, e_1e_3e_3^-1e_1^-1 ] ] +]]> + + + <#/GAPDoc> + <#GAPDoc Label="GeneratingCongruencesOfLattice"> diff --git a/doc/semigraph.xml b/doc/semigraph.xml index 0bc680519..cd91baf46 100644 --- a/doc/semigraph.xml +++ b/doc/semigraph.xml @@ -187,7 +187,7 @@ gap> GraphOfGraphInverseSemigroup(S); <#GAPDoc Label="IsGraphInverseSemigroupElementCollection"> - + Every collection of elements of a graph inverse semigroup belongs to the category IsGraphInverseSemigroupElementCollection. For example, @@ -258,8 +258,8 @@ gap> VerticesOfGraphInverseSemigroup(S); A positive integer. If v is a vertex of a graph inverse semigroup (i.e. it satisfies - ), then this attribute returns - the index of this vertex in its graph inverse semigroup.

+ ), then this attribute returns the + index of this vertex in S.

D := Digraph([[3, 4], [3, 4], [4], []]); @@ -273,3 +273,74 @@ gap> IndexOfVertexOfGraphInverseSemigroup(v_3); <#/GAPDoc> + +<#GAPDoc Label="EdgesWithRange"> + + + A list of graph inverse semigroup elements. + + If x is a vertex of a graph inverse semigroup (i.e. it satisfies + ), then this attribute returns a list + of all edges e such that Range(e)=x. If x is not a vertex + then it returns all edges with range Source(x). + + +<#/GAPDoc> + +<#GAPDoc Label="PathsWithRange"> + + + A list of graph inverse semigroup elements. + + If x is a vertex of a graph inverse semigroup (i.e. it satisfies + ), then this attribute returns a list + of all paths (products of edges) p such that Range(p)=x, including + vertices as paths of length 0. If x is not a vertex then it returns all + paths with range Source(x). + + +<#/GAPDoc> + +<#GAPDoc Label="EdgesWithSource"> + + + A list of graph inverse semigroup elements. + + If x is a vertex of a graph inverse semigroup (i.e. it satisfies + ), then this attribute returns a list + of all edges e such that Source(e)=x. If x is not a vertex + then it returns all edges with source Range(x). + + +<#/GAPDoc> + +<#GAPDoc Label="PathsWithSource"> + + + A list of graph inverse semigroup elements. + + If x is a vertex of a graph inverse semigroup (i.e. it satisfies + ), then this attribute returns a list + of all paths (products of edges) p such that Source(p)=x, including + vertices as paths of length 0. If x is not a vertex then it returns all + paths with source Range(x). + D := Digraph([[2, 3], [3, 4], [4], []]); + +gap> S := GraphInverseSemigroup(D); + +gap> EdgesWithRange(VerticesOfGraphInverseSemigroup(G)[4]); +Error, Variable: 'G' must have a value +not in any function at *stdin*:3 +gap> EdgesWithRange(VerticesOfGraphInverseSemigroup(S)[4]); +[ e_4, e_5 ] +gap> PathsWithRange(VerticesOfGraphInverseSemigroup(S)[4]); +[ v_4, e_4, e_1e_4, e_5, e_2e_5, e_3e_5, e_1e_3e_5 ] +gap> EdgesWithSource(VerticesOfGraphInverseSemigroup(S)[2]); +[ e_3, e_4 ] +gap> PathsWithSource(VerticesOfGraphInverseSemigroup(S)[2]); +[ v_2, e_3, e_3e_5, e_4 ] +]]> + + +<#/GAPDoc> diff --git a/doc/z-chap07.xml b/doc/z-chap07.xml index f39ccdfbf..da91137d8 100644 --- a/doc/z-chap07.xml +++ b/doc/z-chap07.xml @@ -248,6 +248,11 @@ <#Include Label = "IsGraphInverseSubsemigroup"> <#Include Label = "VerticesOfGraphInverseSemigroup"> <#Include Label = "IndexOfVertexOfGraphInverseSemigroup"> + <#Include Label = "EdgesWithRange"> + <#Include Label = "EdgesWithSource"> + <#Include Label = "PathsWithRange"> + <#Include Label = "PathsWithSource"> + diff --git a/gap/congruences/congsemigraph.gd b/gap/congruences/congsemigraph.gd index b665d5e10..a91fff829 100644 --- a/gap/congruences/congsemigraph.gd +++ b/gap/congruences/congsemigraph.gd @@ -23,6 +23,20 @@ DeclareOperation("CongruenceByWangPair", DeclareOperation("AsCongruenceByWangPair", [IsSemigroupCongruence]); DeclareOperation("MinimalHereditarySubsetsVertex", - [IsGraphInverseSemigroup, IsPosInt]); + [IsDigraph, IsPosInt]); DeclareAttribute("GeneratingCongruencesOfLattice", IsGraphInverseSemigroup); + +DeclareCategory("IsTraceOfCongruenceByWangPair", + IsSemigroupCongruence + and CanComputeEquivalenceRelationPartition + and IsMagmaCongruence + and IsAttributeStoringRep + and IsFinite); + +DeclareAttribute("TraceOfCongruenceByWangPair", IsCongruenceByWangPair); + +DeclareAttribute("EdgesWithRange", IsGraphInverseSemigroupElement); +DeclareAttribute("EdgesWithSource", IsGraphInverseSemigroupElement); +DeclareOperation("PathsWithRange", [IsGraphInverseSemigroupElement]); +DeclareOperation("PathsWithSource", [IsGraphInverseSemigroupElement]); diff --git a/gap/congruences/congsemigraph.gi b/gap/congruences/congsemigraph.gi index f1a9b4a79..259e1dd22 100644 --- a/gap/congruences/congsemigraph.gi +++ b/gap/congruences/congsemigraph.gi @@ -1,8 +1,9 @@ ############################################################################ ## ## congsemigraph.gi -## Copyright (C) 2022 Marina Anagnostopoulou-Merkouri +## Copyright (C) 2022-2026 Marina Anagnostopoulou-Merkouri ## James Mitchell +## Joseph Ward ## ## Licensing information can be found in the README file of this package. ## @@ -287,3 +288,374 @@ InstallMethod(TrivialCongruence, "for a graph inverse semigroup", [IsGraphInverseSemigroup], S -> AsCongruenceByWangPair(SemigroupCongruence(S, []))); + +InstallMethod(TraceOfCongruenceByWangPair, +"for a congruence by Wang pair", +[IsCongruenceByWangPair], +function(cong) + local S, fam, tr; + + S := IdempotentGeneratedSubsemigroup(Source(cong)); + + fam := GeneralMappingsFamily(ElementsFamily(FamilyObj(S)), + ElementsFamily(FamilyObj(S))); + tr := Objectify(NewType(fam, IsTraceOfCongruenceByWangPair), + rec(cong := cong)); + SetSource(tr, S); + SetRange(tr, S); + return tr; +end); + +InstallMethod(JoinSemigroupCongruences, +"for two traces of congruences by Wang pair", +[IsTraceOfCongruenceByWangPair, IsTraceOfCongruenceByWangPair], +{tr1, tr2} -> TraceOfCongruenceByWangPair( +JoinSemigroupCongruences(tr1!.cong, tr2!.cong))); + +InstallMethod(MeetSemigroupCongruences, +"for two traces of congruences by Wang pair", +[IsTraceOfCongruenceByWangPair, IsTraceOfCongruenceByWangPair], +{tr1, tr2} -> TraceOfCongruenceByWangPair( + MeetSemigroupCongruences(tr1!.cong, tr2!.cong))); + +InstallMethod(IsSubrelation, +"for two traces of congruences by Wang pair", +[IsTraceOfCongruenceByWangPair, IsTraceOfCongruenceByWangPair], +{tr1, tr2} -> IsSubrelation(tr1!.cong, tr2!.cong)); + +InstallMethod(IsSuperrelation, +"for two traces of congruences by Wang pair", +[IsTraceOfCongruenceByWangPair, IsTraceOfCongruenceByWangPair], +{tr1, tr2} -> IsSuperrelation(tr1!.cong, tr2!.cong)); + +InstallMethod(ViewObj, "for trace of a congruence by Wang pair", +[IsTraceOfCongruenceByWangPair], +tr -> Print(ViewString(tr))); + +InstallMethod(ViewString, "for a congruence by Wang pair", +[IsTraceOfCongruenceByWangPair], +function(tr) + return StringFormatted( + "", + ViewString(tr!.cong!.H), + ViewString(tr!.cong!.W)); +end); + +# TODO write an explanation of what the next function implements +# TODO add more examples +InstallMethod(CongruenceTestMembershipNC, +"for the trace of a congruence by Wang pair", +[IsTraceOfCongruenceByWangPair, + IsGraphInverseSemigroupElement, + IsGraphInverseSemigroupElement], +function(tr, elm1, elm2) + local p1, p2, range_elm1_in_H, range_elm2_in_H, tmp, S, e, i; + + if elm1 = elm2 then + return true; + fi; + + p1 := PositivePath(elm1); + p2 := PositivePath(elm2); + + range_elm1_in_H := IsMultiplicativeZero(Source(tr), elm1) + or IndexOfVertexOfGraphInverseSemigroup(Range(p1)) in tr!.cong!.H; + range_elm2_in_H := IsMultiplicativeZero(Source(tr), elm2) + or IndexOfVertexOfGraphInverseSemigroup(Range(p2)) in tr!.cong!.H; + + if range_elm1_in_H or range_elm2_in_H then + return range_elm1_in_H and range_elm2_in_H; + # If either is in the zero class, then the other must be + + elif Source(elm1) <> Source(elm2) or Range(elm1) <> Range(elm2) then + return false; # Since the elements are outside the zero class, + # they cannot be related if they have different source and range + fi; + if Length(p1![1]) > Length(p2![1]) then + tmp := p1; + p1 := p2; + p2 := tmp; # let p1 be the longer path + fi; + + for i in [1 .. Length(p1![1])] do + if p1![1][i] <> p2![1][i] then + return false; # check if the shorter path is a prefix of the longer one + fi; + od; + + S := Source(tr!.cong); + for i in [Length(p1![1]) .. Length(p2![1])] do + e := EdgesOfGraphInverseSemigroup(S)[p2![1][i]]; + if not IndexOfVertexOfGraphInverseSemigroup(Source(e)) in tr!.cong!.W then + return false; + # if any of the edges in the longer path are not W edges, + # then the elements are not related + fi; + od; + + return true; + # p1 is a prefix of p2 and every edge in p2 outside p1 is a W-edge, + # so the pair is related +end); + +# TODO add family check to install method below +InstallMethod(EdgesWithRange, +"for a graph inverse semigroup element", +[IsGraphInverseSemigroupElement], +function(x) + local G; + G := FamilyObj(x)!.semigroup; + if not x in G then + Error("TODO"); + elif not IsVertex(x) then + return EdgesWithRange(Source(x)); + else + return Filtered(EdgesOfGraphInverseSemigroup(G), e -> Range(e) = x); + fi; +end); + +InstallMethod(PathsWithRange, +"for a graph inverse semigroup element", +[IsGraphInverseSemigroupElement], +function(x) + local inPaths, e, inPathsPerEdge, G; + G := FamilyObj(x)!.semigroup; + if not x in G then + Error("TODO"); + else + inPaths := [[x]]; + for e in EdgesWithRange(Source(x)) do + inPathsPerEdge := List(PathsWithRange(Source(e)), p -> p * e * x); + Add(inPaths, inPathsPerEdge); + od; + fi; + return Concatenation(inPaths); +end); + +InstallMethod(EdgesWithSource, +"for a graph inverse semigroup element", +[IsGraphInverseSemigroupElement], +function(x) + local G; + G := FamilyObj(x)!.semigroup; + if not x in G then + Error("TODO"); + elif not IsVertex(x) then + return EdgesWithSource(Range(x)); + else + return Filtered(EdgesOfGraphInverseSemigroup(G), e -> Source(e) = x); + fi; +end); + +InstallMethod(PathsWithSource, +"for a graph inverse semigroup element", +[IsGraphInverseSemigroupElement], +function(x) + local outPaths, e, outPathsPerEdge, G; + G := FamilyObj(x)!.semigroup; + if not x in G then + Error("TODO"); + else + outPaths := [[x]]; + for e in EdgesWithSource(Range(x)) do + outPathsPerEdge := List(PathsWithSource(Range(e)), p -> x * e * p); + Add(outPaths, outPathsPerEdge); + od; + fi; + return Concatenation(outPaths); +end); + +InstallMethod(ImagesElm, +"for the trace of a congruence by Wang pair and an element", +[IsTraceOfCongruenceByWangPair, IsGraphInverseSemigroupElement], +function(tr, x) + local class, p; + if not IsIdempotent(x) then + Error("TODO"); + elif not FamilyRange(FamilyObj(tr!.cong))!.semigroup = + FamilyObj(x)!.semigroup then + Error("TODO"); + fi; + p := PositivePath(x); + if IsMultiplicativeZero(Source(tr!.cong), x) or ( + IndexOfVertexOfGraphInverseSemigroup(Range(p)) in tr!.cong!.H) then + return Concatenation([MultiplicativeZero(Source(tr!.cong))], + Concatenation(List(tr!.cong!.H, h -> List(PathsWithRange( + VerticesOfGraphInverseSemigroup(Source(tr!.cong))[h]), + p -> p * p ^ -1)))); + else + class := [x]; + while IndexOfVertexOfGraphInverseSemigroup(Range(p)) in tr!.cong!.W do + p := p * First(Filtered(EdgesWithSource(Range(p)), e -> not + IndexOfVertexOfGraphInverseSemigroup(Range(e)) + in tr!.cong!.H)); + Add(class, p * p ^ -1); + od; + if not IsVertex(x) then + p := PositivePath(x); + while (not (IsVertex(p)) and IndexOfVertexOfGraphInverseSemigroup( + Source(EdgesOfGraphInverseSemigroup(Source(tr!.cong))[Last(p![1])])) + in tr!.cong!.W) do + if Length(p![1]) > 1 then + p := EvaluateWord(GeneratorsOfSemigroup(Source(tr!.cong)), + p![1]{[1 .. Length(p![1]) - 1]}); + else + p := Source(p); + fi; + Add(class, p * p ^ -1); + od; + fi; + fi; + return class; +end); + +InstallMethod(EquivalenceRelationPartition, +"for the trace of a congruence by Wang Pair", +[IsTraceOfCongruenceByWangPair], +function(tr) + local classes, w, p; + classes := [Concatenation([MultiplicativeZero(Source(tr!.cong))], + Concatenation(List(tr!.cong!.H, h -> List(PathsWithRange( + VerticesOfGraphInverseSemigroup(Source(tr!.cong))[h]), + p -> p * p ^ -1))))]; + if Length(classes[1]) = 1 then + classes := []; + fi; + for w in tr!.cong!.W do + if Intersection(InNeighbours(GraphOfGraphInverseSemigroup(Source( + tr!.cong)))[w], tr!.cong!.W) = [] then + for p in PathsWithRange(VerticesOfGraphInverseSemigroup( + Source(tr!.cong))[w]) do + Add(classes, p * ImagesElm(tr, VerticesOfGraphInverseSemigroup( + Source(tr!.cong))[w]) * p ^ -1); + od; + else + Add(classes, ImagesElm(tr, VerticesOfGraphInverseSemigroup(Source( + tr!.cong))[w])); + fi; + od; + return classes; +end); + + # +InstallMethod(EquivalenceRelationPartition, +"for a congruence by Wang Pair", +[IsCongruenceByWangPair], +function(cong) + local classes, w, p, q, ps, pws; + classes := [Concatenation([MultiplicativeZero(Source(cong))], + Concatenation(List(cong!.H, h -> Concatenation(List(PathsWithRange( + VerticesOfGraphInverseSemigroup(Source(cong))[h]), p -> List( + PathsWithRange(VerticesOfGraphInverseSemigroup(Source(cong))[h]), + q -> p * q ^ -1))))))]; + if Length(classes[1]) = 1 then + classes := []; + fi; + for w in cong!.W do + if Intersection(InNeighbours(GraphOfGraphInverseSemigroup( + Source(cong)))[w], cong!.W) = [] then + for p in PathsWithRange(VerticesOfGraphInverseSemigroup( + Source(cong))[w]) do + for q in PathsWithRange(VerticesOfGraphInverseSemigroup( + Source(cong))[w]) do + Add(classes, p * ImagesElm(TraceOfCongruenceByWangPair(cong), + VerticesOfGraphInverseSemigroup(Source(cong))[w]) * q ^ -1); + od; + od; + else + ps := PathsWithRange(VerticesOfGraphInverseSemigroup(Source(cong))[w]); + pws := Filtered(ps, p -> (not IsVertex(p)) and ( + IndexOfVertexOfGraphInverseSemigroup(Source( + EdgesOfGraphInverseSemigroup(Source(cong))[Last(p![1])])) + in cong!.W)); + ps := Difference(ps, pws); + for p in ps do + for q in ps do + Add(classes, p * ImagesElm(TraceOfCongruenceByWangPair(cong), + VerticesOfGraphInverseSemigroup(Source(cong))[w]) * q ^ -1); + od; + for q in pws do + Add(classes, p * ImagesElm(TraceOfCongruenceByWangPair(cong), + VerticesOfGraphInverseSemigroup(Source(cong))[w]) * q ^ -1); + od; + od; + for p in pws do + for q in ps do + Add(classes, p * ImagesElm(TraceOfCongruenceByWangPair(cong), + VerticesOfGraphInverseSemigroup(Source(cong))[w]) * q ^ -1); + od; + for q in pws do + if Last(p![1]) <> Last(q![1]) then + Add(classes, p * ImagesElm(TraceOfCongruenceByWangPair(cong), + VerticesOfGraphInverseSemigroup(Source(cong))[w]) * q ^ -1); + fi; + od; + od; + fi; + od; + return classes; +end); + +InstallMethod(ImagesElm, +"for a congruence by Wang Pair and an element", +[IsCongruenceByWangPair, IsGraphInverseSemigroupElement], +function(cong, x) + local p, q; + if not x in Source(cong) then + Error("TODO"); + elif IsMultiplicativeZero(Source(cong), x) or ( + IndexOfVertexOfGraphInverseSemigroup(Range(PositivePath(x))) in cong!.H) + then + return Concatenation([MultiplicativeZero(Source(cong))], Concatenation( + Concatenation(List(cong!.H, h -> List(PathsWithRange( + VerticesOfGraphInverseSemigroup(Source(cong))[h]), + p -> List(PathsWithRange( + VerticesOfGraphInverseSemigroup(Source(cong))[h]), + q -> p * q ^ -1)))))); + elif IsIdempotent(x) then + return ImagesElm(TraceOfCongruenceByWangPair(cong), x); + else + p := PositivePath(x); + q := NegativePath(x); + if Last(p![1]) = - First(q![1]) and (not IsVertex(p)) + and (IndexOfVertexOfGraphInverseSemigroup(Source( + EdgesOfGraphInverseSemigroup(Source(cong))[-First(q![1])])) + in cong!.W) then + if Length(p![1]) = 1 then + p := Source(p); + q := EvaluateWord(GeneratorsOfSemigroup(Source(cong)), + q![1]{[2 .. Length(q![1])]}); + elif Length(q![1]) = 1 then + p := EvaluateWord(GeneratorsOfSemigroup(Source(cong)), + p![1]{[1 .. Length(p![1]) - 1]}); + q := Range(q); + else + p := EvaluateWord(GeneratorsOfSemigroup(Source(cong)), + p![1]{[1 .. Length(p![1]) - 1]}); + q := EvaluateWord(GeneratorsOfSemigroup(Source(cong)), + q![1]{[2 .. Length(q![1])]}); + fi; + return ImagesElm(cong, p * q); + else + return p * ImagesElm(TraceOfCongruenceByWangPair(cong), Range(p)) * q; + fi; + fi; +end); + +InstallMethod(CongruenceTestMembershipNC, +"for a congruence by Wang pair and two graph inverse semigroup elements", +[IsCongruenceByWangPair, IsGraphInverseSemigroupElement, + IsGraphInverseSemigroupElement], +138, +function(cong, x, y) + return CongruenceTestMembershipNC(TraceOfCongruenceByWangPair(cong), + x ^ -1 * x, y ^ -1 * y) + and (IsIdempotent(x * y ^ -1) + or IndexOfVertexOfGraphInverseSemigroup(Range + (PositivePath(x * y ^ -1))) in cong!.H); +end); + +InstallMethod(TraceOfSemigroupCongruence, +"for a congruence by Wang Pair", +[IsCongruenceByWangPair], +138, TraceOfCongruenceByWangPair); diff --git a/gap/semigroups/semigraph.gd b/gap/semigroups/semigraph.gd index 69de98a70..e939730c3 100644 --- a/gap/semigroups/semigraph.gd +++ b/gap/semigroups/semigraph.gd @@ -27,6 +27,10 @@ DeclareAttribute("Source", IsGraphInverseSemigroupElement); DeclareOperation("IsVertex", [IsGraphInverseSemigroupElement]); +DeclareAttribute("PositivePath", IsGraphInverseSemigroupElement); +DeclareAttribute("NegativePath", IsGraphInverseSemigroupElement); +# TODO IsEdge? + InstallTrueMethod(IsGeneratorsOfInverseSemigroup, IsGraphInverseSemigroupElementCollection); diff --git a/gap/semigroups/semigraph.gi b/gap/semigroups/semigraph.gi index 69e2b0f79..46778e5be 100644 --- a/gap/semigroups/semigraph.gi +++ b/gap/semigroups/semigraph.gi @@ -8,6 +8,10 @@ ############################################################################# ## +# TODO: Implement special methods for: +# * NrIdempotents +# * IdempotentGeneratedSubsemigroup + InstallMethod(AsMonoid, "for a graph inverse semigroup", [IsGraphInverseSemigroup], ReturnFail); @@ -302,3 +306,25 @@ InstallMethod(IsWholeFamily, "for a subsemigroup of a graph inverse semigroup", [IsGraphInverseSubsemigroup], S -> Size(ElementsFamily(FamilyObj(S))!.semigroup) = Size(S)); + +InstallMethod(PositivePath, +"for a graph inverse semigroup element", +[IsGraphInverseSemigroupElement], +function(elt) + local pos, S; + + pos := PositionProperty(elt![1], IsNegInt); + if pos = fail then + return elt; + elif pos = 1 then + return Source(elt); + fi; + # Get the semigroup containing "elt" + S := FamilyObj(elt)!.semigroup; + return EvaluateWord(GeneratorsOfSemigroup(S), elt![1]{[1 .. pos - 1]}); +end); + +InstallMethod(NegativePath, +"for a graph inverse semigroup element", +[IsGraphInverseSemigroupElement], +elt -> PositivePath(elt ^ -1) ^ -1); diff --git a/tst/standard/congruences/congsemigraph.tst b/tst/standard/congruences/congsemigraph.tst index a4a18b243..ef21ecce0 100644 --- a/tst/standard/congruences/congsemigraph.tst +++ b/tst/standard/congruences/congsemigraph.tst @@ -9,7 +9,7 @@ ############################################################################ # -#@local C, D, L, S, cong, cong1, cong2, e_1, e_3, i, j, join, meet, pos, val +#@local c, C, D, L, S, cong, cong1, cong2, e_1, e_3, i, j, join, meet, pos, val gap> START_TEST("Semigroups package: standard/congruences/congsemigraph.tst"); gap> LoadPackage("semigroups", false);; @@ -98,15 +98,14 @@ gap> AsSemigroupCongruenceByGeneratingPairs(C); <2-sided semigroup congruence over with 2 generating pairs> gap> EquivalenceRelationPartition(C); -[ [ e_1, e_1e_3e_3^-1 ], - [ e_4, v_4, e_4^-1, 0, e_2e_4, e_3e_4, e_4e_4^-1, e_4^-1e_2^-1, - e_4^-1e_3^-1, e_1e_3e_4, e_2e_4e_4^-1, e_3e_4e_4^-1, e_4e_4^-1e_2^-1, - e_4e_4^-1e_3^-1, e_4^-1e_3^-1e_1^-1, e_1e_3e_4e_4^-1, - e_2e_4e_4^-1e_2^-1, e_2e_4e_4^-1e_3^-1, e_3e_4e_4^-1e_2^-1, - e_3e_4e_4^-1e_3^-1, e_4e_4^-1e_3^-1e_1^-1, e_1e_3e_4e_4^-1e_2^-1, - e_1e_3e_4e_4^-1e_3^-1, e_2e_4e_4^-1e_3^-1e_1^-1, - e_3e_4e_4^-1e_3^-1e_1^-1, e_1e_3e_4e_4^-1e_3^-1e_1^-1 ], - [ v_2, e_3e_3^-1 ], [ e_1^-1, e_3e_3^-1e_1^-1 ], +[ [ 0, v_4, e_4^-1, e_4^-1e_2^-1, e_4^-1e_3^-1, e_4^-1e_3^-1e_1^-1, e_4, + e_4e_4^-1, e_4e_4^-1e_2^-1, e_4e_4^-1e_3^-1, e_4e_4^-1e_3^-1e_1^-1, + e_2e_4, e_2e_4e_4^-1, e_2e_4e_4^-1e_2^-1, e_2e_4e_4^-1e_3^-1, + e_2e_4e_4^-1e_3^-1e_1^-1, e_3e_4, e_3e_4e_4^-1, e_3e_4e_4^-1e_2^-1, + e_3e_4e_4^-1e_3^-1, e_3e_4e_4^-1e_3^-1e_1^-1, e_1e_3e_4, + e_1e_3e_4e_4^-1, e_1e_3e_4e_4^-1e_2^-1, e_1e_3e_4e_4^-1e_3^-1, + e_1e_3e_4e_4^-1e_3^-1e_1^-1 ], [ v_2, e_3e_3^-1 ], + [ e_1^-1, e_3e_3^-1e_1^-1 ], [ e_1, e_1e_3e_3^-1 ], [ e_1e_1^-1, e_1e_3e_3^-1e_1^-1 ] ] gap> D := ChainDigraph(4); @@ -287,6 +286,10 @@ gap> IsSuperrelation(cong1, cong2); false gap> IsSuperrelation(cong2, cong1); true +gap> IsSubrelation(TraceOfCongruenceByWangPair(cong1), TraceOfCongruenceByWangPair(cong2)) = IsSubrelation(cong1, cong2); +true +gap> IsSuperrelation(TraceOfCongruenceByWangPair(cong1), TraceOfCongruenceByWangPair(cong2)) = IsSuperrelation(cong1, cong2); +true gap> cong1 := CongruenceByWangPair(S, [2, 3, 4], []); gap> cong2 := CongruenceByWangPair(S, [4], [1]); @@ -416,6 +419,25 @@ gap> val := true;; > od; > val; true +gap> c := C[6]; + +gap> EquivalenceRelationPartition(c); +[ [ 0, v_4, e_3^-1, e_3^-1e_1^-1, e_4^-1, e_4^-1e_2^-1, e_4^-1e_2^-1e_1^-1, + e_3, e_3e_3^-1, e_3e_3^-1e_1^-1, e_3e_4^-1, e_3e_4^-1e_2^-1, + e_3e_4^-1e_2^-1e_1^-1, e_1e_3, e_1e_3e_3^-1, e_1e_3e_3^-1e_1^-1, + e_1e_3e_4^-1, e_1e_3e_4^-1e_2^-1, e_1e_3e_4^-1e_2^-1e_1^-1, e_4, + e_4e_3^-1, e_4e_3^-1e_1^-1, e_4e_4^-1, e_4e_4^-1e_2^-1, + e_4e_4^-1e_2^-1e_1^-1, e_2e_4, e_2e_4e_3^-1, e_2e_4e_3^-1e_1^-1, + e_2e_4e_4^-1, e_2e_4e_4^-1e_2^-1, e_2e_4e_4^-1e_2^-1e_1^-1, e_1e_2e_4, + e_1e_2e_4e_3^-1, e_1e_2e_4e_3^-1e_1^-1, e_1e_2e_4e_4^-1, + e_1e_2e_4e_4^-1e_2^-1, e_1e_2e_4e_4^-1e_2^-1e_1^-1 ], + [ v_1, e_1e_1^-1, e_1e_2e_2^-1e_1^-1 ], [ v_2, e_2e_2^-1 ], + [ e_1^-1, e_2e_2^-1e_1^-1 ], [ e_1, e_1e_2e_2^-1 ] ] +gap> EquivalenceRelationPartition(TraceOfCongruenceByWangPair(c)); +[ [ 0, v_4, e_3e_3^-1, e_1e_3e_3^-1e_1^-1, e_4e_4^-1, e_2e_4e_4^-1e_2^-1, + e_1e_2e_4e_4^-1e_2^-1e_1^-1 ], [ v_1, e_1e_1^-1, e_1e_2e_2^-1e_1^-1 ], + [ v_2, e_2e_2^-1 ] ] +gap> # gap> SEMIGROUPS.StopTest(); diff --git a/tst/standard/semigroups/semigraph.tst b/tst/standard/semigroups/semigraph.tst index 3f40e5004..0a18a04c7 100644 --- a/tst/standard/semigroups/semigraph.tst +++ b/tst/standard/semigroups/semigraph.tst @@ -8,8 +8,7 @@ ############################################################################# ## -#@local D, DigraphNrVertices, DigraphRange, DigraphSource, S, gr, s, x, y -#@local G, H +#@local D, DigraphNrVertices, DigraphRange, DigraphSource, S, gr, s, x, y, G, H gap> START_TEST("Semigroups package: standard/semigroups/semigraph.tst"); gap> LoadPackage("semigroups", false);; @@ -59,6 +58,63 @@ gap> List(x, Range); [ v_4, v_4, v_2, v_1, v_2, v_1, v_1, v_2, v_1, v_3, v_4, v_2, v_1, v_5, v_4, v_2, v_1, v_3, v_4, v_2, v_1, v_5, v_4, v_2, v_1, v_3, v_4, v_2, v_1, v_5, v_4, v_2, v_1, v_1, v_2, v_3, v_4, v_5 ] +gap> List(x, PositivePath); +[ v_5, v_3, v_5, v_5, v_3, v_3, v_2, e_1, e_1, e_1e_2, e_1e_2, e_1e_2, + e_1e_2, e_1e_3, e_1e_3, e_1e_3, e_1e_3, e_2, e_2, e_2, e_2, e_3, e_3, e_3, + e_3, e_4, e_4, e_4, e_4, e_5, e_5, e_5, e_5, v_1, v_2, v_3, v_4, v_5 ] +gap> List(x, NegativePath); +[ e_5^-1, e_4^-1, e_3^-1, e_3^-1e_1^-1, e_2^-1, e_2^-1e_1^-1, e_1^-1, v_2, + e_1^-1, v_3, e_4^-1, e_2^-1, e_2^-1e_1^-1, v_5, e_5^-1, e_3^-1, + e_3^-1e_1^-1, v_3, e_4^-1, e_2^-1, e_2^-1e_1^-1, v_5, e_5^-1, e_3^-1, + e_3^-1e_1^-1, v_3, e_4^-1, e_2^-1, e_2^-1e_1^-1, v_5, e_5^-1, e_3^-1, + e_3^-1e_1^-1, v_1, v_2, v_3, v_4, v_5 ] +gap> List(x, EdgesWithSource); +[ [ e_4, e_5 ], [ e_4, e_5 ], [ e_2, e_3 ], [ e_1 ], [ e_2, e_3 ], [ e_1 ], + [ e_1 ], [ e_2, e_3 ], [ e_1 ], [ ], [ e_4, e_5 ], [ e_2, e_3 ], [ e_1 ], + [ ], [ e_4, e_5 ], [ e_2, e_3 ], [ e_1 ], [ ], [ e_4, e_5 ], + [ e_2, e_3 ], [ e_1 ], [ ], [ e_4, e_5 ], [ e_2, e_3 ], [ e_1 ], [ ], + [ e_4, e_5 ], [ e_2, e_3 ], [ e_1 ], [ ], [ e_4, e_5 ], [ e_2, e_3 ], + [ e_1 ], [ e_1 ], [ e_2, e_3 ], [ ], [ e_4, e_5 ], [ ] ] +gap> List(x, EdgesWithRange); +[ [ e_3, e_5 ], [ e_2, e_4 ], [ e_3, e_5 ], [ e_3, e_5 ], [ e_2, e_4 ], + [ e_2, e_4 ], [ e_1 ], [ ], [ ], [ ], [ ], [ ], [ ], [ ], [ ], + [ ], [ ], [ e_1 ], [ e_1 ], [ e_1 ], [ e_1 ], [ e_1 ], [ e_1 ], [ e_1 ], + [ e_1 ], [ ], [ ], [ ], [ ], [ ], [ ], [ ], [ ], [ ], [ e_1 ], + [ e_2, e_4 ], [ ], [ e_3, e_5 ] ] +gap> List(x, PathsWithSource); +[ [ e_5^-1, 0, v_5 ], [ e_4^-1, v_3, 0 ], [ e_3^-1, 0, v_5 ], + [ e_3^-1e_1^-1, e_3^-1, 0, v_5 ], [ e_2^-1, v_3, 0 ], + [ e_2^-1e_1^-1, e_2^-1, v_3, 0 ], [ e_1^-1, v_2, e_2, e_3 ], + [ e_1, e_1e_2, e_1e_3 ], [ e_1e_1^-1, e_1, e_1e_2, e_1e_3 ], [ e_1e_2 ], + [ e_1e_2e_4^-1, e_1e_2, 0 ], [ e_1e_2e_2^-1, e_1e_2, 0 ], + [ e_1e_2e_2^-1e_1^-1, e_1e_2e_2^-1, e_1e_2, 0 ], [ e_1e_3 ], + [ e_1e_3e_5^-1, 0, e_1e_3 ], [ e_1e_3e_3^-1, 0, e_1e_3 ], + [ e_1e_3e_3^-1e_1^-1, e_1e_3e_3^-1, 0, e_1e_3 ], [ e_2 ], + [ e_2e_4^-1, e_2, 0 ], [ e_2e_2^-1, e_2, 0 ], + [ e_2e_2^-1e_1^-1, e_2e_2^-1, e_2, 0 ], [ e_3 ], [ e_3e_5^-1, 0, e_3 ], + [ e_3e_3^-1, 0, e_3 ], [ e_3e_3^-1e_1^-1, e_3e_3^-1, 0, e_3 ], [ e_4 ], + [ e_4e_4^-1, e_4, 0 ], [ e_4e_2^-1, e_4, 0 ], + [ e_4e_2^-1e_1^-1, e_4e_2^-1, e_4, 0 ], [ e_5 ], [ e_5e_5^-1, 0, e_5 ], + [ e_5e_3^-1, 0, e_5 ], [ e_5e_3^-1e_1^-1, e_5e_3^-1, 0, e_5 ], + [ v_1, e_1, e_1e_2, e_1e_3 ], [ v_2, e_2, e_3 ], [ v_3 ], [ v_4, e_4, e_5 ], + [ v_5 ] ] +gap> List(x, PathsWithRange); +[ [ e_5^-1, e_3e_5^-1, e_1e_3e_5^-1, e_5e_5^-1 ], + [ e_4^-1, e_2e_4^-1, e_1e_2e_4^-1, e_4e_4^-1 ], + [ e_3^-1, e_3e_3^-1, e_1e_3e_3^-1, e_5e_3^-1 ], + [ e_3^-1e_1^-1, e_3e_3^-1e_1^-1, e_1e_3e_3^-1e_1^-1, e_5e_3^-1e_1^-1 ], + [ e_2^-1, e_2e_2^-1, e_1e_2e_2^-1, e_4e_2^-1 ], + [ e_2^-1e_1^-1, e_2e_2^-1e_1^-1, e_1e_2e_2^-1e_1^-1, e_4e_2^-1e_1^-1 ], + [ e_1^-1, e_1e_1^-1 ], [ e_1 ], [ e_1e_1^-1 ], [ e_1e_2 ], [ e_1e_2e_4^-1 ], + [ e_1e_2e_2^-1 ], [ e_1e_2e_2^-1e_1^-1 ], [ e_1e_3 ], [ e_1e_3e_5^-1 ], + [ e_1e_3e_3^-1 ], [ e_1e_3e_3^-1e_1^-1 ], [ e_2, e_1e_2 ], + [ e_2e_4^-1, e_1e_2e_4^-1 ], [ e_2e_2^-1, e_1e_2e_2^-1 ], + [ e_2e_2^-1e_1^-1, e_1e_2e_2^-1e_1^-1 ], [ e_3, e_1e_3 ], + [ e_3e_5^-1, e_1e_3e_5^-1 ], [ e_3e_3^-1, e_1e_3e_3^-1 ], + [ e_3e_3^-1e_1^-1, e_1e_3e_3^-1e_1^-1 ], [ e_4 ], [ e_4e_4^-1 ], + [ e_4e_2^-1 ], [ e_4e_2^-1e_1^-1 ], [ e_5 ], [ e_5e_5^-1 ], [ e_5e_3^-1 ], + [ e_5e_3^-1e_1^-1 ], [ v_1 ], [ v_2, e_1 ], [ v_3, e_2, e_1e_2, e_4 ], + [ v_4 ], [ v_5, e_3, e_1e_3, e_5 ] ] gap> AssignGeneratorVariables(S); gap> String(gr); "DigraphFromDigraph6String(\"&DOS@O?\")"