Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions doc/attr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,52 @@ gap> DigraphAllChordlessCycles(D);
</ManSection>
<#/GAPDoc>


<#GAPDoc Label="DigraphIsRotationSystem">
<ManSection>
<Oper Name="IsDigraphRotationSystem" Arg="digraph, list"/>
<Returns>A boolean.</Returns>
<Description>
<C>IsDigraphRotationSystem</C> returns <C>true</C> if <A>digraph</A> is a symmetric digraph
and <A>list</A> is a rotation system of <A>digraph</A>, and <C>false</C> otherwise.
A rotation system of <A>digraph</A> describes, for every vertex, a cyclic
ordering of its neighbours. More precisely, <A>list</A> is a rotation
system of <A>digraph</A> if and only if:
<List>
<Item>
<A>list</A> has length <C>DigraphNrVertices(<A>digraph</A>)</C>,
i.e. there is exactly one entry for every vertex; and
</Item>
<Item>
for every vertex <C>v</C>, the entry <C><A>list</A>[v]</C> is a list
which contains every neighbour of <C>v</C> exactly once, and no other
vertices.
</Item>
</List>
The order of the entries in <C><A>list</A>[v]</C> is interpreted
cyclically: the successor of the last neighbour is the first one. Hence
two lists which differ only by cyclic shifts of their entries describe
the same rotation system.
Every rotation system defines an embedding of <A>digraph</A> into an
orientable surface, whose faces are given by
<Ref Oper="FacialWalks"/>.

The operation <C>IsDigraphRotationSystem</C> ignores multiple edges and loops.<P/>
Here are some examples:
<Example><![CDATA[
gap> 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
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>


<#GAPDoc Label="FacialWalks">
<ManSection>
<Oper Name="FacialWalks" Arg="digraph, list"/>
Expand Down
1 change: 1 addition & 0 deletions gap/attr.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
43 changes: 32 additions & 11 deletions gap/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1853,6 +1853,34 @@ 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 <D> must be a symmetric digraph,");
elif 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],
Expand All @@ -1863,17 +1891,9 @@ function(D, rotationSystem)
ErrorNoReturn("the argument <D> must be a symmetric digraph,");
fi;

if Length(rotationSystem) <> DigraphNrVertices(D)
or not ForAll(rotationSystem, IsList) then
ErrorNoReturn("the 2nd argument (dense list <rotationSystem>) is not a ",
"rotation system for the 1st argument (digraph <D>), ",
"expected a list of ", DigraphNrVertices(D), " lists,");
fi;

if Union(rotationSystem) <> DigraphVertices(D) then
ErrorNoReturn("the 2nd argument (dense list <rotationSystem>) is not a ",
"rotation system for the 1st argument (digraph <D>), ",
"expected its union to be the vertices of <D>,");
if not IsDigraphRotationSystem(D, rotationSystem) then
ErrorNoReturn("the 2nd argument (list <rotationSystem>) is not a rotation ",
"system for the 1st argument (digraph <D>)");
fi;

# computes a facial cycles starting with the edge 'startEdge'
Expand Down Expand Up @@ -3639,6 +3659,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
Expand Down
51 changes: 40 additions & 11 deletions tst/standard/attr.tst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <rotationSystem>) is not a rotation system\
for the 1st argument (digraph <D>), expected a list of 3 lists,
gap> FacialWalks(g, [1]);
Error, the 2nd argument (dense list <rotationSystem>) is not a rotation system\
for the 1st argument (digraph <D>), expected a list of 3 lists,
gap> FacialWalks(g, [[4], [1], [3]]);
Error, the 2nd argument (dense list <rotationSystem>) is not a rotation system\
for the 1st argument (digraph <D>), expected its union to be the vertices of \
<D>,
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 ] ]
Expand Down
Loading