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
21 changes: 11 additions & 10 deletions doc/attr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1535,29 +1535,29 @@ gap> DigraphAllChordlessCycles(D);
<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>,
If <A>digraph</A> is a symmetric 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.
A rotation system defines for each vertex of a symmetric digraph the ordering of the 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/>
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> D1 := DigraphSymmetricClosure(CycleDigraph(4));;
gap> planar := PlanarEmbedding(D1);
[ [ 2 ], [ 3 ], [ 4 ], [ 1 ] ]
[ [ 2, 4 ], [ 3, 1 ], [ 4, 2 ], [ 1, 3 ] ]
gap> FacialWalks(D1, planar);
[ [ 1, 2, 3, 4 ] ]
[ [ 1, 2, 3, 4 ], [ 1, 4, 3, 2 ] ]
gap> nonPlanar := [[2, 4], [1, 3], [2, 4], [1, 3]];;
gap> FacialWalks(D1, nonPlanar);
[ [ 1, 2, 3, 4 ] ]
gap> D2 := CompleteMultipartiteDigraph([2, 2, 2]);;
[ [ 1, 2, 3, 4 ], [ 1, 4, 3, 2 ] ]
gap> D2 := DigraphSymmetricClosure(
> 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 ] ]
Expand All @@ -1567,7 +1567,8 @@ gap> FacialWalks(D2, rotationSystem);
]]></Example>
Here is an example of a non-planar digraph with a corresponding rotation system:
<Example><![CDATA[
gap> D3 := CompleteMultipartiteDigraph([3, 3]);;
gap> D3 := DigraphSymmetricClosure(
> 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 ],
Expand Down
53 changes: 29 additions & 24 deletions doc/planar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,13 @@ gap> KuratowskiOuterPlanarSubdigraph(D);
<Attr Name="PlanarEmbedding" Arg="digraph"/>
<Returns>A list or <K>fail</K>.</Returns>
<Description>
If <A>digraph</A> is a planar digraph, then <C>PlanarEmbedding</C> returns
the immutable list of lists of out-neighbours of <A>digraph</A> (excluding
multiple edges and loops) such that each vertex's neighbours are given in
clockwise order. If <A>digraph</A> is not planar, then <K>fail</K> is
returned. <P/>
If <A>digraph</A> is a planar symmetric digraph, then <C>PlanarEmbedding</C>
returns the immutable list of lists of out-neighbours of <A>digraph</A>
(excluding multiple edges and loops) such that each vertex's neighbours are
given in clockwise order. If <A>digraph</A> is not planar, then <K>fail</K>
is returned. <P/>

The directions and multiplicities of any edges in <A>digraph</A> are ignored
The multiplicities of any edges in <A>digraph</A> are ignored
by <C>PlanarEmbedding</C>.
<P/>

Expand All @@ -258,29 +258,32 @@ gap> KuratowskiOuterPlanarSubdigraph(D);
in <Cite Key="BM06"/>.

<Example><![CDATA[
gap> D := Digraph([[3, 5, 10], [8, 9, 10], [1, 4], [3, 6],
> [1, 7, 11], [4, 7], [6, 8], [2, 7], [2, 11], [1, 2], [5, 9]]);
<immutable digraph with 11 vertices, 25 edges>
gap> D := DigraphSymmetricClosure(Digraph([[3, 5, 10], [8, 9, 10],
> [1, 4], [3, 6], [1, 7, 11], [4, 7], [6, 8], [2, 7], [2, 11],
> [1, 2], [5, 9]]));
<immutable symmetric digraph with 11 vertices, 26 edges>
gap> PlanarEmbedding(D);
[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11, 7 ],
[ 7, 4 ], [ 8, 6 ], [ 7, 2 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> D := Digraph([[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10],
> [2, 5, 8, 9], [1, 2, 3, 4, 6, 7, 9, 10], [3, 4, 5, 7, 9, 10],
> [3, 4, 5, 6, 9, 10], [3, 4, 5, 7, 9], [2, 3, 5, 6, 7, 8], [3, 5]]);
<immutable digraph with 10 vertices, 50 edges>
[ 7, 4 ], [ 5, 8, 6 ], [ 7, 2 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> D := DigraphSymmetricClosure(Digraph([[2, 4, 7, 9, 10],
> [1, 3, 4, 6, 9, 10], [6, 10], [2, 5, 8, 9], [1, 2, 3, 4, 6, 7, 9, 10],
> [3, 4, 5, 7, 9, 10], [3, 4, 5, 6, 9, 10], [3, 4, 5, 7, 9],
> [2, 3, 5, 6, 7, 8], [3, 5]]));
<immutable symmetric digraph with 10 vertices, 70 edges>
gap> PlanarEmbedding(D);
fail
gap> D := Digraph(IsMutableDigraph, [[3, 5, 10], [8, 9, 10], [1, 4],
> [3, 6], [1, 7, 11], [4, 7], [6, 8], [2, 7], [2, 11], [1, 2], [5, 9]]);
<mutable digraph with 11 vertices, 25 edges>
gap> D := DigraphSymmetricClosure(Digraph(IsMutableDigraph,
> [[3, 5, 10], [8, 9, 10], [1, 4], [3, 6], [1, 7, 11], [4, 7],
> [6, 8], [2, 7], [2, 11], [1, 2], [5, 9]]));
<mutable digraph with 11 vertices, 26 edges>
gap> PlanarEmbedding(D);
[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11, 7 ],
[ 7, 4 ], [ 8, 6 ], [ 7, 2 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> D := Digraph(IsMutableDigraph, [[2, 4, 7, 9, 10],
> [1, 3, 4, 6, 9, 10], [6, 10], [2, 5, 8, 9],
[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11, 7 ],
[ 7, 4 ], [ 5, 8, 6 ], [ 7, 2 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> D := DigraphSymmetricClosure(Digraph(IsMutableDigraph,
> [[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10], [2, 5, 8, 9],
> [1, 2, 3, 4, 6, 7, 9, 10], [3, 4, 5, 7, 9, 10],
> [3, 4, 5, 6, 9, 10], [3, 4, 5, 7, 9], [2, 3, 5, 6, 7, 8], [3, 5]]);
<mutable digraph with 10 vertices, 50 edges>
> [3, 4, 5, 6, 9, 10], [3, 4, 5, 7, 9], [2, 3, 5, 6, 7, 8], [3, 5]]));
<mutable digraph with 10 vertices, 70 edges>
gap> PlanarEmbedding(D);
fail
]]></Example>
Expand Down Expand Up @@ -433,13 +436,15 @@ fail
<Attr Name="DualPlanarGraph" Arg="digraph"/>
<Returns>A digraph or <K>fail</K>.</Returns>
<Description>
If <A>digraph</A> is a planar digraph, then <Ref Attr="DualPlanarGraph"/> returns the the dual graph of <A>digraph</A>.
If <A>digraph</A> is a planar digraph, then <Ref Attr="DualPlanarGraph"/> returns the symmetric dual graph
of <A>digraph</A>.
If <A>digraph</A> is not planar, then <K>fail</K> is returned.<P/>

The dual graph of a planar digraph <A>digraph</A> has a vertex for each face of <A>digraph</A> and an edge for
each pair of faces that are separated by an edge from each other.
Vertex <A>i</A> of the dual graph corresponds to the facial walk at the <A>i</A>-th position calling
<Ref Oper="FacialWalks"/> of <A>digraph</A> with the rotation system returned by <Ref Attr="PlanarEmbedding"/>.
The directions and multiplicities of any edges in digraph are ignored by <Ref Attr="DualPlanarGraph"/>.
<P/>

Note that <Ref Attr="PlanarEmbedding"/>, and therefore
Expand Down
4 changes: 2 additions & 2 deletions gap/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1859,8 +1859,8 @@ InstallMethod(FacialWalks, "for a digraph and a dense list",
function(D, rotationSystem)
local FacialWalk, facialWalks, remEdges, cycle;

if not IsEulerianDigraph(D) then
ErrorNoReturn("the 1st argument (digraph <D>) must be Eulerian");
if not IsSymmetricDigraph(D) then
ErrorNoReturn("the argument <D> must be a symmetric digraph,");
fi;

if Length(rotationSystem) <> DigraphNrVertices(D)
Expand Down
4 changes: 4 additions & 0 deletions gap/planar.gi
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ end);

InstallMethod(PlanarEmbedding, "for a digraph", [IsDigraph],
function(D)
if not IsSymmetricDigraph(D) then
ErrorNoReturn("the argument <D> must be a symmetric digraph,");
fi;
D := DigraphMutableCopyIfMutable(D);
if DIGRAPHS_HasTrivialRotationSystem(D) then;
return OutNeighbors(D);
fi;
Expand Down
20 changes: 11 additions & 9 deletions tst/standard/attr.tst
Original file line number Diff line number Diff line change
Expand Up @@ -1097,18 +1097,20 @@ gap> DigraphAllUndirectedSimpleCircuits(g);
[ 9, 5, 6, 10 ], [ 9, 5, 7, 8, 6, 10 ] ]

# FacialCycles
gap> FacialWalks(ChainDigraph(3), []);
Error, the 1st argument (digraph <D>) must be Eulerian
gap> FacialWalks(CycleDigraph(3), []);
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(CycleDigraph(3), [1]);
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(CycleDigraph(3), [[4], [1], [3]]);
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> g := DigraphSymmetricClosure(ChainDigraph(3));;
gap> FacialWalks(g, PlanarEmbedding(g));
[ [ 1, 2, 3, 2 ] ]
gap> g := Digraph([]);;
gap> rotationSy := [];;
gap> FacialWalks(g, rotationSy);
Expand All @@ -1117,14 +1119,14 @@ 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> g := DigraphSymmetricClosure(CycleDigraph(4));;
gap> planar := PlanarEmbedding(g);
[ [ 2 ], [ 3 ], [ 4 ], [ 1 ] ]
[ [ 2, 4 ], [ 3, 1 ], [ 4, 2 ], [ 1, 3 ] ]
gap> FacialWalks(g, planar);
[ [ 1, 2, 3, 4 ] ]
[ [ 1, 2, 3, 4 ], [ 1, 4, 3, 2 ] ]
gap> nonPlanar := [[2, 4], [1, 3], [2, 4], [1, 3]];;
gap> FacialWalks(g, nonPlanar);
[ [ 1, 2, 3, 4 ] ]
[ [ 1, 2, 3, 4 ], [ 1, 4, 3, 2 ] ]
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 ],
Expand Down
6 changes: 3 additions & 3 deletions tst/standard/planar.tst
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ true
gap> D := Digraph([[3, 5, 10], [8, 9, 10], [1, 4], [3, 6], [1, 7, 11], [4, 7],
> [6, 8], [2, 7], [2, 11], [1, 2], [5, 9]]);
<immutable digraph with 11 vertices, 25 edges>
gap> PlanarEmbedding(D);
gap> PlanarEmbedding(DigraphSymmetricClosure(D));
[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11, 7 ], [ 7, 4 ],
[ 8, 6 ], [ 7, 2 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
[ 5, 8, 6 ], [ 7, 2 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> D := Digraph([[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10],
> [2, 5, 8, 9], [1, 2, 3, 4, 6, 7, 9, 10], [3, 4, 5, 7, 9, 10],
> [3, 4, 5, 6, 9, 10], [3, 4, 5, 7, 9], [2, 3, 5, 6, 7, 8], [3, 5]]);
<immutable digraph with 10 vertices, 50 edges>
gap> IsPlanarDigraph(D);
false
gap> PlanarEmbedding(D);
gap> PlanarEmbedding(DigraphSymmetricClosure(D));
fail
gap> D := NullDigraph(0);
<immutable empty digraph with 0 vertices>
Expand Down
Loading