From 03bbfef808cc99284bed06ce8caafe47fd2b1de0 Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Tue, 23 Jun 2026 13:41:35 +0100 Subject: [PATCH 1/2] gis: add +/-ve path --- gap/semigroups/semigraph.gd | 4 ++++ gap/semigroups/semigraph.gi | 22 ++++++++++++++++++++++ tst/standard/semigroups/semigraph.tst | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+) 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..c11778e0a 100644 --- a/gap/semigroups/semigraph.gi +++ b/gap/semigroups/semigraph.gi @@ -302,3 +302,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/semigroups/semigraph.tst b/tst/standard/semigroups/semigraph.tst index 3f40e5004..a836eb840 100644 --- a/tst/standard/semigroups/semigraph.tst +++ b/tst/standard/semigroups/semigraph.tst @@ -148,6 +148,26 @@ false gap> G.1 = H.1; false +# Positive/NegativePath +gap> D := ChainDigraph(4); + +gap> S := GraphInverseSemigroup(D); + +gap> x := S.2 * S.3 * S.3 ^ -1 * S.2 ^ -1 * S.1 ^ -1; +e_2e_3e_3^-1e_2^-1e_1^-1 +gap> NegativePath(x); +e_3^-1e_2^-1e_1^-1 +gap> x = PositivePath(x) * NegativePath(x); +true +gap> Size(S); +31 +gap> ForAll(S, x -> x = PositivePath(x) * NegativePath(x)); +true +gap> PositivePath(MultiplicativeZero(S)); +0 +gap> NegativePath(MultiplicativeZero(S)); +0 + # gap> SEMIGROUPS.StopTest(); gap> STOP_TEST("Semigroups package: standard/semigroups/semigraph.tst"); From e2f8fe9a35cb63363dd37cab036a2950f13355ea Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Tue, 23 Jun 2026 14:27:40 +0100 Subject: [PATCH 2/2] congsemigraph: start adding methods for the trace --- gap/congruences/congsemigraph.gd | 9 +++ gap/congruences/congsemigraph.gi | 104 ++++++++++++++++++++++++++++++- gap/semigroups/semigraph.gi | 4 ++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/gap/congruences/congsemigraph.gd b/gap/congruences/congsemigraph.gd index b665d5e10..e9dd44e08 100644 --- a/gap/congruences/congsemigraph.gd +++ b/gap/congruences/congsemigraph.gd @@ -26,3 +26,12 @@ DeclareOperation("MinimalHereditarySubsetsVertex", [IsGraphInverseSemigroup, IsPosInt]); DeclareAttribute("GeneratingCongruencesOfLattice", IsGraphInverseSemigroup); + +DeclareCategory("IsTraceOfCongruenceByWangPair", + IsSemigroupCongruence + and CanComputeEquivalenceRelationPartition + and IsMagmaCongruence + and IsAttributeStoringRep + and IsFinite); + +DeclareAttribute("TraceOfCongruenceByWangPair", IsCongruenceByWangPair); diff --git a/gap/congruences/congsemigraph.gi b/gap/congruences/congsemigraph.gi index f1a9b4a79..ed00b7323 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,104 @@ 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(ViewObj, "for trace of a congruence by Wang pair", +[IsTraceOfCongruenceByWangPair], +function(tr) + Print(ViewString(tr)); +end); + +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; + elif Source(elm1) <> Source(elm2) or Range(elm1) <> Range(elm2) then + return false; + fi; + if Length(p1![1]) > Length(p2![1]) then + tmp := p1; + p1 := p2; + p2 := tmp; + fi; + + for i in [1 .. Length(p1![1])] do + if p1![1][i] <> p2![1][i] then + return false; + 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; + fi; + od; + + return true; +end); + +# TODO add family check to install method below +InstallMethod(ImagesElm, +"for the trace of a congruence by Wang pair and an element", +[IsTraceOfCongruenceByWangPair, IsGraphInverseSemigroupElement], +function(tr, x) + + if not IsIdempotent(x) then + Error("TODO"); + elif not x in Source(tr) then + # TODO if family check done above then remove this clause. + Error("TODO"); + fi; + + #TODO + + +end); + diff --git a/gap/semigroups/semigraph.gi b/gap/semigroups/semigraph.gi index c11778e0a..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);