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