diff --git a/.codespellrc b/.codespellrc index 1816cb1ef..6520d3fde 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,3 +1,3 @@ [codespell] -skip = ./.git,./tmp,./data,./extern,./tst,./bin,./libtool,configure,configure~,./gh-pages,./autom4te.cache,./cnf,aclocal.m4,./m4,./doc/*.log,./doc/*.html,./doc/*.txt,./doc/*.six,./doc/*.js,./doc/*.bbl,./doc/*.tex,./doc/*.bib +skip = ./.git,./tmp,./data,./extern,./tst,./bin,./libtool,configure,configure~,./gh-pages,./autom4te.cache,./cnf,aclocal.m4,./m4,./doc/*.log,./doc/*.html,./doc/*.txt,./doc/*.six,./doc/*.js,./doc/*.bbl,./doc/*.tex,./doc/*.bib,./digraphs-lib/* ignore-words-list=ist,manuel,MIS,mis 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 977a2f72d..cb4de63c8 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -10,12 +10,13 @@ ## <#GAPDoc Label="PKGVERSIONDATA"> ## -## +## ## ## ## ## ## +## ## ## ## <#/GAPDoc> @@ -387,9 +388,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 index 95ee02d6b..e5c287f5a 100644 --- a/doc/main.xml +++ b/doc/main.xml @@ -3,10 +3,13 @@ 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"> 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 new file mode 100755 index 000000000..e50ea5a89 --- /dev/null +++ b/etc/code-coverage-test-gap.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +""" +This is a simple script to run code coverage for some test files. +""" +# pylint: disable=invalid-name + +import argparse +import os +import re +import subprocess +import sys +import tempfile + +from os.path import exists, isdir, isfile +from os import getcwd + +_ERR_PREFIX = "\033[31mcode-coverage-test-gap.py: error: " +_INFO_PREFIX = "\033[0m\033[1m" + +_PARSER = argparse.ArgumentParser( + prog="code-coverage-test-gap.py", usage="%(prog)s [options]" +) +_PARSER.add_argument( + "tstfiles", + 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( + "--open", + nargs="?", + type=str, + help=("open the html page for this file (default: None)"), + default=None, +) + +_ARGS = _PARSER.parse_args() +if not _ARGS.gap_root[-1] == "/": + _ARGS.gap_root += "/" + +if exists("gap") and isdir("gap"): + _PROFILE_DIR = "/gap/" +elif exists("lib") and isdir("lib"): + _PROFILE_DIR = "/lib/" +else: + sys.exit(f"{_ERR_PREFIX}no directory gap or lib to profile!\033[0m") + +_ARGS.gap_root = os.path.expanduser(_ARGS.gap_root) +if not (exists(_ARGS.gap_root) and isdir(_ARGS.gap_root)): + sys.exit(f"{_ERR_PREFIX}can't find GAP root directory!\033[0m") + +for f in _ARGS.tstfiles: + if not (exists(f) and isfile(f)): + sys.exit(f"{_ERR_PREFIX}{f} does not exist!\033[0m") + +_DIR = tempfile.mkdtemp() +print(f"{_INFO_PREFIX}Using temporary directory: {_DIR}\033[0m") + +_COMMANDS = 'echo "' +_COMMANDS += "".join(rf"Test(\"{f}\");;\n" for f in _ARGS.tstfiles) +_COMMANDS += rf"""UncoverageLineByLine();; +LoadPackage(\"profiling\", false);; +filesdir := \"{getcwd()}{_PROFILE_DIR}\";;\n""" + +_COMMANDS += rf"outdir := \"{_DIR}\";;\n" +_COMMANDS += rf"x := ReadLineByLineProfile(\"{_DIR}/profile.gz\");;\n" +_COMMANDS += 'OutputAnnotatedCodeCoverageFiles(x, filesdir, outdir);"' + +_RUN_GAP = f"{_ARGS.gap_root}/gap -A -m 1g -T --cover {_DIR}/profile.gz" + +with subprocess.Popen(_COMMANDS, stdout=subprocess.PIPE, shell=True) as pro1: + try: + with subprocess.Popen(_RUN_GAP, stdin=pro1.stdout, shell=True) as pro2: + pro2.wait() + except KeyboardInterrupt: + pro1.terminate() + pro1.wait() + sys.exit("\033[31mKilled!\033[0m") + except (subprocess.CalledProcessError, IOError, OSError): + sys.exit(_ERR_PREFIX + "Something went wrong calling GAP!\033[0m") + + +def rewrite_fname(fname: str) -> str: + return fname.replace("/", "_") + + +suffix = "" +if _ARGS.open: + filename = f"{_DIR}/{rewrite_fname(getcwd())}/{rewrite_fname(_ARGS.open)}.html" + p = re.compile(r"") + with open(filename, "r", encoding="utf-8") as f: + m = p.search(f.read()) + if m: + suffix += "#line" + m.group(1) +else: + filename = _DIR + "/index.html" +print(f"{_INFO_PREFIX}\nSUCCESS!\033[0m") +print(f"{_INFO_PREFIX} See {filename}") +sys.exit(0) 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 f55429169..fe7acd3eb 100644 --- a/gap/display.gi +++ b/gap/display.gi @@ -1,515 +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; - if x = (l - 1) then - return true; - else - return false; - fi; -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; - - # file - file := "vizpicture"; # default - if IsBound(opt.filename) then - file := opt.filename; - fi; +############################################################################# +# Vertex and edge coloured graphs and digraphs +############################################################################# - # 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; +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)); - # 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 beae97a2f..261f3369d 100644 --- a/init.g +++ b/init.g @@ -63,5 +63,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 3dfbecb7e..f374567f4 100644 --- a/read.g +++ b/read.g @@ -41,3 +41,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 index 76b7ef493..0b30d3e74 100644 --- a/tst/standard/display.tst +++ b/tst/standard/display.tst @@ -1,7 +1,7 @@ ############################################################################# ## #W standard/display.tst -#Y Copyright (C) 2014-15 James D. Mitchell +#Y Copyright (C) 2014-24 James D. Mitchell ## ## Licensing information can be found in the README file of this package. ## @@ -34,8 +34,8 @@ gap> PrintString(gr); "DigraphFromDigraph6String(\"&CQ?G\")" gap> String(gr); "DigraphFromDigraph6String(\"&CQ?G\")" -gap> r := rec(DigraphVertices := [1, 2, 3], -> DigraphSource := [1, 2], +gap> r := rec(DigraphVertices := [1, 2, 3], +> DigraphSource := [1, 2], > DigraphRange := [2, 3]);; gap> gr := Digraph(r); @@ -51,9 +51,9 @@ gap> gr := Digraph(r); gap> dot := DotDigraph(gr);; gap> dot{[1 .. 50]}; -"//dot\ndigraph hgn{\nnode [shape=circle]\n1\n2\n3\n1 -> " +"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3" gap> dot{[51 .. 75]}; -"1\n1 -> 2\n1 -> 2\n1 -> 3\n}\n" +"\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], @@ -62,41 +62,44 @@ gap> r := rec(DigraphVertices := [1 .. 8], gap> gr1 := Digraph(r); gap> DotDigraph(gr1){[50 .. 109]}; -"6\n7\n8\n1 -> 6\n1 -> 7\n2 -> 1\n2 -> 6\n3 -> 5\n4 -> 1\n4 -> 4\n4 -> " +"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{\nnode [shape=circle]\n1\n2\n3\n4\n1 -> 2\n2 -> 1\n2 -> 3\n3 -> 2\n" +"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{\nnode [shape=circle]\n\n1\n2\n3\n4\n1 -- 2\n2 -- 3\n3 -- 3\n3 -" +" 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 must be a symmetric digraph, +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[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[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[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][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; gap> edgecolors[4][3] := "purple";; gap> DotColoredDigraph(D, vertcolors, edgecolors){[1 .. 30]}; -"//dot\ndigraph hgn{\nnode [shape" +"//dot\ndigraph hgn {\n\tnode [sha" gap> D := Digraph([[2], [1, 3], [2]]); gap> vertcolors := [];; @@ -110,9 +113,9 @@ 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{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=pink, style=filled]\n3[color=purple, style=filled]\n1 -- 2[color=green]\n2 -\ -- 3[color=red]\n}\n" +"//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 := [];; @@ -125,10 +128,10 @@ 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{\nnode [shape=circle]\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n1 -> 2[color=orange]\n1 ->\ - 3[color=yellow]\n2 -> 1[color=orange]\n2 -> 3[color=pink]\n3 -> 1[color=yello\ -w]\n}\n" +"//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 := [];; @@ -145,203 +148,195 @@ gap> D; gap> D := Digraph([[2, 4], [1, 3], [2], [1]]); -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] := "orange";; edgecolors[1][2] := "orange";; -gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "orange";; -gap> edgecolors[3][1] := "orange";; edgecolors[4][1] := "orange";; +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); -"//dot\ngraph hgn{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n4[color=yellow, style=fill\ -ed]\n1 -- 2[color=orange]\n1 -- 4[color=orange]\n2 -- 3[color=orange]\n}\n" +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 := [];; -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] := "orange";; edgecolors[1][2] := "orange";; -gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "orange";; -gap> edgecolors[3][1] := "orange";; edgecolors[4][1] := "orange";; +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); -"//dot\ngraph hgn{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n4[color=yellow, style=fill\ -ed]\n1 -- 2[color=orange]\n1 -- 4[color=orange]\n2 -- 3[color=orange]\n}\n" +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 := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "banana";; -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){[5 .. 35]}; -Error, expected RGB Value or valid color name as defined by GraphViz 2.44.1 X1\ -1 Color Scheme http://graphviz.org/doc/info/colors.html -gap> D := CompleteDigraph(4); - -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; -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> 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 vertex colors must be the same as the number of vertices,\ - expected 4 but found 3 +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 := [];; -gap> vertcolors[1] := 2;; vertcolors[2] := 1;; -gap> vertcolors[3] := 1;; vertcolors[4] := 3;; -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> 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, expected a string +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 := [];; -gap> vertcolors[1] := "#AB3487";; vertcolors[2] := "#DF4738";; -gap> vertcolors[3] := "#4BF234";; vertcolors[4] := "#AF34C9";; -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); -"//dot\ndigraph hgn{\nnode [shape=circle]\n1[color=#AB3487, style=filled]\n2[c\ -olor=#DF4738, style=filled]\n3[color=#4BF234, style=filled]\n4[color=#AF34C9, \ -style=filled]\n1 -> 2[color=lightblue]\n1 -> 3[color=pink]\n1 -> 4[color=purpl\ -e]\n2 -> 1[color=lightblue]\n2 -> 3[color=pink]\n2 -> 4[color=purple]\n3 -> 1[\ -color=lightblue]\n3 -> 2[color=pink]\n3 -> 4[color=purple]\n4 -> 1[color=light\ -blue]\n4 -> 2[color=pink]\n4 -> 3[color=purple]\n}\n" +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[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[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[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][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, expected RGB Value or valid color name as defined by GraphViz 2.44.1 X1\ -1 Color Scheme http://graphviz.org/doc/info/colors.html +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[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[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[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][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") gap> DotColoredDigraph(D, vertcolors, edgecolors); -Error, the list of edge colors needs to have the same shape as the out-neighbo\ -urs of the digraph +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[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 +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); @@ -349,44 +344,61 @@ gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; +gap> edgecolors[1] := [];; edgecolors[2] := [];; gap> edgecolors[3] := [];; gap> DotVertexColoredDigraph(D, vertcolors); -"//dot\ndigraph hgn{\nnode [shape=circle]\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n}\n" +"//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[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[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][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; gap> edgecolors[4][3] := "purple";; gap> DotEdgeColoredDigraph(D, edgecolors); -"//dot\ndigraph hgn{\nnode [shape=circle]\n1\n2\n3\n4\n1 -> 2[color=lightblue]\ -\n1 -> 3[color=pink]\n1 -> 4[color=purple]\n2 -> 1[color=lightblue]\n2 -> 3[co\ -lor=pink]\n2 -> 4[color=purple]\n3 -> 1[color=lightblue]\n3 -> 2[color=pink]\n\ -3 -> 4[color=purple]\n4 -> 1[color=lightblue]\n4 -> 2[color=pink]\n4 -> 3[colo\ -r=purple]\n}\n" +"//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 list of edge colors needs to have the same shape as the out-neighbo\ -urs of the digraph +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 list of edge colors needs to have the same shape as the out-neighbo\ -urs of the digraph +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, expected a string +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]]); @@ -396,8 +408,9 @@ gap> vertcolors[1] := "blue";; gap> vertcolors[2] := "pink";; gap> vertcolors[3] := "purple";; gap> DotSymmetricVertexColoredDigraph(D, vertcolors); -"//dot\ngraph hgn{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=pink, style=filled]\n3[color=purple, style=filled]\n1 -- 2\n2 -- 3\n}\n" +"//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]]); @@ -408,8 +421,8 @@ 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{\nnode [shape=circle]\n\n1\n2\n3\n1 -- 2[color=green]\n2 -- \ -3[color=red]\n}\n" +"//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], @@ -418,17 +431,17 @@ gap> gr := Digraph(r); gap> dot := DotVertexLabelledDigraph(gr);; gap> dot; -"//dot\ndigraph hgn{\nnode [shape=circle]\n1 [label=\"1\"]\n2 [label=\"2\"]\n3\ - [label=\"3\"]\n1 -> 1\n1 -> 2\n1 -> 2\n1 -> 3\n}\n" +"//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{\nnode [shape=circle]\n1 [label=\"2\"]\n2 [label=\"2\"]\n3\ - [label=\"3\"]\n1 -> 1\n1 -> 2\n1 -> 2\n1 -> 3\n}\n" +"//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 +# Splash gap> Splash(1); -Error, the 1st argument must be a string, +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"); @@ -438,7 +451,7 @@ 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, +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" @@ -469,83 +482,84 @@ 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 +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 +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 must be a partial order digraph, +Error, the argument (a digraph) must be a partial order # DotPreorderDigraph and DotQuasiorderDigraph gap> DotPreorderDigraph(CompleteDigraph(5)); -Error, the argument must be a preorder digraph, +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 + 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; -1 [label= + node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1" + gap> gr := DigraphDisjointUnion(CompleteDigraph(10), > CompleteDigraph(5), > CycleDigraph(2));; @@ -555,83 +569,118 @@ 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 + 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 hgn{ -subgraph lowverts{ -node [shape=circle, color=black] - edge [color=black] -3 -} -subgraph highverts{ -node [shape=circle, color=red] - edge [color=red] -1 -2 -} -subgraph lowverts{ -3 -> 1 -3 -> 3 -} -subgraph highverts{ -1 -> 2 -1 -> 3 [color=black] -2 -> 2 -} +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 must be a list of vertices of the 1st argu\ -ment , +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, the 3rd argument must be a string containing the name of a\ - colour, +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, the 4th argument must be a string containing the name of a \ -colour, +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 hgn{ -subgraph lowverts{ -node [shape=circle, color=grey] - edge [color=grey] -1 -3 -5 -} -subgraph highverts{ -node [shape=circle, color=black] - edge [color=black] -2 -4 -} -subgraph lowverts{ -1 -> 2 -3 -> 4 -5 -> 1 -} -subgraph highverts{ -2 -> 3 [color=grey] -4 -> 5 [color=grey] -} +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, +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\ -, +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);