diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml
index f487b0287..1f4bf16e6 100644
--- a/.github/workflows/manual.yml
+++ b/.github/workflows/manual.yml
@@ -38,7 +38,14 @@ jobs:
- uses: gap-actions/setup-gap@v3
with:
gap-version: latest
+ - name: Build GraphvizForGAP manual . . .
+ run: |
+ git clone https://github.com/digraphs/graphviz.git "${GAPROOT}/pkg/graphviz"
+ cd "${GAPROOT}/pkg/graphviz"
+ NOPDF=1 $GAP makedoc.g
- uses: gap-actions/build-pkg-docs@v2
+ with:
+ use-latex: true
- name: Upload compiled manuals . . .
uses: actions/upload-artifact@v7
with:
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index 5cce2c273..f0d4dd244 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -41,11 +41,6 @@ jobs:
pkgs-to-clone: https://github.com/digraphs/graphviz.git https://github.com/gap-packages/NautyTracesInterface.git
pkgs-to-build: io orb datastructures profiling grape NautyTracesInterface
- - gap-version: v4.11 # Note: NautyTracesInterface requires GAP 4.12
- mode: default # There wouldn't be much point testing GAP v4.11 with only needed packages. The only difference is whether Grape is loaded.
- pkgs-to-clone: https://github.com/digraphs/graphviz.git
- pkgs-to-build: io* orb* datastructures* profiling* grape*
-
steps:
- uses: actions/checkout@v7
- name: Output g++ version . . .
diff --git a/PackageInfo.g b/PackageInfo.g
index fc2385239..0f4be548b 100644
--- a/PackageInfo.g
+++ b/PackageInfo.g
@@ -568,9 +568,10 @@ PackageDoc := rec(
),
Dependencies := rec(
- GAP := ">=4.11.0",
+ GAP := ">=4.12.0",
NeededOtherPackages := [["IO", ">=4.5.1"],
["orb", ">=4.8.2"],
+ ["GraphvizForGAP", ">=0.0.0"],
["datastructures", ">=0.2.5"]],
SuggestedOtherPackages := [["GAPDoc", ">=1.6.3"],
["GRAPE", ">=4.8.1"],
diff --git a/README.md b/README.md
index ac6707a7b..21fdbab41 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ For questions, remarks, suggestions, and issues please use the
## Installation
It is assumed that you have a working copy of [GAP][] with version number
-4.11.0 or higher. The most up-to-date version of GAP, and instructions on how
+4.12.0 or higher. The most up-to-date version of GAP, and instructions on how
to install it, can be obtained from the
[main GAP webpage](https://www.gap-system.org).
diff --git a/doc/display.xml b/doc/display.xml
index df8da62f4..26d16200d 100644
--- a/doc/display.xml
+++ b/doc/display.xml
@@ -1,414 +1,334 @@
#############################################################################
##
#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:
+
+
+
+
+ They return the strings
+ AsString(GraphvizDigraph(D)) and
+ AsString(GraphvizGraph(D)), respectively.
+ DotSymmetricDigraph requires D to be symmetric.
+
+
+<#/GAPDoc>
-<#GAPDoc Label="Splash">
+<#GAPDoc Label="GraphvizDigraph">
-
- Nothing.
+
+
+ A &GRAPHVIZFORGAP; 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 &GRAPHVIZFORGAP;
+ 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.
+ GraphvizGraph requires D to be symmetric; see
+ .
+
+
+ To display the result, use
+ . Its documentation
+ describes the optional record controlling the output directory,
+ filename, viewer, rendering engine, and file type.
+ Splash(GraphvizDigraph(D));
+]]>
+ To write the Graphviz source to a file, use
+ FileString("digraph.dot", AsString(GraphvizDigraph(D)));
+ see .
+
- 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.
+ 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>
+
+<#GAPDoc Label="GraphvizColoredDigraph">
+
+
+
+
+
+
+
+ A &GRAPHVIZFORGAP; object.
+
+ These operations produce colored &GRAPHVIZFORGAP; objects representing
+ the digraph D according to the specified colors. The variants ending
+ in Graph require D to be symmetric.
+ 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
+
+
- This function is provided to allow convenient, immediate viewing of the
- pictures produced by the function .
+ GraphvizVertexColoredDigraph and GraphvizVertexColoredGraph
+ require their argument colors to be a list of length equal to the
+ number of vertices of D consisting of strings representing colors
+ as described above.
+
- The optional second argument opts should be a record with
- components corresponding to various options, given below.
+ GraphvizEdgeColoredDigraph and GraphvizEdgeColoredGraph
+ require their 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 require
+ their arguments:
- 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.
-
+ vert_colors
+ -
+ to represent vertex colors as described for
+ GraphvizVertexColoredDigraph;
+
+ edge_colors
+ -
+ to represent edge colors as described for
+ GraphvizEdgeColoredDigraph;
+
- This function was written by Attila Egri-Nagy and Manuel Delgado with some
- minor changes by J. D. Mitchell.
- Splash(DotDigraph(RandomDigraph(4)));
-]]>
+ See the &GRAPHVIZFORGAP; package documentation for more details.
+
+
+ See also
+ D := Digraph([[2], [1, 3], [2]]);
+
+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 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.
-
- DotColoredEdgeLabelledDigraph differs from DotColoredDigraph
- only in that the values given in the third list labels is used to
- label the edges of the graph when displayed. The list labels should
- be a list of equal length to the lists for vertex and edge colours. 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 .
-
- See also .
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of the following operations, respectively:
+
+
+
+
+
+
+
+
+ Each takes the same arguments as its replacement and returns
+ AsString applied to the resulting &GRAPHVIZFORGAP; object.
+ For example,
+ DotColoredDigraph(D, vert_colors, edge_colors) returns
+ AsString(GraphvizColoredDigraph(D, vert_colors, edge_colors)).
+ The DotSymmetric variants require D to be symmetric.
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="GraphvizVertexLabelledDigraph">
+
+
+
+ A &GRAPHVIZFORGAP; object.
+
+ These operations produce the same pictures as
+ and ,
+ respectively, using to label the
+ vertices instead of their numbers. Labels are converted to strings.
+ GraphvizVertexLabelledGraph requires D to be symmetric.
+
+
+ Use to set the vertex labels.
+ The resulting object can be displayed using
+ .
D := CompleteDigraph(4);
-
-gap> vertcolors := ["blue", "green", "red", "yellow"];;
-gap> Print(DotVertexLabelledDigraph(D));
-//dot
-digraph hgn{
-node [shape=circle]
-1 [label="1"]
-2 [label="2"]
-3 [label="3"]
-4 [label="4"]
-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> Print(DotVertexColoredDigraph(D, vertcolors));
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=blue, style=filled]
-2[color=green, style=filled]
-3[color=red, 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> colors := ["lightblue", "pink", "purple"];;
-gap> edgecolors := ListWithIdenticalEntries(4, colors);;
-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> Print(DotColoredDigraph(D, vertcolors, edgecolors));
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=blue, style=filled]
-2[color=green, style=filled]
-3[color=red, 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> FileString("k4.dot", DotDigraph(D));
-133
-gap> D := Digraph([[2, 3], [1, 3], [1]]);
-
-gap> vertcolors := ["blue", "red", "green"];;
-gap> edgecolors := [["orange", "yellow"], ["orange",
-> "pink"], ["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> FileString("digraph.dot", DotDigraph(D));
-82]]>
+gap> D := Digraph([[2], [1]]);;
+gap> SetDigraphVertexLabels(D, ["left", "right"]);
+gap> GraphvizVertexLabelledDigraph(D);
+
+gap> GraphvizVertexLabelledGraph(D);
+
+]]>
- <#/GAPDoc>
+<#/GAPDoc>
-<#GAPDoc Label="DotSymmetricDigraph">
+<#GAPDoc Label="DotVertexLabelledDigraph">
-
-
-
-
+
A string.
- 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 .
+ WARNING! As of v2.0.0 of &Digraphs; this function is
+ deprecated in favour of:
+
+
+
+ It returns
+ AsString(GraphvizVertexLabelledDigraph(D)), using
+ as the vertex labels.
+
+
+<#/GAPDoc>
+<#GAPDoc Label="GraphvizColoredEdgeLabelledDigraph">
+
+
+ A &GRAPHVIZFORGAP; object.
+
+ This operation produces the same picture as
+ , with labels on the edges.
+ The arguments vert_colors and edge_colors specify colors
+ as described there. The argument labels must be a list of lists
+ with the same shape as OutNeighbours(D):
+ labels[i][j] labels the edge from vertex i to
+ OutNeighbours(D)[i][j].
+
+
+ See also for displaying edge
+ weights and highlighting a path.
D := Digraph([[2], [1, 3], [2]]);
-
-gap> IsSymmetricDigraph(D);
-true
-gap> vertcolors := ["blue", "pink", "purple"];;
-gap> edgecolors := [["green"], ["green", "red"], ["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> 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
-}
-
-gap> Print(DotSymmetricEdgeColoredDigraph(D, edgecolors));
-//dot
-graph hgn{
-node [shape=circle]
-
-1
-2
-3
-1 -- 2[color=green]
-2 -- 3[color=red]
-}
+gap> D := Digraph([[2], [3], []]);;
+gap> vert_colors := ["blue", "red", "green"];;
+gap> edge_colors := [["black"], ["black"], []];;
+gap> labels := [[5], [7], []];;
+gap> GraphvizColoredEdgeLabelledDigraph(D, vert_colors,
+> edge_colors, labels);
+
]]>
<#/GAPDoc>
+<#GAPDoc Label="DotColoredEdgeLabelledDigraph">
+
+
+ A string.
+
+ WARNING! As of v2.0.0 of &Digraphs; this function is
+ deprecated in favour of:
+
+
+
+ It takes the same arguments and returns
+ AsString(GraphvizColoredEdgeLabelledDigraph(D, vert_colors,
+ edge_colors, labels)). In particular, both edge_colors and
+ labels have the same shape as OutNeighbours(D).
+
+
+<#/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 .
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+
+
+
+ It returns
+ AsString(GraphvizPartialOrderDigraph(digraph)).
+
+
+<#/GAPDoc>
- Since digraph is a partial order, it is both reflexive and
- transitive. The output of DotPartialOrderDigraph is the
- of the
- of digraph.
+<#GAPDoc Label="GraphvizPartialOrderDigraph">
+
+
+ A &GRAPHVIZFORGAP; object.
+
+ This function produces a &GRAPHVIZFORGAP; object representing a partial
+ order digraph D. GraphvizPartialOrderDigraph will return an
+ error if D is not a partial order digraph. See .
- 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.
+ Since D is a partial order, it is both reflexive and
+ transitive. The output of GraphvizPartialOrderDigraph is the
+ of the
+ of D.
- The string returned by DotPartialOrderDigraph can be written to a
- file using the command .
+ See the &GRAPHVIZFORGAP; package documentation for more details.
+
+ See also
poset := Digraph([[1, 4], [2], [2, 3, 4], [4]]);
+gap> D := Digraph([[1, 4], [2], [2, 3, 4], [4]]);
-gap> IsPartialOrderDigraph(poset);
+gap> IsPartialOrderDigraph(D);
true
-gap> FileString("poset.dot", DotPartialOrderDigraph(poset));
-70]]>
+gap> GraphvizPartialOrderDigraph(D);
+]]>
<#/GAPDoc>
@@ -419,67 +339,192 @@ gap> FileString("poset.dot", DotPartialOrderDigraph(poset));
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:
+ ]
+
+
+
+ They return
+ AsString(GraphvizPreorderDigraph(digraph)).
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="GraphvizPreorderDigraph">
+
+
+
+ A &GRAPHVIZFORGAP; object.
+
+ These functions produce &GRAPHVIZFORGAP; objects representing a preorder
+ digraph D. These functions 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 &GRAPHVIZFORGAP; 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],
+gap> D := Digraph([[1, 2, 4, 5], [1, 2, 4, 5], [3, 4], [4],
> [1, 2, 4, 5]]);
-gap> IsPreorderDigraph(preset);
+gap> IsPreorderDigraph(D);
true
-gap> FileString("preset.dot", DotPreorderDigraph(preset));
-179]]>
+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.
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+
+
+
+
+ It takes the same arguments as GraphvizHighlightedDigraph
+ and returns AsString applied to the resulting &GRAPHVIZFORGAP;
+ object. The default colors are "black" and "grey".
+
+
+<#/GAPDoc>
- Note that DotHighlightedDigraph does not validate the colours
- colour1 and colour2 - consult the GraphViz documentation to
- see what is available.
+<#GAPDoc Label="GraphvizHighlightedDigraph">
+
+
+
+ A &GRAPHVIZFORGAP; object.
+
+ These functions produce &GRAPHVIZFORGAP; 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 for more details on the output.
+ See and
+ for more details on the output.
digraph := Digraph([[2, 3], [2], [1, 3]]);
+gap> D := Digraph([[2, 3], [2], [1, 3]]);
-gap> FileString("my_digraph.dot", DotHighlightedDigraph(digraph,
-> [1, 2], "red", "black"));
-264]]>
+gap> GraphvizHighlightedDigraph(D, [1, 2], "red", "black");
+
+gap> D := DigraphSymmetricClosure(D);
+
+gap> GraphvizHighlightedGraph(D, [1, 2], "red", "black");
+]]>
<#/GAPDoc>
+
+<#GAPDoc Label="GraphvizEdgeWeightedDigraph">
+
+
+ A string.
+
+ These operations produces &GRAPHVIZFORGAP; objects representing the
+ edge-weighted digraph digraph, in dot format. Its output will
+ be similar to that of , but the diagram will
+ also show the weights of the digraph's edges.
+
+ If the optional argument path is specified, it should be a list of
+ lists describing a path in digraph, in the format described in . If specified, the path's edges will be highlighted in
+ the diagram, as will its start and end vertices.
+
+ If the optional argument colors is specified, it should be a record
+ containing any of the following components:
+
+
+ -
+ vert: the colour of ordinary vertices (default "grey");
+
+ -
+ edge: the colour of ordinary edges (default "black");
+
+ -
+ highlight: the colour of any edges on path, if any
+ (default "blue");
+
+ -
+ source: the colour of the first vertex in path, if any
+ (default "yellowgreen");
+
+ -
+ dest: the colour of the final vertex in path, if any
+ (default "lightpink").
+
+
+
+ Each value in the record should be a string representing a colour
+ understood by the GraphViz software. For details about this format,
+ see https://www.graphviz.org. If any of the above components are
+ not specified, or if no colors argument is given, the default value
+ will be used.
+
+ The output of this operation can be passed to
+ to
+ attempt to display it graphically on the computer's screen.
+
+ gr := EdgeWeightedDigraph([[2], [3], []], [[10], [15], []]);;
+gap> path := EdgeWeightedDigraphShortestPath(gr, 2, 3);
+[ [ 2, 3 ], [ 1 ] ]
+gap> Print(AsString(GraphvizEdgeWeightedDigraph(gr, path)));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1 [color=gray, style=filled]
+ 2 [color=yellowgreen, style=filled]
+ 3 [color=lightpink, style=filled]
+ 1 -> 2 [color=black, label=10]
+ 2 -> 3 [color=blue, label=15]
+}
+]]>
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="DotEdgeWeightedDigraph">
+
+
+ A string.
+
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+
+ .
+
+
+ DotEdgeWeightedDigraph takes the same arguments as GraphvizHighlightedDigraph
+ and returns AsString applied to the resulting &GRAPHVIZFORGAP;
+ object.
+
+
+<#/GAPDoc>
diff --git a/doc/weights.xml b/doc/weights.xml
index cc569a088..b42c261cb 100644
--- a/doc/weights.xml
+++ b/doc/weights.xml
@@ -365,69 +365,3 @@ gap> RandomUniqueEdgeWeightedDigraph(IsEulerianDigraph, 5, 1 / 3);
<#/GAPDoc>
-<#GAPDoc Label="DotEdgeWeightedDigraph">
-
-
- A string.
-
- This operation produces a graphical representation of the edge-weighted
- digraph digraph, in dot format. Its output will be similar to
- that of , but the diagram will also show the weights
- of the digraph's edges.
-
- If the optional argument path is specified, it should be a list of
- lists describing a path in digraph, in the format described in . If specified, the path's edges will be highlighted in
- the diagram, as will its start and end vertices.
-
- If the optional argument colors is specified, it should be a record
- containing any of the following components:
-
-
- -
- vert: the colour of ordinary vertices (default "grey");
-
- -
- edge: the colour of ordinary edges (default "black");
-
- -
- highlight: the colour of any edges on path, if any
- (default "blue");
-
- -
- source: the colour of the first vertex in path, if any
- (default "yellowgreen");
-
- -
- dest: the colour of the final vertex in path, if any
- (default "lightpink").
-
-
-
- Each value in the record should be a string representing a colour understood
- by the GraphViz software. For details about this format, see
- https://www.graphviz.org. If any of the above components are not
- specified, or if no colors argument is given, the default value will
- be used.
-
- The output of this operation can be passed to to
- attempt to display it graphically on the computer's screen.
-
- gr := EdgeWeightedDigraph([[2], [3], []], [[10], [15], []]);
-
-gap> path := EdgeWeightedDigraphShortestPath(g, 2, 3);
-[ [ 2, 3 ], [ 1 ] ]
-gap> Print(DotEdgeWeightedDigraph(gr, path));
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=gray, style=filled]
-2[color=yellowgreen, style=filled]
-3[color=lightpink, style=filled]
-1 -> 2[color=black, label=10]
-2 -> 3[color=blue, label=15]
-}]]>
-
-
-<#/GAPDoc>
diff --git a/doc/z-chap5.xml b/doc/z-chap5.xml
index 491deb4c8..b97a694b3 100644
--- a/doc/z-chap5.xml
+++ b/doc/z-chap5.xml
@@ -35,7 +35,6 @@
<#Include Label="DigraphMinimumCut">
<#Include Label="DigraphMinimumCutSet">
<#Include Label="RandomUniqueEdgeWeightedDigraph">
- <#Include Label="DotEdgeWeightedDigraph">
Orders
diff --git a/doc/z-chap9.xml b/doc/z-chap9.xml
index a3599c40a..682fd0c04 100644
--- a/doc/z-chap9.xml
+++ b/doc/z-chap9.xml
@@ -1,12 +1,29 @@
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="GraphvizColoredEdgeLabelledDigraph">
+ <#Include Label="DotColoredEdgeLabelledDigraph">
+
+ <#Include Label="GraphvizPartialOrderDigraph">
<#Include Label="DotPartialOrderDigraph">
+
+ <#Include Label="GraphvizPreorderDigraph">
<#Include Label="DotPreorderDigraph">
+
+ <#Include Label="GraphvizHighlightedDigraph">
<#Include Label="DotHighlightedDigraph">
+
+ <#Include Label="GraphvizEdgeWeightedDigraph">
+ <#Include Label="DotEdgeWeightedDigraph">
Reading and writing digraphs to a file
diff --git a/etc/code-coverage-test-gap.py b/etc/code-coverage-test-gap.py
index f52bbdf31..11c6e5666 100755
--- a/etc/code-coverage-test-gap.py
+++ b/etc/code-coverage-test-gap.py
@@ -71,7 +71,7 @@
_GAP_COMMANDS.extend(
[
"UncoverageLineByLine();;",
- rf"LoadPackage(\"profiling\", false);;",
+ r"LoadPackage(\"profiling\", false);;",
rf"filesdir := \"{getcwd()}{_PROFILE_DIR}\";;",
rf"outdir := \"{_DIR}\";;",
rf"x := ReadLineByLineProfile(\"{_DIR}/profile.gz\");;",
diff --git a/gap/deprecated.gd b/gap/deprecated.gd
new file mode 100644
index 000000000..2e2e3e6f2
--- /dev/null
+++ b/gap/deprecated.gd
@@ -0,0 +1,43 @@
+#############################################################################
+##
+## 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]);
+
+DeclareOperation("DotColoredEdgeLabelledDigraph",
+ [IsDigraph, IsList, IsList, IsList]);
+
+DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph]);
+DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsList]);
+DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsRecord]);
+DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsList, IsRecord]);
diff --git a/gap/deprecated.gi b/gap/deprecated.gi
new file mode 100644
index 000000000..f344b127e
--- /dev/null
+++ b/gap/deprecated.gi
@@ -0,0 +1,162 @@
+#############################################################################
+##
+## 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, String)), "` 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);
+
+InstallMethod(DotColoredEdgeLabelledDigraph,
+"for a digraph by out-neighbours and three lists",
+[IsDigraphByOutNeighboursRep, IsList, IsList, IsList],
+function(D, vert, edge, weight)
+ _PrintDeprecated("DotColoredEdgeLabelledDigraph",
+ "GraphvizColoredEdgeLabelledDigraph");
+ return AsString(GraphvizColoredEdgeLabelledDigraph(D, vert, edge, weight));
+end);
+
+#############################################################################
+# Weighted digraphs
+#############################################################################
+
+InstallMethod(DotEdgeWeightedDigraph, "for a digraph",
+[IsDigraph],
+function(digraph)
+ _PrintDeprecated("DotEdgeWeightedDigraph",
+ "GraphvizEdgeWeightedDigraph");
+ return AsString(GraphvizEdgeWeightedDigraph(digraph));
+end);
+
+InstallMethod(DotEdgeWeightedDigraph, "for a digraph and a list",
+[IsDigraph, IsList],
+function(digraph, path)
+ _PrintDeprecated("DotEdgeWeightedDigraph",
+ "GraphvizEdgeWeightedDigraph");
+ return AsString(GraphvizEdgeWeightedDigraph(digraph, path));
+end);
+
+InstallMethod(DotEdgeWeightedDigraph, "for a digraph and a record",
+[IsDigraph, IsRecord],
+function(digraph, colors)
+ _PrintDeprecated("DotEdgeWeightedDigraph",
+ "GraphvizEdgeWeightedDigraph");
+ return AsString(GraphvizEdgeWeightedDigraph(digraph, colors));
+end);
+
+InstallMethod(DotEdgeWeightedDigraph, "for a digraph, a list, and a record",
+[IsDigraph, IsList, IsRecord],
+function(digraph, path, colors)
+ _PrintDeprecated("DotEdgeWeightedDigraph",
+ "GraphvizEdgeWeightedDigraph");
+ return AsString(GraphvizEdgeWeightedDigraph(
+ digraph, path, colors));
+end);
diff --git a/gap/display.gd b/gap/display.gd
index 5e0f381e5..d904d9e65 100644
--- a/gap/display.gd
+++ b/gap/display.gd
@@ -1,27 +1,81 @@
-#############################################################################
+############################################################################
##
## display.gd
-## Copyright (C) 2017-19 James D. Mitchell
+## Copyright (C) 2017-26 James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
-DeclareAttribute("DotDigraph", IsDigraph);
-DeclareOperation("DotColoredDigraph", [IsDigraph, IsList, IsList]);
-DeclareOperation("DotColoredEdgeLabelledDigraph",
- [IsDigraph, IsList, 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]);
+
+#############################################################################
+# Edge labelled graphs and digraphs
+#############################################################################
+
+DeclareOperation("GraphvizColoredEdgeLabelledDigraph",
+[IsDigraph, IsList, IsList, IsList]);
+# TODO impl DeclareOperation("GraphvizColoredEdgeLabelledGraph", [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]);
+
+#############################################################################
+# Weighted digraphs
+#############################################################################
+
+DeclareOperation("GraphvizEdgeWeightedDigraph", [IsDigraph]);
+DeclareOperation("GraphvizEdgeWeightedDigraph", [IsDigraph, IsList]);
+DeclareOperation("GraphvizEdgeWeightedDigraph", [IsDigraph, IsRecord]);
+DeclareOperation("GraphvizEdgeWeightedDigraph", [IsDigraph, IsList, IsRecord]);
diff --git a/gap/display.gi b/gap/display.gi
index 64c230d33..833754a4c 100644
--- a/gap/display.gi
+++ b/gap/display.gi
@@ -1,531 +1,406 @@
#############################################################################
##
## display.gi
-## Copyright (C) 2014-21 James D. Mitchell
+## Copyright (C) 2014-24 James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
-# AN's code, adapted by WW
-
-BindGlobal("DIGRAPHS_DotDigraph",
-function(D, node_funcs, edge_funcs)
- local str, out, i, func, j, l;
- str := "//dot\n";
- Append(str, "digraph hgn{\n");
- Append(str, "node [shape=circle]\n");
- for i in DigraphVertices(D) do
- Append(str, StringFormatted("{}", i));
- for func in node_funcs do
- Append(str, func(i));
- od;
- Append(str, "\n");
+
+# TODO:
+# * add graph6 string or whatever as a comment at the start of the string
+# * check JupyterInterface Splash function
+# * for edge colored non-digraphs, should ensure that the edge colors are
+# symmetric, i.e. the same colors for x -> y and y -> x
+
+#############################################################################
+# Graphs and digraphs
+#############################################################################
+
+InstallOtherMethod(GraphvizDigraph, "for a digraph by out-neighbours",
+[IsDigraphByOutNeighboursRep],
+function(D)
+ local gv, x, y;
+ gv := GraphvizDigraph("hgn");
+ GraphvizSetAttr(gv, "node [shape=circle]");
+ for x in DigraphVertices(D) do
+ GraphvizAddNode(gv, x);
od;
- out := OutNeighbours(D);
- for i in DigraphVertices(D) do
- l := Length(out[i]);
- for j in [1 .. l] do
- Append(str, StringFormatted("{} -> {}", i, out[i][j]));
- for func in edge_funcs do
- Append(str, func(i, j));
- od;
- Append(str, "\n");
+ for x in DigraphVertices(D) do
+ for y in OutNeighboursOfVertexNC(D, x) do
+ GraphvizAddEdge(gv, x, y);
od;
od;
- Append(str, "}\n");
- return str;
-end);
-
-BindGlobal("DIGRAPHS_ValidRGBValue",
-function(str)
- local l, chars, x, i;
- l := Length(str);
- x := 0;
- chars := "0123456789ABCDEFabcdef";
- if l = 7 then
- if str[1] = '#' then
- for i in [2 .. l] do
- if str[i] in chars then
- x := x + 1;
- fi;
- od;
- fi;
- fi;
- return x = (l - 1);
-end);
-
-BindGlobal("DIGRAPHS_GraphvizColorsList", fail);
-
-BindGlobal("DIGRAPHS_GraphvizColors",
-function()
- local f;
- if DIGRAPHS_GraphvizColorsList = fail then
- f := IO_File(Concatenation(DIGRAPHS_Dir(), "/data/colors.p"));
- MakeReadWriteGlobal("DIGRAPHS_GraphvizColorsList");
- DIGRAPHS_GraphvizColorsList := IO_Unpickle(f);
- MakeReadOnlyGlobal("DIGRAPHS_GraphvizColorsList");
- IO_Close(f);
- fi;
- return DIGRAPHS_GraphvizColorsList;
+ return gv;
end);
-BindGlobal("DIGRAPHS_ValidVertColors",
-function(D, verts)
- local v, sum, colors, col;
- v := DigraphVertices(D);
- sum := 0;
- if Length(verts) <> Length(v) then
- ErrorNoReturn("the number of vertex colors must be the same as the number",
- " of vertices, expected ", Length(v), " but found ", Length(verts), "");
+InstallOtherMethod(GraphvizGraph, "for a digraph by out-neighbours",
+[IsDigraphByOutNeighboursRep],
+function(D)
+ local gv, x, y;
+ if not IsSymmetricDigraph(D) then
+ ErrorNoReturn("the argument (a digraph) must be symmetric");
fi;
- colors := DIGRAPHS_GraphvizColors();
- if Length(verts) = Length(v) then
- for col in verts do
- if not IsString(col) then
- ErrorNoReturn("expected a string");
- elif DIGRAPHS_ValidRGBValue(col) = false and
- (col in colors) = false then
- ErrorNoReturn("expected RGB Value or valid color name as defined",
- " by GraphViz 2.44.1 X11 Color Scheme",
- " http://graphviz.org/doc/info/colors.html");
- else
- sum := sum + 1;
+ gv := GraphvizGraph("hgn");
+ GraphvizSetAttr(gv, "node [shape=circle]");
+ for x in DigraphVertices(D) do
+ GraphvizAddNode(gv, x);
+ od;
+ for x in DigraphVertices(D) do
+ for y in OutNeighboursOfVertexNC(D, x) do
+ if x >= y then
+ GraphvizAddEdge(gv, x, y);
fi;
od;
- if sum = Length(verts) then
- return true;
- fi;
- fi;
+ od;
+ return gv;
end);
-BindGlobal("DIGRAPHS_ValidEdgeColors",
-function(D, edge)
- local out, l, counter, sum, colors, v, col;
- out := OutNeighbours(D);
- l := Length(edge);
- counter := 0;
- sum := 0;
- colors := DIGRAPHS_GraphvizColors();
- if Length(edge) <> Length(out) then
- ErrorNoReturn("the list of edge colors needs to have the",
- " same shape as the out-neighbours of the digraph");
- else
- for v in [1 .. l] do
- sum := 0;
- if Length(out[v]) <> Length(edge[v]) then
- ErrorNoReturn("the list of edge colors needs to have the",
- " same shape as the out-neighbours of the digraph");
- else
- for col in edge[v] do
- if not IsString(col) then
- ErrorNoReturn("expected a string");
- elif DIGRAPHS_ValidRGBValue(col) = false and
- (col in colors) = false then
- ErrorNoReturn("expected RGB Value or valid color name as defined",
- " by GraphViz 2.44.1 X11 Color Scheme",
- " http://graphviz.org/doc/info/colors.html");
- else
- sum := sum + 1;
- fi;
- od;
- if sum = Length(edge[v]) then
- counter := counter + 1;
- fi;
- fi;
- od;
- if counter = Length(edge) then
- return true;
- fi;
- fi;
-end);
+#############################################################################
+# Vertex coloured graphs and digraphs
+#############################################################################
-InstallMethod(DotDigraph, "for a digraph by out-neighbours",
-[IsDigraphByOutNeighboursRep],
-D -> DIGRAPHS_DotDigraph(D, [], []));
-
-InstallMethod(DotColoredDigraph,
-"for a digraph by out-neighbours and two lists",
-[IsDigraphByOutNeighboursRep, IsList, IsList],
-function(D, vert, edge)
- local vert_func, edge_func;
- if DIGRAPHS_ValidVertColors(D, vert)
- and DIGRAPHS_ValidEdgeColors(D, edge) then
- vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]);
- edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]);
- return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]);
- fi;
-end);
+InstallMethod(GraphvizVertexColoredDigraph, "for a digraph and a list",
+[IsDigraph, IsList],
+{D, colors} -> GraphvizSetNodeColors(GraphvizDigraph(D), colors));
-InstallMethod(DotColoredEdgeLabelledDigraph,
-"for a digraph by out-neighbours and three lists",
-[IsDigraphByOutNeighboursRep, IsList, IsList, IsList],
-function(D, vert, edge, weight)
- local vert_func, edge_func;
- # See https://graphs.grevian.org/example
- 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={}, label={}]",
- edge[i][j], weight[i][j]);
- return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]);
- fi;
-end);
+InstallMethod(GraphvizVertexColoredGraph, "for a digraph and a list",
+[IsDigraph, IsList],
+# IsSymmetricDigraph checked by GraphvizGraph
+{D, colors} -> GraphvizSetNodeColors(GraphvizGraph(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);
+#############################################################################
+# Edge coloured graphs and digraphs
+#############################################################################
-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]);
+# This function is here rather than graphviz b/c otherwise if D has multiple
+# edges we can't reliably get the corresponding graphviz edge from the head and
+# tail of the edge from gv.
+BindGlobal("DIGRAPHS_ErrorIfNotEdgeColoring",
+function(D, colors)
+ local out, i;
+
+ out := OutNeighbours(D);
+ if Length(colors) <> Length(out) then
+ ErrorFormatted("the 2nd argument (edge colors) must have ",
+ "the same number of entries as the 1st argument ",
+ "(a digraph) has nodes, expected {} but found {}",
+ Length(out),
+ Length(colors));
fi;
+ for i in [1 .. Length(colors)] do
+ if not IsList(colors[i]) then
+ ErrorFormatted("the 2nd argument (edge colors) must be ",
+ "a list of lists, found {} in position {}",
+ TNAM_OBJ(colors[i]),
+ i);
+ elif Length(out[i]) <> Length(colors[i]) then
+ ErrorFormatted("the 2nd argument (edge colors) must have ",
+ "the same shape as the out neighbours of the 1st ",
+ "argument (a digraph), in position {} expected ",
+ "a list of length {} but found list of length {}",
+ i,
+ Length(out[i]),
+ Length(colors[i]));
+ fi;
+ Perform(colors[i], ErrorIfNotValidColor);
+ od;
end);
-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);
+BindGlobal("DIGRAPHS_AddEdgesAndColorsNC",
+function(D, gv, colors)
+ local out, e, n, 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,");
- 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");
- 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");
+ # 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;
+ return gv;
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;
-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;
+#############################################################################
+# Vertex and edge coloured graphs and digraphs
+#############################################################################
- if not IsString(arg[1]) then
- ErrorNoReturn("the 1st argument must be a string,");
- fi;
- str := arg[1];
+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));
- 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;
+#############################################################################
+# Vertex labelled graphs and digraphs
+#############################################################################
- # path
- path := UserHomeExpand("~/"); # default
- if IsBound(opt.path) then
- path := opt.path;
- fi;
+InstallMethod(GraphvizVertexLabelledDigraph, "for a digraph",
+[IsDigraph],
+D -> GraphvizSetNodeLabels(GraphvizDigraph(D), DigraphVertexLabels(D)));
- # 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;
+InstallMethod(GraphvizVertexLabelledGraph, "for a digraph",
+[IsDigraph],
+# symmetry checked in GraphvizGraph
+D -> GraphvizSetNodeLabels(GraphvizGraph(D), DigraphVertexLabels(D)));
- # file
- file := "vizpicture"; # default
- if IsBound(opt.filename) then
- file := opt.filename;
- fi;
+#############################################################################
+# Edge labelled 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;
+# TODO maybe don't include this?
- # 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;
+InstallMethod(GraphvizColoredEdgeLabelledDigraph,
+"for a digraph, vertex colors, edge colors, and edge labels",
+[IsDigraph, IsList, IsList, IsList],
+function(D, n_colors, e_colors, weights)
+ local gv, out, edge, v, i;
- # 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;
+ DIGRAPHS_ErrorIfNotEdgeColoring(D, e_colors);
+ gv := GraphvizVertexColoredDigraph(
+ NullDigraph(DigraphNrVertices(D)), n_colors);
+ out := OutNeighbours(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 -interaction=nonstopmode ",
- 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;
+ for v in DigraphVertices(D) do
+ for i in [1 .. Length(out[v])] do
+ edge := GraphvizAddEdge(gv, v, out[v][i]);
+ GraphvizSetAttr(edge, "color", e_colors[v][i]);
+ GraphvizSetAttr(edge, "label", weights[v][i]);
+ od;
+ od;
+ return gv;
+end);
-# 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"));
+#############################################################################
+# Highlighted subdigraphs
+#############################################################################
-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,");
+BindGlobal("DIGRAPHS_GraphvizHighlight",
+function(D, gv, hi_verts, hi, lo)
+ local node, color, out, nodes, edge, v, i, j;
+
+ if 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);
- lowverts := Difference(DigraphVertices(D), highverts);
- out := OutNeighbours(D);
- str := "//dot\n";
+ GraphvizSetAttr(gv, "shape", "circle");
- Append(str, "digraph hgn{\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, "subgraph lowverts{\n");
- Append(str, Concatenation("node [shape=circle, color=",
- lowcolour,
- "]\n edge [color=",
- lowcolour,
- "]\n"));
+ out := OutNeighbours(D);
+ nodes := GraphvizNodes(gv);
- for i in lowverts do
- Append(str, Concatenation(String(i), "\n"));
+ for i in DigraphVertices(D) do
+ for j in out[i] do
+ if IsGraphvizDigraph(gv) or i >= j then
+ edge := GraphvizAddEdge(gv, nodes[i], nodes[j]);
+ if i in hi_verts and j in hi_verts then
+ color := hi;
+ else
+ color := lo;
+ fi;
+ GraphvizSetAttr(edge, "color", color);
+ fi;
+ od;
od;
- Append(str, "}\n");
+ return gv;
+end);
- Append(str, "subgraph highverts{\n");
- Append(str, Concatenation("node [shape=circle, color=",
- highcolour,
- "]\n edge [color=",
- highcolour,
- "]\n"));
+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));
- for i in highverts do
- Append(str, Concatenation(String(i), "\n"));
- od;
+InstallMethod(GraphvizHighlightedDigraph, "for a digraph and list",
+[IsDigraph, IsList],
+{D, list} -> GraphvizHighlightedDigraph(D, list, "black", "grey"));
- Append(str, "}\n");
+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);
- 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");
+InstallMethod(GraphvizHighlightedGraph, "for a digraph and list",
+[IsDigraph, IsList],
+# IsSymmetricDigraph checked in GraphvizHighlightedGraph
+{D, list} -> GraphvizHighlightedGraph(D, list, "black", "grey"));
- Append(str, "subgraph highverts{\n");
- for i in highverts do
- for j in out[i] do
- Append(str, Concatenation(String(i), " -> ", String(j)));
- if j in lowverts then
- Append(str, Concatenation(" [color=", lowcolour, "]"));
- fi;
- Append(str, "\n");
- od;
+#############################################################################
+# Weighted digraphs
+#############################################################################
+
+InstallMethod(GraphvizEdgeWeightedDigraph, "for a digraph",
+[IsDigraph],
+digraph -> GraphvizEdgeWeightedDigraph(digraph, [[], []], rec()));
+
+InstallMethod(GraphvizEdgeWeightedDigraph, "for a digraph and a list",
+[IsDigraph, IsList],
+{digraph, path} -> GraphvizEdgeWeightedDigraph(digraph, path, rec()));
+
+InstallMethod(GraphvizEdgeWeightedDigraph, "for a digraph and a record",
+[IsDigraph, IsRecord],
+{digraph, colors} -> GraphvizEdgeWeightedDigraph(digraph, [[], []], colors));
+
+# TODO JDM is not completely sure this is implemented in the spirit of the
+# other functions in this file.
+
+InstallMethod(GraphvizEdgeWeightedDigraph,
+"for a digraph, a list, and a record",
+[IsDigraph, IsList, IsRecord],
+function(digraph, path, colors)
+ local default_colors, edge, vert, source, dest, name, vertColours,
+ edgeColours, path_verts, path_edge_indices, path_length, i;
+
+ # Use default colours for any that aren't specified
+ default_colors := rec(highlight := "blue",
+ edge := "black",
+ vert := "gray",
+ source := "yellowgreen",
+ dest := "lightpink");
+ for name in RecNames(colors) do
+ if IsBound(default_colors.(name)) then
+ default_colors.(name) := colors.(name);
+ else
+ Error("the 3rd argument contains unsupported option ",
+ "named '", name, "'");
+ fi;
od;
- Append(str, "}\n}\n");
+ colors := default_colors;
+
+ # fill with basic colours
+ vertColours := ListWithIdenticalEntries(DigraphNrVertices(digraph),
+ colors.vert);
+ edgeColours := List(OutNeighbours(digraph),
+ outs_u -> List(outs_u, _ -> colors.edge));
+
+ # highlight the path
+ path_verts := path[1];
+ path_edge_indices := path[2];
+ path_length := Length(path_edge_indices);
+ if not IsEmpty(path_verts) then
+ for i in [1 .. path_length] do
+ edgeColours[path_verts[i]][path_edge_indices[i]] := colors.highlight;
+ od;
+ vertColours[path_verts[1]] := colors.source;
+ vertColours[path_verts[path_length + 1]] := colors.dest;
+ fi;
- return str;
+ # draw with the weights as labels
+ return GraphvizColoredEdgeLabelledDigraph(digraph,
+ vertColours, edgeColours, EdgeWeights(digraph));
end);
diff --git a/gap/weights.gd b/gap/weights.gd
index 423950b61..4bcacf378 100644
--- a/gap/weights.gd
+++ b/gap/weights.gd
@@ -54,8 +54,3 @@ DeclareOperation("RandomUniqueEdgeWeightedDigraph",
DeclareOperation("RandomUniqueEdgeWeightedDigraph",
[IsFunction, IsPosInt, IsRat]);
-# 7. Drawing edge weighted digraphs
-DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph]);
-DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsList]);
-DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsRecord]);
-DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsList, IsRecord]);
diff --git a/gap/weights.gi b/gap/weights.gi
index dc1081fcf..93030fe01 100644
--- a/gap/weights.gi
+++ b/gap/weights.gi
@@ -905,58 +905,3 @@ DIGRAPHS_RandomEdgeWeightedDigraphFilt);
# 7. Drawing edge weighted digraphs
#############################################################################
-InstallMethod(DotEdgeWeightedDigraph, "for a digraph",
-[IsDigraph],
-digraph -> DotEdgeWeightedDigraph(digraph, [[], []], rec()));
-
-InstallMethod(DotEdgeWeightedDigraph, "for a digraph and a list",
-[IsDigraph, IsList],
-{digraph, path} -> DotEdgeWeightedDigraph(digraph, path, rec()));
-
-InstallMethod(DotEdgeWeightedDigraph, "for a digraph and a record",
-[IsDigraph, IsRecord],
-{digraph, colors} -> DotEdgeWeightedDigraph(digraph, [[], []], colors));
-
-InstallMethod(DotEdgeWeightedDigraph, "for a digraph, a list, and a record",
-[IsDigraph, IsList, IsRecord],
-function(digraph, path, colors)
- local default_colors, edge, vert, source, dest, name, vertColours,
- edgeColours, path_verts, path_edge_indices, path_length, i;
-
- # Use default colours for any that aren't specified
- default_colors := rec(highlight := "blue",
- edge := "black",
- vert := "gray",
- source := "yellowgreen",
- dest := "lightpink");
- for name in RecNames(colors) do
- if IsBound(default_colors.(name)) then
- default_colors.(name) := colors.(name);
- else
- Error("3rd arg contains unsupported option named '", name, "'");
- fi;
- od;
- colors := default_colors;
-
- # fill with basic colours
- vertColours := ListWithIdenticalEntries(DigraphNrVertices(digraph),
- colors.vert);
- edgeColours := List(OutNeighbours(digraph),
- outs_u -> List(outs_u, _ -> colors.edge));
-
- # highlight the path
- path_verts := path[1];
- path_edge_indices := path[2];
- path_length := Length(path_edge_indices);
- if not IsEmpty(path_verts) then
- for i in [1 .. path_length] do
- edgeColours[path_verts[i]][path_edge_indices[i]] := colors.highlight;
- od;
- vertColours[path_verts[1]] := colors.source;
- vertColours[path_verts[path_length + 1]] := colors.dest;
- fi;
-
- # draw with the weights as labels
- return DotColoredEdgeLabelledDigraph(digraph, vertColours, edgeColours,
- EdgeWeights(digraph));
-end);
diff --git a/init.g b/init.g
index 20ed2f3dd..b61165fc4 100644
--- a/init.g
+++ b/init.g
@@ -64,5 +64,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 40ae189c5..50f8815c5 100644
--- a/read.g
+++ b/read.g
@@ -47,3 +47,4 @@ ReadPackage("digraphs", "gap/cliques.gi");
ReadPackage("digraphs", "gap/planar.gi");
ReadPackage("digraphs", "gap/examples.gi");
ReadPackage("digraphs", "gap/weights.gi");
+ReadPackage("digraphs", "gap/deprecated.gi");
diff --git a/tst/standard/display.tst b/tst/standard/display.tst
new file mode 100644
index 000000000..a6d09ee31
--- /dev/null
+++ b/tst/standard/display.tst
@@ -0,0 +1,700 @@
+#############################################################################
+##
+#W standard/display.tst
+#Y Copyright (C) 2014-24 James D. Mitchell
+##
+## Licensing information can be found in the README file of this package.
+##
+#############################################################################
+##
+gap> START_TEST("Digraphs package: standard/display.tst");
+gap> LoadPackage("digraphs", false);;
+
+#
+gap> DIGRAPHS_StartTest();
+
+# Display and PrintString and String
+gap> Digraph([]);
+
+gap> Digraph([[]]);
+
+gap> Digraph([[1]]);
+
+gap> Digraph([[2], []]);
+
+gap> gr := Digraph([[1, 2], [2], []]);
+
+gap> PrintString(gr);
+"DigraphFromDigraph6String(\"&Bq?\")"
+gap> String(gr);
+"DigraphFromDigraph6String(\"&Bq?\")"
+gap> gr := Digraph([[2], [1], [], [3]]);
+
+gap> PrintString(gr);
+"DigraphFromDigraph6String(\"&CQ?G\")"
+gap> String(gr);
+"DigraphFromDigraph6String(\"&CQ?G\")"
+gap> r := rec(DigraphVertices := [1, 2, 3],
+> DigraphSource := [1, 2],
+> DigraphRange := [2, 3]);;
+gap> gr := Digraph(r);
+
+gap> PrintString(gr);
+"ChainDigraph(3)"
+gap> String(gr);
+"ChainDigraph(3)"
+
+# DotDigraph and DotSymmetricDigraph
+gap> r := rec(DigraphVertices := [1 .. 3], DigraphSource := [1, 1, 1, 1],
+> DigraphRange := [1, 2, 2, 3]);;
+gap> gr := Digraph(r);
+
+gap> dot := DotDigraph(gr);;
+gap> dot{[1 .. 50]};
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3"
+gap> dot{[51 .. 75]};
+"\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n"
+gap> r := rec(DigraphVertices := [1 .. 8],
+> DigraphSource := [1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 8,
+> 8],
+> DigraphRange := [6, 7, 1, 6, 5, 1, 4, 8, 1, 3, 6, 6, 7, 7, 1, 4, 4, 5, 7, 5,
+> 6]);;
+gap> gr1 := Digraph(r);
+
+gap> DotDigraph(gr1){[50 .. 109]};
+"3\n\t4\n\t5\n\t6\n\t7\n\t8\n\t1 -> 6\n\t1 -> 7\n\t2 -> 1\n\t2 -> 6\n\t3 -> 5\
+\n\t4 "
+gap> adj := [[2], [1, 3], [2, 3, 4], [3]];
+[ [ 2 ], [ 1, 3 ], [ 2, 3, 4 ], [ 3 ] ]
+gap> gr2 := Digraph(adj);
+
+gap> DotDigraph(gr2){[11 .. 75]};
+"aph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2\n\t2 -> 1\n\t\
+2 ->"
+gap> DotSymmetricDigraph(gr2){[12 .. 70]};
+" hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t2 -- 1\n\t3 -- 2\n\t3"
+gap> DotSymmetricDigraph(gr1);
+Error, the argument (a digraph) must be symmetric
+
+#DotColoredDigraph and DotSymmetriColoredDigraph
+# TODO fix the colors here!
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "lightblue";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "lightblue";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+gap> edgecolors[4][3] := "purple";;
+gap> DotColoredDigraph(D, vertcolors, edgecolors){[1 .. 30]};
+"//dot\ndigraph hgn {\n\tnode [sha"
+gap> D := Digraph([[2], [1, 3], [2]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";;
+gap> vertcolors[2] := "pink";;
+gap> vertcolors[3] := "purple";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "green";;
+gap> edgecolors[2][1] := "green";;
+gap> edgecolors[3][1] := "red";; edgecolors[2][2] := "red";;
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\n\
+\t2 [color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t2 -- 1 [co\
+lor=green]\n\t3 -- 2 [color=red]\n}\n"
+gap> D := Digraph([[2, 3], [1, 3], [1]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "yellow";;
+gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "pink";;
+gap> edgecolors[3][1] := "yellow";;
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\
+\n\t2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t1 -> 2 [co\
+lor=orange]\n\t1 -> 3 [color=yellow]\n\t2 -> 1 [color=orange]\n\t2 -> 3 [color\
+=pink]\n\t3 -> 1 [color=yellow]\n}\n"
+gap> D := Digraph(IsMutableDigraph, [[2, 3], [1, 3], [1]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "yellow";;
+gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "pink";;
+gap> edgecolors[3][1] := "yellow";;
+gap> DotColoredDigraph(D, vertcolors, edgecolors);;
+gap> D;
+
+gap> D := Digraph([[2, 4], [1, 3], [2], [1]]);
+
+gap> vertcolors := ["blue", "red", "green", "yellow"];;
+gap> edgecolors := ListWithIdenticalEntries(3,
+> ["orange", "orange", "orange"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st argument (a digraph) has nodes, expected 4 but found 3
+#@else
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st\
+ argument (a digraph) has nodes, expected 4 but found 3
+#@fi
+gap> D := Digraph(IsMutableDigraph, [[2, 4], [1, 3], [2], [1]]);
+
+gap> vertcolors := ["blue", "red", "green", "yellow"];;
+gap> edgecolors := ListWithIdenticalEntries(3,
+> ["orange", "orange", "orange"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st argument (a digraph) has nodes, expected 4 but found 3
+#@else
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st\
+ argument (a digraph) has nodes, expected 4 but found 3
+#@fi
+gap> D;
+
+gap> D := CompleteDigraph(4);;
+gap> vertcolors := ["blue", "banana", "green", "yellow"];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/c\
+olors.html
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := ["blue", "red", "green"];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the number of node colors must be the same as the number of nodes, expe\
+cted 4 but found 3
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the number of node colors must be the same as the number of nodes, expe\
+cted 4 but found 3
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [2, 1, 1, 3];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color 2 (integer), valid colors are RGB values or names from th\
+e GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.html
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color 2 (integer), valid colors are RGB values or names from th\
+e GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := ["#AB3487", "#DF4738", "#4BF234", "#AF34C9"];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1 [color="#AB3487", style=filled]
+ 2 [color="#DF4738", style=filled]
+ 3 [color="#4BF234", style=filled]
+ 4 [color="#AF34C9", style=filled]
+ 1 -> 2 [color=lightblue]
+ 1 -> 3 [color=pink]
+ 1 -> 4 [color=purple]
+ 2 -> 1 [color=lightblue]
+ 2 -> 3 [color=pink]
+ 2 -> 4 [color=purple]
+ 3 -> 1 [color=lightblue]
+ 3 -> 2 [color=pink]
+ 3 -> 4 [color=purple]
+ 4 -> 1 [color=lightblue]
+ 4 -> 2 [color=pink]
+ 4 -> 3 [color=purple]
+}
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "banana";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "cherry";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+gap> edgecolors[4][3] := "purple";;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/c\
+olors.html
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "lightblue";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "lightblue";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same shape as the out neig\
+hbours of the 1st argument (a digraph), in position 4 expected a list of lengt\
+h 3 but found list of length 2
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same shape as the out neig\
+hbours \
+of the 1st argument (a digraph), in position 4 expected a list of length 3 but\
+ found list of length 2
+#@fi
+
+# DotVertexColoredDigraph
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> Print(DotVertexColoredDigraph(D, vertcolors));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1 [color=blue, style=filled]
+ 2 [color=red, style=filled]
+ 3 [color=green, style=filled]
+ 4 [color=yellow, style=filled]
+ 1 -> 2
+ 1 -> 3
+ 1 -> 4
+ 2 -> 1
+ 2 -> 3
+ 2 -> 4
+ 3 -> 1
+ 3 -> 2
+ 3 -> 4
+ 4 -> 1
+ 4 -> 2
+ 4 -> 3
+}
+gap> D := EmptyDigraph(3);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> DotVertexColoredDigraph(D, vertcolors);
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\
+\n\t2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n}\n"
+
+# DotEdgeColoredDigraph
+gap> D := CompleteDigraph(4);
+
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "lightblue";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "lightblue";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+gap> edgecolors[4][3] := "purple";;
+gap> DotEdgeColoredDigraph(D, edgecolors);
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2 [c\
+olor=lightblue]\n\t1 -> 3 [color=pink]\n\t1 -> 4 [color=purple]\n\t2 -> 1 [col\
+or=lightblue]\n\t2 -> 3 [color=pink]\n\t2 -> 4 [color=purple]\n\t3 -> 1 [color\
+=lightblue]\n\t3 -> 2 [color=pink]\n\t3 -> 4 [color=purple]\n\t4 -> 1 [color=l\
+ightblue]\n\t4 -> 2 [color=pink]\n\t4 -> 3 [color=purple]\n}\n"
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotEdgeColoredDigraph(CycleDigraph(3), []);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st argument (a digraph) has nodes, expected 3 but found 0
+gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail, fail], [fail], [fail]]);
+Error, the 2nd argument (edge colors) must have the same shape as the out neig\
+hbours of the 1st argument (a digraph), in position 1 expected a list of lengt\
+h 1 but found list of length 2
+#@else
+gap> DotEdgeColoredDigraph(CycleDigraph(3), []);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st\
+ argument (a digraph) has nodes, expected 3 but found 0
+#@fi
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]);
+Error, invalid color fail (boolean or fail), valid colors are RGB values or na\
+mes from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/col\
+ors.html
+#@else
+gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]);
+Error, invalid color fail (boolean or fail), valid colors are RGB values or na\
+mes from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+
+# DotSymmetricVertexColoredDigraph
+gap> D := Digraph([[2], [1, 3], [2]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";;
+gap> vertcolors[2] := "pink";;
+gap> vertcolors[3] := "purple";;
+gap> DotSymmetricVertexColoredDigraph(D, vertcolors);
+"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\n\
+\t2 [color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t2 -- 1\n\t\
+3 -- 2\n}\n"
+
+# DotSymmetricEdgeColoredDigraph
+gap> D := Digraph([[2], [1, 3], [2]]);
+
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "green";; edgecolors[2][1] := "green";;
+gap> edgecolors[2][2] := "red";; edgecolors[3][1] := "red";;
+gap> DotSymmetricEdgeColoredDigraph(D, edgecolors);
+"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t2 -- 1 [color=gr\
+een]\n\t3 -- 2 [color=red]\n}\n"
+
+# DotVertexLabelledDigraph
+gap> r := rec(DigraphVertices := [1 .. 3], DigraphSource := [1, 1, 1, 1],
+> DigraphRange := [1, 2, 2, 3]);;
+gap> gr := Digraph(r);
+
+gap> dot := DotVertexLabelledDigraph(gr);;
+gap> dot;
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [label=\"1\"]\n\t2 [label=\
+\"2\"]\n\t3 [label=\"3\"]\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n\t1 -> 3\n}\n"
+gap> SetDigraphVertexLabel(gr, 1, 2);
+gap> dot := DotVertexLabelledDigraph(gr);;
+gap> dot;
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [label=\"2\"]\n\t2 [label=\
+\"2\"]\n\t3 [label=\"3\"]\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n\t1 -> 3\n}\n"
+
+# Splash
+gap> Splash(1);
+Error, the 1st argument must be a string or graphviz graph, found integer
+gap> Splash("string", 0);
+Error, the 2nd argument must be a record
+gap> Splash("string");
+Error, the component "type" of the 2nd argument must be "dot" or "\
+latex",
+gap> Splash("string", rec(path := "~/", filename := "filename"));
+Error, the component "type" of the 2nd argument must be "dot" or "\
+latex",
+gap> Splash("string", rec(viewer := "bad"));
+Error, the viewer "bad" specified in the option `viewer` is not available
+gap> Splash("string", rec(type := "dot", engine := "dott"));
+Error, the component "engine" of the 2nd argument must be one of: "\
+dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork"
+gap> tmpdir := Filename(DirectoryTemporary(), "");;
+gap> Splash("string",
+> rec(path := tmpdir,
+> directory := "digraphs_temporary_directory"));
+Error, the component "type" of the 2nd argument must be "dot" or "\
+latex",
+gap> Splash("%latex", rec(filetype := "latex", engine := fail));
+Error, the component "engine" of the 2nd argument must be one of: "\
+dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork"
+gap> Splash("//dot", rec(filetype := "pdf", engine := fail));
+Error, the component "engine" of the 2nd argument must be one of: "\
+dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork"
+gap> MakeReadWriteGlobal("VizViewers");
+gap> VizViewers_backup := ShallowCopy(VizViewers);;
+gap> VizViewers := ["nonexistent-viewer"];;
+gap> Splash("//dot");
+Error, none of the default viewers [ "nonexistent-viewer"
+ ] is available, please specify an available viewer in the options record comp\
+onent `viewer`,
+gap> VizViewers := VizViewers_backup;;
+gap> MakeReadOnlyGlobal("VizViewers");
+
+# DotPartialOrderDigraph
+gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 4], [1 .. 5], [1 .. 6],
+> [1, 2, 3, 4, 5, 7], [1, 8]]);;
+gap> Print(DotPartialOrderDigraph(gr));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 2 -> 1
+ 3 -> 1
+ 4 -> 1
+ 5 -> 2
+ 5 -> 3
+ 5 -> 4
+ 6 -> 5
+ 7 -> 5
+ 8 -> 1
+}
+gap> gr := Digraph([[1], [2], [1, 3], [2, 4], [1, 2, 3, 4, 5], [1, 2, 3, 6]]);;
+gap> Print(DotPartialOrderDigraph(gr));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 3 -> 1
+ 4 -> 2
+ 5 -> 3
+ 5 -> 4
+ 6 -> 3
+ 6 -> 2
+}
+gap> gr := Digraph([[1], []]);;
+gap> DotPartialOrderDigraph(gr);
+Error, the argument (a digraph) must be a partial order
+
+# DotPreorderDigraph and DotQuasiorderDigraph
+gap> DotPreorderDigraph(CompleteDigraph(5));
+Error, the argument (a digraph) must be a preorder
+gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 4], [1 .. 5], [1 .. 6],
+> [1, 2, 3, 4, 5, 7], [1, 8]]);;
+gap> Print(DotPreorderDigraph(gr), "\n");
+//dot
+digraph graphname {
+ node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1"
+ 1 [label="1", width=0.5]
+ 2 [label="2", width=0.5]
+ 3 [label="3", width=0.5]
+ 4 [label="4", width=0.5]
+ 5 [label="5", width=0.5]
+ 6 [label="6", width=0.5]
+ 7 [label="7", width=0.5]
+ 8 [label="8", width=0.5]
+ 2 -> 1
+ 3 -> 1
+ 4 -> 1
+ 5 -> 2
+ 5 -> 3
+ 5 -> 4
+ 6 -> 5
+ 7 -> 5
+ 8 -> 1
+}
+
+gap> gr := Concatenation("&X_?_A]|^Vr[nHpmVcy~zy[A????_???G??B]nhtmvcwvJq\\^~",
+> "|m??_AEx]Rb[nHo??__vJy[??A??O_aV~^Zb]njo???_???GZdxMLy}n_");;
+gap> gr := DigraphFromDigraph6String(gr);;
+gap> Print(DotPreorderDigraph(gr){[1 .. 94]}, "\n");
+//dot
+digraph graphname {
+ node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1"
+
+gap> gr := DigraphDisjointUnion(CompleteDigraph(10),
+> CompleteDigraph(5),
+> CycleDigraph(2));;
+gap> gr := DigraphReflexiveTransitiveClosure(DigraphAddEdge(gr, [10, 11]));;
+gap> IsPreorderDigraph(gr);
+true
+gap> Print(DotPreorderDigraph(gr), "\n");
+//dot
+digraph graphname {
+ node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1"
+ 1 [label="11|12|13|14|15", width=2.5]
+ 2 [label="1|2|3|4|5|6|7|8|9|10", width=5.]
+ 3 [label="16|17", width=1.]
+ 2 -> 1
+}
+
+
+# DotHighlightedDigraph
+gap> gr := Digraph([[2, 3], [2], [1, 3]]);
+
+gap> Print(DotHighlightedDigraph(gr, [1, 2], "red", "black"));
+//dot
+digraph {
+ shape=circle
+ 1 [color=red]
+ 2 [color=red]
+ 3 [color=black]
+ 1 -> 2 [color=red]
+ 1 -> 3 [color=black]
+ 2 -> 2 [color=red]
+ 3 -> 1 [color=black]
+ 3 -> 3 [color=black]
+}
+gap> D := CycleDigraph(5);;
+gap> DotHighlightedDigraph(D, [10], "black", "grey");
+Error, the 2nd argument (list) must consist of vertices of the 1st argument (a\
+ digraph)
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotHighlightedDigraph(D, [1], "", "grey");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.\
+html
+#@else
+gap> DotHighlightedDigraph(D, [1], "", "grey");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotHighlightedDigraph(D, [1], "black", "");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.\
+html
+#@else
+gap> DotHighlightedDigraph(D, [1], "black", "");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> Print(DotHighlightedDigraph(D, Filtered(DigraphVertices(D), IsEvenInt)));
+//dot
+digraph {
+ shape=circle
+ 1 [color=grey]
+ 2 [color=black]
+ 3 [color=grey]
+ 4 [color=black]
+ 5 [color=grey]
+ 1 -> 2 [color=grey]
+ 2 -> 3 [color=grey]
+ 3 -> 4 [color=grey]
+ 4 -> 5 [color=grey]
+ 5 -> 1 [color=grey]
+}
+
+# Splash
+gap> Splash(DotDigraph(RandomDigraph(10)), rec(viewer := 1));
+Error, the option `viewer` must be a string, not an integer
+gap> Splash(DotDigraph(RandomDigraph(10)), rec(viewer := "asdfasfa"));
+Error, the viewer "asdfasfa" specified in the option `viewer` is not available
+
+# Test errors
+gap> GraphvizEdgeColoredGraph(ChainDigraph(3), ["blue"]);
+Error, the argument (a digraph) must be symmetric
+gap> D := DigraphSymmetricClosure(ChainDigraph(3));;
+gap> GraphvizVertexLabelledGraph(D);
+
+gap> GraphvizEdgeColoredGraph(D, List(DigraphVertices(D), ReturnFail));
+Error, the 2nd argument (edge colors) must be a list of lists, found boolean o\
+r fail in position 1
+gap> GraphvizHighlightedDigraph(D, [2]);
+
+gap> GraphvizHighlightedGraph(D, [2]);
+
+gap> Print(AsString(last));
+//dot
+graph {
+ shape=circle
+ 1 [color=grey]
+ 2 [color=black]
+ 3 [color=grey]
+ 2 -- 1 [color=grey]
+ 3 -- 2 [color=grey]
+}
+gap> GraphvizHighlightedGraph(D, [1, 2], "red", "blue");
+
+gap> Print(AsString(last));
+//dot
+graph {
+ shape=circle
+ 1 [color=red]
+ 2 [color=red]
+ 3 [color=blue]
+ 2 -- 1 [color=red]
+ 3 -- 2 [color=blue]
+}
+gap> GraphvizHighlightedGraph(ChainDigraph(3), [1, 2], "red", "blue");
+Error, the argument (a digraph) must be symmetric
+gap> D := Digraph([[], [1, 1]]);;
+gap> GraphvizHighlightedDigraph(D, [2]);
+
+
+# DIGRAPHS_UnbindVariables
+gap> Unbind(D);
+gap> Unbind(adj);
+gap> Unbind(backup);
+gap> Unbind(dot);
+gap> Unbind(edgecolors);
+gap> Unbind(gr);
+gap> Unbind(gr1);
+gap> Unbind(gr2);
+gap> Unbind(r);
+gap> Unbind(tmpdir);
+gap> Unbind(vertcolors);
+
+#
+gap> DIGRAPHS_StopTest();
+gap> STOP_TEST("Digraphs package: standard/display.tst", 0);
diff --git a/tst/standard/weights.tst b/tst/standard/weights.tst
index 036dac4d0..8963587c9 100644
--- a/tst/standard/weights.tst
+++ b/tst/standard/weights.tst
@@ -511,39 +511,46 @@ true
gap> gr := EdgeWeightedDigraph([[2], []], [[10], []]);;
gap> Print(DotEdgeWeightedDigraph(gr));
//dot
-digraph hgn{
-node [shape=circle]
-1[color=gray, style=filled]
-2[color=gray, style=filled]
-1 -> 2[color=black, label=10]
+digraph hgn {
+ node [shape=circle]
+ 1 [color=gray, style=filled]
+ 2 [color=gray, style=filled]
+ 1 -> 2 [color=black, label=10]
}
gap> Print(DotEdgeWeightedDigraph(gr, rec(vert := "orange")));
//dot
-digraph hgn{
-node [shape=circle]
-1[color=orange, style=filled]
-2[color=orange, style=filled]
-1 -> 2[color=black, label=10]
+digraph hgn {
+ node [shape=circle]
+ 1 [color=orange, style=filled]
+ 2 [color=orange, style=filled]
+ 1 -> 2 [color=black, label=10]
}
+# Parallel edges and loops retain distinct weights when highlighting a path.
+gap> gr := EdgeWeightedDigraph([[1, 2, 1, 2], []], [[3, 10, 7, 20], []]);;
+gap> path := [[1, 2], [4]];;
+gap> List(GraphvizEdges(GraphvizEdgeWeightedDigraph(gr, path)),
+> e -> [GraphvizAttrs(e)["color"], GraphvizAttrs(e)["label"]]);
+[ [ "black", "3" ], [ "black", "10" ], [ "black", "7" ], [ "blue", "20" ] ]
+
# Cycle example
gap> gr := EdgeWeightedDigraph(CycleDigraph(5), [[10], [4], [8], [2], [8]]);;
gap> path := DigraphPath(gr, 3, 1);
[ [ 3, 4, 5, 1 ], [ 1, 1, 1 ] ]
gap> Print(DotEdgeWeightedDigraph(gr, path, rec(highlight := "red")));
//dot
-digraph hgn{
-node [shape=circle]
-1[color=lightpink, style=filled]
-2[color=gray, style=filled]
-3[color=yellowgreen, style=filled]
-4[color=gray, style=filled]
-5[color=gray, style=filled]
-1 -> 2[color=black, label=10]
-2 -> 3[color=black, label=4]
-3 -> 4[color=red, label=8]
-4 -> 5[color=red, label=2]
-5 -> 1[color=red, label=8]
+digraph hgn {
+ node [shape=circle]
+ 1 [color=lightpink, style=filled]
+ 2 [color=gray, style=filled]
+ 3 [color=yellowgreen, style=filled]
+ 4 [color=gray, style=filled]
+ 5 [color=gray, style=filled]
+ 1 -> 2 [color=black, label=10]
+ 2 -> 3 [color=black, label=4]
+ 3 -> 4 [color=red, label=8]
+ 4 -> 5 [color=red, label=2]
+ 5 -> 1 [color=red, label=8]
}
# Large example
@@ -555,28 +562,28 @@ gap> path := EdgeWeightedDigraphShortestPath(gr, 1, 2);
[ [ 1, 7, 6, 2 ], [ 2, 1, 2 ] ]
gap> Print(DotEdgeWeightedDigraph(gr, path));
//dot
-digraph hgn{
-node [shape=circle]
-1[color=yellowgreen, style=filled]
-2[color=lightpink, style=filled]
-3[color=gray, style=filled]
-4[color=gray, style=filled]
-5[color=gray, style=filled]
-6[color=gray, style=filled]
-7[color=gray, style=filled]
-1 -> 5[color=black, label=8]
-1 -> 7[color=blue, label=4]
-2 -> 5[color=black, label=12]
-3 -> 1[color=black, label=11]
-3 -> 3[color=black, label=2]
-3 -> 6[color=black, label=10]
-4 -> 1[color=black, label=3]
-4 -> 3[color=black, label=7]
-5 -> 4[color=black, label=9]
-5 -> 5[color=black, label=13]
-6 -> 1[color=black, label=1]
-6 -> 2[color=blue, label=6]
-7 -> 6[color=blue, label=5]
+digraph hgn {
+ node [shape=circle]
+ 1 [color=yellowgreen, style=filled]
+ 2 [color=lightpink, style=filled]
+ 3 [color=gray, style=filled]
+ 4 [color=gray, style=filled]
+ 5 [color=gray, style=filled]
+ 6 [color=gray, style=filled]
+ 7 [color=gray, style=filled]
+ 1 -> 5 [color=black, label=8]
+ 1 -> 7 [color=blue, label=4]
+ 2 -> 5 [color=black, label=12]
+ 3 -> 1 [color=black, label=11]
+ 3 -> 3 [color=black, label=2]
+ 3 -> 6 [color=black, label=10]
+ 4 -> 1 [color=black, label=3]
+ 4 -> 3 [color=black, label=7]
+ 5 -> 4 [color=black, label=9]
+ 5 -> 5 [color=black, label=13]
+ 6 -> 1 [color=black, label=1]
+ 6 -> 2 [color=blue, label=6]
+ 7 -> 6 [color=blue, label=5]
}
# Bad arguments
@@ -585,7 +592,7 @@ gap> DotEdgeWeightedDigraph(
> [[1, 2], [3, 4], [5, 6]],
> rec(vert := "blue", mrblobby := "pink")
> );
-Error, 3rd arg contains unsupported option named 'mrblobby'
+Error, the 3rd argument contains unsupported option named 'mrblobby'
#
gap> DIGRAPHS_StopTest();