From a6da28d94b081b76e5f8cb9d641db1ae40df70d7 Mon Sep 17 00:00:00 2001
From: Joe Edwards <80713360+Joseph-Edwards@users.noreply.github.com>
Date: Thu, 5 Sep 2024 19:38:15 +0100
Subject: [PATCH] Fix planarity (#696)
---
doc/attr.xml | 42 +++++++++++++
doc/planar.xml | 124 ++++++++++++++++++++------------------
doc/z-chap4.xml | 2 +
gap/attr.gd | 2 +
gap/attr.gi | 6 ++
gap/planar.gi | 83 +++++++++----------------
src/digraphs.c | 58 ++++++++++++++++++
src/digraphs.h | 2 +
src/planar.c | 84 +++++++++++++++++++-------
tst/standard/attr.tst | 38 ++++++++++++
tst/standard/examples.tst | 2 +
tst/standard/planar.tst | 100 +++++++++++++++---------------
tst/testinstall.tst | 4 ++
13 files changed, 364 insertions(+), 183 deletions(-)
diff --git a/doc/attr.xml b/doc/attr.xml
index 91e995611..7eecc5721 100644
--- a/doc/attr.xml
+++ b/doc/attr.xml
@@ -138,6 +138,48 @@ gap> DigraphNrEdges(D);
<#/GAPDoc>
+<#GAPDoc Label="DigraphNrAdjacencies">
+
+
+ An integer.
+ Returns the number of sets \{u, v\} of vertices of the digraph digraph, such that
+ either (u, v) or (v, u) is an edge. The following equality holds for
+ any digraph D with no multiple edges: DigraphNrAdjacencies(D) * 2 - DigraphNrLoops(D)
+ = DigraphNrEdges(DigraphSymmetricClosure(D)).
+ gr := Digraph([
+> [1, 3, 4, 5], [1, 2, 3, 5], [2, 4, 5], [2, 4, 5], [1]]);;
+gap> DigraphNrAdjacencies(gr);
+13
+gap> DigraphNrAdjacencies(gr) * 2 - DigraphNrLoops(gr) =
+> DigraphNrEdges(DigraphSymmetricClosure(gr));
+true
+]]>
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="DigraphNrAdjacenciesWithoutLoops">
+
+
+ An integer.
+ Returns the number of sets \{u, v\} of vertices of the digraph digraph, such that
+ u \neq v and either (u, v) or (v, u) is an edge. The following equality holds for
+ any digraph D with no multiple edges: DigraphNrAdjacenciesWithoutLoops(D) * 2 + DigraphNrLoops(D)
+ = DigraphNrEdges(DigraphSymmetricClosure(D)).
+ gr := Digraph([
+> [1, 3, 4, 5], [1, 2, 3, 5], [2, 4, 5], [2, 4, 5], [1]]);;
+gap> DigraphNrAdjacenciesWithoutLoops(gr);
+10
+gap> DigraphNrAdjacenciesWithoutLoops(gr) * 2 + DigraphNrLoops(gr) =
+> DigraphNrEdges(DigraphSymmetricClosure(gr));
+true
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="DigraphNrLoops">
diff --git a/doc/planar.xml b/doc/planar.xml
index 77e3bde4f..6c9e44d5c 100644
--- a/doc/planar.xml
+++ b/doc/planar.xml
@@ -112,14 +112,15 @@ true
A list or fail.
- KuratowskiPlanarSubdigraph returns the immutable list of
- lists of out-neighbours of a (not necessarily induced) subdigraph of the
- digraph digraph that witnesses the fact that digraph is not
- planar, or fail if digraph is planar. In other words,
- KuratowskiPlanarSubdigraph returns the out-neighbours of a
- subdigraph of digraph that is homeomorphic to the complete graph
- with 5 vertices, or to the complete bipartite graph with vertex sets
- of sizes 3 and 3.
+ KuratowskiPlanarSubdigraph returns the immutable list of lists of
+ out-neighbours of an induced subdigraph (excluding multiple edges and loops)
+ of the digraph digraph that witnesses the fact that digraph is
+ not planar, or fail if digraph is planar. In other words,
+ KuratowskiPlanarSubdigraph returns the out-neighbours of a subdigraph
+ of digraph that is homeomorphic to the complete graph with 5
+ vertices, or to the complete bipartite graph with vertex sets of sizes
+ 3 and 3.
+
The directions and multiplicities of any edges in digraph are
ignored when considering whether or not digraph is planar.
@@ -145,8 +146,8 @@ gap> D := Digraph([[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10],
gap> IsPlanarDigraph(D);
false
gap> KuratowskiPlanarSubdigraph(D);
-[ [ 2, 9, 7 ], [ 3 ], [ 6 ], [ 5, 9 ], [ 6 ], [ ], [ 4 ],
- [ 7, 9, 3 ], [ ], [ ] ]
+[ [ 2, 9, 7 ], [ 1, 3 ], [ 6 ], [ 5, 9 ], [ 6, 4 ], [ 3, 5 ], [ 4 ],
+ [ 7, 9, 3 ], [ 8 ], [ ] ]
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]]);
@@ -160,8 +161,8 @@ gap> D := Digraph(IsMutableDigraph, [[2, 4, 7, 9, 10],
gap> IsPlanarDigraph(D);
false
gap> KuratowskiPlanarSubdigraph(D);
-[ [ 2, 9, 7 ], [ 3 ], [ 6 ], [ 5, 9 ], [ 6 ], [ ], [ 4 ],
- [ 7, 9, 3 ], [ ], [ ] ]
+[ [ 2, 9, 7 ], [ 1, 3 ], [ 6 ], [ 5, 9 ], [ 6, 4 ], [ 3, 5 ], [ 4 ],
+ [ 7, 9, 3 ], [ 8 ], [ ] ]
]]>
@@ -173,17 +174,18 @@ gap> KuratowskiPlanarSubdigraph(D);
A list or fail.
KuratowskiOuterPlanarSubdigraph returns the immutable list of
- immutable lists of out-neighbours of a (not necessarily induced)
- subdigraph of the digraph digraph that witnesses the fact
- that digraph is not outer planar, or fail if
- digraph is outer planar. In other words,
+ immutable lists of out-neighbours of an induced subdigraph (excluding
+ multiple edges and loops) of the digraph digraph that witnesses the
+ fact that digraph is not outer planar, or fail if
+ digraph is outer planar. In other words,
KuratowskiOuterPlanarSubdigraph returns the out-neighbours of a
- subdigraph of digraph that is homeomorphic to the complete graph
- with 4 vertices, or to the complete bipartite graph with vertex sets
- of sizes 2 and 3.
+ subdigraph of digraph that is homeomorphic to the complete graph with
+ 4 vertices, or to the complete bipartite graph with vertex sets of
+ sizes 2 and 3.
+
- The directions and multiplicities of any edges in digraph are
- ignored when considering whether or not digraph is outer planar.
+ The directions and multiplicities of any edges in digraph are ignored
+ when considering whether or not digraph is outer planar.
See also
@@ -201,8 +203,8 @@ 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]]);
gap> KuratowskiOuterPlanarSubdigraph(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
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]]);
@@ -210,14 +212,14 @@ gap> D := Digraph([[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10],
gap> IsOuterPlanarDigraph(D);
false
gap> KuratowskiOuterPlanarSubdigraph(D);
-[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9 ], [ ],
- [ ] ]
+[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9, 4 ],
+ [ 8, 7 ], [ ] ]
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]]);
gap> KuratowskiOuterPlanarSubdigraph(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
gap> D := 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],
@@ -226,8 +228,8 @@ gap> D := Digraph(IsMutableDigraph, [[2, 4, 7, 9, 10],
gap> IsOuterPlanarDigraph(D);
false
gap> KuratowskiOuterPlanarSubdigraph(D);
-[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9 ], [ ],
- [ ] ]]]>
+[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9, 4 ],
+ [ 8, 7 ], [ ] ]]]>
<#/GAPDoc>
@@ -237,14 +239,14 @@ gap> KuratowskiOuterPlanarSubdigraph(D);
A list or fail.
- If digraph is a planar digraph, then
- PlanarEmbedding returns the immutable list of lists of
- out-neighbours of a subdigraph of digraph such that each vertex's
- neighbours are given in clockwise order. If digraph is not planar,
- then fail is returned.
+ If digraph is a planar digraph, then PlanarEmbedding returns
+ the immutable list of lists of out-neighbours of digraph (excluding
+ multiple edges and loops) such that each vertex's neighbours are given in
+ clockwise order. If digraph is not planar, then fail is
+ returned.
- The directions and multiplicities of any edges in digraph are
- ignored by PlanarEmbedding.
+ The directions and multiplicities of any edges in digraph are ignored
+ by PlanarEmbedding.
See also
@@ -260,8 +262,8 @@ 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]]);
gap> PlanarEmbedding(D);
-[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4 ], [ 6 ], [ 11, 7 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 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]]);
@@ -272,8 +274,8 @@ 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]]);
gap> PlanarEmbedding(D);
-[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4 ], [ 6 ], [ 11, 7 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 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],
> [1, 2, 3, 4, 6, 7, 9, 10], [3, 4, 5, 7, 9, 10],
@@ -292,10 +294,10 @@ fail
A list or fail.
If digraph is an outer planar digraph, then
- OuterPlanarEmbedding returns the immutable list of lists
- of out-neighbours of a subdigraph of digraph such that each
- vertex's neighbours are given in clockwise order. If digraph is not
- outer planar, then fail is returned.
+ OuterPlanarEmbedding returns the immutable list of lists of
+ out-neighbours of digraph (excluding multiple edges and loops) such
+ that each vertex's neighbours are given in clockwise order. If
+ digraph is not outer planar, then fail is returned.
The directions and multiplicities of any edges in digraph are
ignored by OuterPlanarEmbedding.
@@ -321,7 +323,7 @@ gap> D := Digraph([[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10],
gap> OuterPlanarEmbedding(D);
fail
gap> OuterPlanarEmbedding(CompleteBipartiteDigraph(2, 2));
-[ [ 3, 4 ], [ 4, 3 ], [ ], [ ] ]
+[ [ 3, 4 ], [ 4, 3 ], [ 2, 1 ], [ 1, 2 ] ]
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]]);
@@ -335,7 +337,7 @@ gap> D := Digraph(IsMutableDigraph, [[2, 4, 7, 9, 10],
gap> OuterPlanarEmbedding(D);
fail
gap> OuterPlanarEmbedding(CompleteBipartiteDigraph(2, 2));
-[ [ 3, 4 ], [ 4, 3 ], [ ], [ ] ]
+[ [ 3, 4 ], [ 4, 3 ], [ 2, 1 ], [ 1, 2 ] ]
]]>
@@ -369,19 +371,19 @@ 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]]);
gap> SubdigraphHomeomorphicToK4(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 7, 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 7, 11 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
gap> SubdigraphHomeomorphicToK23(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
gap> D := Digraph([[3, 5, 10], [8, 9, 10], [1, 4], [3, 6], [1, 11],
> [4, 7], [6, 8], [2, 7], [2, 11], [1, 2], [5, 9]]);
gap> SubdigraphHomeomorphicToK4(D);
fail
gap> SubdigraphHomeomorphicToK23(D);
-[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4, 1 ], [ 6, 3 ], [ 11, 1 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> SubdigraphHomeomorphicToK33(D);
fail
gap> SubdigraphHomeomorphicToK23(NullDigraph(0));
@@ -389,26 +391,27 @@ fail
gap> SubdigraphHomeomorphicToK33(CompleteDigraph(5));
fail
gap> SubdigraphHomeomorphicToK33(CompleteBipartiteDigraph(3, 3));
-[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ ], [ ], [ ] ]
+[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ 1, 2, 3 ], [ 3, 2, 1 ],
+ [ 2, 3, 1 ] ]
gap> SubdigraphHomeomorphicToK4(CompleteDigraph(3));
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]]);
gap> SubdigraphHomeomorphicToK4(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 7, 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 7, 11 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
gap> SubdigraphHomeomorphicToK23(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
gap> D := Digraph(IsMutableDigraph, [[3, 5, 10], [8, 9, 10], [1, 4],
> [3, 6], [1, 11], [4, 7], [6, 8], [2, 7], [2, 11], [1, 2], [5, 9]]);
gap> SubdigraphHomeomorphicToK4(D);
fail
gap> SubdigraphHomeomorphicToK23(D);
-[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ],
- [ ], [ 11 ], [ ], [ ] ]
+[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4, 1 ], [ 6, 3 ], [ 11, 1 ],
+ [ 7, 4 ], [ 8, 6 ], [ 2, 7 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> SubdigraphHomeomorphicToK33(D);
fail
gap> SubdigraphHomeomorphicToK23(NullDigraph(0));
@@ -416,7 +419,8 @@ fail
gap> SubdigraphHomeomorphicToK33(CompleteDigraph(5));
fail
gap> SubdigraphHomeomorphicToK33(CompleteBipartiteDigraph(3, 3));
-[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ ], [ ], [ ] ]
+[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ 1, 2, 3 ], [ 3, 2, 1 ],
+ [ 2, 3, 1 ] ]
gap> SubdigraphHomeomorphicToK4(CompleteDigraph(3));
fail
]]>
diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml
index 4af3cab3e..4e87e055b 100644
--- a/doc/z-chap4.xml
+++ b/doc/z-chap4.xml
@@ -4,6 +4,8 @@
<#Include Label="DigraphNrVertices">
<#Include Label="DigraphEdges">
<#Include Label="DigraphNrEdges">
+ <#Include Label="DigraphNrAdjacencies">
+ <#Include Label="DigraphNrAdjacenciesWithoutLoops">
<#Include Label="DigraphNrLoops">
<#Include Label="DigraphSinks">
<#Include Label="DigraphSources">
diff --git a/gap/attr.gd b/gap/attr.gd
index 020bf0899..7814a5f37 100644
--- a/gap/attr.gd
+++ b/gap/attr.gd
@@ -14,6 +14,8 @@ DeclareAttribute("DigraphVertices", IsDigraph);
DeclareAttribute("DigraphNrVertices", IsDigraph);
DeclareAttribute("DigraphEdges", IsDigraph);
DeclareAttribute("DigraphNrEdges", IsDigraph);
+DeclareAttribute("DigraphNrAdjacencies", IsDigraph);
+DeclareAttribute("DigraphNrAdjacenciesWithoutLoops", IsDigraph);
DeclareAttribute("DigraphNrLoops", IsDigraph);
DeclareAttribute("DigraphHash", IsDigraph);
diff --git a/gap/attr.gi b/gap/attr.gi
index 8864416bc..67bb792ac 100644
--- a/gap/attr.gi
+++ b/gap/attr.gi
@@ -701,6 +701,12 @@ function(D)
return m;
end);
+InstallMethod(DigraphNrAdjacencies, "for a digraph",
+[IsDigraphByOutNeighboursRep], DIGRAPH_NRADJACENCIES);
+
+InstallMethod(DigraphNrAdjacenciesWithoutLoops, "for a digraph",
+[IsDigraphByOutNeighboursRep], DIGRAPH_NRADJACENCIESWITHOUTLOOPS);
+
InstallMethod(DigraphNrLoops,
"for a digraph by out-neighbours",
[IsDigraphByOutNeighboursRep],
diff --git a/gap/planar.gi b/gap/planar.gi
index 0c9ba14f4..8a36385ca 100644
--- a/gap/planar.gi
+++ b/gap/planar.gi
@@ -30,72 +30,48 @@
# 1. Attributes
########################################################################
-InstallMethod(PlanarEmbedding, "for a digraph", [IsDigraph],
+BindGlobal("DIGRAPHS_HasTrivialRotationSystem",
function(D)
- if IsEmptyDigraph(D) or DigraphNrVertices(D) < 3 then
- return [];
+ if IsMultiDigraph(D) then
+ ErrorNoReturn("expected a digraph with no multiple edges");
elif HasIsPlanarDigraph(D) and not IsPlanarDigraph(D) then
- return fail;
+ return false;
+ elif DigraphNrVertices(D) < 3 then
+ return true;
+ fi;
+ return DigraphNrAdjacenciesWithoutLoops(D) = 0;
+end);
+
+InstallMethod(PlanarEmbedding, "for a digraph", [IsDigraph],
+function(D)
+ if DIGRAPHS_HasTrivialRotationSystem(D) then;
+ return OutNeighbors(D);
fi;
- D := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
return PLANAR_EMBEDDING(D);
end);
InstallMethod(OuterPlanarEmbedding, "for a digraph", [IsDigraph],
function(D)
- if IsEmptyDigraph(D) or DigraphNrVertices(D) < 3 then
- return [];
- elif HasIsOuterPlanarDigraph(D) and not IsOuterPlanarDigraph(D) then
- return fail;
+ if DIGRAPHS_HasTrivialRotationSystem(D) then;
+ return OutNeighbors(D);
fi;
- D := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
return OUTER_PLANAR_EMBEDDING(D);
end);
InstallMethod(KuratowskiPlanarSubdigraph, "for a digraph", [IsDigraph],
-function(D)
- if IsPlanarDigraph(D) then
- return fail;
- fi;
- D := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
- return KURATOWSKI_PLANAR_SUBGRAPH(D);
-end);
+KURATOWSKI_PLANAR_SUBGRAPH);
InstallMethod(KuratowskiOuterPlanarSubdigraph, "for a digraph", [IsDigraph],
-function(D)
- if IsOuterPlanarDigraph(D) then
- return fail;
- fi;
- D := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
- return KURATOWSKI_OUTER_PLANAR_SUBGRAPH(D);
-end);
+KURATOWSKI_OUTER_PLANAR_SUBGRAPH);
InstallMethod(SubdigraphHomeomorphicToK23, "for a digraph", [IsDigraph],
-function(D)
- if IsOuterPlanarDigraph(D) then
- return fail;
- fi;
- D := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
- return SUBGRAPH_HOMEOMORPHIC_TO_K23(D);
-end);
+SUBGRAPH_HOMEOMORPHIC_TO_K23);
InstallMethod(SubdigraphHomeomorphicToK4, "for a digraph", [IsDigraph],
-function(D)
- if IsOuterPlanarDigraph(D) then
- return fail;
- fi;
- D := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
- return SUBGRAPH_HOMEOMORPHIC_TO_K4(D);
-end);
+SUBGRAPH_HOMEOMORPHIC_TO_K4);
InstallMethod(SubdigraphHomeomorphicToK33, "for a digraph", [IsDigraph],
-function(D)
- if IsPlanarDigraph(D) then
- return fail;
- fi;
- D := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
- return SUBGRAPH_HOMEOMORPHIC_TO_K33(D);
-end);
+SUBGRAPH_HOMEOMORPHIC_TO_K33);
########################################################################
# 2. Properties
@@ -103,33 +79,34 @@ end);
InstallMethod(IsPlanarDigraph, "for a digraph", [IsDigraph],
function(D)
- local C, v, e;
- C := MaximalAntiSymmetricSubdigraph(DigraphMutableCopyIfMutable(D));
+ local v, e;
v := DigraphNrVertices(D);
- e := DigraphNrEdges(C);
+ e := DigraphNrAdjacenciesWithoutLoops(D);
+ if HasIsPlanarDigraph(D) then
+ return IsPlanarDigraph(D);
+ fi;
if v < 5 or e < 9 then
return true;
elif (IsConnectedDigraph(D) and e > 3 * v - 6)
or (HasChromaticNumber(D) and ChromaticNumber(D) > 4) then
return false;
fi;
- return IS_PLANAR(C);
+ return IS_PLANAR(D);
end);
InstallMethod(IsOuterPlanarDigraph, "for a digraph", [IsDigraph],
function(D)
- local C, v, e;
+ local v, e;
if HasIsPlanarDigraph(D) and not IsPlanarDigraph(D) then
return false;
fi;
v := DigraphNrVertices(D);
- e := DigraphNrEdges(D);
+ e := DigraphNrAdjacenciesWithoutLoops(D);
if v < 4 or e < 6 then
return true;
elif HasChromaticNumber(D) and ChromaticNumber(D) > 3 then
# Outer planar graphs are 3-colourable
return false;
fi;
- C := DigraphMutableCopyIfMutable(D);
- return IS_OUTER_PLANAR(MaximalAntiSymmetricSubdigraph(C));
+ return IS_OUTER_PLANAR(D);
end);
diff --git a/src/digraphs.c b/src/digraphs.c
index 53ea3f390..6697ad613 100644
--- a/src/digraphs.c
+++ b/src/digraphs.c
@@ -138,6 +138,62 @@ static Obj FuncDIGRAPH_NREDGES(Obj self, Obj D) {
return INTOBJ_INT(DigraphNrEdges(D));
}
+Int DigraphNrAdjacencies(Obj D) {
+ Int nr = 0;
+ if (IsbPRec(D, RNamName("DigraphNrAdjacencies"))) {
+ return INT_INTOBJ(ElmPRec(D, RNamName("DigraphNrAdjacencies")));
+ } else {
+ Obj const out = FuncOutNeighbours(0L, D);
+ for (Int v = 1; v <= LEN_LIST(out); ++v) {
+ Obj const out_v = ELM_LIST(out, v);
+ for (Int w = 1; w <= LEN_LIST(out_v); ++w) {
+ Int u = INT_INTOBJ(ELM_LIST(out_v, w));
+ if (v <= u
+ || CALL_3ARGS(IsDigraphEdge, D, INTOBJ_INT(u), INTOBJ_INT(v))
+ == False) {
+ ++nr;
+ }
+ }
+ }
+ }
+ if (IsAttributeStoringRep(D)) {
+ AssPRec(D, RNamName("DigraphNrAdjacencies"), INTOBJ_INT(nr));
+ }
+ return nr;
+}
+
+static Obj FuncDIGRAPH_NRADJACENCIES(Obj self, Obj D) {
+ return INTOBJ_INT(DigraphNrAdjacencies(D));
+}
+
+Int DigraphNrAdjacenciesWithoutLoops(Obj D) {
+ Int nr = 0;
+ if (IsbPRec(D, RNamName("DigraphNrAdjacenciesWithoutLoops"))) {
+ return INT_INTOBJ(ElmPRec(D, RNamName("DigraphNrAdjacenciesWithoutLoops")));
+ } else {
+ Obj const out = FuncOutNeighbours(0L, D);
+ for (Int v = 1; v <= LEN_LIST(out); ++v) {
+ Obj const out_v = ELM_LIST(out, v);
+ for (Int w = 1; w <= LEN_LIST(out_v); ++w) {
+ Int u = INT_INTOBJ(ELM_LIST(out_v, w));
+ if (v < u
+ || CALL_3ARGS(IsDigraphEdge, D, INTOBJ_INT(u), INTOBJ_INT(v))
+ == False) {
+ ++nr;
+ }
+ }
+ }
+ }
+ if (IsAttributeStoringRep(D)) {
+ AssPRec(D, RNamName("DigraphNrAdjacenciesWithoutLoops"), INTOBJ_INT(nr));
+ }
+ return nr;
+}
+
+static Obj FuncDIGRAPH_NRADJACENCIESWITHOUTLOOPS(Obj self, Obj D) {
+ return INTOBJ_INT(DigraphNrAdjacenciesWithoutLoops(D));
+}
+
/****************************************************************************
**
*F FuncGABOW_SCC
@@ -2113,6 +2169,8 @@ FuncMULTIDIGRAPH_CANONICAL_LABELLING(Obj self, Obj digraph, Obj colours) {
static StructGVarFunc GVarFuncs[] = {
GVAR_FUNC(DIGRAPH_NREDGES, 1, "digraph"),
+ GVAR_FUNC(DIGRAPH_NRADJACENCIES, 1, "digraph"),
+ GVAR_FUNC(DIGRAPH_NRADJACENCIESWITHOUTLOOPS, 1, "digraph"),
GVAR_FUNC(GABOW_SCC, 1, "adj"),
GVAR_FUNC(DIGRAPH_CONNECTED_COMPONENTS, 1, "digraph"),
GVAR_FUNC(IS_ACYCLIC_DIGRAPH, 1, "adj"),
diff --git a/src/digraphs.h b/src/digraphs.h
index f7b1f1ff8..a5a2708e3 100644
--- a/src/digraphs.h
+++ b/src/digraphs.h
@@ -24,6 +24,8 @@ Obj FuncIS_ANTISYMMETRIC_DIGRAPH(Obj self, Obj D);
Obj FuncADJACENCY_MATRIX(Obj self, Obj D);
Int DigraphNrEdges(Obj digraph);
+Int DigraphNrAdjacencies(Obj digraph);
+Int DigraphNrAdjacenciesWithoutLoops(Obj digraph);
Obj DigraphSource(Obj digraph);
Obj DigraphRange(Obj digraph);
diff --git a/src/planar.c b/src/planar.c
index b53355416..1cdf94a76 100644
--- a/src/planar.c
+++ b/src/planar.c
@@ -49,6 +49,9 @@
#pragma GCC diagnostic pop
#endif
+// Forward declaration of the main function in this file.
+Obj trivial_planarity_output(Int V, bool krtwsk);
+
// Forward declaration of the main function in this file.
Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk);
@@ -98,6 +101,28 @@ Obj FuncSUBGRAPH_HOMEOMORPHIC_TO_K4(Obj self, Obj digraph) {
// The implementation of the main functions in this file.
+Obj trivial_planarity_output(Int V, bool krtwsk) {
+ Obj res;
+ if (krtwsk) {
+ Obj subgraph = NEW_PLIST_IMM(T_PLIST, V);
+ SET_LEN_PLIST(subgraph, V);
+ for (int i = 1; i <= V; ++i) {
+ Obj list = NEW_PLIST_IMM(T_PLIST, 0);
+ SET_LEN_PLIST(list, 0);
+ SET_ELM_PLIST(subgraph, i, list);
+ CHANGED_BAG(subgraph);
+ }
+ res = NEW_PLIST_IMM(T_PLIST, 2);
+ SET_LEN_PLIST(res, 2);
+ SET_ELM_PLIST(res, 1, True);
+ SET_ELM_PLIST(res, 2, subgraph);
+ CHANGED_BAG(res);
+ } else {
+ res = True;
+ }
+ return res;
+}
+
// This function only accepts digraphs without multiple edges
Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) {
@@ -112,15 +137,19 @@ Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) {
(Int) TNAM_OBJ(digraph),
0L);
}
- Obj const out = FuncOutNeighbours(0L, digraph);
- if (FuncIS_ANTISYMMETRIC_DIGRAPH(0L, out) != True) {
- ErrorQuit("Digraphs: boyers_planarity_check (C): the 1st argument must be "
- "an antisymmetric digraph",
- 0L,
- 0L);
+ if (CALL_1ARGS(IsMultiDigraph, digraph) == True) {
+ ErrorQuit("expected a digraph without multiple edges!", 0L, 0L);
}
+
Int V = DigraphNrVertices(digraph);
- Int E = DigraphNrEdges(digraph);
+ if (V == 0) {
+ return trivial_planarity_output(0, krtwsk);
+ }
+
+ Int E = DigraphNrAdjacenciesWithoutLoops(digraph);
+ if (E == 0) {
+ return trivial_planarity_output(V, krtwsk);
+ }
if (V > INT_MAX) {
// Cannot currently test this, it might always be true, depending on the
// definition of Int.
@@ -139,19 +168,7 @@ Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) {
}
graphP theGraph = gp_New();
- switch (flags) {
- case EMBEDFLAGS_SEARCHFORK33:
- gp_AttachK33Search(theGraph);
- break;
- case EMBEDFLAGS_SEARCHFORK23:
- gp_AttachK23Search(theGraph);
- break;
- case EMBEDFLAGS_SEARCHFORK4:
- gp_AttachK4Search(theGraph);
- break;
- default:
- break;
- }
+
if (gp_InitGraph(theGraph, V) != OK) {
gp_Free(&theGraph);
ErrorQuit("Digraphs: boyers_planarity_check (C): invalid number of nodes!",
@@ -166,16 +183,34 @@ Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) {
return 0L;
}
- int status;
+ switch (flags) {
+ case EMBEDFLAGS_SEARCHFORK33:
+ gp_AttachK33Search(theGraph);
+ break;
+ case EMBEDFLAGS_SEARCHFORK23:
+ gp_AttachK23Search(theGraph);
+ break;
+ case EMBEDFLAGS_SEARCHFORK4:
+ gp_AttachK4Search(theGraph);
+ break;
+ default:
+ break;
+ }
+
+ int status;
+ Obj const out = FuncOutNeighbours(0L, digraph);
+ // Construct the antisymmetric digraph with no loops
for (Int v = 1; v <= LEN_LIST(out); ++v) {
DIGRAPHS_ASSERT(gp_VertexInRange(theGraph, v));
gp_SetVertexIndex(theGraph, v, v);
Obj const out_v = ELM_LIST(out, v);
for (Int w = 1; w <= LEN_LIST(out_v); ++w) {
DIGRAPHS_ASSERT(gp_VertexInRange(theGraph, w));
- int u = INT_INTOBJ(ELM_LIST(out_v, w));
- if (v != u) {
+ Int u = INT_INTOBJ(ELM_LIST(out_v, w));
+ if (v < u
+ || CALL_3ARGS(IsDigraphEdge, digraph, INTOBJ_INT(u), INTOBJ_INT(v))
+ == False) {
status = gp_AddEdge(theGraph, v, 0, u, 0);
if (status != OK) {
// Cannot currently test this, i.e. it shouldn't happen (and
@@ -190,6 +225,7 @@ Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) {
}
}
}
+
status = gp_Embed(theGraph, flags);
if (status == NOTOK) {
// Cannot currently test this, i.e. it shouldn't happen (and
@@ -197,6 +233,8 @@ Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) {
gp_Free(&theGraph);
ErrorQuit("Digraphs: boyers_planarity_check (C): status is not ok", 0L, 0L);
}
+
+ // Construct the return value
Obj res;
if (krtwsk) {
// Kuratowski subgraph isolator
diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst
index a1bf70123..3d79a8c5f 100644
--- a/tst/standard/attr.tst
+++ b/tst/standard/attr.tst
@@ -192,6 +192,44 @@ gap> AdjacencyMatrix(Digraph(rec(DigraphNrVertices := 0,
> DigraphRange := [])));
[ ]
+# DigraphNrAdjacencies
+gap> G := Digraph([[1, 3, 4, 5, 6, 7, 10, 12, 14, 15, 16, 17, 19, 20, 21, 22, 23, 26, 28, 29, 30],
+> [2, 3, 4, 6, 7, 8, 11, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30],
+> [1, 2, 4, 5, 6, 9, 10, 12, 14, 15, 17, 20, 22, 24, 25, 26, 27, 28, 30],
+> [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29],
+> [1, 4, 6, 7, 9, 10, 11, 12, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30],
+> [1, 5, 6, 7, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 28, 29, 30],
+> [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 13, 15, 16, 18, 19, 21, 22, 23, 25, 26, 27, 28, 30],
+> [2, 5, 6, 8, 9, 10, 12, 13, 14, 15, 19, 20, 21, 22, 23, 24, 25, 26, 29],
+> [1, 5, 6, 9, 12, 13, 14, 16, 18, 20, 21, 22, 23, 24, 25, 26, 29, 30],
+> [1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 13, 15, 16, 18, 19, 20, 21, 22, 25, 28],
+> [1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29],
+> [1, 2, 5, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30],
+> [1, 3, 4, 5, 8, 9, 10, 14, 16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29, 30],
+> [2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30],
+> [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 20, 22, 23, 24, 25, 26, 27, 28],
+> [1, 3, 6, 8, 10, 11, 13, 14, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28],
+> [1, 2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 22, 23, 26, 27, 30],
+> [1, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 30],
+> [1, 3, 4, 5, 6, 10, 11, 13, 14, 15, 18, 19, 20, 21, 22, 24, 25, 27, 28, 29],
+> [1, 2, 4, 7, 8, 9, 10, 11, 18, 20, 21, 22, 23, 24, 25, 26, 28, 30],
+> [1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 18, 19, 20, 21, 22, 24, 25, 26, 28, 29, 30],
+> [1, 3, 5, 7, 8, 9, 10, 12, 13, 14, 17, 18, 19, 21, 24, 26, 29, 30],
+> [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 16, 17, 18, 19, 20, 21, 23, 24, 25, 27, 28, 29],
+> [1, 2, 3, 6, 8, 9, 11, 12, 14, 16, 17, 18, 20, 22, 25, 26, 27, 28, 29, 30],
+> [1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 24, 25, 27, 28, 29, 30],
+> [1, 2, 5, 6, 7, 10, 12, 13, 14, 15, 16, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30],
+> [1, 2, 4, 5, 6, 7, 9, 10, 13, 17, 18, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30],
+> [1, 3, 4, 7, 8, 9, 11, 12, 13, 14, 16, 17, 19, 20, 21, 23, 24, 26, 27, 29],
+> [1, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, 20, 21, 23, 24, 25, 27, 28, 30],
+> [1, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 18, 19, 20, 21, 22, 24, 27, 28, 29]]);;
+gap> DigraphNrAdjacencies(G) * 2 - DigraphNrLoops(G) =
+> DigraphNrEdges(DigraphSymmetricClosure(G));
+true
+gap> DigraphNrAdjacenciesWithoutLoops(G) * 2 + DigraphNrLoops(G) =
+> DigraphNrEdges(DigraphSymmetricClosure(G));
+true
+
# DigraphTopologicalSort
gap> r := rec(DigraphNrVertices := 20000,
> DigraphSource := [],
diff --git a/tst/standard/examples.tst b/tst/standard/examples.tst
index d52bf344e..56d1359d5 100644
--- a/tst/standard/examples.tst
+++ b/tst/standard/examples.tst
@@ -249,6 +249,8 @@ gap> DigraphNrVertices(D);
8
gap> DigraphNrEdges(D);
26
+gap> DigraphNrAdjacencies(D);
+13
gap> DigraphUndirectedGirth(D);
3
gap> LollipopGraph(IsMutableDigraph, 5, 3);
diff --git a/tst/standard/planar.tst b/tst/standard/planar.tst
index 869f7397a..b0d08f622 100644
--- a/tst/standard/planar.tst
+++ b/tst/standard/planar.tst
@@ -79,8 +79,8 @@ 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]]);
gap> PlanarEmbedding(D);
-[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4 ], [ 6 ], [ 11, 7 ], [ 7 ], [ 8 ], [ ],
- [ 11 ], [ ], [ ] ]
+[ [ 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]]);
@@ -98,34 +98,39 @@ gap> D := List(["D??", "D?_", "D?o", "D?w", "D?{", "DCO", "DCW", "DCc", "DCo",
> "DQo", "DQw", "DQ{", "DTk", "DTw", "DT{", "DUW", "DUw", "DU{", "DV{", "D]w",
> "D]{", "D^{", "D~{"], DigraphFromGraph6String);;
gap> List(D, PlanarEmbedding);
-[ [ ], [ [ 5 ], [ ], [ ], [ ], [ ] ], [ [ 5 ], [ 5 ], [ ], [ ], [ ] ],
- [ [ 5 ], [ 5 ], [ 5 ], [ ], [ ] ], [ [ 5 ], [ 5 ], [ 5 ], [ 5 ], [ ] ],
- [ [ 4 ], [ 5 ], [ ], [ ], [ ] ], [ [ 4 ], [ 5 ], [ 5 ], [ ], [ ] ],
- [ [ 4, 5 ], [ ], [ ], [ 5 ], [ ] ], [ [ 4, 5 ], [ 5 ], [ ], [ ], [ ] ]
- , [ [ 4, 5 ], [ 5 ], [ ], [ 5 ], [ ] ],
- [ [ 4, 5 ], [ 5 ], [ 5 ], [ ], [ ] ],
- [ [ 4, 5 ], [ 5 ], [ 5 ], [ 5 ], [ ] ],
- [ [ 4, 5 ], [ 4 ], [ 5 ], [ 5 ], [ ] ],
- [ [ 4, 5 ], [ 5, 4 ], [ ], [ ], [ ] ],
- [ [ 4, 5 ], [ 5, 4 ], [ ], [ 5 ], [ ] ],
- [ [ 4, 5 ], [ 5, 4 ], [ 5 ], [ ], [ ] ],
- [ [ 4, 5 ], [ 5, 4 ], [ 5 ], [ 5 ], [ ] ],
- [ [ 4, 5 ], [ 5, 4 ], [ 4, 5 ], [ ], [ ] ],
- [ [ 4, 5 ], [ 5, 4 ], [ 4, 5 ], [ 5 ], [ ] ],
- [ [ 3, 5 ], [ 4 ], [ 5 ], [ ], [ ] ],
- [ [ 3, 5 ], [ 5, 4 ], [ ], [ ], [ ] ],
- [ [ 3, 5 ], [ 5, 4 ], [ 5 ], [ ], [ ] ],
- [ [ 3, 5 ], [ 4, 5 ], [ 5 ], [ 5 ], [ ] ],
- [ [ 3, 5, 4 ], [ ], [ 4, 5 ], [ 5 ], [ ] ],
- [ [ 3, 5, 4 ], [ 5 ], [ 4, 5 ], [ ], [ ] ],
- [ [ 3, 5, 4 ], [ 5 ], [ 4, 5 ], [ 5 ], [ ] ],
- [ [ 3, 4 ], [ 4, 5 ], [ 5 ], [ ], [ ] ],
- [ [ 3, 5, 4 ], [ 4, 5 ], [ 5 ], [ ], [ ] ],
- [ [ 3, 5, 4 ], [ 4, 5 ], [ 5 ], [ 5 ], [ ] ],
- [ [ 3, 5, 4 ], [ 5, 4 ], [ 4, 5 ], [ 5 ], [ ] ],
- [ [ 3, 5, 4 ], [ 4, 5, 3 ], [ 5 ], [ ], [ ] ],
- [ [ 3, 5, 4 ], [ 4, 5, 3 ], [ 5 ], [ 5 ], [ ] ],
- [ [ 3, 5, 4 ], [ 4, 5, 3 ], [ 4, 5 ], [ 5 ], [ ] ], fail ]
+[ [ [ ], [ ], [ ], [ ], [ ] ], [ [ 5 ], [ ], [ ], [ ], [ 1 ] ],
+ [ [ 5 ], [ 5 ], [ ], [ ], [ 1, 2 ] ],
+ [ [ 5 ], [ 5 ], [ 5 ], [ ], [ 1, 2, 3 ] ],
+ [ [ 5 ], [ 5 ], [ 5 ], [ 5 ], [ 1, 2, 3, 4 ] ],
+ [ [ 4 ], [ 5 ], [ ], [ 1 ], [ 2 ] ],
+ [ [ 4 ], [ 5 ], [ 5 ], [ 1 ], [ 2, 3 ] ],
+ [ [ 4, 5 ], [ ], [ ], [ 5, 1 ], [ 1, 4 ] ],
+ [ [ 4, 5 ], [ 5 ], [ ], [ 1 ], [ 1, 2 ] ],
+ [ [ 4, 5 ], [ 5 ], [ ], [ 5, 1 ], [ 1, 4, 2 ] ],
+ [ [ 4, 5 ], [ 5 ], [ 5 ], [ 1 ], [ 1, 2, 3 ] ],
+ [ [ 4, 5 ], [ 5 ], [ 5 ], [ 5, 1 ], [ 1, 4, 2, 3 ] ],
+ [ [ 4, 5 ], [ 4 ], [ 5 ], [ 5, 1, 2 ], [ 1, 4, 3 ] ],
+ [ [ 4, 5 ], [ 5, 4 ], [ ], [ 2, 1 ], [ 1, 2 ] ],
+ [ [ 4, 5 ], [ 5, 4 ], [ ], [ 2, 5, 1 ], [ 1, 4, 2 ] ],
+ [ [ 4, 5 ], [ 5, 4 ], [ 5 ], [ 2, 1 ], [ 1, 2, 3 ] ],
+ [ [ 4, 5 ], [ 5, 4 ], [ 5 ], [ 2, 5, 1 ], [ 1, 4, 2, 3 ] ],
+ [ [ 4, 5 ], [ 5, 4 ], [ 4, 5 ], [ 2, 3, 1 ], [ 1, 3, 2 ] ],
+ [ [ 4, 5 ], [ 5, 4 ], [ 4, 5 ], [ 2, 5, 3, 1 ], [ 1, 3, 4, 2 ] ],
+ [ [ 3, 5 ], [ 4 ], [ 5, 1 ], [ 2 ], [ 1, 3 ] ],
+ [ [ 3, 5 ], [ 5, 4 ], [ 1 ], [ 2 ], [ 1, 2 ] ],
+ [ [ 3, 5 ], [ 5, 4 ], [ 5, 1 ], [ 2 ], [ 1, 3, 2 ] ],
+ [ [ 3, 5 ], [ 4, 5 ], [ 5, 1 ], [ 5, 2 ], [ 1, 3, 2, 4 ] ],
+ [ [ 4, 5, 3 ], [ ], [ 1, 5, 4 ], [ 3, 5, 1 ], [ 1, 4, 3 ] ],
+ [ [ 4, 3, 5 ], [ 5 ], [ 5, 1, 4 ], [ 3, 1 ], [ 1, 3, 2 ] ],
+ [ [ 4, 5, 3 ], [ 5 ], [ 1, 5, 4 ], [ 3, 5, 1 ], [ 1, 4, 3, 2 ] ],
+ [ [ 4, 3 ], [ 5, 4 ], [ 1, 5 ], [ 2, 1 ], [ 3, 2 ] ],
+ [ [ 4, 5, 3 ], [ 5, 4 ], [ 1, 5 ], [ 2, 1 ], [ 3, 1, 2 ] ],
+ [ [ 4, 5, 3 ], [ 5, 4 ], [ 1, 5 ], [ 2, 5, 1 ], [ 3, 1, 4, 2 ] ],
+ [ [ 4, 3, 5 ], [ 5, 4 ], [ 1, 4, 5 ], [ 2, 5, 3, 1 ], [ 1, 3, 4, 2 ] ],
+ [ [ 4, 5, 3 ], [ 3, 5, 4 ], [ 1, 5, 2 ], [ 2, 1 ], [ 1, 2, 3 ] ],
+ [ [ 4, 5, 3 ], [ 3, 5, 4 ], [ 1, 5, 2 ], [ 2, 5, 1 ], [ 1, 4, 2, 3 ] ],
+ [ [ 4, 5, 3 ], [ 3, 5, 4 ], [ 1, 5, 2, 4 ], [ 3, 2, 5, 1 ], [ 1, 4, 2, 3 ] ]
+ , fail ]
# OuterPlanarEmbedding
gap> D := Digraph([[3, 5, 10], [8, 9, 10], [1, 4], [3, 6], [1, 7, 11], [4, 7],
@@ -148,26 +153,26 @@ gap> OuterPlanarEmbedding(D);
gap> D := CompleteDigraph(3);
gap> OuterPlanarEmbedding(D);
-[ [ 2, 3 ], [ 3 ], [ ] ]
+[ [ 2, 3 ], [ 3, 1 ], [ 1, 2 ] ]
# SubdigraphHomeomorphicToK23/33/4
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]]);
gap> SubdigraphHomeomorphicToK4(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 7, 11 ], [ 7 ], [ 8 ], [ ],
- [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 7, 11 ], [ 7, 4 ],
+ [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
gap> SubdigraphHomeomorphicToK23(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ], [ ],
- [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11 ], [ 7, 4 ],
+ [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
gap> D := Digraph([[3, 5, 10], [8, 9, 10], [1, 4], [3, 6], [1, 11], [4, 7],
> [6, 8], [2, 7], [2, 11], [1, 2], [5, 9]]);
gap> SubdigraphHomeomorphicToK4(D);
fail
gap> SubdigraphHomeomorphicToK23(D);
-[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ], [ ],
- [ 11 ], [ ], [ ] ]
+[ [ 3, 10, 5 ], [ 10, 8, 9 ], [ 4, 1 ], [ 6, 3 ], [ 11, 1 ], [ 7, 4 ],
+ [ 8, 6 ], [ 2, 7 ], [ 2, 11 ], [ 1, 2 ], [ 9, 5 ] ]
gap> SubdigraphHomeomorphicToK33(D);
fail
gap> SubdigraphHomeomorphicToK23(NullDigraph(0));
@@ -175,7 +180,8 @@ fail
gap> SubdigraphHomeomorphicToK33(CompleteDigraph(5));
fail
gap> SubdigraphHomeomorphicToK33(CompleteBipartiteDigraph(3, 3));
-[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ ], [ ], [ ] ]
+[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ 1, 2, 3 ], [ 3, 2, 1 ],
+ [ 2, 3, 1 ] ]
gap> SubdigraphHomeomorphicToK4(CompleteDigraph(3));
fail
@@ -192,8 +198,8 @@ gap> D := Digraph([[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10],
gap> IsPlanarDigraph(D);
false
gap> KuratowskiPlanarSubdigraph(D);
-[ [ 2, 9, 7 ], [ 3 ], [ 6 ], [ 5, 9 ], [ 6 ], [ ], [ 4 ], [ 7, 9, 3 ], [ ],
- [ ] ]
+[ [ 2, 9, 7 ], [ 1, 3 ], [ 6 ], [ 5, 9 ], [ 6, 4 ], [ 3, 5 ], [ 4 ],
+ [ 7, 9, 3 ], [ 8 ], [ ] ]
gap> D := NullDigraph(0);
gap> KuratowskiPlanarSubdigraph(D);
@@ -204,8 +210,8 @@ 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]]);
gap> KuratowskiOuterPlanarSubdigraph(D);
-[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ], [ ],
- [ 11 ], [ ], [ ] ]
+[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4, 1 ], [ 6, 3 ], [ 1, 11 ], [ 7, 4 ],
+ [ 8, 6 ], [ 2, 7 ], [ 11, 2 ], [ 2, 1 ], [ 5, 9 ] ]
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]]);
@@ -213,7 +219,8 @@ gap> D := Digraph([[2, 4, 7, 9, 10], [1, 3, 4, 6, 9, 10], [6, 10],
gap> IsOuterPlanarDigraph(D);
false
gap> KuratowskiOuterPlanarSubdigraph(D);
-[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9 ], [ ], [ ] ]
+[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9, 4 ], [ 8, 7 ],
+ [ ] ]
gap> D := NullDigraph(0);
gap> KuratowskiOuterPlanarSubdigraph(D);
@@ -228,14 +235,13 @@ gap> IS_PLANAR(2);
Error, Digraphs: boyers_planarity_check (C): the 1st argument must be a digrap\
h, not integer
gap> IS_PLANAR(NullDigraph(0));
-Error, Digraphs: boyers_planarity_check (C): invalid number of nodes!
+true
gap> IS_PLANAR(NullDigraph(70000));
-Error, Digraphs: boyers_planarity_check (C): invalid number of edges!
+true
gap> IsPlanarDigraph(NullDigraph(70000));
true
gap> IS_PLANAR(CompleteDigraph(2));
-Error, Digraphs: boyers_planarity_check (C): the 1st argument must be an antis\
-ymmetric digraph
+true
# DIGRAPHS_UnbindVariables
gap> Unbind(D);
diff --git a/tst/testinstall.tst b/tst/testinstall.tst
index e165c78c2..0012bcd8e 100644
--- a/tst/testinstall.tst
+++ b/tst/testinstall.tst
@@ -246,9 +246,13 @@ gap> gr := DigraphRemoveEdge(gr, [1, 2]);;
gap> gr := DigraphRemoveEdges(gr, [[1, 2], [2, 1]]);;
gap> DigraphNrEdges(gr);
40
+gap> DigraphNrAdjacencies(gr);
+20
gap> gr2 := DigraphClosure(gr, 7);;
gap> DigraphNrEdges(gr2);
42
+gap> DigraphNrAdjacencies(gr2);
+21
# Fix seg fault cause by wrong handling of no edges in
# FuncDIGRAPH_SOURCE_RANGE