diff --git a/doc/attr.xml b/doc/attr.xml
index a167e3207..7af5c5db5 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 ] ]