diff --git a/.gitignore b/.gitignore index ad376dfd5..42ef9aa39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,80 +1,62 @@ *.DS_Store *.Plo +*.Tpo *.aux *.bbl *.blg *.brf *.digraphs *.g6 +*.gcda +*.gcno +*.guess *.gz *.html *.idx *.ilg *.ind +*.la +*.lab *.lo *.log *.o -*.orig *.out *.pdf *.pnr *.pyc *.six +*.status +*.sub *.swp *.synctex.gz *.tex +*.tex *.toc *.top *.tui *.txt -.libs/digraphs.la -.libs/digraphs.lai -.libs/**/digraphs.so -.libs/graphs.la -.libs/graphs.lai -.libs/graphs.so +.dirstamp +.libs/* Makefile Makefile.in -Transitions* aclocal.m4 autom4te.* bin/* -cnf/ar-lib -cnf/compile -cnf/config.guess -cnf/config.sub -cnf/depcomp -cnf/install-sh -cnf/ltmain.sh -cnf/missing -cnf/pkgconfig.h.in -config.status +cnf/* configure +digraphs-config.h digraphs-lib -digraphs.la -digraphs.tex -digraphs_dev.tex -digraphs_la-homos.Tpo -digraphs_la-schreier-sims.Tpo -graphs.la +gh-pages/ libtool -m4/libtool.m4 -m4/ltoptions.m4 -m4/ltsugar.m4 -m4/ltversion.m4 -m4/lt~obsolete.m4 -mt-cc.py -pkgconfig.h.in~ -release-checklist.tst -src/.deps/.dirstamp -src/.deps/digraphs_la-digraphs.Plo -src/.deps/digraphs_la-digraphs.Tpo -src/.dirstamp -src/.libs/digraphs_la-digraphs.o -src/bliss-0.72/.deps/.dirstamp -src/bliss-0.72/.dirstamp -src/digraphs_la-digraphs.lo +ltmain.sh +m4/* +planarity +src/.deps/* +src/.libs/* src/_pkgconfig.h +src/edge-addition-planarity-suite-Version_3.0.0.5/.libs +src/edge-addition-planarity-suite-Version_3.0.0.5/c/.deps +src/edge-addition-planarity-suite-Version_3.0.0.5/m4 src/stamp-h1 tags tst/out/* diff --git a/Makefile.am b/Makefile.am index ff3b59ade..9d8817e41 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,31 +4,47 @@ # This file is part of the build system of a GAP kernel extension. # Requires automake. # + ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = @PLANARITY_SUITE_DIR@ + +PLANAR_INCLUDE = -I@PLANARITY_SUITE_DIR@/ + BINARCHDIR = bin/$(GAPARCH) -GAPINSTALLLIB = $(abs_top_srcdir)/$(BINARCHDIR)/digraphs.so +GAPINSTALLLIB = $(abs_top_srcdir)/$(BINARCHDIR)/ lib_LTLIBRARIES = digraphs.la -digraphs_la_SOURCES = src/digraphs.c src/homos.c src/perms.c src/schreier-sims.c -digraphs_la_SOURCES += src/bliss-0.73/defs.cc src/bliss-0.73/graph.cc -digraphs_la_SOURCES += src/bliss-0.73/partition.cc src/bliss-0.73/orbit.cc -digraphs_la_SOURCES += src/bliss-0.73/uintseqhash.cc src/bliss-0.73/heap.cc -digraphs_la_SOURCES += src/bliss-0.73/timer.cc src/bliss-0.73/utils.cc +digraphs_la_SOURCES = src/digraphs.c +digraphs_la_SOURCES += src/homos.c +digraphs_la_SOURCES += src/perms.c +digraphs_la_SOURCES += src/planar.c +digraphs_la_SOURCES += src/schreier-sims.c +digraphs_la_SOURCES += src/bliss-0.73/defs.cc +digraphs_la_SOURCES += src/bliss-0.73/graph.cc +digraphs_la_SOURCES += src/bliss-0.73/partition.cc +digraphs_la_SOURCES += src/bliss-0.73/orbit.cc +digraphs_la_SOURCES += src/bliss-0.73/uintseqhash.cc +digraphs_la_SOURCES += src/bliss-0.73/heap.cc +digraphs_la_SOURCES += src/bliss-0.73/timer.cc +digraphs_la_SOURCES += src/bliss-0.73/utils.cc digraphs_la_SOURCES += src/bliss-0.73/bliss_C.cc -digraphs_la_CPPFLAGS = $(GAP_CPPFLAGS) -digraphs_la_CXXFLAGS = -O3 -march=native -mpopcnt -digraphs_la_CFLAGS = -O3 -march=native -mpopcnt $(GAP_CFLAGS) +digraphs_la_CPPFLAGS = $(GAP_CPPFLAGS) +digraphs_la_CXXFLAGS = -O3 -march=native -mpopcnt $(PLANAR_INCLUDE) +digraphs_la_CFLAGS = -O3 -march=native -mpopcnt $(GAP_CFLAGS) $(PLANAR_INCLUDE) digraphs_la_LDFLAGS = $(GAP_LDFLAGS) -module -avoid-version +digraphs_la_LIBADD = @PLANARITY_SUITE_DIR@/libplanarity.la + if SYS_IS_CYGWIN digraphs_la_LDFLAGS += -no-undefined -version-info 0:0:0 -Wl,$(GAPROOT)/bin/$(GAPARCH)/gap.dll endif all-local: digraphs.la - $(mkdir_p) $(top_srcdir)/$(BINARCHDIR) + $(mkdir_p) $(top_srcdir)/$(BINARCHDIR) $(top_srcdir)/bin/lib + cp -RL @PLANARITY_SUITE_DIR@/.libs/* $(top_srcdir)/bin/lib/ if SYS_IS_CYGWIN cp .libs/digraphs.dll $(GAPINSTALLLIB) else diff --git a/configure.ac b/configure.ac index b4c933e74..94afe0a4f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ # -# graphs: +# digraphs # # This file is part of the build system of a GAP kernel extension. # Requires GNU autoconf, GNU automake and GNU libtool. @@ -14,6 +14,10 @@ AC_CONFIG_SRCDIR([src/digraphs.c]) AC_CONFIG_HEADER([src/_pkgconfig.h:cnf/pkgconfig.h.in]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([cnf]) +AC_CONFIG_SUBDIRS([src/edge-addition-planarity-suite-Version_3.0.0.5]) + +PLANARITY_SUITE_DIR=src/edge-addition-planarity-suite-Version_3.0.0.5 +AC_SUBST(PLANARITY_SUITE_DIR) dnl ## dnl ## Get canonical host info @@ -29,6 +33,8 @@ AM_PROG_AR AX_PREFIX_CONFIG_H([src/digraphs-config.h],[],[src/_pkgconfig.h]) +AC_PREFIX_DEFAULT('${abs_top_builddir}/../../bin/') + dnl ## dnl ## Set the language dnl ## diff --git a/doc/attr.xml b/doc/attr.xml index e70a0630e..5b3761a41 100644 --- a/doc/attr.xml +++ b/doc/attr.xml @@ -1352,3 +1352,36 @@ gap> HamiltonianPath(g); <#/GAPDoc> + +<#GAPDoc Label="MaximalAntiSymmetricSubdigraph"> + + + A digraph. + + If digraph is a digraph, then MaximalAntiSymmetricSubdigraph + returns a anti-symmetric subdigraph of digraph which does not have + multiple edges, has the same vertex set as digraph, and whose + edge list is formed from digraph by ignoring the multiplicity of + edges, and by having either an edge from the vertex u to the vertex + v, or the edge from v to u (but not both) whenever + both edges belong to digraph. +

+ + See for more information. + D := Digraph([[2, 2], [1, 3], [4], [3, 1]]); + +gap> not IsAntiSymmetricDigraph(D) and IsMultiDigraph(D); +true +gap> OutNeighbours(D); +[ [ 2, 2 ], [ 1, 3 ], [ 4 ], [ 3, 1 ] ] +gap> D := MaximalAntiSymmetricSubdigraph(D); + +gap> IsAntiSymmetricDigraph(D) and not IsMultiDigraph(D); +true +gap> OutNeighbours(D); +[ [ 2 ], [ 3 ], [ 4 ], [ 1 ] ] +]]> + + +<#/GAPDoc> diff --git a/doc/digraphs.bib b/doc/digraphs.bib index 459a70e54..06d04084e 100644 --- a/doc/digraphs.bib +++ b/doc/digraphs.bib @@ -1,26 +1,41 @@ %% This BibTeX bibliography file was created using BibDesk. -%% http://bibdesk.sourceforge.net/ +%% https://bibdesk.sourceforge.io/ - -%% Created for James Mitchell at 2014-10-31 17:35:22 +0000 +%% Created for James Mitchell at 2018-12-13 18:13:21 +0000 %% Saved with string encoding Unicode (UTF-8) -@article{McKay201494, -title = "Practical graph isomorphism, \{II\} ", -journal = "Journal of Symbolic Computation ", -volume = "60", -number = "0", -pages = "94 - 112", -year = "2014", -note = "", -issn = "0747-7171", -doi = "http://dx.doi.org/10.1016/j.jsc.2013.09.003", -url = "http://www.sciencedirect.com/science/article/pii/S0747717113001193", -author = "Brendan D. McKay and Adolfo Piperno" -} + +@incollection{Boyer2006aa, + Author = {John M. Boyer and Wendy J. Myrvold}, + Booktitle = {Graph Algorithms and Applications 5}, + Date-Added = {2018-12-13 18:10:56 +0000}, + Date-Modified = {2018-12-13 18:11:05 +0000}, + Doi = {10.1142/9789812773289_0014}, + Month = {jun}, + Pages = {241--273}, + Publisher = {{WORLD} {SCIENTIFIC}}, + Title = {On the Cutting Edge: Simplified O(n) Planarity by Edge Addition}, + Url = {https://doi.org/10.1142/9789812773289_0014}, + Year = {2006}, + Bdsk-Url-1 = {https://doi.org/10.1142/9789812773289_0014}} + +@article{McKay201494, + Author = {Brendan D. McKay and Adolfo Piperno}, + Doi = {http://dx.doi.org/10.1016/j.jsc.2013.09.003}, + Issn = {0747-7171}, + Journal = {Journal of Symbolic Computation}, + Number = {0}, + Pages = {94 - 112}, + Title = {Practical graph isomorphism, \{II\}}, + Url = {http://www.sciencedirect.com/science/article/pii/S0747717113001193}, + Volume = {60}, + Year = {2014}, + Bdsk-Url-1 = {http://www.sciencedirect.com/science/article/pii/S0747717113001193}, + Bdsk-Url-2 = {http://dx.doi.org/10.1016/j.jsc.2013.09.003}} + @article{Gabow2000aa, Author = {Harold N. Gabow}, Date-Added = {2014-09-15 09:28:26 +0000}, @@ -35,76 +50,67 @@ @article{Gabow2000aa Url = {http://www.sciencedirect.com/science/article/pii/S002001900000051X}, Volume = {74}, Year = {2000}, - Bdsk-File-1 = {YnBsaXN0MDDUAQIDBAUGJCVYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoKgHCBMUFRYaIVUkbnVsbNMJCgsMDxJXTlMua2V5c1pOUy5vYmplY3RzViRjbGFzc6INDoACgAOiEBGABIAFgAdccmVsYXRpdmVQYXRoWWFsaWFzRGF0YV8QTS4uLy4uLy4uLy4uLy4uLy4uL1ZvbHVtZXMvR29vZ2xlRHJpdmUvRmlsZWQvMS1zMi4wLVMwMDIwMDE5MDAwMDAwNTFYLW1haW4ucGRm0hcLGBlXTlMuZGF0YU8RAY4AAAAAAY4AAgAAC0dvb2dsZURyaXZlAAAAAAAAAAAAAAAAAAAAAAAAAABCRAAB/////x8xLXMyLjAtUzAwMjAwMTkwMDAjRkZGRkZGRkYucGRmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAA/////wAAEgBjdQAAAAAAAAAAAAAAAAAFRmlsZWQAAAIAPS86Vm9sdW1lczpHb29nbGVEcml2ZTpGaWxlZDoxLXMyLjAtUzAwMjAwMTkwMDAwMDA1MVgtbWFpbi5wZGYAAA4ARAAhADEALQBzADIALgAwAC0AUwAwADAAMgAwADAAMQA5ADAAMAAwADAAMAAwADUAMQBYAC0AbQBhAGkAbgAuAHAAZABmAA8AGAALAEcAbwBvAGcAbABlAEQAcgBpAHYAZQASACgvRmlsZWQvMS1zMi4wLVMwMDIwMDE5MDAwMDAwNTFYLW1haW4ucGRmABMAFC9Wb2x1bWVzL0dvb2dsZURyaXZl//8AAIAG0hscHR5aJGNsYXNzbmFtZVgkY2xhc3Nlc11OU011dGFibGVEYXRhox0fIFZOU0RhdGFYTlNPYmplY3TSGxwiI1xOU0RpY3Rpb25hcnmiIiBfEA9OU0tleWVkQXJjaGl2ZXLRJidUcm9vdIABAAgAEQAaACMALQAyADcAQABGAE0AVQBgAGcAagBsAG4AcQBzAHUAdwCEAI4A3gDjAOsCfQJ/AoQCjwKYAqYCqgKxAroCvwLMAs8C4QLkAukAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAC6w==}, + Bdsk-File-1 = {YnBsaXN0MDDSAQIDBFxyZWxhdGl2ZVBhdGhZYWxpYXNEYXRhXxBNLi4vLi4vLi4vLi4vLi4vLi4vVm9sdW1lcy9Hb29nbGVEcml2ZS9GaWxlZC8xLXMyLjAtUzAwMjAwMTkwMDAwMDA1MVgtbWFpbi5wZGZPEQGOAAAAAAGOAAIAAAtHb29nbGVEcml2ZQAAAAAAAAAAAAAAAAAAAAAAAAAAQkQAAf////8fMS1zMi4wLVMwMDIwMDE5MDAwI0ZGRkZGRkZGLnBkZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAP////8AABIAY3UAAAAAAAAAAAAAAAAABUZpbGVkAAACAD0vOlZvbHVtZXM6R29vZ2xlRHJpdmU6RmlsZWQ6MS1zMi4wLVMwMDIwMDE5MDAwMDAwNTFYLW1haW4ucGRmAAAOAEQAIQAxAC0AcwAyAC4AMAAtAFMAMAAwADIAMAAwADEAOQAwADAAMAAwADAAMAA1ADEAWAAtAG0AYQBpAG4ALgBwAGQAZgAPABgACwBHAG8AbwBnAGwAZQBEAHIAaQB2AGUAEgAoL0ZpbGVkLzEtczIuMC1TMDAyMDAxOTAwMDAwMDUxWC1tYWluLnBkZgATABQvVm9sdW1lcy9Hb29nbGVEcml2Zf//AAAACAANABoAJAB0AAAAAAAAAgEAAAAAAAAABQAAAAAAAAAAAAAAAAAAAgY=}, Bdsk-Url-1 = {http://www.sciencedirect.com/science/article/pii/S002001900000051X}, Bdsk-Url-2 = {http://dx.doi.org/10.1016/S0020-0190(00)00051-X}} -@InProceedings{JunttilaKaski, - author = {Tommi Junttila and Petteri Kaski}, - title = {Engineering an efficient canonical labeling tool for - large and sparse graphs}, - booktitle = {Proceedings of the Ninth Workshop on Algorithm Engineering - and Experiments and - the Fourth Workshop on Analytic Algorithms and - Combinatorics}, - pages = {135--149}, - year = {2007}, - editor = {David Applegate and Gerth St{\o}lting Brodal and - Daniel Panario and Robert Sedgewick}, - OPTaddress = {New Orleans, LA}, - OPTmonth = {January 6}, - publisher = {SIAM}, - OPTpublisher = {Society for Industrial and Applied Mathematics}, -} +@inproceedings{JunttilaKaski, + Author = {Tommi Junttila and Petteri Kaski}, + Booktitle = {Proceedings of the Ninth Workshop on Algorithm Engineering and Experiments and the Fourth Workshop on Analytic Algorithms and Combinatorics}, + Editor = {David Applegate and Gerth St{\o}lting Brodal and Daniel Panario and Robert Sedgewick}, + Optaddress = {New Orleans, LA}, + Optmonth = {January 6}, + Optpublisher = {Society for Industrial and Applied Mathematics}, + Pages = {135--149}, + Publisher = {SIAM}, + Title = {Engineering an efficient canonical labeling tool for large and sparse graphs}, + Year = {2007}} -@article {CalderbankKantor1986, - AUTHOR = {Calderbank, R. and Kantor, W. M.}, - TITLE = {The geometry of two-weight codes}, - JOURNAL = {Bull. London Math. Soc.}, - FJOURNAL = {The Bulletin of the London Mathematical Society}, - VOLUME = {18}, - YEAR = {1986}, - NUMBER = {2}, - PAGES = {97--122}, - ISSN = {0024-6093}, - CODEN = {LMSBBT}, - MRCLASS = {51E20 (05B25 05C25 94B60)}, - MRNUMBER = {818812 (87h:51022)}, -MRREVIEWER = {J. W. P. Hirschfeld}, - DOI = {10.1112/blms/18.2.97}, - URL = {http://dx.doi.org/10.1112/blms/18.2.97}, -} +@article{CalderbankKantor1986, + Author = {Calderbank, R. and Kantor, W. M.}, + Coden = {LMSBBT}, + Doi = {10.1112/blms/18.2.97}, + Fjournal = {The Bulletin of the London Mathematical Society}, + Issn = {0024-6093}, + Journal = {Bull. London Math. Soc.}, + Mrclass = {51E20 (05B25 05C25 94B60)}, + Mrnumber = {818812 (87h:51022)}, + Mrreviewer = {J. W. P. Hirschfeld}, + Number = {2}, + Pages = {97--122}, + Title = {The geometry of two-weight codes}, + Url = {http://dx.doi.org/10.1112/blms/18.2.97}, + Volume = {18}, + Year = {1986}, + Bdsk-Url-1 = {http://dx.doi.org/10.1112/blms/18.2.97}} -@article {vanLintSchrijver1981, - AUTHOR = {van Lint, J. H. and Schrijver, A.}, - TITLE = {Construction of strongly regular graphs, two-weight codes and - partial geometries by finite fields}, - JOURNAL = {Combinatorica}, - FJOURNAL = {Combinatorica. An International Journal of the J\'anos Bolyai - Mathematical Society}, - VOLUME = {1}, - YEAR = {1981}, - NUMBER = {1}, - PAGES = {63--73}, - ISSN = {0209-9683}, - CODEN = {COMBDI}, - MRCLASS = {05B25 (05C25 94B25)}, - MRNUMBER = {602417 (82d:05041)}, -MRREVIEWER = {Joseph A. Thas}, - DOI = {10.1007/BF02579178}, - URL = {http://dx.doi.org/10.1007/BF02579178}, -} +@article{vanLintSchrijver1981, + Author = {van Lint, J. H. and Schrijver, A.}, + Coden = {COMBDI}, + Doi = {10.1007/BF02579178}, + Fjournal = {Combinatorica. An International Journal of the J\'anos Bolyai Mathematical Society}, + Issn = {0209-9683}, + Journal = {Combinatorica}, + Mrclass = {05B25 (05C25 94B25)}, + Mrnumber = {602417 (82d:05041)}, + Mrreviewer = {Joseph A. Thas}, + Number = {1}, + Pages = {63--73}, + Title = {Construction of strongly regular graphs, two-weight codes and partial geometries by finite fields}, + Url = {http://dx.doi.org/10.1007/BF02579178}, + Volume = {1}, + Year = {1981}, + Bdsk-Url-1 = {http://dx.doi.org/10.1007/BF02579178}} @article{Welsh1967aa, -author = {Welsh, D. J. A. and Powell, M. B.}, -title = {An upper bound for the chromatic number of a graph and its application to timetabling problems}, -journal = {The Computer Journal}, -volume = {10}, -number = {1}, -pages = {85-86}, -year = {1967}, -doi = {10.1093/comjnl/10.1.85}, -URL = {http://dx.doi.org/10.1093/comjnl/10.1.85}, -eprint = {/oup/backfile/content_public/journal/comjnl/10/1/10.1093/comjnl/10.1.85/2/100085.pdf} -} - + Author = {Welsh, D. J. A. and Powell, M. B.}, + Doi = {10.1093/comjnl/10.1.85}, + Eprint = {/oup/backfile/content_public/journal/comjnl/10/1/10.1093/comjnl/10.1.85/2/100085.pdf}, + Journal = {The Computer Journal}, + Number = {1}, + Pages = {85-86}, + Title = {An upper bound for the chromatic number of a graph and its application to timetabling problems}, + Url = {http://dx.doi.org/10.1093/comjnl/10.1.85}, + Volume = {10}, + Year = {1967}, + Bdsk-Url-1 = {http://dx.doi.org/10.1093/comjnl/10.1.85}} diff --git a/doc/main.xml b/doc/main.xml index 40058ee12..b75c4d545 100644 --- a/doc/main.xml +++ b/doc/main.xml @@ -6,6 +6,9 @@ http://www.tcs.tkk.fi/Software/bliss/bliss"> + https://github.com/graph-algorithms/edge-addition-planarity-suiteedge-addition-planarity-suite"> http://pallini.di.uniroma1.it/nauty"> diff --git a/doc/planar.xml b/doc/planar.xml new file mode 100644 index 000000000..2bcc113ba --- /dev/null +++ b/doc/planar.xml @@ -0,0 +1,318 @@ +############################################################################# +## +#W planar.xml +#Y Copyright (C) 2018 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## + +<#GAPDoc Label="IsPlanarDigraph"> + + + true or false. + + A planar digraph is a digraph that can be embedded in the plane in + such a way that its edges do not intersect. A digraph is planar if and only + if it does not have a subdigraph that is homeomorphic to either the + complete graph on 5 vertices or the complete bipartite graph with + vertex sets of sizes 3 and 3. +

+ + IsPlanarDigraph returns true if the digraph digraph is + planar and false if it is not. The directions and multiplicities of + any edges in digraph are ignored by IsPlanarDigraph. +

+ + See also . +

+ + This method uses the reference implementation in + &edge-addition-planarity-suite; by John Boyer of the algorithms described + in . + + IsPlanarDigraph(CompleteDigraph(4)); +true +gap> IsPlanarDigraph(CompleteDigraph(5)); +false +gap> IsPlanarDigraph(CompleteBipartiteDigraph(2, 3)); +true +gap> IsPlanarDigraph(CompleteBipartiteDigraph(3, 3)); +false +]]> + + +<#/GAPDoc> + +<#GAPDoc Label="IsOuterPlanarDigraph"> + + + true or false. + + An outer planar digraph is a digraph that can be embedded in the + plane in such a way that its edges do not intersect, and all vertices + belong to the unbounded face of the embedding. A digraph is outer planar + if and only if it does not have a subdigraph that is homeomorphic to either + the complete graph on 4 vertices or the complete bipartite graph + with vertex sets of sizes 2 and 3. +

+ + IsOuterPlanarDigraph returns true if the digraph + digraph is outer planar and false if it is not. The + directions and multiplicities of any edges in digraph are ignored by + IsPlanarDigraph.

+ + See also . + + This method uses the reference implementation in + &edge-addition-planarity-suite; by John Boyer of the algorithms described + in . + + IsOuterPlanarDigraph(CompleteDigraph(4)); +false +gap> IsOuterPlanarDigraph(CompleteDigraph(5)); +false +gap> IsOuterPlanarDigraph(CompleteBipartiteDigraph(2, 3)); +false +gap> IsOuterPlanarDigraph(CompleteBipartiteDigraph(3, 3)); +false +gap> IsOuterPlanarDigraph(CycleDigraph(10)); +true +]]> + + +<#/GAPDoc> + +<#GAPDoc Label="KuratowskiPlanarSubdigraph"> + + + A list or fail. + + KuratowskiPlanarSubdigraph returns the list 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.

+ + The directions and multiplicities of any edges in digraph are + ignored when considering whether or not digraph is planar.

+ + See also + and . +

+ + This method uses the reference implementation in + &edge-addition-planarity-suite; by John Boyer of the algorithms described + in . + + 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> KuratowskiPlanarSubdigraph(D); +fail +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]]); + +gap> IsPlanarDigraph(D); +false +gap> KuratowskiPlanarSubdigraph(D); +[ [ 2, 9, 7 ], [ 3 ], [ 6 ], [ 5, 9 ], [ 6 ], [ ], [ 4 ], + [ 7, 9, 3 ], [ ], [ ] ] +]]> + + +<#/GAPDoc> + +<#GAPDoc Label="KuratowskiOuterPlanarSubdigraph"> + + + A list or fail. + + KuratowskiOuterPlanarSubdigraph returns the list 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, + 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.

+ + The directions and multiplicities of any edges in digraph are + ignored when considering whether or not digraph is outer planar. +

+ + See also + , + , and + . +

+ + This method uses the reference implementation in + &edge-addition-planarity-suite; by John Boyer of the algorithms described + in . + + 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 ], [ ], [ ] ] +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]]); + +gap> IsOuterPlanarDigraph(D); +false +gap> KuratowskiOuterPlanarSubdigraph(D); +[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9 ], [ ], + [ ] ] +]]> + + +<#/GAPDoc> + +<#GAPDoc Label="PlanarEmbedding"> + + + A list or fail. + + If digraph is a planar digraph, then + PlanarEmbedding returns the list 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.

+ + The directions and multiplicities of any edges in digraph are + ignored by PlanarEmbedding. +

+ + See also + . +

+ + This method uses the reference implementation in + &edge-addition-planarity-suite; by John Boyer of the algorithms described + in . + + 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 ], [ ], [ ] ] +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]]); + +gap> PlanarEmbedding(D); +fail +]]> + + +<#/GAPDoc> + +<#GAPDoc Label="OuterPlanarEmbedding"> + + + A list or fail. + + If digraph is an outer planar digraph, then + OuterPlanarEmbedding returns the list 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.

+ + The directions and multiplicities of any edges in digraph are + ignored by OuterPlanarEmbedding. +

+ + See also . +

+ + This method uses the reference implementation in + &edge-addition-planarity-suite; by John Boyer of the algorithms described + in . + + 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> OuterPlanarEmbedding(D); +fail +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]]); + +gap> OuterPlanarEmbedding(D); +fail +gap> OuterPlanarEmbedding(CompleteBipartiteDigraph(2, 2)); +[ [ 3, 4 ], [ 4, 3 ], [ ], [ ] ] +]]> + + +<#/GAPDoc> + +<#GAPDoc Label="SubdigraphHomeomorphicToK"> + + + + + A list or fail. + + These attributes return the list of out-neighbours of a subdigraph of + the digraph digraph which is homeomorphic to one of the following: + the complete bipartite graph with vertex sets of sizes 2 and + 3; the complete bipartite graph with vertex sets of sizes 3 + and 3; or the complete graph with 4 vertices. If + digraph has no such subdigraphs, then fail is returned. +

+ + See also and for more details.

+ + This method uses the reference implementation in + &edge-addition-planarity-suite; by John Boyer of the algorithms described + in . + + 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 ], [ ], [ ] ] +gap> SubdigraphHomeomorphicToK23(D); +[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ], + [ ], [ 11 ], [ ], [ ] ] +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 ], [ ], [ ] ] +gap> SubdigraphHomeomorphicToK33(D); +fail +gap> SubdigraphHomeomorphicToK23(NullDigraph(0)); +fail +gap> SubdigraphHomeomorphicToK33(CompleteDigraph(5)); +fail +gap> SubdigraphHomeomorphicToK33(CompleteBipartiteDigraph(3, 3)); +[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ ], [ ], [ ] ] +gap> SubdigraphHomeomorphicToK4(CompleteDigraph(3)); +fail +]]> + + +<#/GAPDoc> diff --git a/doc/z-chap2.xml b/doc/z-chap2.xml index 52b01d9e7..4265e3f38 100644 --- a/doc/z-chap2.xml +++ b/doc/z-chap2.xml @@ -28,6 +28,7 @@ <#Include Label="InducedSubdigraph"> <#Include Label="ReducedDigraph"> <#Include Label="MaximalSymmetricSubdigraph"> + <#Include Label="MaximalAntiSymmetricSubdigraph"> <#Include Label="UndirectedSpanningTree"> <#Include Label="QuotientDigraph"> <#Include Label="DigraphReverse"> diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml index fae693463..6193030fc 100644 --- a/doc/z-chap4.xml +++ b/doc/z-chap4.xml @@ -69,5 +69,13 @@

Associated semigroups <#Include Label="AsSemigroup">
+ +
Planarity + <#Include Label="KuratowskiPlanarSubdigraph"> + <#Include Label="KuratowskiOuterPlanarSubdigraph"> + <#Include Label="PlanarEmbedding"> + <#Include Label="OuterPlanarEmbedding"> + <#Include Label="SubdigraphHomeomorphicToK"> +
diff --git a/doc/z-chap5.xml b/doc/z-chap5.xml index 966f7d459..bd11f80f1 100644 --- a/doc/z-chap5.xml +++ b/doc/z-chap5.xml @@ -39,4 +39,9 @@ <#Include Label="IsCycleDigraph"> +
Planarity + <#Include Label="IsPlanarDigraph"> + <#Include Label="IsOuterPlanarDigraph"> +
+ diff --git a/doc/z-title.xml b/doc/z-title.xml index 61ea4188d..bb92d739f 100644 --- a/doc/z-title.xml +++ b/doc/z-title.xml @@ -1,6 +1,5 @@ &Digraphs; - Methods for digraphs Version &VERSION; Jan De Beule @@ -57,8 +56,8 @@ - We would like to thank Christopher Jefferson for his help in including the - &bliss; tool in the package. + We would like to thank Christopher Jefferson for his help in including + &bliss; in &Digraphs;. This package's methods for computing digraph homomorphisms are based on work by Max Neunhöffer, and independently Artur Schäfer. diff --git a/gap/attr.gd b/gap/attr.gd index 1bb2dfe88..365b98346 100644 --- a/gap/attr.gd +++ b/gap/attr.gd @@ -64,6 +64,7 @@ DeclareAttribute("AdjacencyMatrix", IsDigraph); DeclareAttribute("BooleanAdjacencyMatrix", IsDigraph); DeclareAttribute("ReducedDigraph", IsDigraph); DeclareAttribute("MaximalSymmetricSubdigraph", IsDigraph); +DeclareAttribute("MaximalAntiSymmetricSubdigraph", IsDigraph); DeclareAttribute("MaximalSymmetricSubdigraphWithoutLoops", IsDigraph); DeclareOperation("DIGRAPHS_MaximalSymmetricSubdigraph", [IsDigraph, IsBool]); diff --git a/gap/attr.gi b/gap/attr.gi index e57a0ce67..348ce6b68 100644 --- a/gap/attr.gi +++ b/gap/attr.gi @@ -1483,3 +1483,50 @@ function(gr) od; return fail; end); + +InstallMethod(MaximalAntiSymmetricSubdigraph, "for a digraph", +[IsDigraph], +function(D) + local n, m, out, i, j; + + n := DigraphNrVertices(D); + if IsMultiDigraph(D) then + return MaximalAntiSymmetricSubdigraph(DigraphRemoveAllMultipleEdges(D)); + elif n <= 1 + or (HasIsAntisymmetricDigraph(D) and IsAntisymmetricDigraph(D)) then + return D; + fi; + + # The average degree + m := Float(Sum(OutDegreeSequence(D)) / n); + + if Float(n * (n - 1) / 2) < n * m * Log2(m) then + # The approximate complexity of using the adjacency matrix (first method) + # is n * (n - 1) / 2, and that of repeatedly calling AddSet (second method) + # is n * m * log2(m) where m is the mean degree of any vertex. Some + # experimenting showed that the comparison below is a reasonable way to + # decide which method to use. + out := BooleanAdjacencyMatrixMutableCopy(D); + for i in [1 .. n] do + for j in [i + 1 .. n] do + if out[i][j] then + out[j][i] := false; + fi; + od; + od; + out := DigraphByAdjacencyMatrixNC(out); + else + out := OutNeighboursMutableCopy(D); + Perform(out, Sort); + for i in [1 .. n] do + for j in out[i] do + if i <> j then + RemoveSet(out[j], i); + fi; + od; + od; + out := DigraphNC(out); + fi; + SetIsAntisymmetricDigraph(out, true); + return out; +end); diff --git a/gap/digraph.gi b/gap/digraph.gi index cef0e544b..1f7a4cd0b 100644 --- a/gap/digraph.gi +++ b/gap/digraph.gi @@ -1142,6 +1142,7 @@ function(mat) if IsInt(mat[1][1]) then SetAdjacencyMatrix(out, mat); else # boolean matrix + SetBooleanAdjacencyMatrix(out, mat); SetIsMultiDigraph(out, false); fi; diff --git a/gap/oper.gd b/gap/oper.gd index 99c093604..b04d11b0b 100644 --- a/gap/oper.gd +++ b/gap/oper.gd @@ -66,7 +66,7 @@ DeclareOperation("OutNeighboursOfVertexNC", [IsDigraph, IsPosInt]); DeclareOperation("DigraphInEdges", [IsDigraph, IsPosInt]); DeclareOperation("DigraphOutEdges", [IsDigraph, IsPosInt]); DeclareOperation("IsDigraphEdge", [IsDigraph, IsList]); -DeclareOperation("IsDigraphEdge", [IsDigraph, IsPosInt, IsPosInt]); +DeclareOperation("IsDigraphEdge", [IsDigraph, IsInt, IsInt]); DeclareOperation("DigraphConnectedComponent", [IsDigraph, IsPosInt]); DeclareOperation("DigraphStronglyConnectedComponent", [IsDigraph, IsPosInt]); diff --git a/gap/oper.gi b/gap/oper.gi index 58e8acd7f..c2b251060 100644 --- a/gap/oper.gi +++ b/gap/oper.gi @@ -1004,14 +1004,14 @@ function(digraph, edge) return IsDigraphEdge(digraph, edge[1], edge[2]); end); -InstallMethod(IsDigraphEdge, "for a digraph, pos int, pos int", -[IsDigraph, IsPosInt, IsPosInt], +InstallMethod(IsDigraphEdge, "for a digraph, int, int", +[IsDigraph, IsInt, IsInt], function(digraph, u, v) local n; n := DigraphNrVertices(digraph); - if u > n or v > n then + if u > n or v > n or u <= 0 or v <= 0 then return false; elif HasAdjacencyMatrix(digraph) then return AdjacencyMatrix(digraph)[u][v] <> 0; diff --git a/gap/planar.gd b/gap/planar.gd new file mode 100644 index 000000000..6afb5f1e8 --- /dev/null +++ b/gap/planar.gd @@ -0,0 +1,40 @@ +############################################################################# +## +## planar.gd +## Copyright (C) 2018 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## + +# The methods in this file utilise the kernel module functions that wrap +# Boyer's reference implementation (in C) of the planarity and subgraph +# homeomorphism algorithms from: +# +# John M. Boyer and Wendy J. Myrvold, On the Cutting Edge: Simplified O(n) +# Planarity by Edge Addition. Journal of Graph Algorithms and Applications, Vol. +# 8, No. 3, pp. 241-273, 2004. + +# Attributes . . . + +DeclareAttribute("PlanarEmbedding", IsDigraph); +DeclareAttribute("OuterPlanarEmbedding", IsDigraph); +DeclareAttribute("KuratowskiPlanarSubdigraph", IsDigraph); +DeclareAttribute("KuratowskiOuterPlanarSubdigraph", IsDigraph); +DeclareAttribute("SubdigraphHomeomorphicToK23", IsDigraph); +DeclareAttribute("SubdigraphHomeomorphicToK4", IsDigraph); +DeclareAttribute("SubdigraphHomeomorphicToK33", IsDigraph); + +# Properties . . . + +DeclareProperty("IsPlanarDigraph", IsDigraph); +DeclareProperty("IsOuterPlanarDigraph", IsDigraph); + +# True methods . . . + +InstallTrueMethod(IsBiconnectedDigraph, + IsOuterPlanarDigraph and IsHamiltonianDigraph); +InstallTrueMethod(IsHamiltonianDigraph, + IsOuterPlanarDigraph and IsBiconnectedDigraph); +InstallTrueMethod(IsPlanarDigraph, IsOuterPlanarDigraph); diff --git a/gap/planar.gi b/gap/planar.gi new file mode 100644 index 000000000..d05d6556d --- /dev/null +++ b/gap/planar.gi @@ -0,0 +1,142 @@ +############################################################################# +## +## planar.gi +## Copyright (C) 2018 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## + +# The methods in this file utilise the kernel module functions that wrap +# Boyer's reference implementation (in C) of the planarity and subgraph +# homeomorphism algorithms from: +# +# John M. Boyer and Wendy J. Myrvold, On the Cutting Edge: Simplified O(n) +# Planarity by Edge Addition. Journal of Graph Algorithms and Applications, +# Vol. 8, No. 3, pp. 241-273, 2004. + +######################################################################## +# +# This file is organised as follows: +# +# 1. Attributes +# +# 2. Properties +# +######################################################################## + +######################################################################## +# 1. Attributes +######################################################################## + +InstallMethod(PlanarEmbedding, "for a digraph", [IsDigraph], +function(D) + if DigraphNrEdges(D) = 0 or DigraphNrVertices(D) < 3 then + return []; + elif HasIsPlanarDigraph(D) and not IsPlanarDigraph(D) then + return fail; + fi; + D := DigraphRemoveAllMultipleEdges(D); + D := MaximalAntiSymmetricSubdigraph(D); + return PLANAR_EMBEDDING(D); +end); + +InstallMethod(OuterPlanarEmbedding, "for a digraph", [IsDigraph], +function(D) + if DigraphNrEdges(D) = 0 or DigraphNrVertices(D) < 3 then + return []; + elif HasIsOuterPlanarDigraph(D) and not IsOuterPlanarDigraph(D) then + return fail; + fi; + D := DigraphRemoveAllMultipleEdges(D); + D := MaximalAntiSymmetricSubdigraph(D); + return OUTER_PLANAR_EMBEDDING(D); +end); + +InstallMethod(KuratowskiPlanarSubdigraph, "for a digraph", [IsDigraph], +function(D) + if IsPlanarDigraph(D) then + return fail; + fi; + D := DigraphRemoveAllMultipleEdges(D); + D := MaximalAntiSymmetricSubdigraph(D); + return KURATOWSKI_PLANAR_SUBGRAPH(D); +end); + +InstallMethod(KuratowskiOuterPlanarSubdigraph, "for a digraph", [IsDigraph], +function(D) + if IsOuterPlanarDigraph(D) then + return fail; + fi; + D := DigraphRemoveAllMultipleEdges(D); + D := MaximalAntiSymmetricSubdigraph(D); + return KURATOWSKI_OUTER_PLANAR_SUBGRAPH(D); +end); + +InstallMethod(SubdigraphHomeomorphicToK23, "for a digraph", [IsDigraph], +function(D) + if IsOuterPlanarDigraph(D) then + return fail; + fi; + D := DigraphRemoveAllMultipleEdges(D); + D := MaximalAntiSymmetricSubdigraph(D); + return SUBGRAPH_HOMEOMORPHIC_TO_K23(D); +end); + +InstallMethod(SubdigraphHomeomorphicToK4, "for a digraph", [IsDigraph], +function(D) + if IsOuterPlanarDigraph(D) then + return fail; + fi; + D := DigraphRemoveAllMultipleEdges(D); + D := MaximalAntiSymmetricSubdigraph(D); + return SUBGRAPH_HOMEOMORPHIC_TO_K4(D); +end); + +InstallMethod(SubdigraphHomeomorphicToK33, "for a digraph", [IsDigraph], +function(D) + if IsPlanarDigraph(D) then + return fail; + fi; + D := DigraphRemoveAllMultipleEdges(D); + D := MaximalAntiSymmetricSubdigraph(D); + return SUBGRAPH_HOMEOMORPHIC_TO_K33(D); +end); + +######################################################################## +# 2. Properties +######################################################################## + +InstallMethod(IsPlanarDigraph, "for a digraph", [IsDigraph], +function(D) + local C, v, e; + C := MaximalAntiSymmetricSubdigraph(DigraphRemoveAllMultipleEdges(D)); + v := DigraphNrVertices(C); + e := DigraphNrEdges(C); + 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); +end); + +InstallMethod(IsOuterPlanarDigraph, "for a digraph", [IsDigraph], +function(D) + local C, v, e; + if HasIsPlanarDigraph(D) and not IsPlanarDigraph(D) then + return false; + fi; + C := MaximalAntiSymmetricSubdigraph(DigraphRemoveAllMultipleEdges(D)); + v := DigraphNrVertices(D); + e := DigraphNrEdges(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; + return IS_OUTER_PLANAR(C); +end); diff --git a/gap/prop.gi b/gap/prop.gi index 10b6ce67d..6c27f6136 100644 --- a/gap/prop.gi +++ b/gap/prop.gi @@ -356,11 +356,8 @@ function(digraph) return DigraphPeriod(digraph) = 1; end); -InstallMethod(IsAntisymmetricDigraph, "for a digraph", -[IsDigraph], +InstallMethod(IsAntisymmetricDigraph, "for a digraph", [IsDigraph], function(digraph) - # TODO check if the digraph has multiple edges, if not, then - # this can return false if it has too many edges. return IS_ANTISYMMETRIC_DIGRAPH(OutNeighbours(digraph)); end); diff --git a/gap/utils.gi b/gap/utils.gi index d854e3c12..dc79acd28 100644 --- a/gap/utils.gi +++ b/gap/utils.gi @@ -23,6 +23,7 @@ BindGlobal("DIGRAPHS_DocXMLFiles", ["attr.xml", "isomorph.xml", "oper.xml", "orbits.xml", + "planar.xml", "prop.xml", "utils.xml", "../PackageInfo.g"]); diff --git a/init.g b/init.g index 95c472fdf..017d503a2 100644 --- a/init.g +++ b/init.g @@ -45,5 +45,6 @@ ReadPackage("digraphs", "gap/io.gd"); ReadPackage("digraphs", "gap/grahom.gd"); ReadPackage("digraphs", "gap/orbits.gd"); ReadPackage("digraphs", "gap/cliques.gd"); +ReadPackage("digraphs", "gap/planar.gd"); DeclareInfoClass("InfoDigraphs"); diff --git a/makedoc.g b/makedoc.g index c989a8eb8..2fdc1dd6e 100644 --- a/makedoc.g +++ b/makedoc.g @@ -20,6 +20,7 @@ _DocXMLFiles := ["attr.xml", "isomorph.xml", "oper.xml", "orbits.xml", + "planar.xml", "prop.xml", "utils.xml", "../PackageInfo.g"]; diff --git a/read.g b/read.g index 4d5c27b81..62d264cfe 100644 --- a/read.g +++ b/read.g @@ -33,4 +33,5 @@ ReadPackage("digraphs", "gap/io.gi"); ReadPackage("digraphs", "gap/grahom.gi"); ReadPackage("digraphs", "gap/orbits.gi"); ReadPackage("digraphs", "gap/cliques.gi"); +ReadPackage("digraphs", "gap/planar.gi"); diff --git a/src/digraphs-debug.h b/src/digraphs-debug.h index f1006cc29..8f660e574 100644 --- a/src/digraphs-debug.h +++ b/src/digraphs-debug.h @@ -36,4 +36,3 @@ #endif #endif // DIGRAPHS_SRC_DIGRAPHS_DEBUG_H_ - diff --git a/src/digraphs.c b/src/digraphs.c index 6c506b95a..6d1d7d544 100644 --- a/src/digraphs.c +++ b/src/digraphs.c @@ -25,10 +25,13 @@ static Obj FuncDIGRAPH_OUT_NBS(Obj self, Obj digraph, Obj source, Obj range); static Obj FuncDIGRAPH_SOURCE_RANGE(Obj self, Obj digraph); +Obj IsDigraph; +Obj IsDigraphEdge; + #if !defined(GAP_KERNEL_MAJOR_VERSION) || GAP_KERNEL_MAJOR_VERSION < 3 // compatibility with GAP <= 4.9 static inline Obj NEW_PLIST_IMM(UInt type, Int plen) { - return NEW_PLIST(type | IMMUTABLE, plen); + return NEW_PLIST(type | IMMUTABLE, plen); } #endif @@ -169,8 +172,9 @@ static Obj FuncGABOW_SCC(Obj self, Obj digraph) { comp = NEW_PLIST_IMM(T_PLIST_CYC, nr); SET_LEN_PLIST(comp, nr); - memcpy(ADDR_OBJ(comp) + 1, CONST_ADDR_OBJ(stack1) + (end1 + 1), - nr * sizeof(Obj)); + memcpy(ADDR_OBJ(comp) + 1, + CONST_ADDR_OBJ(stack1) + (end1 + 1), + nr * sizeof(Obj)); nr = LEN_PLIST(comps) + 1; SET_ELM_PLIST(comps, nr, comp); @@ -620,7 +624,7 @@ static Obj FuncDIGRAPH_PATH(Obj self, Obj adj, Obj u, Obj v) { return Fail; } -static Obj FuncIS_ANTISYMMETRIC_DIGRAPH(Obj self, Obj adj) { +Obj FuncIS_ANTISYMMETRIC_DIGRAPH(Obj self, Obj adj) { Int nr, i, j, k, l, level, last1, last2; Obj nbs; UInt *stack, *ptr; @@ -1035,7 +1039,7 @@ static Obj FuncDIGRAPH_IN_OUT_NBS(Obj self, Obj adj) { return inn; } -static Obj FuncADJACENCY_MATRIX(Obj self, Obj digraph) { +Obj FuncADJACENCY_MATRIX(Obj self, Obj digraph) { Int n, i, j, val, len, outj; Obj adj, mat, adji, next; @@ -2205,9 +2209,8 @@ Obj FuncDIGRAPH_HOMOS(Obj self, Obj args) { Obj digraph1_gap = ELM_PLIST(args, 1); // find homomorphisms from digraph1 . . . Obj digraph2_gap = ELM_PLIST(args, 2); // . . . to digraph2 - Obj hook_gap = - ELM_PLIST(args, 3); // apply this function to every homomorphism - // Fail for no function + Obj hook_gap = ELM_PLIST(args, 3); // apply this function to every + // homomorphism Fail for no function Obj user_param_gap = ELM_PLIST(args, 4); // user_param_gap, which can be used in the hook Obj limit_gap = ELM_PLIST(args, 5); // the maximum number of results @@ -2378,8 +2381,8 @@ Obj FuncDIGRAPH_HOMOS(Obj self, Obj args) { /*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * */ /****************************************************************************** -*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export -*/ + *V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export + */ static StructGVarFunc GVarFuncs[] = { #ifdef DEBUG @@ -2574,23 +2577,75 @@ static StructGVarFunc GVarFuncs[] = { FuncDIGRAPH_HOMOS, "src/digraphs.c:FuncDIGRAPH_HOMOS"}, + {"IS_PLANAR", 1, "digraph", FuncIS_PLANAR, "src/planar.c:FuncIS_PLANAR"}, + + {"PLANAR_EMBEDDING", + 1, + "digraph", + FuncPLANAR_EMBEDDING, + "src/planar.c:FuncPLANAR_EMBEDDING"}, + + {"KURATOWSKI_PLANAR_SUBGRAPH", + 1, + "digraph", + FuncKURATOWSKI_PLANAR_SUBGRAPH, + "src/planar.c:FuncKURATOWSKI_PLANAR_SUBGRAPH"}, + + {"IS_OUTER_PLANAR", + 1, + "digraph", + FuncIS_OUTER_PLANAR, + "src/planar.c:FuncIS_OUTER_PLANAR"}, + + {"OUTER_PLANAR_EMBEDDING", + 1, + "digraph", + FuncOUTER_PLANAR_EMBEDDING, + "src/planar.c:FuncOUTER_PLANAR_EMBEDDING"}, + + {"KURATOWSKI_OUTER_PLANAR_SUBGRAPH", + 1, + "digraph", + FuncKURATOWSKI_OUTER_PLANAR_SUBGRAPH, + "src/planar.c:FuncKURATOWSKI_OUTER_PLANAR_SUBGRAPH"}, + + {"SUBGRAPH_HOMEOMORPHIC_TO_K23", + 1, + "digraph", + FuncSUBGRAPH_HOMEOMORPHIC_TO_K23, + "src/planar.c:FuncSUBGRAPH_HOMEOMORPHIC_TO_K23"}, + + {"SUBGRAPH_HOMEOMORPHIC_TO_K33", + 1, + "digraph", + FuncSUBGRAPH_HOMEOMORPHIC_TO_K33, + "src/planar.c:FuncSUBGRAPH_HOMEOMORPHIC_TO_K33"}, + + {"SUBGRAPH_HOMEOMORPHIC_TO_K4", + 1, + "digraph", + FuncSUBGRAPH_HOMEOMORPHIC_TO_K4, + "src/planar.c:FuncSUBGRAPH_HOMEOMORPHIC_TO_K4"}, + {0, 0, 0, 0, 0} /* Finish with an empty entry */ }; /****************************************************************************** -*F InitKernel( ) . . . . . . . . initialise kernel data structures -*/ + *F InitKernel( ) . . . . . . . . initialise kernel data structures + */ static Int InitKernel(StructInitInfo* module) { /* init filters and functions */ InitHdlrFuncsFromTable(GVarFuncs); + ImportGVarFromLibrary("IsDigraph", &IsDigraph); + ImportGVarFromLibrary("IsDigraphEdge", &IsDigraphEdge); /* return success */ return 0; } /****************************************************************************** -*F InitLibrary( ) . . . . . . . initialise library data structures -*/ + *F InitLibrary( ) . . . . . . . initialise library data structures + */ static Int InitLibrary(StructInitInfo* module) { /* init filters and functions */ InitGVarFuncsFromTable(GVarFuncs); @@ -2600,19 +2655,18 @@ static Int InitLibrary(StructInitInfo* module) { } /****************************************************************************** -*F InitInfopl() . . . . . . . . . . . . . . . . . table of init functions -*/ + *F InitInfopl() . . . . . . . . . . . . . . . . . table of init functions + */ static StructInitInfo module = { #ifdef DIGRAPHSSTATIC .type = MODULE_STATIC, #else .type = MODULE_DYNAMIC, #endif - .name = "digraphs", - .initKernel = InitKernel, + .name = "digraphs", + .initKernel = InitKernel, .initLibrary = InitLibrary, - .postRestore = 0 -}; + .postRestore = 0}; #ifndef DIGRAPHSSTATIC StructInitInfo* Init__Dynamic(void) { diff --git a/src/digraphs.h b/src/digraphs.h index 4921e4d79..fad324269 100644 --- a/src/digraphs.h +++ b/src/digraphs.h @@ -31,4 +31,9 @@ Obj OutNeighbours(Obj digraph); Obj DigraphSource(Obj digraph); Obj DigraphRange(Obj digraph); +Obj FuncIS_ANTISYMMETRIC_DIGRAPH(Obj self, Obj digraph); + +extern Obj IsDigraph; +extern Obj IsDigraphEdge; + #endif // DIGRAPHS_SRC_DIGRAPHS_H_ diff --git a/src/perms.h b/src/perms.h index 9778ef16f..f30f31ab4 100644 --- a/src/perms.h +++ b/src/perms.h @@ -43,9 +43,9 @@ struct perm_coll { typedef struct perm_coll PermColl; -void set_perms_degree(UIntS deg_arg); +void set_perms_degree(UIntS deg_arg); PermColl* new_perm_coll(UIntS upper_bound); -void add_perm_coll(PermColl* coll, Perm gen); +void add_perm_coll(PermColl* coll, Perm gen); PermColl* copy_perm_coll(PermColl* coll); // void reset_perm_coll(PermColl* coll); void free_perm_coll(PermColl* coll); diff --git a/src/planar.c b/src/planar.c new file mode 100644 index 000000000..9d8c8b55e --- /dev/null +++ b/src/planar.c @@ -0,0 +1,219 @@ +/******************************************************************************** +** +*A planar.c Planarity testing +** +** +** Copyright (C) 2018 - J. D. Mitchell +** +** This file is free software, see the digraphs/LICENSE. +** +********************************************************************************/ + +#include "planar.h" + +// C headers +#include // for INT_MAX +#include // for true and false + +// Digraphs package headers +#include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "digraphs.h" // for DigraphNrVertices, DigraphNrEdges, . . . + +// edge-addition-planarity-suite headers +#include "c/graph.h" +#include "c/graphK23Search.h" +#include "c/graphK33Search.h" +#include "c/graphK4Search.h" + +#if !defined(GAP_KERNEL_MAJOR_VERSION) || GAP_KERNEL_MAJOR_VERSION < 3 +// compatibility with GAP <= 4.9 +static inline Obj NEW_PLIST_IMM(UInt type, Int plen) { + return NEW_PLIST(type | IMMUTABLE, plen); +} +#endif + +// Forward declaration of the main function in this file. +Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk); + +// GAP level functions +Obj FuncIS_PLANAR(Obj self, Obj digraph) { + return boyers_planarity_check(digraph, EMBEDFLAGS_PLANAR, false); +} + +Obj FuncKURATOWSKI_PLANAR_SUBGRAPH(Obj self, Obj digraph) { + Obj res = boyers_planarity_check(digraph, EMBEDFLAGS_PLANAR, true); + return (ELM_PLIST(res, 1) == False ? ELM_PLIST(res, 2) : Fail); +} + +Obj FuncPLANAR_EMBEDDING(Obj self, Obj digraph) { + Obj res = boyers_planarity_check(digraph, EMBEDFLAGS_PLANAR, true); + return (ELM_PLIST(res, 1) == True ? ELM_PLIST(res, 2) : Fail); +} + +Obj FuncIS_OUTER_PLANAR(Obj self, Obj digraph) { + return boyers_planarity_check(digraph, EMBEDFLAGS_OUTERPLANAR, false); +} + +Obj FuncKURATOWSKI_OUTER_PLANAR_SUBGRAPH(Obj self, Obj digraph) { + Obj res = boyers_planarity_check(digraph, EMBEDFLAGS_OUTERPLANAR, true); + return (ELM_PLIST(res, 1) == False ? ELM_PLIST(res, 2) : Fail); +} + +Obj FuncOUTER_PLANAR_EMBEDDING(Obj self, Obj digraph) { + Obj res = boyers_planarity_check(digraph, EMBEDFLAGS_OUTERPLANAR, true); + return (ELM_PLIST(res, 1) == True ? ELM_PLIST(res, 2) : Fail); +} + +Obj FuncSUBGRAPH_HOMEOMORPHIC_TO_K23(Obj self, Obj digraph) { + Obj res = boyers_planarity_check(digraph, EMBEDFLAGS_SEARCHFORK23, true); + return (ELM_PLIST(res, 1) == False ? ELM_PLIST(res, 2) : Fail); +} + +Obj FuncSUBGRAPH_HOMEOMORPHIC_TO_K33(Obj self, Obj digraph) { + Obj res = boyers_planarity_check(digraph, EMBEDFLAGS_SEARCHFORK33, true); + return (ELM_PLIST(res, 1) == False ? ELM_PLIST(res, 2) : Fail); +} + +Obj FuncSUBGRAPH_HOMEOMORPHIC_TO_K4(Obj self, Obj digraph) { + Obj res = boyers_planarity_check(digraph, EMBEDFLAGS_SEARCHFORK4, true); + return (ELM_PLIST(res, 1) == False ? ELM_PLIST(res, 2) : Fail); +} + +// The implementation of the main functions in this file. + +// This function only accepts digraphs without multiple edges + +Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) { + DIGRAPHS_ASSERT(flags == EMBEDFLAGS_PLANAR || flags == EMBEDFLAGS_OUTERPLANAR + || flags == EMBEDFLAGS_SEARCHFORK23 + || flags == EMBEDFLAGS_SEARCHFORK4 + || flags == EMBEDFLAGS_SEARCHFORK33); + + if (CALL_1ARGS(IsDigraph, digraph) != True) { + ErrorQuit("Digraphs: boyers_planarity_check (C): the 1st argument must be " + "a digraph, not %s", + (Int) TNAM_OBJ(digraph), + 0L); + } + Obj const out = OutNeighbours(digraph); + if (FuncIS_ANTISYMMETRIC_DIGRAPH(0L, out) != True) { + ErrorQuit("Digraphs: boyers_planarity_check (C): the 1st argument must be " + "an antisymmetric digraph", + 0L, + 0L); + } + Int V = DigraphNrVertices(digraph); + Int E = DigraphNrEdges(digraph); + if (V > INT_MAX) { + // Cannot currently test this, it might always be true, depending on the + // definition of Int. + ErrorQuit("Digraphs: boyers_planarity_check (C): the maximum number of " + "nodes is %d, found %d", + INT_MAX, + V); + return 0L; + } else if (2 * E > INT_MAX) { + // Cannot currently test this + ErrorQuit("Digraphs: boyers_planarity_check (C): the maximum number of " + "edges is %d, found %d", + INT_MAX / 2, + E); + return 0L; + } + + 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; + } + if (gp_InitGraph(theGraph, V) != OK) { + gp_Free(&theGraph); + ErrorQuit("Digraphs: boyers_planarity_check (C): invalid number of nodes!", + 0L, + 0L); + return 0L; + } else if (gp_EnsureArcCapacity(theGraph, 2 * E) != OK) { + gp_Free(&theGraph); + ErrorQuit("Digraphs: boyers_planarity_check (C): invalid number of edges!", + 0L, + 0L); + return 0L; + } + + int status; + + 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) { + status = gp_AddEdge(theGraph, v, 0, u, 0); + if (status != OK) { + // Cannot currently test this, i.e. it shouldn't happen (and + // currently there is no example where it does happen) + gp_Free(&theGraph); + ErrorQuit("Digraphs: boyers_planarity_check (C): internal error, " + "can't add edge from %d to %d", + (Int) v, + (Int) u); + return 0L; + } + } + } + } + status = gp_Embed(theGraph, flags); + if (status == NOTOK) { + // Cannot currently test this, i.e. it shouldn't happen (and + // currently there is no example where it does happen) + gp_Free(&theGraph); + ErrorQuit("Digraphs: boyers_planarity_check (C): status is not ok", 0L, 0L); + } + Obj res; + if (krtwsk) { + // Kuratowski subgraph isolator + gp_SortVertices(theGraph); + Obj subgraph = NEW_PLIST_IMM(T_PLIST, theGraph->N); + SET_LEN_PLIST(subgraph, theGraph->N); + for (int i = 1; i <= theGraph->N; ++i) { + int nr = 0; + Obj list = NEW_PLIST_IMM(T_PLIST, 0); + int j = theGraph->V[i].link[1]; + while (j) { + if (CALL_3ARGS(IsDigraphEdge, + digraph, + INTOBJ_INT((Int) i), + INTOBJ_INT((Int) theGraph->E[j].neighbor)) + == True) { + AssPlist(list, ++nr, INTOBJ_INT(theGraph->E[j].neighbor)); + } + j = theGraph->E[j].link[1]; + } + if (nr == 0) { + RetypeBag(list, T_PLIST_EMPTY); + } + 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, (status == NONEMBEDDABLE ? False : True)); + SET_ELM_PLIST(res, 2, subgraph); + CHANGED_BAG(res); + } else if (status == NONEMBEDDABLE) { + res = False; + } else { + res = True; + } + gp_Free(&theGraph); + return res; +} diff --git a/src/planar.h b/src/planar.h new file mode 100644 index 000000000..d64960ca3 --- /dev/null +++ b/src/planar.h @@ -0,0 +1,30 @@ +/******************************************************************************** +** +*A planar.h Planarity testing +** +** +** Copyright (C) 2018 - J. D. Mitchell +** +** This file is free software, see the digraphs/LICENSE. +** +********************************************************************************/ + +#ifndef DIGRAPHS_SRC_PLANAR_H_ +#define DIGRAPHS_SRC_PLANAR_H_ + +// GAP headers +#include "src/compiled.h" + +Obj FuncIS_PLANAR(Obj self, Obj digraph); +Obj FuncKURATOWSKI_PLANAR_SUBGRAPH(Obj self, Obj digraph); +Obj FuncPLANAR_EMBEDDING(Obj self, Obj digraph); + +Obj FuncIS_OUTER_PLANAR(Obj self, Obj digraph); +Obj FuncKURATOWSKI_OUTER_PLANAR_SUBGRAPH(Obj self, Obj digraph); +Obj FuncOUTER_PLANAR_EMBEDDING(Obj self, Obj digraph); + +Obj FuncSUBGRAPH_HOMEOMORPHIC_TO_K23(Obj self, Obj digraph); +Obj FuncSUBGRAPH_HOMEOMORPHIC_TO_K33(Obj self, Obj digraph); +Obj FuncSUBGRAPH_HOMEOMORPHIC_TO_K4(Obj self, Obj digraph); + +#endif // DIGRAPHS_SRC_PLANAR_H_ diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst index ff46ea535..04481e2ce 100644 --- a/tst/standard/attr.tst +++ b/tst/standard/attr.tst @@ -1678,6 +1678,30 @@ gap> gr := DigraphAddEdges(DigraphAddVertex(CycleDigraph(600)), gap> HamiltonianPath(gr); fail +# MaximalAntiSymmetricSubdigraph +gap> MaximalAntiSymmetricSubdigraph(NullDigraph(0)); + +gap> IsAntisymmetricDigraph(DigraphCopy(last)); +true +gap> MaximalAntiSymmetricSubdigraph(NullDigraph(1)); + +gap> IsAntisymmetricDigraph(DigraphCopy(last)); +true +gap> MaximalAntiSymmetricSubdigraph(CompleteDigraph(1)); + +gap> IsAntisymmetricDigraph(DigraphCopy(last)); +true +gap> MaximalAntiSymmetricSubdigraph(CompleteBipartiteDigraph(2, 30000)); + +gap> IsAntisymmetricDigraph(DigraphCopy(last)); +true +gap> MaximalAntiSymmetricSubdigraph(Digraph([[1, 1, 2, 2], []])); + +gap> OutNeighbours(last); +[ [ 1, 2 ], [ ] ] +gap> MaximalAntiSymmetricSubdigraph(CompleteDigraph(10)); + + # DIGRAPHS_UnbindVariables gap> Unbind(adj); gap> Unbind(adj1); diff --git a/tst/standard/planar.tst b/tst/standard/planar.tst new file mode 100644 index 000000000..0e0f3a504 --- /dev/null +++ b/tst/standard/planar.tst @@ -0,0 +1,244 @@ +############################################################################# +## +#W standard/planar.tst +#Y Copyright (C) 2018 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## +gap> START_TEST("Digraphs package: standard/planar.tst"); +gap> LoadPackage("digraphs", false);; + +# +gap> DIGRAPHS_StartTest(); + +# IsPlanarDigraph +gap> D := NullDigraph(0); + +gap> IsPlanarDigraph(D); +true +gap> D := CompleteDigraph(4); + +gap> IsPlanarDigraph(D); +true +gap> D := CompleteDigraph(5); + +gap> IsPlanarDigraph(D); +false +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]]); + +gap> ChromaticNumber(D); +5 +gap> IsPlanarDigraph(D); +false +gap> D := CompleteBipartiteDigraph(3, 3); + +gap> D := DigraphDisjointUnion(D, D); + +gap> IsPlanarDigraph(D); +false + +# IsOuterPlanarDigraph +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]]); + +gap> ChromaticNumber(D); +5 +gap> IsPlanarDigraph(D); +false +gap> IsOuterPlanarDigraph(D); +false +gap> D := NullDigraph(0); + +gap> IsOuterPlanarDigraph(D); +true +gap> D := CompleteDigraph(4); + +gap> IsOuterPlanarDigraph(D); +false +gap> D := CompleteDigraph(4); + +gap> ChromaticNumber(D); +4 +gap> IsOuterPlanarDigraph(D); +false +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> IsOuterPlanarDigraph(D); +false +gap> IsPlanarDigraph(D); +true + +# PlanarEmbedding +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 ], [ ], [ ] ] +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]]); + +gap> IsPlanarDigraph(D); +false +gap> PlanarEmbedding(D); +fail +gap> D := NullDigraph(0); + +gap> PlanarEmbedding(D); +[ ] +gap> D := List(["D??", "D?_", "D?o", "D?w", "D?{", "DCO", "DCW", "DCc", "DCo", +> "DCs", "DCw", "DC{", "DEk", "DEo", "DEs", "DEw", "DE{", "DFw", "DF{", "DQg", +> "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 ] + +# OuterPlanarEmbedding +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> OuterPlanarEmbedding(D); +fail +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]]); + +gap> IsOuterPlanarDigraph(D); +false +gap> OuterPlanarEmbedding(D); +fail +gap> D := NullDigraph(0); + +gap> OuterPlanarEmbedding(D); +[ ] +gap> D := CompleteDigraph(3); + +gap> OuterPlanarEmbedding(D); +[ [ 2, 3 ], [ 3 ], [ ] ] + +# 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 ], [ ], [ ] ] +gap> SubdigraphHomeomorphicToK23(D); +[ [ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 11 ], [ 7 ], [ 8 ], [ ], + [ 11 ], [ ], [ ] ] +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 ], [ ], [ ] ] +gap> SubdigraphHomeomorphicToK33(D); +fail +gap> SubdigraphHomeomorphicToK23(NullDigraph(0)); +fail +gap> SubdigraphHomeomorphicToK33(CompleteDigraph(5)); +fail +gap> SubdigraphHomeomorphicToK33(CompleteBipartiteDigraph(3, 3)); +[ [ 4, 6, 5 ], [ 4, 5, 6 ], [ 6, 5, 4 ], [ ], [ ], [ ] ] +gap> SubdigraphHomeomorphicToK4(CompleteDigraph(3)); +fail + +# KuratowskiPlanarSubdigraph +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> KuratowskiPlanarSubdigraph(D); +fail +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]]); + +gap> IsPlanarDigraph(D); +false +gap> KuratowskiPlanarSubdigraph(D); +[ [ 2, 9, 7 ], [ 3 ], [ 6 ], [ 5, 9 ], [ 6 ], [ ], [ 4 ], [ 7, 9, 3 ], [ ], + [ ] ] +gap> D := NullDigraph(0); + +gap> KuratowskiPlanarSubdigraph(D); +fail + +# KuratowskiOuterPlanarSubdigraph +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 ], [ ], [ ] ] +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]]); + +gap> IsOuterPlanarDigraph(D); +false +gap> KuratowskiOuterPlanarSubdigraph(D); +[ [ ], [ ], [ ], [ 8, 9 ], [ ], [ ], [ 9, 4 ], [ 7, 9 ], [ ], [ ] ] +gap> D := NullDigraph(0); + +gap> KuratowskiOuterPlanarSubdigraph(D); +fail +gap> D := CompleteDigraph(3); + +gap> KuratowskiOuterPlanarSubdigraph(D); +fail + +# Kernel function boyers_planarity_check, errors +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! +gap> IS_PLANAR(NullDigraph(70000)); +Error, Digraphs: boyers_planarity_check (C): invalid number of edges! +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 + +# +gap> DIGRAPHS_StopTest(); +gap> STOP_TEST("Digraphs package: standard/attr.tst", 0); + +#T# DigraphSource and DigraphRange