Skip to content

Commit

Permalink
added FacialWalks
Browse files Browse the repository at this point in the history
  • Loading branch information
MeikeWeiss committed Sep 17, 2024
1 parent b080f74 commit eaacded
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 0 deletions.
49 changes: 49 additions & 0 deletions doc/attr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1495,6 +1495,55 @@ gap> DigraphAllChordlessCycles(D);
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="FacialWalks">
<ManSection>
<Oper Name="FacialWalks" Arg="digraph, list"/>
<Returns>A list of lists of vertices.</Returns>
<Description>
If <A>digraph</A> is an Eulerian digraph and <A>list</A> is a rotation system of <A>digraph</A>,
then <C>FacialWalks</C> returns a list of the <E>facial walks</E> in <A>digraph</A>. <P/>

A rotation system defines for each vertex the ordering of the out-neighbours.
For example, the method <Ref Subsect="PlanarEmbedding" Style="Number" /> computes for a
planar digraph <A>D</A> the rotation system of a planar embedding of <A>D</A>.
The facial walks of <A>digraph</A> are closed walks and they are defined by the rotation system <A>list</A>.
They describe the boundaries of the faces of the embedding of <A>digraph</A> given
by the rotation system <A>list</A>.

The operation <C>FacialWalks</C> ignores
multiple edges and loops.<P/>
Here are some examples for planar embeddings:
<Example><![CDATA[
gap> D1 := CycleDigraph(4);;
gap> planar := PlanarEmbedding(D1);
[ [ 2 ], [ 3 ], [ 4 ], [ 1 ] ]
gap> FacialWalks(D1, planar);
[ [ 1, 2, 3, 4 ] ]
gap> nonPlanar := [[2, 4], [1, 3], [2, 4], [1, 3]];;
gap> FacialWalks(D1, nonPlanar);
[ [ 1, 2, 3, 4 ] ]
gap> D2 := CompleteMultipartiteDigraph([2, 2, 2]);;
gap> rotationSystem := PlanarEmbedding(D2);
[ [ 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> FacialWalks(D2, rotationSystem);
[ [ 1, 3, 6 ], [ 1, 4, 5 ], [ 1, 5, 3 ], [ 1, 6, 4 ], [ 2, 3, 5 ],
[ 2, 4, 6 ], [ 2, 5, 4 ], [ 2, 6, 3 ] ]
]]></Example>
Here is an example of a non-planar digraph with a corresponding rotation system:
<Example><![CDATA[
gap> D3 := CompleteMultipartiteDigraph([3, 3]);;
gap> rot := [[6, 5, 4], [6, 5, 4], [6, 5, 4], [1, 2, 3],
> [1, 2, 3], [1, 2, 3]];
[ [ 6, 5, 4 ], [ 6, 5, 4 ], [ 6, 5, 4 ], [ 1, 2, 3 ], [ 1, 2, 3 ],
[ 1, 2, 3 ] ]
gap> FacialWalks(D3, rot);
[ [ 1, 4, 2, 6, 3, 5 ], [ 1, 5, 2, 4, 3, 6 ], [ 1, 6, 2, 5, 3, 4 ] ]
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="HamiltonianPath">
<ManSection>
<Attr Name="HamiltonianPath" Arg="digraph"/>
Expand Down
1 change: 1 addition & 0 deletions doc/z-chap4.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
<#Include Label="DigraphLongestSimpleCircuit">
<#Include Label="DigraphAllUndirectedSimpleCircuits">
<#Include Label="DigraphAllChordlessCycles">
<#Include Label="FacialWalks">
<#Include Label="DigraphLayers">
<#Include Label="DigraphDegeneracy">
<#Include Label="DigraphDegeneracyOrdering">
Expand Down
1 change: 1 addition & 0 deletions gap/attr.gd
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ DeclareAttribute("DigraphAllSimpleCircuits", IsDigraph);
DeclareAttribute("DigraphLongestSimpleCircuit", IsDigraph);
DeclareAttribute("DigraphAllUndirectedSimpleCircuits", IsDigraph);
DeclareAttribute("DigraphAllChordlessCycles", IsDigraph);
DeclareOperation("FacialWalks", [IsDigraph, IsList]);
DeclareAttribute("HamiltonianPath", IsDigraph);
DeclareAttribute("DigraphPeriod", IsDigraph);
DeclareAttribute("DigraphLoops", IsDigraph);
Expand Down
69 changes: 69 additions & 0 deletions gap/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1653,6 +1653,75 @@ function(D)
return C;
end);

# Compute for a given rotation system the facial walks
InstallMethod(FacialWalks, "for a digraph and a list",
[IsDigraph, IsList],
function(D, rotationSystem)

local FacialWalk, facialWalks, remEdges, cycle;

if not IsEulerianDigraph(D) then
Error("The given digraph is not Eulerian.");
fi;

if not IsDenseList(rotationSystem) or Length(rotationSystem)
<> DigraphNrVertices(D) then
Error("The given rotation system does not fit to the given digraph.");
fi;

if Difference(DuplicateFreeList(Flat(rotationSystem)), DigraphVertices(D))
<> [] then
Error("The given rotation system does not fit to the given digraph.");
fi;

# computes a facial cycles starting with the edge 'startEdge'
FacialWalk := function(rotationSystem, startEdge)
local startVertex, preVertex, actVertex, cycle, nextVertex, pos;

startVertex := startEdge[1];
actVertex := startEdge[2];
preVertex := startVertex;

cycle := [startVertex, actVertex];

nextVertex := 0; # just an initialization
while true do
pos := Position(rotationSystem[actVertex], preVertex);

if pos < Length(rotationSystem[actVertex]) then
nextVertex := rotationSystem[actVertex][pos + 1];
else
nextVertex := rotationSystem[actVertex][1];
fi;
if nextVertex <> startEdge[2] or actVertex <> startVertex then
Add(cycle, nextVertex);
Remove(remEdges, Position(remEdges, [preVertex, actVertex]));
preVertex := actVertex;
actVertex := nextVertex;
else
break;
fi;
od;
Remove(remEdges, Position(remEdges, [preVertex, startVertex]));
# Remove the last vertex, otherwise otherwise
# the start vertex is contained twice
Remove(cycle);
return cycle;
end;

D := DigraphRemoveLoops(DigraphRemoveAllMultipleEdges(
DigraphMutableCopyIfMutable(D)));

facialWalks := [];
remEdges := ShallowCopy(DigraphEdges(D));

while remEdges <> [] do
cycle := FacialWalk(rotationSystem, remEdges[1]);
Add(facialWalks, cycle);
od;
return facialWalks;
end);

# The following method 'DIGRAPHS_Bipartite' was originally written by Isabella
# Scott and then modified by FLS.
# It is the backend to IsBipartiteDigraph, Bicomponents, and DigraphColouring
Expand Down
25 changes: 25 additions & 0 deletions tst/standard/attr.tst
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,31 @@ 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
gap> g := Digraph([]);;
gap> rotationSy := [];;
gap> FacialWalks(g,rotationSy);
[ ]
gap> g := Digraph([[2],[1,3],[2,4],[3]]);;;
gap> rotationSy := [[2],[1,3],[2,4],[3]];;
gap> FacialWalks(g,rotationSy);
[ [ 1, 2, 3, 4, 3, 2 ] ]
gap> g := CycleDigraph(4);;
gap> planar := PlanarEmbedding(g);
[ [ 2 ], [ 3 ], [ 4 ], [ 1 ] ]
gap> FacialWalks(g, planar);
[ [ 1, 2, 3, 4 ] ]
gap> nonPlanar := [[2, 4], [1, 3], [2, 4], [1, 3]];;
gap> FacialWalks(g, nonPlanar);
[ [ 1, 2, 3, 4 ] ]
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> FacialWalks(g, rotationSystem);
[ [ 1, 3, 6 ], [ 1, 4, 5 ], [ 1, 5, 3 ], [ 1, 6, 4 ], [ 2, 3, 5 ],
[ 2, 4, 6 ], [ 2, 5, 4 ], [ 2, 6, 3 ] ]

# Issue #676
gap> D := Digraph([[], [3], []]);;
gap> SetDigraphVertexLabels(D, ["one", "two", "three"]);
Expand Down

0 comments on commit eaacded

Please sign in to comment.