From eae96f758b966cbeac1432c6b2e96841c2e0a2c7 Mon Sep 17 00:00:00 2001 From: Meike Weiss Date: Fri, 9 Oct 2026 12:21:45 +0200 Subject: [PATCH 1/2] add IsDigraphRotationSystem --- doc/attr.xml | 28 ++++++++++++++++++++++++ gap/attr.gd | 1 + gap/attr.gi | 46 ++++++++++++++++++++++++++++---------- tst/standard/attr.tst | 51 +++++++++++++++++++++++++++++++++---------- 4 files changed, 104 insertions(+), 22 deletions(-) diff --git a/doc/attr.xml b/doc/attr.xml index a167e3207..cf02e8201 100644 --- a/doc/attr.xml +++ b/doc/attr.xml @@ -1530,6 +1530,34 @@ gap> DigraphAllChordlessCycles(D); <#/GAPDoc> + +<#GAPDoc Label="DigraphIsRotationSystem"> + + + A boolean. + + If digraph is a symmetric digraph and list is a rotation system of digraph, + then IsDigraphRotationSystem returns true if list is a rotation system for + digraph, and false otherwise. + list is a rotation system of digraph if list has an entry for each vertex + v containing all neighbours of v. + + The operation IsDigraphRotationSystem ignores multiple edges and loops.

+ Here are some examples: + D1 := DigraphSymmetricClosure(CycleDigraph(4));; +gap> planar := PlanarEmbedding(D1);; +gap> IsDigraphRotationSystem(D1,planar); +true +gap> nonPlanar := [[2, 4], [1, 3], [2, 4], [1, 3]];; +gap> IsDigraphRotationSystem(D1,nonPlanar); +true +]]> + + +<#/GAPDoc> + + <#GAPDoc Label="FacialWalks"> diff --git a/gap/attr.gd b/gap/attr.gd index 30e284684..446d1040d 100644 --- a/gap/attr.gd +++ b/gap/attr.gd @@ -65,6 +65,7 @@ DeclareAttribute("DigraphAllUndirectedSimpleCircuits", IsDigraph); DeclareOperation("DigraphAllChordlessCyclesOfMaximalLength", [IsDigraph, IsInt]); DeclareAttribute("DigraphAllChordlessCycles", IsDigraph); +DeclareOperation("IsDigraphRotationSystem", [IsDigraph, IsList]); DeclareOperation("FacialWalks", [IsDigraph, IsList]); DeclareAttribute("HamiltonianPath", IsDigraph); DeclareAttribute("DigraphPeriod", IsDigraph); diff --git a/gap/attr.gi b/gap/attr.gi index 06a21c091..857c96994 100644 --- a/gap/attr.gi +++ b/gap/attr.gi @@ -1853,6 +1853,37 @@ InstallMethod(DigraphAllChordlessCycles, "for a digraph", [IsDigraph], D -> DigraphAllChordlessCyclesOfMaximalLength(D, INTOBJ_MAX)); +# Checks if a given list is a rotation system for a given digraph +InstallMethod(IsDigraphRotationSystem, "for a digraph and a list", +[IsDigraph, IsList], +function(digraph, rotationSystem) + + local D, i, v; + + if not IsSymmetricDigraph(digraph) then + ErrorNoReturn("the argument must be a symmetric digraph,"); + fi; + + if Length(rotationSystem) <> DigraphNrVertices(digraph) then + return false; + fi; + + D := DigraphRemoveLoops(DigraphRemoveAllMultipleEdges( + DigraphMutableCopyIfMutable(digraph))); + + for i in [1 .. Length(rotationSystem)] do + if Length(rotationSystem[i]) <> Length(OutNeighboursOfVertex(D, i)) then + return false; + fi; + for v in rotationSystem[i] do + if not IsDigraphEdge(D, i, v) then + return false; + fi; + od; + od; + return true; +end); + # Compute for a given rotation system the facial walks InstallMethod(FacialWalks, "for a digraph and a dense list", [IsDigraph, IsDenseList], @@ -1863,17 +1894,9 @@ function(D, rotationSystem) ErrorNoReturn("the argument must be a symmetric digraph,"); fi; - if Length(rotationSystem) <> DigraphNrVertices(D) - or not ForAll(rotationSystem, IsList) then - ErrorNoReturn("the 2nd argument (dense list ) is not a ", - "rotation system for the 1st argument (digraph ), ", - "expected a list of ", DigraphNrVertices(D), " lists,"); - fi; - - if Union(rotationSystem) <> DigraphVertices(D) then - ErrorNoReturn("the 2nd argument (dense list ) is not a ", - "rotation system for the 1st argument (digraph ), ", - "expected its union to be the vertices of ,"); + if not IsDigraphRotationSystem(D, rotationSystem) then + ErrorNoReturn("the 2nd argument (list ) is not a rotation ", + "system for the 1st argument (digraph )"); fi; # computes a facial cycles starting with the edge 'startEdge' @@ -3639,6 +3662,7 @@ function(digraph) fi; return Minimum(min, Minimum(OutDegrees(EdgeD)), Minimum(InDegrees(EdgeD))); + end); # The following function is a transliteration from python to GAP of diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst index 579fcc8ad..d091377b1 100644 --- a/tst/standard/attr.tst +++ b/tst/standard/attr.tst @@ -1097,18 +1097,47 @@ gap> DigraphAllUndirectedSimpleCircuits(g); [ 4, 3, 9, 5, 7, 8, 6, 10 ], [ 4, 3, 9, 10 ], [ 5, 6, 8, 7 ], [ 9, 5, 6, 10 ], [ 9, 5, 7, 8, 6, 10 ] ] -# FacialCycles +# IsDigraphRotationSystem gap> g := DigraphSymmetricClosure(CycleDigraph(3));; -gap> FacialWalks(g, []); -Error, the 2nd argument (dense list ) is not a rotation system\ - for the 1st argument (digraph ), expected a list of 3 lists, -gap> FacialWalks(g, [1]); -Error, the 2nd argument (dense list ) is not a rotation system\ - for the 1st argument (digraph ), expected a list of 3 lists, -gap> FacialWalks(g, [[4], [1], [3]]); -Error, the 2nd argument (dense list ) is not a rotation system\ - for the 1st argument (digraph ), expected its union to be the vertices of \ -, +gap> IsDigraphRotationSystem(g, []); +false +gap> IsDigraphRotationSystem(g, [1]); +false +gap> IsDigraphRotationSystem(g, [[4], [1], [3]]); +false +gap> g := DigraphSymmetricClosure(ChainDigraph(3));; +gap> IsDigraphRotationSystem(g, PlanarEmbedding(g)); +true +gap> g := Digraph([]);; +gap> rotationSy := [];; +gap> IsDigraphRotationSystem(g, rotationSy); +true +gap> g := Digraph([[2], [1, 3], [2, 4], [3]]);;; +gap> rotationSy := [[2], [1, 3], [2, 4], [3]];; +gap> IsDigraphRotationSystem(g, rotationSy); +true +gap> g := DigraphSymmetricClosure(CycleDigraph(4));; +gap> planar := PlanarEmbedding(g); +[ [ 2, 4 ], [ 3, 1 ], [ 4, 2 ], [ 1, 3 ] ] +gap> IsDigraphRotationSystem(g, planar); +true +gap> nonPlanar := [[2, 4], [1, 3], [2, 4], [1, 3]];; +gap> IsDigraphRotationSystem(g, nonPlanar); +true +gap> g := CompleteMultipartiteDigraph([2, 2, 2]);; +gap> rotationSystem := PlanarEmbedding(g); +[ [ 3, 5, 4, 6 ], [ 6, 4, 5, 3 ], [ 6, 2, 5, 1 ], [ 1, 5, 2, 6 ], + [ 1, 3, 2, 4 ], [ 1, 4, 2, 3 ] ] +gap> IsDigraphRotationSystem(g, rotationSystem); +true +gap> g := Digraph([[2, 3, 4], [1, 3, 5], [1, 2, 4], [1, 3, 5], [2, 4, 6], [5, 7, 9], [6, 8, 10], [7, 9, 10], [6, 8, 10], [7, 8, 9]]);; +gap> rotationSy := PlanarEmbedding(g); +[ [ 2, 4, 3 ], [ 3, 5, 1 ], [ 1, 4, 2 ], [ 1, 5, 3 ], [ 2, 4, 6 ], + [ 5, 7, 9 ], [ 8, 10, 6 ], [ 9, 10, 7 ], [ 6, 10, 8 ], [ 7, 8, 9 ] ] +gap> IsDigraphRotationSystem(g, rotationSy); +true + +# FacialCycles gap> g := DigraphSymmetricClosure(ChainDigraph(3));; gap> FacialWalks(g, PlanarEmbedding(g)); [ [ 1, 2, 3, 2 ] ] From 2c285417e89430e04575e02aa2f320a32a7a7a89 Mon Sep 17 00:00:00 2001 From: Meike Weiss Date: Fri, 9 Oct 2026 12:31:21 +0200 Subject: [PATCH 2/2] gaplint error --- doc/attr.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/attr.xml b/doc/attr.xml index cf02e8201..7af5c5db5 100644 --- a/doc/attr.xml +++ b/doc/attr.xml @@ -1547,10 +1547,10 @@ gap> DigraphAllChordlessCycles(D); D1 := DigraphSymmetricClosure(CycleDigraph(4));; gap> planar := PlanarEmbedding(D1);; -gap> IsDigraphRotationSystem(D1,planar); +gap> IsDigraphRotationSystem(D1, planar); true gap> nonPlanar := [[2, 4], [1, 3], [2, 4], [1, 3]];; -gap> IsDigraphRotationSystem(D1,nonPlanar); +gap> IsDigraphRotationSystem(D1, nonPlanar); true ]]>