From 144c2e0fb1fba30e45cc746c61fe3c2488362927 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 3 May 2024 10:37:43 +0100 Subject: [PATCH 1/3] Checkout files from mpan322/main --- .github/workflows/gap.yml | 133 ++++++ PackageInfo.g | 3 +- doc/display.xml | 846 +++++++++++++-------------------- doc/main.xml | 60 +++ doc/z-chap9.xml | 15 +- etc/code-coverage-test-c.py | 151 ++++++ etc/code-coverage-test-gap.py | 2 +- gap/.null-ls_141605_display.gi | 484 +++++++++++++++++++ gap/deprecated.gd | 35 ++ gap/deprecated.gi | 116 +++++ gap/display.gd | 69 ++- gap/display.gi | 664 +++++++++----------------- init.g | 1 + read.g | 1 + tst/standard/display.tst | 700 +++++++++++++++++++++++++++ 15 files changed, 2316 insertions(+), 964 deletions(-) create mode 100644 .github/workflows/gap.yml create mode 100644 doc/main.xml create mode 100755 etc/code-coverage-test-c.py create mode 100644 gap/.null-ls_141605_display.gi create mode 100644 gap/deprecated.gd create mode 100644 gap/deprecated.gi create mode 100644 tst/standard/display.tst diff --git a/.github/workflows/gap.yml b/.github/workflows/gap.yml new file mode 100644 index 000000000..9ec6f1a19 --- /dev/null +++ b/.github/workflows/gap.yml @@ -0,0 +1,133 @@ +name: "GAP" +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + - stable-*.* + schedule: + # Every day at 3:30 AM UTC + - cron: '30 3 * * *' + +env: + DIGRAPHS_LIB: digraphs-lib-0.6 + +jobs: + test-unix: + name: "${{ matrix.os }}${{ matrix.ABI }} / GAP ${{ matrix.gap-branch }}" + runs-on: "${{ matrix.os }}-latest" + strategy: + fail-fast: false + matrix: + os: + - ubuntu + gap-branch: + - master + - stable-4.11 + - stable-4.12 + - stable-4.13 + ABI: [''] + pkgs-to-clone: + - NautyTracesInterface + + include: + - gap-branch: master + os: macos + pkgs-to-clone: "NautyTracesInterface" + - gap-branch: master + os: ubuntu + ABI: 32 + + steps: + - uses: actions/checkout@v4 + - name: "Install dependencies" + if: ${{ runner.os == 'macOS' }} + run: brew install automake + - name: "Install GAP and clone/compile necessary packages" + uses: gap-actions/setup-gap@v2 + with: + GAP_PKGS_TO_CLONE: "${{ matrix.pkgs-to-clone }} digraphs/graphviz" + GAP_PKGS_TO_BUILD: "io orb profiling grape NautyTracesInterface datastructures" + GAPBRANCH: ${{ matrix.gap-branch }} + ABI: ${{ matrix.ABI }} + - name: "Build Digraphs" + uses: gap-actions/build-pkg@v1 + with: + ABI: ${{ matrix.ABI }} + - name: "Install digraphs-lib" + run: | + curl --retry 5 -L -O "https://digraphs.github.io/Digraphs/${{ env.DIGRAPHS_LIB }}.tar.gz" + tar xf "${{ env.DIGRAPHS_LIB }}.tar.gz" + - name: "Run DigraphsTestInstall" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/install.g" + - name: "Run DigraphsTestStandard" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/standard.g" + - name: "Run DigraphsTestManualExamples" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/examples.g" + - name: "Run DigraphsTestExtreme" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/extreme.g" + - uses: gap-actions/process-coverage@v2 + - uses: codecov/codecov-action@v3 + + test-cygwin: + name: "cygwin / GAP master" + runs-on: windows-2019 + env: + CHERE_INVOKING: 1 + steps: + - uses: actions/checkout@v4 + - uses: gap-actions/setup-cygwin@v1 + - uses: gap-actions/setup-gap@cygwin-v2 + with: + GAP_PKGS_TO_BUILD: "io orb profiling grape datastructures" + GAP_PKGS_TO_CLONE: "digraphs/graphviz" + - uses: gap-actions/build-pkg@cygwin-v1 + - name: "Install digraphs-lib" + run: | + curl --retry 5 -L -O "https://digraphs.github.io/Digraphs/${{ env.DIGRAPHS_LIB }}.tar.gz" + tar xf "${{ env.DIGRAPHS_LIB }}.tar.gz" + - uses: gap-actions/run-pkg-tests@cygwin-v2 + - uses: gap-actions/process-coverage@cygwin-v2 + - uses: codecov/codecov-action@v3 + + with-external-planarity-bliss: + runs-on: "ubuntu-latest" + env: + GAPBRANCH: "stable-4.12" + ABI: 64 + PKG_CONFIG_PATH: "/home/runner/micromamba/envs/digraphs/lib/pkgconfig:/home/runner/micromamba/envs/digraphs/share/pkgconfig/" + LD_LIBRARY_PATH: "/home/runner/micromamba/envs/digraphs/lib" + CFLAGS: "-I/home/runner/micromamba/envs/digraphs/include" + LDFLAGS: "-L/home/runner/micromamba/envs/digraphs/lib" + defaults: + run: + shell: bash -l {0} + steps: + - uses: actions/checkout@v4 + - name: "Install micromamba environment from environment.yml . . ." + uses: mamba-org/setup-micromamba@v1 + with: + environment-file: environment.yml + cache-environment: true + - name: "Activate \"digraphs\" environment . . ." + run: micromamba activate digraphs + - name: "Install GAP and clone/compile necessary packages" + uses: gap-actions/setup-gap@v2 + with: + GAP_PKGS_TO_BUILD: "io orb profiling grape datastructures" + GAP_PKGS_TO_CLONE: "digraphs/graphviz" + - name: "Build Digraphs" + uses: gap-actions/build-pkg@v1 + with: + CONFIGFLAGS: --with-external-planarity --with-external-bliss + - name: "Run Digraphs package's tst/teststandard.g" + uses: gap-actions/run-pkg-tests@v2 diff --git a/PackageInfo.g b/PackageInfo.g index edbfb2e38..87a439a2c 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -539,9 +539,10 @@ PackageDoc := rec( ), Dependencies := rec( - GAP := ">=4.10.0", + GAP := ">=4.11.0", NeededOtherPackages := [["IO", ">=4.5.1"], ["orb", ">=4.8.2"], + ["GraphViz", ">=0.0.0"], ["datastructures", ">=0.2.5"]], SuggestedOtherPackages := [["GAPDoc", ">=1.6.3"], ["GRAPE", ">=4.8.1"], diff --git a/doc/display.xml b/doc/display.xml index f064d9a05..7086f1929 100644 --- a/doc/display.xml +++ b/doc/display.xml @@ -1,518 +1,282 @@ ############################################################################# ## #W display.xml -#Y Copyright (C) 2011-17 James D. Mitchell +#Y Copyright (C) 2014-24 James D. Mitchell ## ## Licensing information can be found in the README file of this package. ## ############################################################################# ## +<#GAPDoc Label="DotDigraph"> + + + + A string. + + WARNING! As of v2.0.0 of &Digraphs; these functions are + deprecated in favour of: + + + + + and return + mutable &GAP; objects representing graphviz objects, which provide a + more flexible means of tailoring pictures of graphs and digraphs to your + needs. The function DotDigraph is synonymous with + AsString(GraphvizDigraph(D)). It is also possible to use + directly on the graphviz objects + returned by the function , i.e. + Splash(GraphvizDigraph(D)) does precisely the same thing as + Splash(DotDigraph(D)). + + +<#/GAPDoc> -<#GAPDoc Label="Splash"> +<#GAPDoc Label="GraphvizDigraph"> - - Nothing. + + + A &graphviz; object. - This function attempts to convert the string str into a pdf - document and open this document, i.e. to splash it all over your monitor.

+ and return + mutable &GAP; objects representing graphviz objects, which provide a + flexible means of tailoring pictures of graphs and digraphs to your + needs. +

+ + GraphvizDigraph and GraphvizGraph produce &graphviz; + objects representing the digraph D. Vertices are displayed as + circles, numbered consistently with D. For GraphvizDigraph, + edges are displayed as arrowed lines between vertices, with the arrowhead + of each line pointing towards the range of the edge. For + GraphvizGraph, edges are displayed without an arrowhead. +

+ + See the &graphviz; package documentation for more details. +

+ + See also + + D := CompleteDigraph(IsMutable, 4); + +gap> gv := GraphvizGraph(D); + +gap> AsString(gv); +"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t2 -\ +- 1\n\t3 -- 1\n\t3 -- 2\n\t4 -- 1\n\t4 -- 2\n\t4 -- 3\n}\n" +gap> DigraphRemoveEdge(D, 1, 3); + +gap> gv := GraphvizDigraph(D); + +gap> AsString(gv); +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1\ + -> 2\n\t1 -> 4\n\t2 -> 1\n\t2 -> 3\n\t2 -> 4\n\t3 -> 1\n\t3 -> 2\n\t3\ + -> 4\n\t4 -> 1\n\t4 -> 2\n\t4 -> 3\n}\n" +]]> + + +<#/GAPDoc> - The string str must correspond to a valid dot or - LaTeX text file and you must have have GraphViz and - pdflatex installed on your computer. For details about these file - formats, see https://www.latex-project.org and - https://www.graphviz.org.

+<#GAPDoc Label="DotVertexLabelledDigraph"> + + + A string. + + WARNING! As of v2.0.0 of &Digraphs; this function is + deprecated in favour of: + + + + + +<#/GAPDoc> - This function is provided to allow convenient, immediate viewing of the - pictures produced by the function .

+<#GAPDoc Label="GraphvizVertexLabelledDigraph"> + + + + A &graphviz; object. + + GraphvizVertexLabelledDigraph and + GraphvizVertexLabelledGraph differ from and only in that + the values in are used to label the + vertices in the produced picture rather than the numbers 1 to + the number of vertices of the digraph.

- The optional second argument opts should be a record with - components corresponding to various options, given below. + See the &graphviz; package documentation for more details. +

- - path - - this should be a string representing the path to the directory where - you want Splash to do its work. The default value of this - option is "~/". - - - directory - - this should be a string representing the name of the directory in - path where you want Splash to do its work. This function - will create this directory if does not already exist.

- - The default value of this option is "tmp.viz" if the option - path is present, and the result of - is used otherwise. - - - filename - - this should be a string representing the name of the file where - str will be written. The default value of this option is - "vizpicture". - - - viewer - - this should be a string representing the name of the program which - should open the files produced by GraphViz or pdflatex. - - - type - - this option can be used to specify that the string str contains - a &LaTeX; or dot document. You can specify this option in - str directly by making the first line "%latex" or - "//dot". There is no default value for this option, this - option must be specified in str or in opt.type. - - - engine - - this option can be used to specify the GraphViz engine to use - to render a dot document. The valid choices are "dot", - "neato", "circo", "twopi", "fdp", - "sfdp", and "patchwork". Please refer to the - GraphViz documentation for details on these engines. - The default value for this option is "dot", and it - must be specified in opt.engine. - - - filetype - - this should be a string representing the type of file which - Splash should produce. For &LaTeX; files, this option is - ignored and the default value "pdf" is used. - - + See also - This function was written by Attila Egri-Nagy and Manuel Delgado with some - minor changes by J. D. Mitchell.

- Splash(DotDigraph(RandomDigraph(4))); -]]> - - + + + <#/GAPDoc> -<#GAPDoc Label="DotDigraph"> +<#GAPDoc Label="DotColoredDigraph"> - - - - - + + + + + + A string. - DotDigraph produces a graphical representation of the digraph - digraph. Vertices are displayed as circles, numbered consistently - with digraph. Edges are displayed as arrowed lines between - vertices, with the arrowhead of each line pointing towards the range - of the edge.

- - DotColoredDigraph differs from DotDigraph only in - that the values in given in the two lists are used to color the vertices and - edges of the graph when displayed. The list for vertex colours should be - a list of length equal to the number of vertices, containing strings that - are accepted by the graphviz software, which is the one used for graph - representation. The list for edge colours should be a list of lists - with the same shape of the outneighbours of the digraph that contains strings - that correspond to colours accepted by the graphviz software. If the lists - are not the appropriate size, or have holes then the function will return - an error.

- - DotVertexColoredDigraph differs from DotDigraph only in - that the values in given in the list are used to color the vertices - of the graph when displayed. The list for vertex colours should be - a list of length equal to the number of vertices, containing strings that - are accepted by the graphviz software, which is the one used for graph - representation. If the list is not the appropriate size, or has holes - then the function will return an error.

- - DotEdgeColoredDigraph differs from DotDigraph only in - that the values in given in the list are used to color the vertices and - edges of the graph when displayed. The list for edge colours should be a list - of lists with the same shape of the outneighbours of the digraph that contains - strings that correspond to colours accepted by the graphviz software. If the - list is not the appropriate size, or has holes then the function will return - an error.

- - DotVertexLabelledDigraph differs from DotDigraph only in - that the values in are used to label - the vertices in the produced picture rather than the numbers 1 to - the number of vertices of the digraph.

- - The output is in dot format (also known as GraphViz) - format. For details about this file format, and information about how to - display or edit this format see https://www.graphviz.org.

- - The string returned by DotDigraph or - DotVertexLabelledDigraph can be written to a file using - the command .

- adj := List([1 .. 4], x -> [1, 1, 1, 1]); -[ [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ] ] -gap> adj[1][3] := 0; -0 -gap> gr := DigraphByAdjacencyMatrix(adj); - -gap> D := CompleteDigraph(4); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; -gap> edgecolors[1][2] := "lightblue";; -gap> edgecolors[1][3] := "pink";; -gap> edgecolors[1][4] := "purple";; -gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][3] := "pink";; -gap> edgecolors[2][4] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; -gap> edgecolors[3][4] := "purple";; -gap> edgecolors[4][1] := "lightblue";; -gap> edgecolors[4][2] := "pink";; -gap> edgecolors[4][3] := "purple";; -gap> Print(DotColoredDigraph(D, vertcolors, edgecolors)); -//dot -digraph hgn{ -node [shape=circle] -1[color=blue, style=filled] -2[color=red, style=filled] -3[color=green, style=filled] -4[color=yellow, style=filled] -1 -> 2[color=lightblue] -1 -> 3[color=pink] -1 -> 4[color=purple] -2 -> 1[color=lightblue] -2 -> 3[color=pink] -2 -> 4[color=purple] -3 -> 1[color=lightblue] -3 -> 2[color=pink] -3 -> 4[color=purple] -4 -> 1[color=lightblue] -4 -> 2[color=pink] -4 -> 3[color=purple] -} -gap> D := EmptyDigraph(3); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; -gap> Print(DotColoredDigraph(D, vertcolors, edgecolors)); -//dot -digraph hgn{ -node [shape=circle] -1[color=blue, style=filled] -2[color=red, style=filled] -3[color=green, style=filled] -} -gap> D := Digraph([[2], [1, 3], [2]]); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; -gap> vertcolors[2] := "pink";; -gap> vertcolors[3] := "purple";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; -gap> edgecolors[1][2] := "green";; edgecolors[2][1] := "green";; -gap> edgecolors[2][3] := "red";; edgecolors[3][2] := "red";; -gap> Print(DotSymmetricColoredDigraph(D, vertcolors, edgecolors)); -//dot -graph hgn{ -node [shape=circle] - -1[color=blue, style=filled] -2[color=pink, style=filled] -3[color=purple, style=filled] -1 -- 2[color=green] -2 -- 3[color=red] -} -gap> D := Digraph([[2, 3], [1, 3], [1]]); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; -gap> edgecolors[1][2] := "orange";; edgecolors[1][3] := "yellow";; -gap> edgecolors[2][1] := "orange";; edgecolors[2][3] := "pink";; -gap> edgecolors[3][1] := "yellow";; -gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));; -//dot -digraph hgn{ -node [shape=circle] -1[color=blue, style=filled] -2[color=red, style=filled] -3[color=green, style=filled] -1 -> 2[color=orange] -1 -> 3[color=yellow] -2 -> 1[color=orange] -2 -> 3[color=pink] -3 -> 1[color=yellow] -} -gap> D := Digraph(IsMutableDigraph, [[2, 3], [1, 3], [1]]); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; -gap> edgecolors[1][2] := "orange";; edgecolors[1][3] := "yellow";; -gap> edgecolors[2][1] := "orange";; edgecolors[2][3] := "pink";; -gap> edgecolors[3][1] := "yellow";; -gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));; -//dot -digraph hgn{ -node [shape=circle] -1[color=blue, style=filled] -2[color=red, style=filled] -3[color=green, style=filled] -1 -> 2[color=orange] -1 -> 3[color=yellow] -2 -> 1[color=orange] -2 -> 3[color=pink] -3 -> 1[color=yellow] -} -gap> D; - -gap> DotSymmetricDigraph(gr2){[12 .. 70]}; -" hgn{\nnode [shape=circle]\n\n1\n2\n3\n4\n1 -- 2\n2 -- 3\n3 -- 3\n3 -" -gap> DotSymmetricDigraph(gr1); -Error, the argument must be a symmetric digraph, -gap> D := CompleteDigraph(4); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; -gap> Print(DotVertexColoredDigraph(D, vertcolors)); -//dot -digraph hgn{ -node [shape=circle] -1[color=blue, style=filled] -2[color=red, style=filled] -3[color=green, style=filled] -4[color=yellow, style=filled] -1 -> 2 -1 -> 3 -1 -> 4 -2 -> 1 -2 -> 3 -2 -> 4 -3 -> 1 -3 -> 2 -3 -> 4 -4 -> 1 -4 -> 2 -4 -> 3 -} -gap> D := CompleteDigraph(4); - -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; -gap> edgecolors[1][2] := "lightblue";; -gap> edgecolors[1][3] := "pink";; -gap> edgecolors[1][4] := "purple";; -gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][3] := "pink";; -gap> edgecolors[2][4] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; -gap> edgecolors[3][4] := "purple";; -gap> edgecolors[4][1] := "lightblue";; -gap> edgecolors[4][2] := "pink";; -gap> edgecolors[4][3] := "purple";; -gap> Print(DotEdgeColoredDigraph(D, edgecolors)); -//dot -digraph hgn{ -node [shape=circle] -1 -2 -3 -4 -1 -> 2[color=lightblue] -1 -> 3[color=pink] -1 -> 4[color=purple] -2 -> 1[color=lightblue] -2 -> 3[color=pink] -2 -> 4[color=purple] -3 -> 1[color=lightblue] -3 -> 2[color=pink] -3 -> 4[color=purple] -4 -> 1[color=lightblue] -4 -> 2[color=pink] -4 -> 3[color=purple] -} -gap> FileString("dot/k4.dot", DotDigraph(gr)); -154]]> + WARNING! As of v2.0.0 of &Digraphs; these functions are + deprecated in favour of: + + + + + + + + + These functions return mutable &GAP; objects representing graphviz + objects, which provide a more flexible means of tailoring pictures of + graphs and digraphs to your needs. The Dot variants of these + functions are synonymous with, for example, + AsString(GraphvizDigraph(D)). It is also possible to use + directly on the graphviz objects + returned by the Graphviz variants of these functions, i.e. + Splash(GraphvizDigraph(D)) does precisely the same thing as + Splash(DotDigraph(D)). <#/GAPDoc> -<#GAPDoc Label="DotSymmetricDigraph"> +<#GAPDoc Label="GraphvizColoredDigraph"> - - - - - A string. + + + + + + + A &graphviz; object. - This function produces a graphical representation of the symmetric - digraph digraph. DotSymmetricDigraph will return an - error if digraph is not a symmetric digraph. See - .

- - The function DotSymmetricColoredDigraph differs from DotDigraph - only in that the values given in the two lists are used to color the vertices - and edges of the graph when displayed. The list for vertex colours should be - a list of length equal to the number of vertices, containing strings that - are accepted by the graphviz software, which is the one used for graph - representation. The list for edge colours should be a list of lists - with the same shape of the outneighbours of the digraph that contains strings - that correspond to colours accepted by the graphviz software. - If the list is not the appropriate size, or has holes then the function - will return an error.

- - The function DotSymmetricVertexColoredDigraph differs from DotDigraph - only in that the values in given in the list is used to color the vertices - of the graph when displayed. The list for vertex colours should be - a list of length equal to the number of vertices, containing strings that - are accepted by the graphviz software, which is the one used for graph - representation. If the list is not the appropriate size, or has holes - then the function will return an error.

- - The function DotSymmetricEdgeColoredDigraph differs from DotDigraph - only in that the values given in the list are used to color the edges - of the graph when displayed. The list for edge colours should be - a list of lists with the same shape of the outneighbours, containing strings that - are accepted by the graphviz software, which is the one used for graph - representation. If the list is not the appropriate size, or has holes - then the function will return an error.

- - Vertices are displayed as circles, numbered consistently with - digraph. Since digraph is symmetric, for every non-loop - edge there is a complementary edge with opposite source and range. - DotSymmetricDigraph displays each pair of complementary edges - as a single line between the relevant vertices, with no arrowhead.

- - The output is in dot format (also known as GraphViz) - format. For details about this file format, and information about how - to display or edit this format see - https://www.graphviz.org.

- - The string returned by DotSymmetricDigraph can be written to a - file using the command .

- - star := Digraph([[2, 2, 3, 4], [1, 1], [1], [1, 4]]); - -gap> IsSymmetricDigraph(star); -true -gap> FileString("dot/star.dot", DotSymmetricDigraph(gr)); -gap> D := Digraph([[2], [1, 3], [2]]); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; -gap> vertcolors[2] := "pink";; -gap> vertcolors[3] := "purple";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; -gap> edgecolors[1][2] := "green";; edgecolors[2][1] := "green";; -gap> edgecolors[2][3] := "red";; edgecolors[3][2] := "red";; -gap> Print(DotSymmetricColoredDigraph(D, vertcolors, edgecolors)); -//dot -graph hgn{ -node [shape=circle] - -1[color=blue, style=filled] -2[color=pink, style=filled] -3[color=purple, style=filled] -1 -- 2[color=green] -2 -- 3[color=red] -} -gap> D := Digraph([[2], [1, 3], [2]]); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; -gap> vertcolors[2] := "pink";; -gap> vertcolors[3] := "purple";; -gap> Print(DotSymmetricVertexColoredDigraph(D, vertcolors)); -//dot -graph hgn{ -node [shape=circle] - -1[color=blue, style=filled] -2[color=pink, style=filled] -3[color=purple, style=filled] -1 -- 2 -2 -- 3 -} + These operations produce colored &graphviz; objects representing the + digraph D according to the specified colors. For all of these + functions valid colors are strings containing: + + RGB + + An RGB color code consisting of 6 hexadecimal digits preceded by + a #. For example, #ff00ff. + + GraphViz 2.4.11 X11 Color Scheme + + One of the color strings specified at: + http://graphviz.org/doc/info/colors.html + + + + GraphvizVertexColoredDigraph and GraphvizVertexColoredGraph + requires its argument colors to be a list of length equal to the + number of vertices of D consisting of strings representing colors + as described above. +

+ + GraphvizEdgeColoredDigraph and GraphvizEdgeColoredGraph + requires its argument colors to be a list of lists with the same + shape of the out-neighbours of the digraph D consisting of strings + representing colors as described above. +

+ + GraphvizColoredDigraph and GraphvizColoredGraph requires + its arguments: + + vert_colors + + to represent vertex colors as described for + GraphvizVertexColoredDigraph; + + edge_colors + + to represent edge colors as described for + GraphvizEdgeColoredDigraph; + + + + See the &graphviz; package documentation for more details. +

+ + See also + D := Digraph([[2], [1, 3], [2]]); -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; -gap> edgecolors[1][2] := "green";; edgecolors[2][1] := "green";; -gap> edgecolors[2][3] := "red";; edgecolors[3][2] := "red";; -gap> Print(DotSymmetricEdgeColoredDigraph(D, edgecolors)); -//dot -graph hgn{ -node [shape=circle] - -1 -2 -3 -1 -- 2[color=green] -2 -- 3[color=red] -} -83]]> +gap> vert_colors := ["blue", "pink", "purple"];; +gap> edge_colors := [["green"], ["green", "red"], ["red"]];; +gap> GraphvizVertexColoredDigraph(D, vert_colors); + +gap> GraphvizVertexColoredGraph(D, vert_colors); + +gap> GraphvizEdgeColoredDigraph(D, edge_colors); + +gap> GraphvizEdgeColoredGraph(D, edge_colors); + +gap> GraphvizColoredDigraph(D, vert_colors, edge_colors); + +gap> GraphvizColoredGraph(D, vert_colors, edge_colors); + +]]> -<#/GAPDoc> + <#/GAPDoc> <#GAPDoc Label="DotPartialOrderDigraph"> A string. - This function produces a graphical representation of a partial order - digraph digraph. DotPartialOrderDigraph will return an error - if digraph is not a partial order digraph. See .

- - Since digraph is a partial order, it is both reflexive and - transitive. The output of DotPartialOrderDigraph is the - of the - of digraph.

- - The output is in dot format (also known as GraphViz) - format. For details about this file format, and information about how - to display or edit this format see - https://www.graphviz.org.

- - The string returned by DotPartialOrderDigraph can be written to a - file using the command .

- - poset := Digraph([[1, 4], [2], [2, 3, 4], [4]); -gap> IsPartialOrderDigraph(gr); + WARNING! As of v2.0.0 of &Digraphs; these functions are + deprecated in favour of: + + + + This function return a mutable &GAP; object representing a graphviz + object, which provides a more flexible means of tailoring pictures of + graphs and digraphs to your needs. The Dot variants of these + functions are synonymous with, for example, + AsString(GraphvizDigraph(D)). It is also possible to use + directly on the graphviz objects + returned by the Graphviz variants of these functions, i.e. + Splash(GraphvizDigraph(D)) does precisely the same thing as + Splash(DotDigraph(D)). + + +<#/GAPDoc> + +<#GAPDoc Label="GraphvizPartialOrderDigraph"> + + + A &graphviz; object. + + This function produces a &graphviz; object representing a partial order + digraph D. GraphvizPartialOrderDigraph will return an + error if D is not a partial order digraph. See .

+ + Since D is a partial order, it is both reflexive and + transitive. The output of GraphvizPartialOrderDigraph is the + of the + of D.

+ + See the &graphviz; package documentation for more details. +

+ + See also + D := Digraph([[1, 4], [2], [2, 3, 4], [4]]); + +gap> IsPartialOrderDigraph(D); true -gap> FileString("dot/poset.dot", DotPartialOrderDigraph(gr)); -83]]> +gap> GraphvizPartialOrderDigraph(D); +]]> <#/GAPDoc> @@ -523,65 +287,119 @@ gap> FileString("dot/poset.dot", DotPartialOrderDigraph(gr)); A string. - This function produces a graphical representation of a preorder - digraph digraph. DotPreorderDigraph will return an error - if digraph is not a preorder digraph. See WARNING! As of v2.0.0 of &Digraphs; these functions are + deprecated in favour of: + + + + + These functions return mutable &GAP; objects representing graphviz + objects, which provide a more flexible means of tailoring pictures of + graphs and digraphs to your needs. The Dot variants of these + functions are synonymous with, for example, + AsString(GraphvizDigraph(D)). It is also possible to use + directly on the graphviz objects + returned by the Graphviz variants of these functions, i.e. + Splash(GraphvizDigraph(D)) does precisely the same thing as + Splash(DotDigraph(D)). + + +<#/GAPDoc> + +<#GAPDoc Label="GraphvizPreorderDigraph"> + + + + A &graphviz; object. + + These functions produce &graphviz; objects representing a preorder + digraph D. These function will give an error + if D is not a preorder digraph. See .

A preorder digraph is reflexive and transitive but in general it is not anti-symmetric and may have strongly connected components containing more than one vertex. The - Q obtained by forming the quotient of digraph by the + Q obtained by forming the quotient of D by the partition of its vertices into the strongly connected components satisfies . Thus every vertex of - Q corresponds to a strongly connected component of digraph. - The output of DotPreorderDigraph displays the + Q corresponds to a strongly connected component of D. + The output of GraphvizPreorderDigraph displays the of Q with vertices displayed as rounded rectangles labelled by all of the vertices - of digraph in the corresponding strongly connected component.

+ of D in the corresponding strongly connected component. +

- The output is in dot format (also known as GraphViz) - format. For details about this file format, and information about how - to display or edit this format see - https://www.graphviz.org.

+ See the &graphviz; package documentation for more details. +

- The string returned by DotPreorderDigraph can be written to a - file using the command .

+ See also - preset := Digraph([[1, 2, 4, 5], [1, 2, 4, 5], [3, 4], [4], [1, 2, 4, 5]); -gap> IsPreorderDigraph(gr); + D := Digraph([[1, 2, 4, 5], [1, 2, 4, 5], [3, 4], [4], +> [1, 2, 4, 5]]); + +gap> IsPreorderDigraph(D); true -gap> FileString("dot/preset.dot", DotProrderDigraph(gr)); -83]]> +gap> GraphvizPreorderDigraph(D); +]]> <#/GAPDoc> <#GAPDoc Label="DotHighlightedDigraph"> - + A string. - DotHighlightedDigraph produces a graphical representation of the - digraph digraph, where the vertices in the list verts, and - edges between them, are drawn with colour colour1 and all other - vertices and edges in digraph are drawn with colour colour2. - If colour1 and colour2 are not given then - DotHighlightedDigraph uses black and grey respectively.

- - Note that DotHighlightedDigraph does not validate the colours - colour1 and colour2 - consult the GraphViz documentation to - see what is available. - - See for more details on the output.

- - digraph := Digraph([[2, 3], [2], [1, 3]]); - -gap> FileString("dot/my_digraph.dot", -> DotHighlightedDigraph(digraph, [1, 2], "red", "black")); -264]]> + WARNING! As of v2.0.0 of &Digraphs; these functions are + deprecated in favour of: + + + + + These functions return mutable &GAP; objects representing graphviz + objects, which provide a more flexible means of tailoring pictures of + graphs and digraphs to your needs. The Dot variants of these + functions are synonymous with, for example, + AsString(GraphvizDigraph(D)). It is also possible to use + directly on the graphviz objects + returned by the Graphviz variants of these functions, i.e. + Splash(GraphvizDigraph(D)) does precisely the same thing as + Splash(DotDigraph(D)). + + +<#/GAPDoc> + +<#GAPDoc Label="GraphvizHighlightedDigraph"> + + + + A &graphviz; object. + + These functions produce &graphviz; objects representing the digraph + D, where the vertices in the list verts, and edges + between them, are drawn with color color1 and all other vertices + and edges in D are drawn with color color2. If + color1 and color2 are not given, then these functions + use \"black\" and \"grey\" respectively. +

+ + See and + for more details on the output. + + D := Digraph([[2, 3], [2], [1, 3]]); + +gap> GraphvizHighlightedDigraph(D, [1, 2], "red", "black"); + +gap> D := DigraphSymmetricClosure(D); + +gap> GraphvizHighlightedGraph(D, [1, 2], "red", "black"); +]]> <#/GAPDoc> diff --git a/doc/main.xml b/doc/main.xml new file mode 100644 index 000000000..e5c287f5a --- /dev/null +++ b/doc/main.xml @@ -0,0 +1,60 @@ +Digraphs"> + https://gap-packages.github.io/grapeGrape"> + https://digraphs.github.io/graphvizGraphviz"> + http://www.tcs.tkk.fi/Software/bliss/bliss"> + https://github.com/graph-algorithms/edge-addition-planarity-suiteedge-addition-planarity-suite"> + https://pallini.di.uniroma1.it/nauty"> + https://github.com/gap-packages/NautyTracesInterfaceNautyTracesInterface"> + + https://gap-packages.github.io/io/ +IO"> + + https://gap-packages.github.io/orb/ + Orb"> + https://github.com/gap-packages/datastructuresdatastructures"> + filt is present, then this should specify the category or representation the digraph being created will belong to. For example, if filt is , then the digraph being created will be mutable, if filt is , then the digraph will be immutable. If the optional first argument filt is not present, then is used by default.

"> + digraph is mutable, then the return value of this property is recomputed every time it is called.

"> + digraph is mutable, then the return value of this attribute is recomputed every time it is called.

"> + . In more detail, the vertices of the digraph are labelled by elements of the Cartesian product [1..m] x [1..n], where the first entry indexes the column (file) of the square in the chessboard, and the second entry indexes the row (rank) of the square. (Note that the files are traditionally indexed by the lowercase letters of the alphabet). The vertices are sorted in ascending order, first by row (second component) and then column (first component).

"> + m by n chessboard is a grid of m columns (‘files’) and n rows (‘ranks’) that intersect in squares. Orthogonally adjacent squares are alternately colored light and dark, with the square in the first rank and file being dark.

"> + <#Include Label="PKGVERSIONDATA"> + ]> + + +<#Include SYSTEM="z-title.xml"> + + + + + <#Include SYSTEM="z-chap0.xml"> + <#Include SYSTEM="z-chap1.xml"> + <#Include SYSTEM="z-chap2.xml"> + <#Include SYSTEM="z-chap3.xml"> + <#Include SYSTEM="z-chap4.xml"> + <#Include SYSTEM="z-chap5.xml"> + <#Include SYSTEM="z-chap6.xml"> + <#Include SYSTEM="z-chap8.xml"> + <#Include SYSTEM="z-chap9.xml"> + + +<#Include SYSTEM="z-appA.xml"> + + + + + diff --git a/doc/z-chap9.xml b/doc/z-chap9.xml index 42adee63f..37891bec0 100644 --- a/doc/z-chap9.xml +++ b/doc/z-chap9.xml @@ -1,11 +1,22 @@ Visualising and IO

Visualising a digraph - <#Include Label="Splash"> + <#Include Label="GraphvizDigraph"> <#Include Label="DotDigraph"> - <#Include Label="DotSymmetricDigraph"> + + <#Include Label="GraphvizColoredDigraph"> + <#Include Label="DotColoredDigraph"> + + <#Include Label="GraphvizVertexLabelledDigraph"> + <#Include Label="DotVertexLabelledDigraph"> + + <#Include Label="GraphvizPartialOrderDigraph"> <#Include Label="DotPartialOrderDigraph"> + + <#Include Label="GraphvizPreorderDigraph"> <#Include Label="DotPreorderDigraph"> + + <#Include Label="GraphvizHighlightedDigraph"> <#Include Label="DotHighlightedDigraph">
diff --git a/etc/code-coverage-test-c.py b/etc/code-coverage-test-c.py new file mode 100755 index 000000000..62cd03294 --- /dev/null +++ b/etc/code-coverage-test-c.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +""" +""" + +# pylint: disable=invalid-name, broad-except + +import argparse +import tempfile +import subprocess +import sys +import os +import webbrowser + +from os.path import exists, isfile + +_ERR_PREFIX = '\033[31merror: ' + +def exec_string(string): + 'execute the string in a subprocess.' + try: + subprocess.check_call(string, shell=True) + except KeyboardInterrupt: + sys.exit('\033[31m\nKilled!\033[0m') + except (subprocess.CalledProcessError, OSError): + sys.exit(_ERR_PREFIX + 'executing:\n' + string + '\n failed!\033[0m') + +_PARSER = argparse.ArgumentParser(prog='code-coverage-test-c.py', + usage='%(prog)s [options]') +_PARSER.add_argument('files', nargs='+', type=str, + help='the test files you want to check code coverage for' + + '(must be at least one)') +_PARSER.add_argument('--gap-root', nargs='?', type=str, + help='the gap root directory (default: ~/gap)', + default='~/gap/') +_PARSER.add_argument('--pkg', nargs='?', type=str, + help='the package to profile (default: None)', + default=None) +_PARSER.add_argument('--build', dest='build', action='store_true', + help='rebuild GAP (default: False)') +_PARSER.set_defaults(build=False) +_PARSER.add_argument('--open', nargs='?', type=str, + help=('open the lcov html page for this file ' + + '(default: None)'), + default=None) +_PARSER.add_argument('--line', nargs='?', type=str, + help=('open the html page for the file specified by --open' + + ' at this line (default: None)'), + default=None) +_ARGS = _PARSER.parse_args() + +if not _ARGS.gap_root[-1] == '/': + _ARGS.gap_root += '/' + +_ARGS.gap_root = os.path.expanduser(_ARGS.gap_root) +if _ARGS.pkg != None: + _ARGS.pkg = _ARGS.gap_root + '/pkg/' + _ARGS.pkg + +if not (os.path.exists(_ARGS.gap_root) and os.path.isdir(_ARGS.gap_root)): + sys.exit('\033[31mcode-coverage-test-c.py: error: can\'t find gap root' + + ' directory!\033[0m') +if (_ARGS.pkg != None and not (os.path.exists(_ARGS.pkg) and + os.path.isdir(_ARGS.pkg))): + sys.exit('\033[31mcode-coverage-test-c.py: error: can\'t find the pkg' + + ' directory %s\033[0m' % _ARGS.pkg) +for f in _ARGS.files: + if not (os.path.exists(f) and os.path.isfile(f)): + sys.exit('\033[31mcode-coverage-test-c.py: error: ' + f + + ' does not exist!\033[0m') + +_DIR = tempfile.mkdtemp() +print('\033[35musing temporary directory: ' + _DIR + '\033[0m') + +_COMMANDS = 'echo "' +for f in _ARGS.files: + _COMMANDS += 'Test(\\"' + f + '\\");;' +_COMMANDS += '"' + +# TODO build if files changed since last build or built with the wrong flags, +# by looking in config.log + +# for source in : +# if time.ctime(os.path.getmtime(file)) + +if _ARGS.build: + cwd = os.getcwd() + os.chdir(_ARGS.gap_root) + exec_string('''rm -rf bin/ && \ + make clean && \ + ./configure CFLAGS="-O0 -g --coverage" \ + CXXFLAGS="-O0 -g --coverage" \ + LDFLAGS="-O0 -g --coverage" && \ + make -j8''') + if _ARGS.pkg != None: + os.chdir(_ARGS.pkg) + exec_string('rm -rf bin/ && \ + make clean && \ + ./configure CFLAGS="-O0 -g --coverage" \ + CXXFLAGS="-O0 -g --coverage" \ + LDFLAGS="-O0 -g --coverage" && \ + make -j8''') + os.chdir(cwd) + +pro1 = subprocess.Popen(_COMMANDS, stdout=subprocess.PIPE, shell=True) +_RUN_GAP = _ARGS.gap_root + 'bin/gap.sh -A -m 1g -T' + +try: + pro2 = subprocess.Popen(_RUN_GAP, + stdin=pro1.stdout, + shell=True) + pro2.wait() + print('') +except KeyboardInterrupt: + pro1.terminate() + pro1.wait() + pro2.terminate() + pro2.wait() + print('\033[31mKilled!\033[0m') + sys.exit(1) +except Exception: + sys.exit('\033[31mcode-coverage-test-c.py: error: something went wrong ' + + 'calling GAP!\033[0m''') +if _ARGS.pkg != None: + exec_string('lcov --capture --directory ' + _ARGS.pkg + + '/src --output-file ' + _DIR + '/lcov.info') +else: + exec_string('lcov --capture --directory ' + _ARGS.gap_root + + '/src --output-file ' + _DIR + '/lcov.info') + +exec_string('genhtml ' + _DIR + '/lcov.info --output-directory ' + _DIR + + '/lcov-out') + +filename = _DIR + '/lcov-out/' +if _ARGS.open: + filename += _ARGS.open + '.gcov.html' +else: + filename += '/index.html' + +if exists(filename) and isfile(filename): + if _ARGS.open and _ARGS.line: + filename += '#' + _ARGS.line + print('file://' + filename) + try: + webbrowser.get('chrome').open('file://' + filename, new=2) + except Exception: + webbrowser.open('file://' + filename, new=2) +else: + sys.exit('\n' + _ERR_PREFIX + 'Failed to open file://' + filename + + '\033[0m') + +print('\n\033[32mSUCCESS!\033[0m') +sys.exit(0) diff --git a/etc/code-coverage-test-gap.py b/etc/code-coverage-test-gap.py index f52bbdf31..11c6e5666 100755 --- a/etc/code-coverage-test-gap.py +++ b/etc/code-coverage-test-gap.py @@ -71,7 +71,7 @@ _GAP_COMMANDS.extend( [ "UncoverageLineByLine();;", - rf"LoadPackage(\"profiling\", false);;", + r"LoadPackage(\"profiling\", false);;", rf"filesdir := \"{getcwd()}{_PROFILE_DIR}\";;", rf"outdir := \"{_DIR}\";;", rf"x := ReadLineByLineProfile(\"{_DIR}/profile.gz\");;", diff --git a/gap/.null-ls_141605_display.gi b/gap/.null-ls_141605_display.gi new file mode 100644 index 000000000..2e58c5084 --- /dev/null +++ b/gap/.null-ls_141605_display.gi @@ -0,0 +1,484 @@ +############################################################################# +## +## display.gi +## Copyright (C) 2014-24 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## + +# TODO: +# * add graph6 string or whatever as a comment at the start of the string +# * check JupyterInterface Splash function +# * for edge colored non-digraphs, should ensure that the edge colors are +# symmetric, i.e. the same colors for x -> y and y -> x + +<<<<<<< HEAD +BindGlobal("DIGRAPHS_ValidRGBValue", +function(str) + local l, chars, x, i; + l := Length(str); + x := 0; + chars := "0123456789ABCDEFabcdef"; + if l = 7 then + if str[1] = '#' then + for i in [2 .. l] do + if str[i] in chars then + x := x + 1; + fi; + od; + fi; + fi; + return x = (l - 1); +end); + +BindGlobal("DIGRAPHS_GraphvizColorsList", fail); + +BindGlobal("DIGRAPHS_GraphvizColors", +function() + local f; + if DIGRAPHS_GraphvizColorsList = fail then + f := IO_File(Concatenation(DIGRAPHS_Dir(), "/data/colors.p")); + MakeReadWriteGlobal("DIGRAPHS_GraphvizColorsList"); + DIGRAPHS_GraphvizColorsList := IO_Unpickle(f); + MakeReadOnlyGlobal("DIGRAPHS_GraphvizColorsList"); + IO_Close(f); + fi; + return DIGRAPHS_GraphvizColorsList; +end); + +BindGlobal("DIGRAPHS_ValidVertColors", +function(D, verts) + local v, sum, colors, col; + v := DigraphVertices(D); + sum := 0; + if Length(verts) <> Length(v) then + ErrorNoReturn("the number of vertex colors must be the same as the number", + " of vertices, expected ", Length(v), " but found ", Length(verts), ""); + fi; + colors := DIGRAPHS_GraphvizColors(); + if Length(verts) = Length(v) then + for col in verts do + if not IsString(col) then + ErrorNoReturn("expected a string"); + elif DIGRAPHS_ValidRGBValue(col) = false and + (col in colors) = false then + ErrorNoReturn("expected RGB Value or valid color name as defined", + " by GraphViz 2.44.1 X11 Color Scheme", + " http://graphviz.org/doc/info/colors.html"); + else + sum := sum + 1; + fi; + od; + if sum = Length(verts) then + return true; + fi; + fi; +end); + +BindGlobal("DIGRAPHS_ValidEdgeColors", +function(D, edge) + local out, l, counter, sum, colors, v, col; + out := OutNeighbours(D); + l := Length(edge); + counter := 0; + sum := 0; + colors := DIGRAPHS_GraphvizColors(); + if Length(edge) <> Length(out) then + ErrorNoReturn("the list of edge colors needs to have the", + " same shape as the out-neighbours of the digraph"); + else + for v in [1 .. l] do + sum := 0; + if Length(out[v]) <> Length(edge[v]) then + ErrorNoReturn("the list of edge colors needs to have the", + " same shape as the out-neighbours of the digraph"); + else + for col in edge[v] do + if not IsString(col) then + ErrorNoReturn("expected a string"); + elif DIGRAPHS_ValidRGBValue(col) = false and + (col in colors) = false then + ErrorNoReturn("expected RGB Value or valid color name as defined", + " by GraphViz 2.44.1 X11 Color Scheme", + " http://graphviz.org/doc/info/colors.html"); + else + sum := sum + 1; + fi; + od; + if sum = Length(edge[v]) then + counter := counter + 1; + fi; + fi; + od; + if counter = Length(edge) then + return true; + fi; + fi; +end); + +InstallMethod(DotDigraph, "for a digraph by out-neighbours", +[IsDigraphByOutNeighboursRep], +D -> DIGRAPHS_DotDigraph(D, [], [])); + +InstallMethod(DotColoredDigraph, +"for a digraph by out-neighbours and two lists", +[IsDigraphByOutNeighboursRep, IsList, IsList], +function(D, vert, edge) + local vert_func, edge_func; + if DIGRAPHS_ValidVertColors(D, vert) + and DIGRAPHS_ValidEdgeColors(D, edge) then + vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]); + edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); + return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]); + fi; +end); + +InstallMethod(DotVertexColoredDigraph, +"for a digraph by out-neighbours and a list", +[IsDigraphByOutNeighboursRep, IsList], +function(D, vert) + local func; + if DIGRAPHS_ValidVertColors(D, vert) then + func := i -> StringFormatted("[color={}, style=filled]", vert[i]); + return DIGRAPHS_DotDigraph(D, [func], []); + fi; +end); + +InstallMethod(DotEdgeColoredDigraph, +"for a digraph by out-neighbours and a list", +[IsDigraphByOutNeighboursRep, IsList], +function(D, edge) + local func; + if DIGRAPHS_ValidEdgeColors(D, edge) then + func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); + return DIGRAPHS_DotDigraph(D, [], [func]); + fi; +end); + +InstallMethod(DotVertexLabelledDigraph, "for a digraph by out-neighbours", +======= +############################################################################# +# Graphs and digraphs +############################################################################# + +InstallOtherMethod(GraphvizDigraph, "for a digraph by out-neighbours", +>>>>>>> 51b65dbf (Checkout files from mpan322/main) +[IsDigraphByOutNeighboursRep], +function(D) + local gv, x, y; + gv := GraphvizDigraph("hgn"); + GraphvizSetAttr(gv, "node [shape=circle]"); + for x in DigraphVertices(D) do + GraphvizAddNode(gv, x); + od; + for x in DigraphVertices(D) do + for y in OutNeighboursOfVertexNC(D, x) do + GraphvizAddEdge(gv, x, y); + od; + od; + return gv; +end); + +InstallOtherMethod(GraphvizGraph, "for a digraph by out-neighbours", +[IsDigraphByOutNeighboursRep], +<<<<<<< HEAD +D -> DIGRAPHS_DotSymmetricDigraph(D, [], [])); + +InstallMethod(DotSymmetricColoredDigraph, +"for a digraph by out-neighbours and two lists", +[IsDigraphByOutNeighboursRep, IsList, IsList], +function(D, vert, edge) + local vert_func, edge_func; + if DIGRAPHS_ValidVertColors(D, vert) + and DIGRAPHS_ValidEdgeColors(D, edge) then + vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]); + edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); + return DIGRAPHS_DotSymmetricDigraph(D, [vert_func], [edge_func]); +======= +function(D) + local gv, x, y; + if not IsSymmetricDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be symmetric"); +>>>>>>> 51b65dbf (Checkout files from mpan322/main) + fi; + gv := GraphvizGraph("hgn"); + GraphvizSetAttr(gv, "node [shape=circle]"); + for x in DigraphVertices(D) do + GraphvizAddNode(gv, x); + od; + for x in DigraphVertices(D) do + for y in OutNeighboursOfVertexNC(D, x) do + if x > y then + GraphvizAddEdge(gv, x, y); + fi; + od; + od; + return gv; +end); + +############################################################################# +# Vertex coloured graphs and digraphs +############################################################################# + +InstallMethod(GraphvizVertexColoredDigraph, "for a digraph and a list", +[IsDigraph, IsList], +{D, colors} -> GraphvizSetNodeColors(GraphvizDigraph(D), colors)); + +InstallMethod(GraphvizVertexColoredGraph, "for a digraph and a list", +[IsDigraph, IsList], +# IsSymmetricDigraph checked by GraphvizGraph +{D, colors} -> GraphvizSetNodeColors(GraphvizGraph(D), colors)); + +############################################################################# +# Edge coloured graphs and digraphs +############################################################################# + +# This function is here rather than graphviz b/c otherwise if D has multiple +# edges we can't reliably get the corresponding graphviz edge from the head and +# tail of the edge from gv. +BindGlobal("DIGRAPHS_ErrorIfNotEdgeColoring", +function(D, colors) + local out, i; + + out := OutNeighbours(D); + if Length(colors) <> Length(out) then + ErrorFormatted("the 2nd argument (edge colors) must have ", + "the same number of entries as the 1st argument ", + "(a digraph) has nodes, expected {} but found {}", + Length(out), + Length(colors)); + fi; + for i in [1 .. Length(colors)] do + if not IsList(colors[i]) then + ErrorFormatted("the 2nd argument (edge colors) must be ", + "a list of lists, found {} in position {}", + TNAM_OBJ(colors[i]), + i); + elif Length(out[i]) <> Length(colors[i]) then + ErrorFormatted("the 2nd argument (edge colors) must have ", + "the same shape as the out neighbours of the 1st ", + "argument (a digraph), in position {} expected ", + "a list of length {} but found list of length {}", + i, + Length(out[i]), + Length(colors[i])); + fi; + Perform(colors[i], ErrorIfNotValidColor); + od; +end); + +BindGlobal("DIGRAPHS_AddEdgesAndColorsNC", +function(D, gv, colors) + local out, e, n, i; + + # This duplicates code in the GraphvizDigraph function because otherwise if D + # has multiple edges we can't reliably get the corresponding graphviz edge + # from the head and tail of the edge from gv. + out := OutNeighbours(D); + for n in DigraphVertices(D) do + for i in [1 .. Length(out[n])] do + if IsGraphvizDigraph(gv) or n > out[n][i] then + e := GraphvizAddEdge(gv, n, out[n][i]); + GraphvizSetAttr(e, "color", colors[n][i]); + fi; + od; + od; + return gv; +end); + +InstallMethod(GraphvizEdgeColoredDigraph, +"for a digraph by out-neighbours and a list", +[IsDigraphByOutNeighboursRep, IsList], +function(D, colors) + local gv; + DIGRAPHS_ErrorIfNotEdgeColoring(D, colors); + gv := GraphvizDigraph(NullDigraph(DigraphNrVertices(D))); + return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors); +end); + +InstallMethod(GraphvizEdgeColoredGraph, +"for a digraph by out-neighbours and a list", +[IsDigraphByOutNeighboursRep, IsList], +function(D, colors) + local gv; + if not IsSymmetricDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be symmetric"); + fi; + DIGRAPHS_ErrorIfNotEdgeColoring(D, colors); + gv := GraphvizGraph(NullDigraph(DigraphNrVertices(D))); + return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors); +end); + +############################################################################# +# Vertex and edge coloured graphs and digraphs +############################################################################# + +InstallMethod(GraphvizColoredDigraph, +"for a digraph, list, and list", +[IsDigraph, IsList, IsList], +{D, n_colors, e_colors} -> GraphvizSetNodeColors( + GraphvizEdgeColoredDigraph(D, e_colors), + n_colors)); + +<<<<<<< HEAD + BindGlobal("Splash", + function(arg...) + local str, opt, path, dir, tdir, file, viewer, type, inn, filetype, out, + engine; +======= +InstallMethod(GraphvizColoredGraph, +"for a digraph, list, and list", +[IsDigraph, IsList, IsList], +# IsSymmetricDigraph checked by GraphvizEdgeColoredGraph +{D, n_colors, e_colors} -> GraphvizSetNodeColors( + GraphvizEdgeColoredGraph(D, e_colors), + n_colors)); +>>>>>>> 51b65dbf (Checkout files from mpan322/main) + +############################################################################# +# Vertex labelled graphs and digraphs +############################################################################# + +InstallMethod(GraphvizVertexLabelledDigraph, "for a digraph", +[IsDigraph], +D -> GraphvizSetNodeLabels(GraphvizDigraph(D), DigraphVertexLabels(D))); + +InstallMethod(GraphvizVertexLabelledGraph, "for a digraph", +[IsDigraph], +# symmetry checked in GraphvizGraph +D -> GraphvizSetNodeLabels(GraphvizGraph(D), DigraphVertexLabels(D))); + +############################################################################# +# Partial and preorder digraphs +############################################################################# + +InstallMethod(GraphvizPartialOrderDigraph, "for a partial order digraph", +[IsDigraph], +function(D) + if not IsPartialOrderDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be a partial order"); + fi; + D := DigraphMutableCopyIfMutable(D); + return GraphvizDigraph(DigraphReflexiveTransitiveReduction(D)); +end); + +InstallMethod(GraphvizPreorderDigraph, "for a preorder digraph", +[IsDigraph], +function(D) + local comps, gv, label, node, nodes, c, x, e; + + if not IsPreorderDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be a preorder"); + fi; + + # Quotient by the strongly connected components to get a partial order + # D and draw this without loops or edges implied by transitivity. + comps := DigraphStronglyConnectedComponents(D).comps; + D := DigraphMutableCopy(D); + DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps)); + DigraphReflexiveTransitiveReduction(D); + + gv := GraphvizDigraph("graphname"); + GraphvizSetAttr(gv, "node [shape=\"Mrecord\"]"); + GraphvizSetAttr(gv, "height=\"0.5\""); + GraphvizSetAttr(gv, "fixedsize=\"true\""); + GraphvizSetAttr(gv, "ranksep=\"1\""); + + for c in [1 .. Length(comps)] do + + label := "\""; + Append(label, String(comps[c][1])); + for x in comps[c]{[2 .. Length(comps[c])]} do + Append(label, "|"); + Append(label, String(x)); + od; + Append(label, "\""); + + node := GraphvizAddNode(gv, c); + GraphvizSetAttr(node, "label", label); + GraphvizSetAttr(node, "width", Float(Length(comps[c]) / 2)); + od; + + nodes := GraphvizNodes(gv); + for e in DigraphEdges(D) do + GraphvizAddEdge(gv, nodes[e[1]], nodes[e[2]]); + od; + + return gv; +end); + +############################################################################# +# Highlighted subdigraphs +############################################################################# + +BindGlobal("DIGRAPHS_GraphvizHighlight", +function(D, gv, hi_verts, hi, lo) + local node, color, out, nodes, edge, v, i, j; + + if IsMultiDigraph(D) then + ErrorNoReturn("the 1st argument (a digraph) must not have multiple edges"); + elif not IsSubset(DigraphVertices(D), hi_verts) then + ErrorNoReturn("the 2nd argument (list) must consist of vertices ", + "of the 1st argument (a digraph)"); + fi; + ErrorIfNotValidColor(hi); + ErrorIfNotValidColor(lo); + + GraphvizSetAttr(gv, "shape", "circle"); + + for v in DigraphVertices(D) do + node := GraphvizAddNode(gv, v); + if v in hi_verts then + color := hi; + else + color := lo; + fi; + GraphvizSetAttr(node, "color", color); + od; + + out := OutNeighbours(D); + nodes := GraphvizNodes(gv); + + for i in DigraphVertices(D) do + for j in out[i] do + if IsGraphvizDigraph(gv) or i > j then + edge := GraphvizAddEdge(gv, nodes[i], nodes[j]); + if i in hi_verts and j in hi_verts then + color := hi; + else + color := lo; + fi; + GraphvizSetAttr(edge, "color", color); + fi; + od; + od; + + return gv; +end); + +InstallMethod(GraphvizHighlightedDigraph, +"for a digraph by out-neighbours, list, and two strings", +[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], +{D, hi_verts, hi, lo} -> +DIGRAPHS_GraphvizHighlight(D, GraphvizDigraph(), hi_verts, hi, lo)); + +InstallMethod(GraphvizHighlightedDigraph, "for a digraph and list", +[IsDigraph, IsList], +{D, list} -> GraphvizHighlightedDigraph(D, list, "black", "grey")); + +InstallMethod(GraphvizHighlightedGraph, +"for a digraph by out-neighbours, list, and two strings", +[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], +function(D, hi_verts, hi, lo) + if not IsSymmetricDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be symmetric"); + fi; + return DIGRAPHS_GraphvizHighlight(D, GraphvizGraph(), hi_verts, hi, lo); +end); + +InstallMethod(GraphvizHighlightedGraph, "for a digraph and list", +[IsDigraph, IsList], +# IsSymmetricDigraph checked in GraphvizHighlightedGraph +{D, list} -> GraphvizHighlightedGraph(D, list, "black", "grey")); diff --git a/gap/deprecated.gd b/gap/deprecated.gd new file mode 100644 index 000000000..d5b6c60c0 --- /dev/null +++ b/gap/deprecated.gd @@ -0,0 +1,35 @@ +############################################################################# +## +## deprecated.gd +## Copyright (C) 2024 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## + +DeclareAttribute("DotDigraph", IsDigraph); +DeclareAttribute("DotSymmetricDigraph", IsDigraph); + +DeclareOperation("DotSymmetricVertexColoredDigraph", [IsDigraph, IsList]); +DeclareOperation("DotVertexColoredDigraph", [IsDigraph, IsList]); + +DeclareOperation("DotEdgeColoredDigraph", [IsDigraph, IsList]); +DeclareOperation("DotSymmetricEdgeColoredDigraph", [IsDigraph, IsList]); + +DeclareOperation("DotColoredDigraph", [IsDigraph, IsList, IsList]); +DeclareOperation("DotSymmetricColoredDigraph", [IsDigraph, IsList, IsList]); + +DeclareOperation("DotVertexLabelledDigraph", [IsDigraph]); + +DeclareAttribute("DotPartialOrderDigraph", IsDigraph); +DeclareAttribute("DotPreorderDigraph", IsDigraph); + +DeclareSynonym("DotQuasiorderDigraph", DotPreorderDigraph); + +DeclareOperation("DotHighlightedDigraph", [IsDigraph, IsList]); +DeclareOperation("DotHighlightedDigraph", + [IsDigraph, IsList, IsString, IsString]); +DeclareOperation("DotHighlightedGraph", [IsDigraph, IsList]); +DeclareOperation("DotHighlightedGraph", + [IsDigraph, IsList, IsString, IsString]); diff --git a/gap/deprecated.gi b/gap/deprecated.gi new file mode 100644 index 000000000..f2c800087 --- /dev/null +++ b/gap/deprecated.gi @@ -0,0 +1,116 @@ +############################################################################# +## +## deprecated.gi +## Copyright (C) 2024 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## + +BindGlobal("_PrintDeprecated", function(old, arg...) + Info(InfoWarning, 1, "`", old, "` is deprecated and will be removed in v3", + " use `", Concatenation(List(arg, AsString)), "` instead!"); +end); + +InstallMethod(DotDigraph, "for a digraph", [IsDigraph], +function(D) + _PrintDeprecated("DotDigraph", "GraphvizDigraph"); + return AsString(GraphvizDigraph(D)); +end); + +InstallMethod(DotSymmetricDigraph, "for a digraph", [IsDigraph], +function(D) + _PrintDeprecated("DotSymmetricDigraph", "GraphvizGraph"); + return AsString(GraphvizGraph(D)); +end); + +InstallMethod(DotSymmetricVertexColoredDigraph, +"for a digraph and list of colors", +[IsDigraph, IsHomogeneousList], +function(D, colors) + _PrintDeprecated("DotSymmetricVertexColoredDigraph", + "GraphvizVertexColoredGraph"); + return AsString(GraphvizVertexColoredGraph(D, colors)); +end); + +InstallMethod(DotVertexColoredDigraph, "for a digraph and a list", +[IsDigraph, IsList], +function(D, colors) + _PrintDeprecated("DotVertexColoredDigraph", + "GraphvizVertexColoredDigraph"); + return AsString(GraphvizVertexColoredDigraph(D, colors)); +end); + +InstallMethod(DotSymmetricEdgeColoredDigraph, +"for a digraph and list of colors", +[IsDigraph, IsHomogeneousList], +function(D, colors) + _PrintDeprecated("DotSymmetricEdgeColoredDigraph", + "GraphvizEdgeColoredGraph"); + return AsString(GraphvizEdgeColoredGraph(D, colors)); +end); + +InstallMethod(DotEdgeColoredDigraph, "for a digraph and a list", +[IsDigraph, IsList], +function(D, colors) + _PrintDeprecated("DotEdgeColoredDigraph", + "GraphvizEdgeColoredDigraph"); + return AsString(GraphvizEdgeColoredDigraph(D, colors)); +end); + +InstallMethod(DotSymmetricColoredDigraph, +"for a digraph, vertex colors, and edge colors", +[IsDigraph, IsHomogeneousList, IsHomogeneousList], +function(D, n_colors, e_colors) + _PrintDeprecated("DotSymmetricColoredDigraph", + "GraphvizColoredGraph"); + return AsString(GraphvizColoredGraph(D, n_colors, e_colors)); +end); + +InstallMethod(DotColoredDigraph, +"for a digraph, vertex colors, and edge colors", +[IsDigraph, IsHomogeneousList, IsHomogeneousList], +function(D, n_colors, e_colors) + _PrintDeprecated("DotColoredDigraph", + "GraphvizColoredDigraph"); + return AsString(GraphvizColoredDigraph(D, n_colors, e_colors)); +end); + +InstallMethod(DotVertexLabelledDigraph, "for a digraph", [IsDigraph], +function(D) + _PrintDeprecated("DotVertexLabelledDigraph", + "GraphvizVertexLabelledDigraph"); + return AsString(GraphvizVertexLabelledDigraph(D)); +end); + +InstallMethod(DotPartialOrderDigraph, "for a digraph", [IsDigraph], +function(D) + _PrintDeprecated("DotPartialOrderDigraph", + "GraphvizPartialOrderDigraph"); + return AsString(GraphvizPartialOrderDigraph(D)); +end); + +InstallMethod(DotPreorderDigraph, "for a digraph", [IsDigraph], +function(D) + _PrintDeprecated("DotPreorderDigraph", + "GraphvizPreorderDigraph"); + return AsString(GraphvizPreorderDigraph(D)); +end); + +InstallMethod(DotHighlightedDigraph, +"for a digraph, list, and two strings", +[IsDigraph, IsList, IsString, IsString], +function(D, hi_verts, hi, lo) + _PrintDeprecated("DotHighlightedDigraph", + "GraphvizHighlightedDigraph"); + return AsString(GraphvizHighlightedDigraph(D, hi_verts, hi, lo)); +end); + +InstallMethod(DotHighlightedDigraph, "for a digraph and list", +[IsDigraph, IsList], +function(D, list) + _PrintDeprecated("DotHighlightedDigraph", + "GraphvizHighlightedDigraph"); + return AsString(GraphvizHighlightedDigraph(D, list, "black", "grey")); +end); diff --git a/gap/display.gd b/gap/display.gd index 5916ef9b9..93a9c937a 100644 --- a/gap/display.gd +++ b/gap/display.gd @@ -1,4 +1,4 @@ -############################################################################# +############################################################################ ## ## display.gd ## Copyright (C) 2017-19 James D. Mitchell @@ -8,18 +8,57 @@ ############################################################################# ## -DeclareAttribute("DotDigraph", IsDigraph); -DeclareOperation("DotColoredDigraph", [IsDigraph, IsList, IsList]); -DeclareOperation("DotVertexColoredDigraph", [IsDigraph, IsList]); -DeclareOperation("DotEdgeColoredDigraph", [IsDigraph, IsList]); -DeclareOperation("DotVertexLabelledDigraph", [IsDigraph]); -DeclareAttribute("DotSymmetricDigraph", IsDigraph); -DeclareOperation("DotSymmetricColoredDigraph", [IsDigraph, IsList, IsList]); -DeclareOperation("DotSymmetricVertexColoredDigraph", [IsDigraph, IsList]); -DeclareOperation("DotSymmetricEdgeColoredDigraph", [IsDigraph, IsList]); -DeclareAttribute("DotPartialOrderDigraph", IsDigraph); -DeclareAttribute("DotPreorderDigraph", IsDigraph); -DeclareSynonym("DotQuasiorderDigraph", DotPreorderDigraph); -DeclareOperation("DotHighlightedDigraph", [IsDigraph, IsList]); -DeclareOperation("DotHighlightedDigraph", +############################################################################# +# Graphs and digraphs +############################################################################# + +DeclareOperation("GraphvizDigraph", [IsDigraph]); +DeclareOperation("GraphvizGraph", [IsDigraph]); + +############################################################################# +# Vertex coloured graphs and digraphs +############################################################################# + +DeclareOperation("GraphvizVertexColoredDigraph", [IsDigraph, IsList]); +DeclareOperation("GraphvizVertexColoredGraph", [IsDigraph, IsList]); + +############################################################################# +# Edge coloured graphs and digraphs +############################################################################# + +DeclareOperation("GraphvizEdgeColoredDigraph", [IsDigraph, IsList]); +DeclareOperation("GraphvizEdgeColoredGraph", [IsDigraph, IsList]); + +############################################################################# +# Vertex and edge coloured graphs and digraphs +############################################################################# + +DeclareOperation("GraphvizColoredDigraph", [IsDigraph, IsList, IsList]); +DeclareOperation("GraphvizColoredGraph", [IsDigraph, IsList, IsList]); + +############################################################################# +# Vertex labelled graphs and digraphs +############################################################################# + +DeclareOperation("GraphvizVertexLabelledDigraph", [IsDigraph]); +DeclareOperation("GraphvizVertexLabelledGraph", [IsDigraph]); + +############################################################################# +# Partial and preorder digraphs +############################################################################# + +DeclareAttribute("GraphvizPartialOrderDigraph", IsDigraph); +DeclareAttribute("GraphvizPreorderDigraph", IsDigraph); + +DeclareSynonym("GraphvizQuasiorderDigraph", GraphvizPreorderDigraph); + +############################################################################# +# Highlighted subdigraphs +############################################################################# + +DeclareOperation("GraphvizHighlightedDigraph", [IsDigraph, IsList]); +DeclareOperation("GraphvizHighlightedDigraph", + [IsDigraph, IsList, IsString, IsString]); +DeclareOperation("GraphvizHighlightedGraph", [IsDigraph, IsList]); +DeclareOperation("GraphvizHighlightedGraph", [IsDigraph, IsList, IsString, IsString]); diff --git a/gap/display.gi b/gap/display.gi index 44db21e7f..fe7acd3eb 100644 --- a/gap/display.gi +++ b/gap/display.gi @@ -1,514 +1,316 @@ ############################################################################# ## ## display.gi -## Copyright (C) 2014-21 James D. Mitchell +## Copyright (C) 2014-24 James D. Mitchell ## ## Licensing information can be found in the README file of this package. ## ############################################################################# ## -# AN's code, adapted by WW - -BindGlobal("DIGRAPHS_DotDigraph", -function(D, node_funcs, edge_funcs) - local str, out, i, func, j, l; - str := "//dot\n"; - Append(str, "digraph hgn{\n"); - Append(str, "node [shape=circle]\n"); - for i in DigraphVertices(D) do - Append(str, StringFormatted("{}", i)); - for func in node_funcs do - Append(str, func(i)); - od; - Append(str, "\n"); + +# TODO: +# * add graph6 string or whatever as a comment at the start of the string +# * check JupyterInterface Splash function +# * for edge colored non-digraphs, should ensure that the edge colors are +# symmetric, i.e. the same colors for x -> y and y -> x + +############################################################################# +# Graphs and digraphs +############################################################################# + +InstallOtherMethod(GraphvizDigraph, "for a digraph by out-neighbours", +[IsDigraphByOutNeighboursRep], +function(D) + local gv, x, y; + gv := GraphvizDigraph("hgn"); + GraphvizSetAttr(gv, "node [shape=circle]"); + for x in DigraphVertices(D) do + GraphvizAddNode(gv, x); od; - out := OutNeighbours(D); - for i in DigraphVertices(D) do - l := Length(out[i]); - for j in [1 .. l] do - Append(str, StringFormatted("{} -> {}", i, out[i][j])); - for func in edge_funcs do - Append(str, func(i, j)); - od; - Append(str, "\n"); + for x in DigraphVertices(D) do + for y in OutNeighboursOfVertexNC(D, x) do + GraphvizAddEdge(gv, x, y); od; od; - Append(str, "}\n"); - return str; -end); - -BindGlobal("DIGRAPHS_ValidRGBValue", -function(str) - local l, chars, x, i; - l := Length(str); - x := 0; - chars := "0123456789ABCDEFabcdef"; - if l = 7 then - if str[1] = '#' then - for i in [2 .. l] do - if str[i] in chars then - x := x + 1; - fi; - od; - fi; - fi; - return x = (l - 1); -end); - -BindGlobal("DIGRAPHS_GraphvizColorsList", fail); - -BindGlobal("DIGRAPHS_GraphvizColors", -function() - local f; - if DIGRAPHS_GraphvizColorsList = fail then - f := IO_File(Concatenation(DIGRAPHS_Dir(), "/data/colors.p")); - MakeReadWriteGlobal("DIGRAPHS_GraphvizColorsList"); - DIGRAPHS_GraphvizColorsList := IO_Unpickle(f); - MakeReadOnlyGlobal("DIGRAPHS_GraphvizColorsList"); - IO_Close(f); - fi; - return DIGRAPHS_GraphvizColorsList; + return gv; end); -BindGlobal("DIGRAPHS_ValidVertColors", -function(D, verts) - local v, sum, colors, col; - v := DigraphVertices(D); - sum := 0; - if Length(verts) <> Length(v) then - ErrorNoReturn("the number of vertex colors must be the same as the number", - " of vertices, expected ", Length(v), " but found ", Length(verts), ""); +InstallOtherMethod(GraphvizGraph, "for a digraph by out-neighbours", +[IsDigraphByOutNeighboursRep], +function(D) + local gv, x, y; + if not IsSymmetricDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be symmetric"); fi; - colors := DIGRAPHS_GraphvizColors(); - if Length(verts) = Length(v) then - for col in verts do - if not IsString(col) then - ErrorNoReturn("expected a string"); - elif DIGRAPHS_ValidRGBValue(col) = false and - (col in colors) = false then - ErrorNoReturn("expected RGB Value or valid color name as defined", - " by GraphViz 2.44.1 X11 Color Scheme", - " http://graphviz.org/doc/info/colors.html"); - else - sum := sum + 1; + gv := GraphvizGraph("hgn"); + GraphvizSetAttr(gv, "node [shape=circle]"); + for x in DigraphVertices(D) do + GraphvizAddNode(gv, x); + od; + for x in DigraphVertices(D) do + for y in OutNeighboursOfVertexNC(D, x) do + if x > y then + GraphvizAddEdge(gv, x, y); fi; od; - if sum = Length(verts) then - return true; - fi; - fi; + od; + return gv; end); -BindGlobal("DIGRAPHS_ValidEdgeColors", -function(D, edge) - local out, l, counter, sum, colors, v, col; - out := OutNeighbours(D); - l := Length(edge); - counter := 0; - sum := 0; - colors := DIGRAPHS_GraphvizColors(); - if Length(edge) <> Length(out) then - ErrorNoReturn("the list of edge colors needs to have the", - " same shape as the out-neighbours of the digraph"); - else - for v in [1 .. l] do - sum := 0; - if Length(out[v]) <> Length(edge[v]) then - ErrorNoReturn("the list of edge colors needs to have the", - " same shape as the out-neighbours of the digraph"); - else - for col in edge[v] do - if not IsString(col) then - ErrorNoReturn("expected a string"); - elif DIGRAPHS_ValidRGBValue(col) = false and - (col in colors) = false then - ErrorNoReturn("expected RGB Value or valid color name as defined", - " by GraphViz 2.44.1 X11 Color Scheme", - " http://graphviz.org/doc/info/colors.html"); - else - sum := sum + 1; - fi; - od; - if sum = Length(edge[v]) then - counter := counter + 1; - fi; - fi; - od; - if counter = Length(edge) then - return true; - fi; - fi; -end); +############################################################################# +# Vertex coloured graphs and digraphs +############################################################################# -InstallMethod(DotDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -D -> DIGRAPHS_DotDigraph(D, [], [])); - -InstallMethod(DotColoredDigraph, -"for a digraph by out-neighbours and two lists", -[IsDigraphByOutNeighboursRep, IsList, IsList], -function(D, vert, edge) - local vert_func, edge_func; - if DIGRAPHS_ValidVertColors(D, vert) - and DIGRAPHS_ValidEdgeColors(D, edge) then - vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]); - edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); - return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]); - fi; -end); +InstallMethod(GraphvizVertexColoredDigraph, "for a digraph and a list", +[IsDigraph, IsList], +{D, colors} -> GraphvizSetNodeColors(GraphvizDigraph(D), colors)); -InstallMethod(DotVertexColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, vert) - local func; - if DIGRAPHS_ValidVertColors(D, vert) then - func := i -> StringFormatted("[color={}, style=filled]", vert[i]); - return DIGRAPHS_DotDigraph(D, [func], []); - fi; -end); +InstallMethod(GraphvizVertexColoredGraph, "for a digraph and a list", +[IsDigraph, IsList], +# IsSymmetricDigraph checked by GraphvizGraph +{D, colors} -> GraphvizSetNodeColors(GraphvizGraph(D), colors)); -InstallMethod(DotEdgeColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, edge) - local func; - if DIGRAPHS_ValidEdgeColors(D, edge) then - func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); - return DIGRAPHS_DotDigraph(D, [], [func]); - fi; -end); +############################################################################# +# Edge coloured graphs and digraphs +############################################################################# -InstallMethod(DotVertexLabelledDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -function(D) - local func; - func := i -> StringFormatted(" [label=\"{}\"]", DigraphVertexLabel(D, i)); - return DIGRAPHS_DotDigraph(D, [func], []); -end); +# This function is here rather than graphviz b/c otherwise if D has multiple +# edges we can't reliably get the corresponding graphviz edge from the head and +# tail of the edge from gv. +BindGlobal("DIGRAPHS_ErrorIfNotEdgeColoring", +function(D, colors) + local out, i; -BindGlobal("DIGRAPHS_DotSymmetricDigraph", -function(D, node_funcs, edge_funcs) - local out, str, i, j, func; - if not IsSymmetricDigraph(D) then - ErrorNoReturn("the argument must be a symmetric digraph,"); + out := OutNeighbours(D); + if Length(colors) <> Length(out) then + ErrorFormatted("the 2nd argument (edge colors) must have ", + "the same number of entries as the 1st argument ", + "(a digraph) has nodes, expected {} but found {}", + Length(out), + Length(colors)); fi; - out := OutNeighbours(D); - str := "//dot\n"; - Append(str, "graph hgn{\n"); - Append(str, "node [shape=circle]\n\n"); - for i in DigraphVertices(D) do - Append(str, StringFormatted("{}", i)); - for func in node_funcs do - Append(str, func(i)); - od; - Append(str, "\n"); + for i in [1 .. Length(colors)] do + if not IsList(colors[i]) then + ErrorFormatted("the 2nd argument (edge colors) must be ", + "a list of lists, found {} in position {}", + TNAM_OBJ(colors[i]), + i); + elif Length(out[i]) <> Length(colors[i]) then + ErrorFormatted("the 2nd argument (edge colors) must have ", + "the same shape as the out neighbours of the 1st ", + "argument (a digraph), in position {} expected ", + "a list of length {} but found list of length {}", + i, + Length(out[i]), + Length(colors[i])); + fi; + Perform(colors[i], ErrorIfNotValidColor); od; - for i in DigraphVertices(D) do - for j in [1 .. Length(out[i])] do - if out[i][j] >= i then - Append(str, StringFormatted("{} -- {}", i, out[i][j])); - for func in edge_funcs do - Append(str, func(i, j)); - od; - Append(str, "\n"); +end); + +BindGlobal("DIGRAPHS_AddEdgesAndColorsNC", +function(D, gv, colors) + local out, e, n, i; + + # This duplicates code in the GraphvizDigraph function because otherwise if D + # has multiple edges we can't reliably get the corresponding graphviz edge + # from the head and tail of the edge from gv. + out := OutNeighbours(D); + for n in DigraphVertices(D) do + for i in [1 .. Length(out[n])] do + if IsGraphvizDigraph(gv) or n > out[n][i] then + e := GraphvizAddEdge(gv, n, out[n][i]); + GraphvizSetAttr(e, "color", colors[n][i]); fi; od; od; - Append(str, "}\n"); - return str; -end); - -InstallMethod(DotSymmetricDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -D -> DIGRAPHS_DotSymmetricDigraph(D, [], [])); - -InstallMethod(DotSymmetricColoredDigraph, -"for a digraph by out-neighbours and two lists", -[IsDigraphByOutNeighboursRep, IsList, IsList], -function(D, vert, edge) - local vert_func, edge_func; - if DIGRAPHS_ValidVertColors(D, vert) - and DIGRAPHS_ValidEdgeColors(D, edge) then - vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]); - edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); - return DIGRAPHS_DotSymmetricDigraph(D, [vert_func], [edge_func]); - fi; + return gv; end); -InstallMethod(DotSymmetricVertexColoredDigraph, +InstallMethod(GraphvizEdgeColoredDigraph, "for a digraph by out-neighbours and a list", [IsDigraphByOutNeighboursRep, IsList], -function(D, vert) - local func; - if DIGRAPHS_ValidVertColors(D, vert) then - func := i -> StringFormatted ("[color={}, style=filled]", vert[i]); - return DIGRAPHS_DotSymmetricDigraph(D, [func], []); - fi; +function(D, colors) + local gv; + DIGRAPHS_ErrorIfNotEdgeColoring(D, colors); + gv := GraphvizDigraph(NullDigraph(DigraphNrVertices(D))); + return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors); end); -InstallMethod(DotSymmetricEdgeColoredDigraph, +InstallMethod(GraphvizEdgeColoredGraph, "for a digraph by out-neighbours and a list", [IsDigraphByOutNeighboursRep, IsList], -function(D, edge) - local func; - if DIGRAPHS_ValidEdgeColors(D, edge) then - func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); - return DIGRAPHS_DotSymmetricDigraph(D, [], [func]); +function(D, colors) + local gv; + if not IsSymmetricDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be symmetric"); fi; + DIGRAPHS_ErrorIfNotEdgeColoring(D, colors); + gv := GraphvizGraph(NullDigraph(DigraphNrVertices(D))); + return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors); end); -# AN's code - -if not IsBound(Splash) then # This function is written by A. Egri-Nagy - BindGlobal("VizViewers", - ["xpdf", "xdg-open", "open", "evince", "okular", "gv"]); - - BindGlobal("Splash", - function(arg...) - local str, opt, path, dir, tdir, file, viewer, type, inn, filetype, out, - engine; - - if not IsString(arg[1]) then - ErrorNoReturn("the 1st argument must be a string,"); - fi; - str := arg[1]; - - opt := rec(); - if IsBound(arg[2]) and IsRecord(arg[2]) then - opt := arg[2]; - elif IsBound(arg[2]) then - ErrorNoReturn("the 2nd argument must be a record,"); - fi; - - # path - path := UserHomeExpand("~/"); # default - if IsBound(opt.path) then - path := opt.path; - fi; - - # directory - if IsBound(opt.directory) then - if not opt.directory in DirectoryContents(path) then - Exec(Concatenation("mkdir ", path, opt.directory)); - fi; - dir := Concatenation(path, opt.directory, "/"); - elif IsBound(opt.path) then - if not "tmp.viz" in DirectoryContents(path) then - tdir := Directory(Concatenation(path, "/", "tmp.viz")); - dir := Filename(tdir, ""); - fi; - else - tdir := DirectoryTemporary(); - dir := Filename(tdir, ""); - fi; +############################################################################# +# Vertex and edge coloured graphs and digraphs +############################################################################# - # file - file := "vizpicture"; # default - if IsBound(opt.filename) then - file := opt.filename; - fi; +InstallMethod(GraphvizColoredDigraph, +"for a digraph, list, and list", +[IsDigraph, IsList, IsList], +{D, n_colors, e_colors} -> GraphvizSetNodeColors( + GraphvizEdgeColoredDigraph(D, e_colors), + n_colors)); + +InstallMethod(GraphvizColoredGraph, +"for a digraph, list, and list", +[IsDigraph, IsList, IsList], +# IsSymmetricDigraph checked by GraphvizEdgeColoredGraph +{D, n_colors, e_colors} -> GraphvizSetNodeColors( + GraphvizEdgeColoredGraph(D, e_colors), + n_colors)); - # viewer - if IsBound(opt.viewer) then - viewer := opt.viewer; - if not IsString(viewer) then - ErrorNoReturn("the option `viewer` must be a string, not an ", - TNAM_OBJ(viewer), ","); - elif Filename(DirectoriesSystemPrograms(), viewer) = fail then - ErrorNoReturn("the viewer \"", viewer, "\" specified in the option ", - "`viewer` is not available,"); - fi; - else - viewer := First(VizViewers, x -> - Filename(DirectoriesSystemPrograms(), x) <> fail); - if viewer = fail then - ErrorNoReturn("none of the default viewers ", VizViewers, - " is available, please specify an available viewer", - " in the options record component `viewer`,"); - fi; - fi; - - # type - if IsBound(opt.type) and (opt.type = "latex" or opt.type = "dot") then - type := opt.type; - elif Length(str) >= 6 and str{[1 .. 6]} = "%latex" then - type := "latex"; - elif Length(str) >= 5 and str{[1 .. 5]} = "//dot" then - type := "dot"; - else - ErrorNoReturn("the component \"type\" of the 2nd argument ", - " must be \"dot\" or \"latex\","); - fi; - if type = "latex" then - inn := Concatenation(dir, file, ".tex"); - else # type = "dot" - inn := Concatenation(dir, file, ".dot"); - fi; +############################################################################# +# Vertex labelled graphs and digraphs +############################################################################# - # output type and name - filetype := "pdf"; # default - if IsBound(opt.filetype) and IsString(opt.filetype) and type <> "latex" then - filetype := opt.filetype; - fi; - out := Concatenation(dir, file, ".", filetype); - - # engine - engine := "dot"; # default - if IsBound(opt.engine) then - engine := opt.engine; - if not engine in ["dot", "neato", "twopi", "circo", - "fdp", "sfdp", "patchwork"] then - ErrorNoReturn("the component \"engine\" of the 2nd argument ", - " must be one of: \"dot\", \"neato\", ", - "\"twopi\", \"circo\", \"fdp\", \"sfdp\", ", - "or \"patchwork\""); - fi; - fi; +InstallMethod(GraphvizVertexLabelledDigraph, "for a digraph", +[IsDigraph], +D -> GraphvizSetNodeLabels(GraphvizDigraph(D), DigraphVertexLabels(D))); - # Write and compile the file - FileString(inn, str); - if type = "latex" then - # Requires GAP >= 4.11: - # Exec(StringFormatted("cd {}; pdflatex {} 2>/dev/null 1>/dev/null", dir); - Exec(Concatenation("cd ", dir, ";", - "pdflatex ", file, " 2>/dev/null 1>/dev/null")); - else # type = "dot" - # Requires GAP >= 4.11: - # Exec(StringFormatted("{} -T {} {} -o {}", engine, filetype, inn, out)); - Exec(Concatenation(engine, " -T", filetype, " ", inn, " -o ", out)); - fi; - Exec(Concatenation(viewer, " ", out, " 2>/dev/null 1>/dev/null &")); - end); -fi; +InstallMethod(GraphvizVertexLabelledGraph, "for a digraph", +[IsDigraph], +# symmetry checked in GraphvizGraph +D -> GraphvizSetNodeLabels(GraphvizGraph(D), DigraphVertexLabels(D))); -# CR's code +############################################################################# +# Partial and preorder digraphs +############################################################################# -InstallMethod(DotPartialOrderDigraph, "for a partial order digraph", +InstallMethod(GraphvizPartialOrderDigraph, "for a partial order digraph", [IsDigraph], function(D) if not IsPartialOrderDigraph(D) then - ErrorNoReturn("the argument must be a partial order digraph,"); + ErrorNoReturn("the argument (a digraph) must be a partial order"); fi; D := DigraphMutableCopyIfMutable(D); - return DotDigraph(DigraphReflexiveTransitiveReduction(D)); + return GraphvizDigraph(DigraphReflexiveTransitiveReduction(D)); end); -InstallMethod(DotPreorderDigraph, "for a preorder digraph", +InstallMethod(GraphvizPreorderDigraph, "for a preorder digraph", [IsDigraph], function(D) - local comps, quo, red, str, c, x, e; + local comps, gv, label, node, nodes, c, x, e; + if not IsPreorderDigraph(D) then - ErrorNoReturn("the argument must be a preorder digraph,"); + ErrorNoReturn("the argument (a digraph) must be a preorder"); fi; # Quotient by the strongly connected components to get a partial order # D and draw this without loops or edges implied by transitivity. - D := DigraphMutableCopyIfMutable(D); - comps := DigraphStronglyConnectedComponents(D).comps; - quo := DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps)); - red := DigraphReflexiveTransitiveReduction(quo); + comps := DigraphStronglyConnectedComponents(D).comps; + D := DigraphMutableCopy(D); + DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps)); + DigraphReflexiveTransitiveReduction(D); - str := "//dot\n"; - Append(str, "digraph graphname {\n"); - Append(str, "node [shape=Mrecord, height=0.5, fixedsize=true]"); - Append(str, "ranksep=1;\n"); + gv := GraphvizDigraph("graphname"); + GraphvizSetAttr(gv, "node [shape=\"Mrecord\"]"); + GraphvizSetAttr(gv, "height=\"0.5\""); + GraphvizSetAttr(gv, "fixedsize=\"true\""); + GraphvizSetAttr(gv, "ranksep=\"1\""); - # Each vertex of the quotient D is labelled by its preimage. for c in [1 .. Length(comps)] do - Append(str, String(c)); - Append(str, " [label=\""); - Append(str, String(comps[c][1])); + + label := "\""; + Append(label, String(comps[c][1])); for x in comps[c]{[2 .. Length(comps[c])]} do - Append(str, "|"); - Append(str, String(x)); + Append(label, "|"); + Append(label, String(x)); od; - Append(str, "\", width="); - Append(str, String(Float(Length(comps[c]) / 2))); - Append(str, "]\n"); + Append(label, "\""); + + node := GraphvizAddNode(gv, c); + GraphvizSetAttr(node, "label", label); + GraphvizSetAttr(node, "width", Float(Length(comps[c]) / 2)); od; - # Add the edges of the quotient D. - for e in DigraphEdges(red) do - Append(str, Concatenation(String(e[1]), " -> ", String(e[2]), "\n")); + nodes := GraphvizNodes(gv); + for e in DigraphEdges(D) do + GraphvizAddEdge(gv, nodes[e[1]], nodes[e[2]]); od; - Append(str, "}"); - return str; + return gv; end); -InstallMethod(DotHighlightedDigraph, "for a digraph and list", -[IsDigraph, IsList], -{D, list} -> DotHighlightedDigraph(D, list, "black", "grey")); - -InstallMethod(DotHighlightedDigraph, -"for a digraph by out-neighbours, list, and two strings", -[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], -function(D, highverts, highcolour, lowcolour) - local lowverts, out, str, i, j; - - if not IsSubset(DigraphVertices(D), highverts) then - ErrorNoReturn("the 2nd argument must be a list of vertices ", - "of the 1st argument ,"); - elif IsEmpty(highcolour) then - ErrorNoReturn("the 3rd argument must be a string ", - "containing the name of a colour,"); - elif IsEmpty(lowcolour) then - ErrorNoReturn("the 4th argument must be a string ", - "containing the name of a colour,"); - fi; - - lowverts := Difference(DigraphVertices(D), highverts); - out := OutNeighbours(D); - str := "//dot\n"; - - Append(str, "digraph hgn{\n"); - - Append(str, "subgraph lowverts{\n"); - Append(str, Concatenation("node [shape=circle, color=", - lowcolour, - "]\n edge [color=", - lowcolour, - "]\n")); +############################################################################# +# Highlighted subdigraphs +############################################################################# - for i in lowverts do - Append(str, Concatenation(String(i), "\n")); - od; +BindGlobal("DIGRAPHS_GraphvizHighlight", +function(D, gv, hi_verts, hi, lo) + local node, color, out, nodes, edge, v, i, j; - Append(str, "}\n"); + if IsMultiDigraph(D) then + ErrorNoReturn("the 1st argument (a digraph) must not have multiple edges"); + elif not IsSubset(DigraphVertices(D), hi_verts) then + ErrorNoReturn("the 2nd argument (list) must consist of vertices ", + "of the 1st argument (a digraph)"); + fi; + ErrorIfNotValidColor(hi); + ErrorIfNotValidColor(lo); - Append(str, "subgraph highverts{\n"); - Append(str, Concatenation("node [shape=circle, color=", - highcolour, - "]\n edge [color=", - highcolour, - "]\n")); + GraphvizSetAttr(gv, "shape", "circle"); - for i in highverts do - Append(str, Concatenation(String(i), "\n")); + for v in DigraphVertices(D) do + node := GraphvizAddNode(gv, v); + if v in hi_verts then + color := hi; + else + color := lo; + fi; + GraphvizSetAttr(node, "color", color); od; - Append(str, "}\n"); - - Append(str, "subgraph lowverts{\n"); - for i in lowverts do - for j in out[i] do - Append(str, Concatenation(String(i), " -> ", String(j), "\n")); - od; - od; - Append(str, "}\n"); + out := OutNeighbours(D); + nodes := GraphvizNodes(gv); - Append(str, "subgraph highverts{\n"); - for i in highverts do + for i in DigraphVertices(D) do for j in out[i] do - Append(str, Concatenation(String(i), " -> ", String(j))); - if j in lowverts then - Append(str, Concatenation(" [color=", lowcolour, "]")); + if IsGraphvizDigraph(gv) or i > j then + edge := GraphvizAddEdge(gv, nodes[i], nodes[j]); + if i in hi_verts and j in hi_verts then + color := hi; + else + color := lo; + fi; + GraphvizSetAttr(edge, "color", color); fi; - Append(str, "\n"); od; od; - Append(str, "}\n}\n"); - return str; + return gv; end); + +InstallMethod(GraphvizHighlightedDigraph, +"for a digraph by out-neighbours, list, and two strings", +[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], +{D, hi_verts, hi, lo} -> +DIGRAPHS_GraphvizHighlight(D, GraphvizDigraph(), hi_verts, hi, lo)); + +InstallMethod(GraphvizHighlightedDigraph, "for a digraph and list", +[IsDigraph, IsList], +{D, list} -> GraphvizHighlightedDigraph(D, list, "black", "grey")); + +InstallMethod(GraphvizHighlightedGraph, +"for a digraph by out-neighbours, list, and two strings", +[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], +function(D, hi_verts, hi, lo) + if not IsSymmetricDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be symmetric"); + fi; + return DIGRAPHS_GraphvizHighlight(D, GraphvizGraph(), hi_verts, hi, lo); +end); + +InstallMethod(GraphvizHighlightedGraph, "for a digraph and list", +[IsDigraph, IsList], +# IsSymmetricDigraph checked in GraphvizHighlightedGraph +{D, list} -> GraphvizHighlightedGraph(D, list, "black", "grey")); diff --git a/init.g b/init.g index 9edfe8d60..09b5afbb8 100644 --- a/init.g +++ b/init.g @@ -71,5 +71,6 @@ ReadPackage("digraphs", "gap/cliques.gd"); ReadPackage("digraphs", "gap/planar.gd"); ReadPackage("digraphs", "gap/examples.gd"); ReadPackage("digraphs", "gap/weights.gd"); +ReadPackage("digraphs", "gap/deprecated.gd"); DeclareInfoClass("InfoDigraphs"); diff --git a/read.g b/read.g index e04a710fe..0466140d1 100644 --- a/read.g +++ b/read.g @@ -53,3 +53,4 @@ ReadPackage("digraphs", "gap/cliques.gi"); ReadPackage("digraphs", "gap/planar.gi"); ReadPackage("digraphs", "gap/examples.gi"); ReadPackage("digraphs", "gap/weights.gi"); +ReadPackage("digraphs", "gap/deprecated.gi"); diff --git a/tst/standard/display.tst b/tst/standard/display.tst new file mode 100644 index 000000000..0b30d3e74 --- /dev/null +++ b/tst/standard/display.tst @@ -0,0 +1,700 @@ +############################################################################# +## +#W standard/display.tst +#Y Copyright (C) 2014-24 James D. Mitchell +## +## Licensing information can be found in the README file of this package. +## +############################################################################# +## +gap> START_TEST("Digraphs package: standard/display.tst"); +gap> LoadPackage("digraphs", false);; + +# +gap> DIGRAPHS_StartTest(); + +# Display and PrintString and String +gap> Digraph([]); + +gap> Digraph([[]]); + +gap> Digraph([[1]]); + +gap> Digraph([[2], []]); + +gap> gr := Digraph([[1, 2], [2], []]); + +gap> PrintString(gr); +"DigraphFromDigraph6String(\"&Bq?\")" +gap> String(gr); +"DigraphFromDigraph6String(\"&Bq?\")" +gap> gr := Digraph([[2], [1], [], [3]]); + +gap> PrintString(gr); +"DigraphFromDigraph6String(\"&CQ?G\")" +gap> String(gr); +"DigraphFromDigraph6String(\"&CQ?G\")" +gap> r := rec(DigraphVertices := [1, 2, 3], +> DigraphSource := [1, 2], +> DigraphRange := [2, 3]);; +gap> gr := Digraph(r); + +gap> PrintString(gr); +"ChainDigraph(3)" +gap> String(gr); +"ChainDigraph(3)" + +# DotDigraph and DotSymmetricDigraph +gap> r := rec(DigraphVertices := [1 .. 3], DigraphSource := [1, 1, 1, 1], +> DigraphRange := [1, 2, 2, 3]);; +gap> gr := Digraph(r); + +gap> dot := DotDigraph(gr);; +gap> dot{[1 .. 50]}; +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3" +gap> dot{[51 .. 75]}; +"\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n" +gap> r := rec(DigraphVertices := [1 .. 8], +> DigraphSource := [1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 8, +> 8], +> DigraphRange := [6, 7, 1, 6, 5, 1, 4, 8, 1, 3, 6, 6, 7, 7, 1, 4, 4, 5, 7, 5, +> 6]);; +gap> gr1 := Digraph(r); + +gap> DotDigraph(gr1){[50 .. 109]}; +"3\n\t4\n\t5\n\t6\n\t7\n\t8\n\t1 -> 6\n\t1 -> 7\n\t2 -> 1\n\t2 -> 6\n\t3 -> 5\ +\n\t4 " +gap> adj := [[2], [1, 3], [2, 3, 4], [3]]; +[ [ 2 ], [ 1, 3 ], [ 2, 3, 4 ], [ 3 ] ] +gap> gr2 := Digraph(adj); + +gap> DotDigraph(gr2){[11 .. 75]}; +"aph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2\n\t2 -> 1\n\t\ +2 ->" +gap> DotSymmetricDigraph(gr2){[12 .. 70]}; +" hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t2 -- 1\n\t3 -- 2\n\t4" +gap> DotSymmetricDigraph(gr1); +Error, the argument (a digraph) must be symmetric + +#DotColoredDigraph and DotSymmetriColoredDigraph +# TODO fix the colors here! +gap> D := CompleteDigraph(4); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; edgecolors[4] := [];; +gap> edgecolors[1][1] := "lightblue";; +gap> edgecolors[1][2] := "pink";; +gap> edgecolors[1][3] := "purple";; +gap> edgecolors[2][1] := "lightblue";; +gap> edgecolors[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "lightblue";; +gap> edgecolors[3][2] := "pink";; +gap> edgecolors[3][3] := "purple";; +gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][2] := "pink";; +gap> edgecolors[4][3] := "purple";; +gap> DotColoredDigraph(D, vertcolors, edgecolors){[1 .. 30]}; +"//dot\ndigraph hgn {\n\tnode [sha" +gap> D := Digraph([[2], [1, 3], [2]]); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; +gap> vertcolors[2] := "pink";; +gap> vertcolors[3] := "purple";; +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; +gap> edgecolors[1][1] := "green";; +gap> edgecolors[2][1] := "green";; +gap> edgecolors[3][1] := "red";; edgecolors[2][2] := "red";; +gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors); +"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\n\ +\t2 [color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t2 -- 1 [co\ +lor=green]\n\t3 -- 2 [color=red]\n}\n" +gap> D := Digraph([[2, 3], [1, 3], [1]]); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[3] := "green";; +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; +gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "yellow";; +gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "pink";; +gap> edgecolors[3][1] := "yellow";; +gap> DotColoredDigraph(D, vertcolors, edgecolors); +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\ +\n\t2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t1 -> 2 [co\ +lor=orange]\n\t1 -> 3 [color=yellow]\n\t2 -> 1 [color=orange]\n\t2 -> 3 [color\ +=pink]\n\t3 -> 1 [color=yellow]\n}\n" +gap> D := Digraph(IsMutableDigraph, [[2, 3], [1, 3], [1]]); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[3] := "green";; +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; +gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "yellow";; +gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "pink";; +gap> edgecolors[3][1] := "yellow";; +gap> DotColoredDigraph(D, vertcolors, edgecolors);; +gap> D; + +gap> D := Digraph([[2, 4], [1, 3], [2], [1]]); + +gap> vertcolors := ["blue", "red", "green", "yellow"];; +gap> edgecolors := ListWithIdenticalEntries(3, +> ["orange", "orange", "orange"]);; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors); +Error, the 2nd argument (edge colors) must have the same number of entries as \ +the 1st argument (a digraph) has nodes, expected 4 but found 3 +#@else +gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors); +Error, the 2nd argument (edge colors) must have the same number of entries as \ +the 1st\ + argument (a digraph) has nodes, expected 4 but found 3 +#@fi +gap> D := Digraph(IsMutableDigraph, [[2, 4], [1, 3], [2], [1]]); + +gap> vertcolors := ["blue", "red", "green", "yellow"];; +gap> edgecolors := ListWithIdenticalEntries(3, +> ["orange", "orange", "orange"]);; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors); +Error, the 2nd argument (edge colors) must have the same number of entries as \ +the 1st argument (a digraph) has nodes, expected 4 but found 3 +#@else +gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors); +Error, the 2nd argument (edge colors) must have the same number of entries as \ +the 1st\ + argument (a digraph) has nodes, expected 4 but found 3 +#@fi +gap> D; + +gap> D := CompleteDigraph(4);; +gap> vertcolors := ["blue", "banana", "green", "yellow"];; +gap> edgecolors := ListWithIdenticalEntries(4, +> ["lightblue", "pink", "purple"]);; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, invalid color "banana" (list (string)), valid colors are RGB values or \ +names from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/c\ +olors.html +#@else +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, invalid color "banana" (list (string)), valid colors are RGB values or \ +names from the GraphViz 2.44.1 X11 Color Sch\ +eme http://graphviz.org/doc/info/colors.html +#@fi +gap> D := CompleteDigraph(4); + +gap> vertcolors := ["blue", "red", "green"];; +gap> edgecolors := ListWithIdenticalEntries(4, +> ["lightblue", "pink", "purple"]);; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, the number of node colors must be the same as the number of nodes, expe\ +cted 4 but found 3 +#@else +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, the number of node colors must be the same as the number of nodes, expe\ +cted 4 but found 3 +#@fi +gap> D := CompleteDigraph(4); + +gap> vertcolors := [2, 1, 1, 3];; +gap> edgecolors := ListWithIdenticalEntries(4, +> ["lightblue", "pink", "purple"]);; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, invalid color 2 (integer), valid colors are RGB values or names from th\ +e GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.html +#@else +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, invalid color 2 (integer), valid colors are RGB values or names from th\ +e GraphViz 2.44.1 X11 Color Sch\ +eme http://graphviz.org/doc/info/colors.html +#@fi +gap> D := CompleteDigraph(4); + +gap> vertcolors := ["#AB3487", "#DF4738", "#4BF234", "#AF34C9"];; +gap> edgecolors := ListWithIdenticalEntries(4, +> ["lightblue", "pink", "purple"]);; +gap> Print(DotColoredDigraph(D, vertcolors, edgecolors)); +//dot +digraph hgn { + node [shape=circle] + 1 [color="#AB3487", style=filled] + 2 [color="#DF4738", style=filled] + 3 [color="#4BF234", style=filled] + 4 [color="#AF34C9", style=filled] + 1 -> 2 [color=lightblue] + 1 -> 3 [color=pink] + 1 -> 4 [color=purple] + 2 -> 1 [color=lightblue] + 2 -> 3 [color=pink] + 2 -> 4 [color=purple] + 3 -> 1 [color=lightblue] + 3 -> 2 [color=pink] + 3 -> 4 [color=purple] + 4 -> 1 [color=lightblue] + 4 -> 2 [color=pink] + 4 -> 3 [color=purple] +} +gap> D := CompleteDigraph(4); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; edgecolors[4] := [];; +gap> edgecolors[1][1] := "banana";; +gap> edgecolors[1][2] := "pink";; +gap> edgecolors[1][3] := "purple";; +gap> edgecolors[2][1] := "lightblue";; +gap> edgecolors[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "cherry";; +gap> edgecolors[3][2] := "pink";; +gap> edgecolors[3][3] := "purple";; +gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][2] := "pink";; +gap> edgecolors[4][3] := "purple";; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, invalid color "banana" (list (string)), valid colors are RGB values or \ +names from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/c\ +olors.html +#@else +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, invalid color "banana" (list (string)), valid colors are RGB values or \ +names from the GraphViz 2.44.1 X11 Color Sch\ +eme http://graphviz.org/doc/info/colors.html +#@fi +gap> D := CompleteDigraph(4); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; edgecolors[4] := [];; +gap> edgecolors[1][1] := "lightblue";; +gap> edgecolors[1][2] := "pink";; +gap> edgecolors[1][3] := "purple";; +gap> edgecolors[2][1] := "lightblue";; +gap> edgecolors[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "lightblue";; +gap> edgecolors[3][2] := "pink";; +gap> edgecolors[3][3] := "purple";; +gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][2] := "pink";; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, the 2nd argument (edge colors) must have the same shape as the out neig\ +hbours of the 1st argument (a digraph), in position 4 expected a list of lengt\ +h 3 but found list of length 2 +#@else +gap> DotColoredDigraph(D, vertcolors, edgecolors); +Error, the 2nd argument (edge colors) must have the same shape as the out neig\ +hbours \ +of the 1st argument (a digraph), in position 4 expected a list of length 3 but\ + found list of length 2 +#@fi + +# DotVertexColoredDigraph +gap> D := CompleteDigraph(4); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; +gap> Print(DotVertexColoredDigraph(D, vertcolors)); +//dot +digraph hgn { + node [shape=circle] + 1 [color=blue, style=filled] + 2 [color=red, style=filled] + 3 [color=green, style=filled] + 4 [color=yellow, style=filled] + 1 -> 2 + 1 -> 3 + 1 -> 4 + 2 -> 1 + 2 -> 3 + 2 -> 4 + 3 -> 1 + 3 -> 2 + 3 -> 4 + 4 -> 1 + 4 -> 2 + 4 -> 3 +} +gap> D := EmptyDigraph(3); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[3] := "green";; +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; +gap> DotVertexColoredDigraph(D, vertcolors); +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\ +\n\t2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n}\n" + +# DotEdgeColoredDigraph +gap> D := CompleteDigraph(4); + +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; edgecolors[4] := [];; +gap> edgecolors[1][1] := "lightblue";; +gap> edgecolors[1][2] := "pink";; +gap> edgecolors[1][3] := "purple";; +gap> edgecolors[2][1] := "lightblue";; +gap> edgecolors[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "lightblue";; +gap> edgecolors[3][2] := "pink";; +gap> edgecolors[3][3] := "purple";; +gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][2] := "pink";; +gap> edgecolors[4][3] := "purple";; +gap> DotEdgeColoredDigraph(D, edgecolors); +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2 [c\ +olor=lightblue]\n\t1 -> 3 [color=pink]\n\t1 -> 4 [color=purple]\n\t2 -> 1 [col\ +or=lightblue]\n\t2 -> 3 [color=pink]\n\t2 -> 4 [color=purple]\n\t3 -> 1 [color\ +=lightblue]\n\t3 -> 2 [color=pink]\n\t3 -> 4 [color=purple]\n\t4 -> 1 [color=l\ +ightblue]\n\t4 -> 2 [color=pink]\n\t4 -> 3 [color=purple]\n}\n" +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotEdgeColoredDigraph(CycleDigraph(3), []); +Error, the 2nd argument (edge colors) must have the same number of entries as \ +the 1st argument (a digraph) has nodes, expected 3 but found 0 +gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail, fail], [fail], [fail]]); +Error, the 2nd argument (edge colors) must have the same shape as the out neig\ +hbours of the 1st argument (a digraph), in position 1 expected a list of lengt\ +h 1 but found list of length 2 +#@else +gap> DotEdgeColoredDigraph(CycleDigraph(3), []); +Error, the 2nd argument (edge colors) must have the same number of entries as \ +the 1st\ + argument (a digraph) has nodes, expected 3 but found 0 +#@fi +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]); +Error, invalid color fail (boolean or fail), valid colors are RGB values or na\ +mes from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/col\ +ors.html +#@else +gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]); +Error, invalid color fail (boolean or fail), valid colors are RGB values or na\ +mes from the GraphViz 2.44.1 X11 Color Sch\ +eme http://graphviz.org/doc/info/colors.html +#@fi + +# DotSymmetricVertexColoredDigraph +gap> D := Digraph([[2], [1, 3], [2]]); + +gap> vertcolors := [];; +gap> vertcolors[1] := "blue";; +gap> vertcolors[2] := "pink";; +gap> vertcolors[3] := "purple";; +gap> DotSymmetricVertexColoredDigraph(D, vertcolors); +"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\n\ +\t2 [color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t2 -- 1\n\t\ +3 -- 2\n}\n" + +# DotSymmetricEdgeColoredDigraph +gap> D := Digraph([[2], [1, 3], [2]]); + +gap> edgecolors := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[3] := [];; +gap> edgecolors[1][1] := "green";; edgecolors[2][1] := "green";; +gap> edgecolors[2][2] := "red";; edgecolors[3][1] := "red";; +gap> DotSymmetricEdgeColoredDigraph(D, edgecolors); +"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t2 -- 1 [color=gr\ +een]\n\t3 -- 2 [color=red]\n}\n" + +# DotVertexLabelledDigraph +gap> r := rec(DigraphVertices := [1 .. 3], DigraphSource := [1, 1, 1, 1], +> DigraphRange := [1, 2, 2, 3]);; +gap> gr := Digraph(r); + +gap> dot := DotVertexLabelledDigraph(gr);; +gap> dot; +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [label=1]\n\t2 [label=2]\n\ +\t3 [label=3]\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n\t1 -> 3\n}\n" +gap> SetDigraphVertexLabel(gr, 1, 2); +gap> dot := DotVertexLabelledDigraph(gr);; +gap> dot; +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [label=2]\n\t2 [label=2]\n\ +\t3 [label=3]\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n\t1 -> 3\n}\n" + +# Splash +gap> Splash(1); +Error, the 1st argument must be a string or graphviz graph, found integer +gap> Splash("string", 0); +Error, the 2nd argument must be a record, +gap> Splash("string"); +Error, the component "type" of the 2nd argument must be "dot" or "\ +latex", +gap> Splash("string", rec(path := "~/", filename := "filename")); +Error, the component "type" of the 2nd argument must be "dot" or "\ +latex", +gap> Splash("string", rec(viewer := "bad")); +Error, the viewer "bad" specified in the option `viewer` is not available +gap> Splash("string", rec(type := "dot", engine := "dott")); +Error, the component "engine" of the 2nd argument must be one of: "\ +dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork" +gap> tmpdir := Filename(DirectoryTemporary(), "");; +gap> Splash("string", +> rec(path := tmpdir, +> directory := "digraphs_temporary_directory")); +Error, the component "type" of the 2nd argument must be "dot" or "\ +latex", +gap> Splash("%latex", rec(filetype := "latex", engine := fail)); +Error, the component "engine" of the 2nd argument must be one of: "\ +dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork" +gap> Splash("//dot", rec(filetype := "pdf", engine := fail)); +Error, the component "engine" of the 2nd argument must be one of: "\ +dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork" +gap> MakeReadWriteGlobal("VizViewers"); +gap> VizViewers_backup := ShallowCopy(VizViewers);; +gap> VizViewers := ["nonexistent-viewer"];; +gap> Splash("//dot"); +Error, none of the default viewers [ "nonexistent-viewer" + ] is available, please specify an available viewer in the options record comp\ +onent `viewer`, +gap> VizViewers := VizViewers_backup;; +gap> MakeReadOnlyGlobal("VizViewers"); + +# DotPartialOrderDigraph +gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 4], [1 .. 5], [1 .. 6], +> [1, 2, 3, 4, 5, 7], [1, 8]]);; +gap> Print(DotPartialOrderDigraph(gr)); +//dot +digraph hgn { + node [shape=circle] + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 2 -> 1 + 3 -> 1 + 4 -> 1 + 5 -> 2 + 5 -> 3 + 5 -> 4 + 6 -> 5 + 7 -> 5 + 8 -> 1 +} +gap> gr := Digraph([[1], [2], [1, 3], [2, 4], [1, 2, 3, 4, 5], [1, 2, 3, 6]]);; +gap> Print(DotPartialOrderDigraph(gr)); +//dot +digraph hgn { + node [shape=circle] + 1 + 2 + 3 + 4 + 5 + 6 + 3 -> 1 + 4 -> 2 + 5 -> 3 + 5 -> 4 + 6 -> 3 + 6 -> 2 +} +gap> gr := Digraph([[1], []]);; +gap> DotPartialOrderDigraph(gr); +Error, the argument (a digraph) must be a partial order + +# DotPreorderDigraph and DotQuasiorderDigraph +gap> DotPreorderDigraph(CompleteDigraph(5)); +Error, the argument (a digraph) must be a preorder +gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 4], [1 .. 5], [1 .. 6], +> [1, 2, 3, 4, 5, 7], [1, 8]]);; +gap> Print(DotPreorderDigraph(gr), "\n"); +//dot +digraph graphname { + node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1" + 1 [label="1", width=0.5] + 2 [label="2", width=0.5] + 3 [label="3", width=0.5] + 4 [label="4", width=0.5] + 5 [label="5", width=0.5] + 6 [label="6", width=0.5] + 7 [label="7", width=0.5] + 8 [label="8", width=0.5] + 2 -> 1 + 3 -> 1 + 4 -> 1 + 5 -> 2 + 5 -> 3 + 5 -> 4 + 6 -> 5 + 7 -> 5 + 8 -> 1 +} + +gap> gr := Concatenation("&X_?_A]|^Vr[nHpmVcy~zy[A????_???G??B]nhtmvcwvJq\\^~", +> "|m??_AEx]Rb[nHo??__vJy[??A??O_aV~^Zb]njo???_???GZdxMLy}n_");; +gap> gr := DigraphFromDigraph6String(gr);; +gap> Print(DotPreorderDigraph(gr){[1 .. 94]}, "\n"); +//dot +digraph graphname { + node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1" + +gap> gr := DigraphDisjointUnion(CompleteDigraph(10), +> CompleteDigraph(5), +> CycleDigraph(2));; +gap> gr := DigraphReflexiveTransitiveClosure(DigraphAddEdge(gr, [10, 11]));; +gap> IsPreorderDigraph(gr); +true +gap> Print(DotPreorderDigraph(gr), "\n"); +//dot +digraph graphname { + node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1" + 1 [label="11|12|13|14|15", width=2.5] + 2 [label="1|2|3|4|5|6|7|8|9|10", width=5.] + 3 [label="16|17", width=1.] + 2 -> 1 +} + + +# DotHighlightedDigraph +gap> gr := Digraph([[2, 3], [2], [1, 3]]); + +gap> Print(DotHighlightedDigraph(gr, [1, 2], "red", "black")); +//dot +digraph { + shape=circle + 1 [color=red] + 2 [color=red] + 3 [color=black] + 1 -> 2 [color=red] + 1 -> 3 [color=black] + 2 -> 2 [color=red] + 3 -> 1 [color=black] + 3 -> 3 [color=black] +} +gap> D := CycleDigraph(5);; +gap> DotHighlightedDigraph(D, [10], "black", "grey"); +Error, the 2nd argument (list) must consist of vertices of the 1st argument (a\ + digraph) +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotHighlightedDigraph(D, [1], "", "grey"); +Error, invalid color "" (list (string)), valid colors are RGB values or names \ +from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.\ +html +#@else +gap> DotHighlightedDigraph(D, [1], "", "grey"); +Error, invalid color "" (list (string)), valid colors are RGB values or names \ +from the GraphViz 2.44.1 X11 Color Sch\ +eme http://graphviz.org/doc/info/colors.html +#@fi +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") +gap> DotHighlightedDigraph(D, [1], "black", ""); +Error, invalid color "" (list (string)), valid colors are RGB values or names \ +from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.\ +html +#@else +gap> DotHighlightedDigraph(D, [1], "black", ""); +Error, invalid color "" (list (string)), valid colors are RGB values or names \ +from the GraphViz 2.44.1 X11 Color Sch\ +eme http://graphviz.org/doc/info/colors.html +#@fi +gap> Print(DotHighlightedDigraph(D, Filtered(DigraphVertices(D), IsEvenInt))); +//dot +digraph { + shape=circle + 1 [color=grey] + 2 [color=black] + 3 [color=grey] + 4 [color=black] + 5 [color=grey] + 1 -> 2 [color=grey] + 2 -> 3 [color=grey] + 3 -> 4 [color=grey] + 4 -> 5 [color=grey] + 5 -> 1 [color=grey] +} + +# Splash +gap> Splash(DotDigraph(RandomDigraph(10)), rec(viewer := 1)); +Error, the option `viewer` must be a string, not an integer +gap> Splash(DotDigraph(RandomDigraph(10)), rec(viewer := "asdfasfa")); +Error, the viewer "asdfasfa" specified in the option `viewer` is not available + +# Test errors +gap> GraphvizEdgeColoredGraph(ChainDigraph(3), ["blue"]); +Error, the argument (a digraph) must be symmetric +gap> D := DigraphSymmetricClosure(ChainDigraph(3));; +gap> GraphvizVertexLabelledGraph(D); + +gap> GraphvizEdgeColoredGraph(D, List(DigraphVertices(D), ReturnFail)); +Error, the 2nd argument (edge colors) must be a list of lists, found boolean o\ +r fail in position 1 +gap> GraphvizHighlightedDigraph(D, [2]); + +gap> GraphvizHighlightedGraph(D, [2]); + +gap> Print(AsString(last)); +//dot +graph { + shape=circle + 1 [color=grey] + 2 [color=black] + 3 [color=grey] + 2 -- 1 [color=grey] + 3 -- 2 [color=grey] +} +gap> GraphvizHighlightedGraph(D, [1, 2], "red", "blue"); + +gap> Print(AsString(last)); +//dot +graph { + shape=circle + 1 [color=red] + 2 [color=red] + 3 [color=blue] + 2 -- 1 [color=red] + 3 -- 2 [color=blue] +} +gap> GraphvizHighlightedGraph(ChainDigraph(3), [1, 2], "red", "blue"); +Error, the argument (a digraph) must be symmetric +gap> D := Digraph([[], [1, 1]]);; +gap> GraphvizHighlightedDigraph(D, [2]); +Error, the 1st argument (a digraph) must not have multiple edges + +# DIGRAPHS_UnbindVariables +gap> Unbind(D); +gap> Unbind(adj); +gap> Unbind(backup); +gap> Unbind(dot); +gap> Unbind(edgecolors); +gap> Unbind(gr); +gap> Unbind(gr1); +gap> Unbind(gr2); +gap> Unbind(r); +gap> Unbind(tmpdir); +gap> Unbind(vertcolors); + +# +gap> DIGRAPHS_StopTest(); +gap> STOP_TEST("Digraphs package: standard/display.tst", 0); From 8e11f57427914ee13b332f62128933d7ce2a8737 Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Wed, 27 Aug 2025 11:51:18 +0200 Subject: [PATCH 2/3] TMP --- doc/main.xml | 75 ++--- gap/.null-ls_141605_display.gi | 484 --------------------------------- 2 files changed, 21 insertions(+), 538 deletions(-) delete mode 100644 gap/.null-ls_141605_display.gi diff --git a/doc/main.xml b/doc/main.xml index e5c287f5a..61d5d1686 100644 --- a/doc/main.xml +++ b/doc/main.xml @@ -1,60 +1,27 @@ -Digraphs"> - https://gap-packages.github.io/grapeGrape"> - https://digraphs.github.io/graphvizGraphviz"> - http://www.tcs.tkk.fi/Software/bliss/bliss"> - https://github.com/graph-algorithms/edge-addition-planarity-suiteedge-addition-planarity-suite"> - https://pallini.di.uniroma1.it/nauty"> - https://github.com/gap-packages/NautyTracesInterfaceNautyTracesInterface"> - - https://gap-packages.github.io/io/ -IO"> - - https://gap-packages.github.io/orb/ - Orb"> - https://github.com/gap-packages/datastructuresdatastructures"> - filt is present, then this should specify the category or representation the digraph being created will belong to. For example, if filt is , then the digraph being created will be mutable, if filt is , then the digraph will be immutable. If the optional first argument filt is not present, then is used by default.

"> - digraph is mutable, then the return value of this property is recomputed every time it is called.

"> - digraph is mutable, then the return value of this attribute is recomputed every time it is called.

"> - . In more detail, the vertices of the digraph are labelled by elements of the Cartesian product [1..m] x [1..n], where the first entry indexes the column (file) of the square in the chessboard, and the second entry indexes the row (rank) of the square. (Note that the files are traditionally indexed by the lowercase letters of the alphabet). The vertices are sorted in ascending order, first by row (second component) and then column (first component).

"> - m by n chessboard is a grid of m columns (‘files’) and n rows (‘ranks’) that intersect in squares. Orthogonally adjacent squares are alternately colored light and dark, with the square in the first rank and file being dark.

"> - <#Include Label="PKGVERSIONDATA"> - ]> - - -<#Include SYSTEM="z-title.xml"> + + + +] +> + +<#Include SYSTEM "title.xml"> - - <#Include SYSTEM="z-chap0.xml"> - <#Include SYSTEM="z-chap1.xml"> - <#Include SYSTEM="z-chap2.xml"> - <#Include SYSTEM="z-chap3.xml"> - <#Include SYSTEM="z-chap4.xml"> - <#Include SYSTEM="z-chap5.xml"> - <#Include SYSTEM="z-chap6.xml"> - <#Include SYSTEM="z-chap8.xml"> - <#Include SYSTEM="z-chap9.xml"> +<#Include SYSTEM "z-chap0.xml"> +<#Include SYSTEM "z-chap1.xml"> +<#Include SYSTEM "z-chap2.xml"> +<#Include SYSTEM "z-chap3.xml"> +<#Include SYSTEM "z-chap4.xml"> +<#Include SYSTEM "z-chap5.xml"> +<#Include SYSTEM "z-chap6.xml"> +<#Include SYSTEM "z-chap8.xml"> +<#Include SYSTEM "z-chap9.xml"> +<#Include SYSTEM "_AutoDocMainFile.xml"> - -<#Include SYSTEM="z-appA.xml"> - - +<#Include SYSTEM "z-appA.xml"> + - diff --git a/gap/.null-ls_141605_display.gi b/gap/.null-ls_141605_display.gi deleted file mode 100644 index 2e58c5084..000000000 --- a/gap/.null-ls_141605_display.gi +++ /dev/null @@ -1,484 +0,0 @@ -############################################################################# -## -## display.gi -## Copyright (C) 2014-24 James D. Mitchell -## -## Licensing information can be found in the README file of this package. -## -############################################################################# -## - -# TODO: -# * add graph6 string or whatever as a comment at the start of the string -# * check JupyterInterface Splash function -# * for edge colored non-digraphs, should ensure that the edge colors are -# symmetric, i.e. the same colors for x -> y and y -> x - -<<<<<<< HEAD -BindGlobal("DIGRAPHS_ValidRGBValue", -function(str) - local l, chars, x, i; - l := Length(str); - x := 0; - chars := "0123456789ABCDEFabcdef"; - if l = 7 then - if str[1] = '#' then - for i in [2 .. l] do - if str[i] in chars then - x := x + 1; - fi; - od; - fi; - fi; - return x = (l - 1); -end); - -BindGlobal("DIGRAPHS_GraphvizColorsList", fail); - -BindGlobal("DIGRAPHS_GraphvizColors", -function() - local f; - if DIGRAPHS_GraphvizColorsList = fail then - f := IO_File(Concatenation(DIGRAPHS_Dir(), "/data/colors.p")); - MakeReadWriteGlobal("DIGRAPHS_GraphvizColorsList"); - DIGRAPHS_GraphvizColorsList := IO_Unpickle(f); - MakeReadOnlyGlobal("DIGRAPHS_GraphvizColorsList"); - IO_Close(f); - fi; - return DIGRAPHS_GraphvizColorsList; -end); - -BindGlobal("DIGRAPHS_ValidVertColors", -function(D, verts) - local v, sum, colors, col; - v := DigraphVertices(D); - sum := 0; - if Length(verts) <> Length(v) then - ErrorNoReturn("the number of vertex colors must be the same as the number", - " of vertices, expected ", Length(v), " but found ", Length(verts), ""); - fi; - colors := DIGRAPHS_GraphvizColors(); - if Length(verts) = Length(v) then - for col in verts do - if not IsString(col) then - ErrorNoReturn("expected a string"); - elif DIGRAPHS_ValidRGBValue(col) = false and - (col in colors) = false then - ErrorNoReturn("expected RGB Value or valid color name as defined", - " by GraphViz 2.44.1 X11 Color Scheme", - " http://graphviz.org/doc/info/colors.html"); - else - sum := sum + 1; - fi; - od; - if sum = Length(verts) then - return true; - fi; - fi; -end); - -BindGlobal("DIGRAPHS_ValidEdgeColors", -function(D, edge) - local out, l, counter, sum, colors, v, col; - out := OutNeighbours(D); - l := Length(edge); - counter := 0; - sum := 0; - colors := DIGRAPHS_GraphvizColors(); - if Length(edge) <> Length(out) then - ErrorNoReturn("the list of edge colors needs to have the", - " same shape as the out-neighbours of the digraph"); - else - for v in [1 .. l] do - sum := 0; - if Length(out[v]) <> Length(edge[v]) then - ErrorNoReturn("the list of edge colors needs to have the", - " same shape as the out-neighbours of the digraph"); - else - for col in edge[v] do - if not IsString(col) then - ErrorNoReturn("expected a string"); - elif DIGRAPHS_ValidRGBValue(col) = false and - (col in colors) = false then - ErrorNoReturn("expected RGB Value or valid color name as defined", - " by GraphViz 2.44.1 X11 Color Scheme", - " http://graphviz.org/doc/info/colors.html"); - else - sum := sum + 1; - fi; - od; - if sum = Length(edge[v]) then - counter := counter + 1; - fi; - fi; - od; - if counter = Length(edge) then - return true; - fi; - fi; -end); - -InstallMethod(DotDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -D -> DIGRAPHS_DotDigraph(D, [], [])); - -InstallMethod(DotColoredDigraph, -"for a digraph by out-neighbours and two lists", -[IsDigraphByOutNeighboursRep, IsList, IsList], -function(D, vert, edge) - local vert_func, edge_func; - if DIGRAPHS_ValidVertColors(D, vert) - and DIGRAPHS_ValidEdgeColors(D, edge) then - vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]); - edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); - return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]); - fi; -end); - -InstallMethod(DotVertexColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, vert) - local func; - if DIGRAPHS_ValidVertColors(D, vert) then - func := i -> StringFormatted("[color={}, style=filled]", vert[i]); - return DIGRAPHS_DotDigraph(D, [func], []); - fi; -end); - -InstallMethod(DotEdgeColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, edge) - local func; - if DIGRAPHS_ValidEdgeColors(D, edge) then - func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); - return DIGRAPHS_DotDigraph(D, [], [func]); - fi; -end); - -InstallMethod(DotVertexLabelledDigraph, "for a digraph by out-neighbours", -======= -############################################################################# -# Graphs and digraphs -############################################################################# - -InstallOtherMethod(GraphvizDigraph, "for a digraph by out-neighbours", ->>>>>>> 51b65dbf (Checkout files from mpan322/main) -[IsDigraphByOutNeighboursRep], -function(D) - local gv, x, y; - gv := GraphvizDigraph("hgn"); - GraphvizSetAttr(gv, "node [shape=circle]"); - for x in DigraphVertices(D) do - GraphvizAddNode(gv, x); - od; - for x in DigraphVertices(D) do - for y in OutNeighboursOfVertexNC(D, x) do - GraphvizAddEdge(gv, x, y); - od; - od; - return gv; -end); - -InstallOtherMethod(GraphvizGraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -<<<<<<< HEAD -D -> DIGRAPHS_DotSymmetricDigraph(D, [], [])); - -InstallMethod(DotSymmetricColoredDigraph, -"for a digraph by out-neighbours and two lists", -[IsDigraphByOutNeighboursRep, IsList, IsList], -function(D, vert, edge) - local vert_func, edge_func; - if DIGRAPHS_ValidVertColors(D, vert) - and DIGRAPHS_ValidEdgeColors(D, edge) then - vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]); - edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]); - return DIGRAPHS_DotSymmetricDigraph(D, [vert_func], [edge_func]); -======= -function(D) - local gv, x, y; - if not IsSymmetricDigraph(D) then - ErrorNoReturn("the argument (a digraph) must be symmetric"); ->>>>>>> 51b65dbf (Checkout files from mpan322/main) - fi; - gv := GraphvizGraph("hgn"); - GraphvizSetAttr(gv, "node [shape=circle]"); - for x in DigraphVertices(D) do - GraphvizAddNode(gv, x); - od; - for x in DigraphVertices(D) do - for y in OutNeighboursOfVertexNC(D, x) do - if x > y then - GraphvizAddEdge(gv, x, y); - fi; - od; - od; - return gv; -end); - -############################################################################# -# Vertex coloured graphs and digraphs -############################################################################# - -InstallMethod(GraphvizVertexColoredDigraph, "for a digraph and a list", -[IsDigraph, IsList], -{D, colors} -> GraphvizSetNodeColors(GraphvizDigraph(D), colors)); - -InstallMethod(GraphvizVertexColoredGraph, "for a digraph and a list", -[IsDigraph, IsList], -# IsSymmetricDigraph checked by GraphvizGraph -{D, colors} -> GraphvizSetNodeColors(GraphvizGraph(D), colors)); - -############################################################################# -# Edge coloured graphs and digraphs -############################################################################# - -# This function is here rather than graphviz b/c otherwise if D has multiple -# edges we can't reliably get the corresponding graphviz edge from the head and -# tail of the edge from gv. -BindGlobal("DIGRAPHS_ErrorIfNotEdgeColoring", -function(D, colors) - local out, i; - - out := OutNeighbours(D); - if Length(colors) <> Length(out) then - ErrorFormatted("the 2nd argument (edge colors) must have ", - "the same number of entries as the 1st argument ", - "(a digraph) has nodes, expected {} but found {}", - Length(out), - Length(colors)); - fi; - for i in [1 .. Length(colors)] do - if not IsList(colors[i]) then - ErrorFormatted("the 2nd argument (edge colors) must be ", - "a list of lists, found {} in position {}", - TNAM_OBJ(colors[i]), - i); - elif Length(out[i]) <> Length(colors[i]) then - ErrorFormatted("the 2nd argument (edge colors) must have ", - "the same shape as the out neighbours of the 1st ", - "argument (a digraph), in position {} expected ", - "a list of length {} but found list of length {}", - i, - Length(out[i]), - Length(colors[i])); - fi; - Perform(colors[i], ErrorIfNotValidColor); - od; -end); - -BindGlobal("DIGRAPHS_AddEdgesAndColorsNC", -function(D, gv, colors) - local out, e, n, i; - - # This duplicates code in the GraphvizDigraph function because otherwise if D - # has multiple edges we can't reliably get the corresponding graphviz edge - # from the head and tail of the edge from gv. - out := OutNeighbours(D); - for n in DigraphVertices(D) do - for i in [1 .. Length(out[n])] do - if IsGraphvizDigraph(gv) or n > out[n][i] then - e := GraphvizAddEdge(gv, n, out[n][i]); - GraphvizSetAttr(e, "color", colors[n][i]); - fi; - od; - od; - return gv; -end); - -InstallMethod(GraphvizEdgeColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, colors) - local gv; - DIGRAPHS_ErrorIfNotEdgeColoring(D, colors); - gv := GraphvizDigraph(NullDigraph(DigraphNrVertices(D))); - return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors); -end); - -InstallMethod(GraphvizEdgeColoredGraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, colors) - local gv; - if not IsSymmetricDigraph(D) then - ErrorNoReturn("the argument (a digraph) must be symmetric"); - fi; - DIGRAPHS_ErrorIfNotEdgeColoring(D, colors); - gv := GraphvizGraph(NullDigraph(DigraphNrVertices(D))); - return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors); -end); - -############################################################################# -# Vertex and edge coloured graphs and digraphs -############################################################################# - -InstallMethod(GraphvizColoredDigraph, -"for a digraph, list, and list", -[IsDigraph, IsList, IsList], -{D, n_colors, e_colors} -> GraphvizSetNodeColors( - GraphvizEdgeColoredDigraph(D, e_colors), - n_colors)); - -<<<<<<< HEAD - BindGlobal("Splash", - function(arg...) - local str, opt, path, dir, tdir, file, viewer, type, inn, filetype, out, - engine; -======= -InstallMethod(GraphvizColoredGraph, -"for a digraph, list, and list", -[IsDigraph, IsList, IsList], -# IsSymmetricDigraph checked by GraphvizEdgeColoredGraph -{D, n_colors, e_colors} -> GraphvizSetNodeColors( - GraphvizEdgeColoredGraph(D, e_colors), - n_colors)); ->>>>>>> 51b65dbf (Checkout files from mpan322/main) - -############################################################################# -# Vertex labelled graphs and digraphs -############################################################################# - -InstallMethod(GraphvizVertexLabelledDigraph, "for a digraph", -[IsDigraph], -D -> GraphvizSetNodeLabels(GraphvizDigraph(D), DigraphVertexLabels(D))); - -InstallMethod(GraphvizVertexLabelledGraph, "for a digraph", -[IsDigraph], -# symmetry checked in GraphvizGraph -D -> GraphvizSetNodeLabels(GraphvizGraph(D), DigraphVertexLabels(D))); - -############################################################################# -# Partial and preorder digraphs -############################################################################# - -InstallMethod(GraphvizPartialOrderDigraph, "for a partial order digraph", -[IsDigraph], -function(D) - if not IsPartialOrderDigraph(D) then - ErrorNoReturn("the argument (a digraph) must be a partial order"); - fi; - D := DigraphMutableCopyIfMutable(D); - return GraphvizDigraph(DigraphReflexiveTransitiveReduction(D)); -end); - -InstallMethod(GraphvizPreorderDigraph, "for a preorder digraph", -[IsDigraph], -function(D) - local comps, gv, label, node, nodes, c, x, e; - - if not IsPreorderDigraph(D) then - ErrorNoReturn("the argument (a digraph) must be a preorder"); - fi; - - # Quotient by the strongly connected components to get a partial order - # D and draw this without loops or edges implied by transitivity. - comps := DigraphStronglyConnectedComponents(D).comps; - D := DigraphMutableCopy(D); - DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps)); - DigraphReflexiveTransitiveReduction(D); - - gv := GraphvizDigraph("graphname"); - GraphvizSetAttr(gv, "node [shape=\"Mrecord\"]"); - GraphvizSetAttr(gv, "height=\"0.5\""); - GraphvizSetAttr(gv, "fixedsize=\"true\""); - GraphvizSetAttr(gv, "ranksep=\"1\""); - - for c in [1 .. Length(comps)] do - - label := "\""; - Append(label, String(comps[c][1])); - for x in comps[c]{[2 .. Length(comps[c])]} do - Append(label, "|"); - Append(label, String(x)); - od; - Append(label, "\""); - - node := GraphvizAddNode(gv, c); - GraphvizSetAttr(node, "label", label); - GraphvizSetAttr(node, "width", Float(Length(comps[c]) / 2)); - od; - - nodes := GraphvizNodes(gv); - for e in DigraphEdges(D) do - GraphvizAddEdge(gv, nodes[e[1]], nodes[e[2]]); - od; - - return gv; -end); - -############################################################################# -# Highlighted subdigraphs -############################################################################# - -BindGlobal("DIGRAPHS_GraphvizHighlight", -function(D, gv, hi_verts, hi, lo) - local node, color, out, nodes, edge, v, i, j; - - if IsMultiDigraph(D) then - ErrorNoReturn("the 1st argument (a digraph) must not have multiple edges"); - elif not IsSubset(DigraphVertices(D), hi_verts) then - ErrorNoReturn("the 2nd argument (list) must consist of vertices ", - "of the 1st argument (a digraph)"); - fi; - ErrorIfNotValidColor(hi); - ErrorIfNotValidColor(lo); - - GraphvizSetAttr(gv, "shape", "circle"); - - for v in DigraphVertices(D) do - node := GraphvizAddNode(gv, v); - if v in hi_verts then - color := hi; - else - color := lo; - fi; - GraphvizSetAttr(node, "color", color); - od; - - out := OutNeighbours(D); - nodes := GraphvizNodes(gv); - - for i in DigraphVertices(D) do - for j in out[i] do - if IsGraphvizDigraph(gv) or i > j then - edge := GraphvizAddEdge(gv, nodes[i], nodes[j]); - if i in hi_verts and j in hi_verts then - color := hi; - else - color := lo; - fi; - GraphvizSetAttr(edge, "color", color); - fi; - od; - od; - - return gv; -end); - -InstallMethod(GraphvizHighlightedDigraph, -"for a digraph by out-neighbours, list, and two strings", -[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], -{D, hi_verts, hi, lo} -> -DIGRAPHS_GraphvizHighlight(D, GraphvizDigraph(), hi_verts, hi, lo)); - -InstallMethod(GraphvizHighlightedDigraph, "for a digraph and list", -[IsDigraph, IsList], -{D, list} -> GraphvizHighlightedDigraph(D, list, "black", "grey")); - -InstallMethod(GraphvizHighlightedGraph, -"for a digraph by out-neighbours, list, and two strings", -[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], -function(D, hi_verts, hi, lo) - if not IsSymmetricDigraph(D) then - ErrorNoReturn("the argument (a digraph) must be symmetric"); - fi; - return DIGRAPHS_GraphvizHighlight(D, GraphvizGraph(), hi_verts, hi, lo); -end); - -InstallMethod(GraphvizHighlightedGraph, "for a digraph and list", -[IsDigraph, IsList], -# IsSymmetricDigraph checked in GraphvizHighlightedGraph -{D, list} -> GraphvizHighlightedGraph(D, list, "black", "grey")); From da322ae28322786a100679d93d4ed26104660bb0 Mon Sep 17 00:00:00 2001 From: Wilf Wilson Date: Fri, 3 Oct 2025 14:40:17 +0100 Subject: [PATCH 3/3] Remove some files --- .github/workflows/gap.yml | 133 -------------------------------------- doc/main.xml | 27 -------- 2 files changed, 160 deletions(-) delete mode 100644 .github/workflows/gap.yml delete mode 100644 doc/main.xml diff --git a/.github/workflows/gap.yml b/.github/workflows/gap.yml deleted file mode 100644 index 9ec6f1a19..000000000 --- a/.github/workflows/gap.yml +++ /dev/null @@ -1,133 +0,0 @@ -name: "GAP" -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - - stable-*.* - schedule: - # Every day at 3:30 AM UTC - - cron: '30 3 * * *' - -env: - DIGRAPHS_LIB: digraphs-lib-0.6 - -jobs: - test-unix: - name: "${{ matrix.os }}${{ matrix.ABI }} / GAP ${{ matrix.gap-branch }}" - runs-on: "${{ matrix.os }}-latest" - strategy: - fail-fast: false - matrix: - os: - - ubuntu - gap-branch: - - master - - stable-4.11 - - stable-4.12 - - stable-4.13 - ABI: [''] - pkgs-to-clone: - - NautyTracesInterface - - include: - - gap-branch: master - os: macos - pkgs-to-clone: "NautyTracesInterface" - - gap-branch: master - os: ubuntu - ABI: 32 - - steps: - - uses: actions/checkout@v4 - - name: "Install dependencies" - if: ${{ runner.os == 'macOS' }} - run: brew install automake - - name: "Install GAP and clone/compile necessary packages" - uses: gap-actions/setup-gap@v2 - with: - GAP_PKGS_TO_CLONE: "${{ matrix.pkgs-to-clone }} digraphs/graphviz" - GAP_PKGS_TO_BUILD: "io orb profiling grape NautyTracesInterface datastructures" - GAPBRANCH: ${{ matrix.gap-branch }} - ABI: ${{ matrix.ABI }} - - name: "Build Digraphs" - uses: gap-actions/build-pkg@v1 - with: - ABI: ${{ matrix.ABI }} - - name: "Install digraphs-lib" - run: | - curl --retry 5 -L -O "https://digraphs.github.io/Digraphs/${{ env.DIGRAPHS_LIB }}.tar.gz" - tar xf "${{ env.DIGRAPHS_LIB }}.tar.gz" - - name: "Run DigraphsTestInstall" - uses: gap-actions/run-pkg-tests@v2 - with: - GAP_TESTFILE: "tst/github_actions/install.g" - - name: "Run DigraphsTestStandard" - uses: gap-actions/run-pkg-tests@v2 - with: - GAP_TESTFILE: "tst/github_actions/standard.g" - - name: "Run DigraphsTestManualExamples" - uses: gap-actions/run-pkg-tests@v2 - with: - GAP_TESTFILE: "tst/github_actions/examples.g" - - name: "Run DigraphsTestExtreme" - uses: gap-actions/run-pkg-tests@v2 - with: - GAP_TESTFILE: "tst/github_actions/extreme.g" - - uses: gap-actions/process-coverage@v2 - - uses: codecov/codecov-action@v3 - - test-cygwin: - name: "cygwin / GAP master" - runs-on: windows-2019 - env: - CHERE_INVOKING: 1 - steps: - - uses: actions/checkout@v4 - - uses: gap-actions/setup-cygwin@v1 - - uses: gap-actions/setup-gap@cygwin-v2 - with: - GAP_PKGS_TO_BUILD: "io orb profiling grape datastructures" - GAP_PKGS_TO_CLONE: "digraphs/graphviz" - - uses: gap-actions/build-pkg@cygwin-v1 - - name: "Install digraphs-lib" - run: | - curl --retry 5 -L -O "https://digraphs.github.io/Digraphs/${{ env.DIGRAPHS_LIB }}.tar.gz" - tar xf "${{ env.DIGRAPHS_LIB }}.tar.gz" - - uses: gap-actions/run-pkg-tests@cygwin-v2 - - uses: gap-actions/process-coverage@cygwin-v2 - - uses: codecov/codecov-action@v3 - - with-external-planarity-bliss: - runs-on: "ubuntu-latest" - env: - GAPBRANCH: "stable-4.12" - ABI: 64 - PKG_CONFIG_PATH: "/home/runner/micromamba/envs/digraphs/lib/pkgconfig:/home/runner/micromamba/envs/digraphs/share/pkgconfig/" - LD_LIBRARY_PATH: "/home/runner/micromamba/envs/digraphs/lib" - CFLAGS: "-I/home/runner/micromamba/envs/digraphs/include" - LDFLAGS: "-L/home/runner/micromamba/envs/digraphs/lib" - defaults: - run: - shell: bash -l {0} - steps: - - uses: actions/checkout@v4 - - name: "Install micromamba environment from environment.yml . . ." - uses: mamba-org/setup-micromamba@v1 - with: - environment-file: environment.yml - cache-environment: true - - name: "Activate \"digraphs\" environment . . ." - run: micromamba activate digraphs - - name: "Install GAP and clone/compile necessary packages" - uses: gap-actions/setup-gap@v2 - with: - GAP_PKGS_TO_BUILD: "io orb profiling grape datastructures" - GAP_PKGS_TO_CLONE: "digraphs/graphviz" - - name: "Build Digraphs" - uses: gap-actions/build-pkg@v1 - with: - CONFIGFLAGS: --with-external-planarity --with-external-bliss - - name: "Run Digraphs package's tst/teststandard.g" - uses: gap-actions/run-pkg-tests@v2 diff --git a/doc/main.xml b/doc/main.xml deleted file mode 100644 index 61d5d1686..000000000 --- a/doc/main.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - -] -> - -<#Include SYSTEM "title.xml"> - - -<#Include SYSTEM "z-chap0.xml"> -<#Include SYSTEM "z-chap1.xml"> -<#Include SYSTEM "z-chap2.xml"> -<#Include SYSTEM "z-chap3.xml"> -<#Include SYSTEM "z-chap4.xml"> -<#Include SYSTEM "z-chap5.xml"> -<#Include SYSTEM "z-chap6.xml"> -<#Include SYSTEM "z-chap8.xml"> -<#Include SYSTEM "z-chap9.xml"> -<#Include SYSTEM "_AutoDocMainFile.xml"> - -<#Include SYSTEM "z-appA.xml"> - - -