diff --git a/PackageInfo.g b/PackageInfo.g
index edbfb2e38..87a439a2c 100644
--- a/PackageInfo.g
+++ b/PackageInfo.g
@@ -539,9 +539,10 @@ PackageDoc := rec(
),
Dependencies := rec(
- GAP := ">=4.10.0",
+ GAP := ">=4.11.0",
NeededOtherPackages := [["IO", ">=4.5.1"],
["orb", ">=4.8.2"],
+ ["GraphViz", ">=0.0.0"],
["datastructures", ">=0.2.5"]],
SuggestedOtherPackages := [["GAPDoc", ">=1.6.3"],
["GRAPE", ">=4.8.1"],
diff --git a/doc/display.xml b/doc/display.xml
index f064d9a05..7086f1929 100644
--- a/doc/display.xml
+++ b/doc/display.xml
@@ -1,518 +1,282 @@
#############################################################################
##
#W display.xml
-#Y Copyright (C) 2011-17 James D. Mitchell
+#Y Copyright (C) 2014-24 James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
+<#GAPDoc Label="DotDigraph">
+
+
+
+ A string.
+
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+
+
+
+
+ and return
+ mutable &GAP; objects representing graphviz objects, which provide a
+ more flexible means of tailoring pictures of graphs and digraphs to your
+ needs. The function DotDigraph is synonymous with
+ AsString(GraphvizDigraph(D)). It is also possible to use
+ directly on the graphviz objects
+ returned by the function , i.e.
+ Splash(GraphvizDigraph(D)) does precisely the same thing as
+ Splash(DotDigraph(D)).
+
+
+<#/GAPDoc>
-<#GAPDoc Label="Splash">
+<#GAPDoc Label="GraphvizDigraph">
-
- Nothing.
+
+
+ A &graphviz; object.
- This function attempts to convert the string str into a pdf
- document and open this document, i.e. to splash it all over your monitor.
+ and return
+ mutable &GAP; objects representing graphviz objects, which provide a
+ flexible means of tailoring pictures of graphs and digraphs to your
+ needs.
+
+
+ GraphvizDigraph and GraphvizGraph produce &graphviz;
+ objects representing the digraph D. Vertices are displayed as
+ circles, numbered consistently with D. For GraphvizDigraph,
+ edges are displayed as arrowed lines between vertices, with the arrowhead
+ of each line pointing towards the range of the edge. For
+ GraphvizGraph, edges are displayed without an arrowhead.
+
+
+ See the &graphviz; package documentation for more details.
+
+
+ See also
+
+ D := CompleteDigraph(IsMutable, 4);
+
+gap> gv := GraphvizGraph(D);
+
+gap> AsString(gv);
+"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t2 -\
+- 1\n\t3 -- 1\n\t3 -- 2\n\t4 -- 1\n\t4 -- 2\n\t4 -- 3\n}\n"
+gap> DigraphRemoveEdge(D, 1, 3);
+
+gap> gv := GraphvizDigraph(D);
+
+gap> AsString(gv);
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1\
+ -> 2\n\t1 -> 4\n\t2 -> 1\n\t2 -> 3\n\t2 -> 4\n\t3 -> 1\n\t3 -> 2\n\t3\
+ -> 4\n\t4 -> 1\n\t4 -> 2\n\t4 -> 3\n}\n"
+]]>
+
+
+<#/GAPDoc>
- The string str must correspond to a valid dot or
- LaTeX text file and you must have have GraphViz and
- pdflatex installed on your computer. For details about these file
- formats, see https://www.latex-project.org and
- https://www.graphviz.org.
+<#GAPDoc Label="DotVertexLabelledDigraph">
+
+
+ A string.
+
+ WARNING! As of v2.0.0 of &Digraphs; this function is
+ deprecated in favour of:
+
+
+
+
+
+<#/GAPDoc>
- This function is provided to allow convenient, immediate viewing of the
- pictures produced by the function .
+<#GAPDoc Label="GraphvizVertexLabelledDigraph">
+
+
+
+ A &graphviz; object.
+
+ GraphvizVertexLabelledDigraph and
+ GraphvizVertexLabelledGraph differ from and only in that
+ the values in are used to label the
+ vertices in the produced picture rather than the numbers 1 to
+ the number of vertices of the digraph.
- The optional second argument opts should be a record with
- components corresponding to various options, given below.
+ See the &graphviz; package documentation for more details.
+
-
- path
- -
- this should be a string representing the path to the directory where
- you want Splash to do its work. The default value of this
- option is "~/".
-
-
- directory
- -
- this should be a string representing the name of the directory in
- path where you want Splash to do its work. This function
- will create this directory if does not already exist.
-
- The default value of this option is "tmp.viz" if the option
- path is present, and the result of
-
is used otherwise.
-
-
- filename
- -
- this should be a string representing the name of the file where
- str will be written. The default value of this option is
- "vizpicture".
-
-
- viewer
- -
- this should be a string representing the name of the program which
- should open the files produced by GraphViz or pdflatex.
-
-
- type
- -
- this option can be used to specify that the string str contains
- a &LaTeX; or dot document. You can specify this option in
- str directly by making the first line "%latex" or
- "//dot". There is no default value for this option, this
- option must be specified in str or in opt.type.
-
-
- engine
- -
- this option can be used to specify the GraphViz engine to use
- to render a dot document. The valid choices are "dot",
- "neato", "circo", "twopi", "fdp",
- "sfdp", and "patchwork". Please refer to the
- GraphViz documentation for details on these engines.
- The default value for this option is "dot", and it
- must be specified in opt.engine.
-
-
- filetype
- -
- this should be a string representing the type of file which
- Splash should produce. For &LaTeX; files, this option is
- ignored and the default value "pdf" is used.
-
-
+ See also
- This function was written by Attila Egri-Nagy and Manuel Delgado with some
- minor changes by J. D. Mitchell.
- Splash(DotDigraph(RandomDigraph(4)));
-]]>
-
-
+
+
+
<#/GAPDoc>
-<#GAPDoc Label="DotDigraph">
+<#GAPDoc Label="DotColoredDigraph">
-
-
-
-
-
+
+
+
+
+
+
A string.
- DotDigraph produces a graphical representation of the digraph
- digraph. Vertices are displayed as circles, numbered consistently
- with digraph. Edges are displayed as arrowed lines between
- vertices, with the arrowhead of each line pointing towards the range
- of the edge.
-
- DotColoredDigraph differs from DotDigraph only in
- that the values in given in the two lists are used to color the vertices and
- edges of the graph when displayed. The list for vertex colours should be
- a list of length equal to the number of vertices, containing strings that
- are accepted by the graphviz software, which is the one used for graph
- representation. The list for edge colours should be a list of lists
- with the same shape of the outneighbours of the digraph that contains strings
- that correspond to colours accepted by the graphviz software. If the lists
- are not the appropriate size, or have holes then the function will return
- an error.
-
- DotVertexColoredDigraph differs from DotDigraph only in
- that the values in given in the list are used to color the vertices
- of the graph when displayed. The list for vertex colours should be
- a list of length equal to the number of vertices, containing strings that
- are accepted by the graphviz software, which is the one used for graph
- representation. If the list is not the appropriate size, or has holes
- then the function will return an error.
-
- DotEdgeColoredDigraph differs from DotDigraph only in
- that the values in given in the list are used to color the vertices and
- edges of the graph when displayed. The list for edge colours should be a list
- of lists with the same shape of the outneighbours of the digraph that contains
- strings that correspond to colours accepted by the graphviz software. If the
- list is not the appropriate size, or has holes then the function will return
- an error.
-
- DotVertexLabelledDigraph differs from DotDigraph only in
- that the values in are used to label
- the vertices in the produced picture rather than the numbers 1 to
- the number of vertices of the digraph.
-
- The output is in dot format (also known as GraphViz)
- format. For details about this file format, and information about how to
- display or edit this format see https://www.graphviz.org.
-
- The string returned by DotDigraph or
- DotVertexLabelledDigraph can be written to a file using
- the command .
- adj := List([1 .. 4], x -> [1, 1, 1, 1]);
-[ [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ] ]
-gap> adj[1][3] := 0;
-0
-gap> gr := DigraphByAdjacencyMatrix(adj);
-
-gap> D := CompleteDigraph(4);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
-gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];; edgecolors[4] := [];;
-gap> edgecolors[1][2] := "lightblue";;
-gap> edgecolors[1][3] := "pink";;
-gap> edgecolors[1][4] := "purple";;
-gap> edgecolors[2][1] := "lightblue";;
-gap> edgecolors[2][3] := "pink";;
-gap> edgecolors[2][4] := "purple";;
-gap> edgecolors[3][1] := "lightblue";;
-gap> edgecolors[3][2] := "pink";;
-gap> edgecolors[3][4] := "purple";;
-gap> edgecolors[4][1] := "lightblue";;
-gap> edgecolors[4][2] := "pink";;
-gap> edgecolors[4][3] := "purple";;
-gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=blue, style=filled]
-2[color=red, style=filled]
-3[color=green, style=filled]
-4[color=yellow, style=filled]
-1 -> 2[color=lightblue]
-1 -> 3[color=pink]
-1 -> 4[color=purple]
-2 -> 1[color=lightblue]
-2 -> 3[color=pink]
-2 -> 4[color=purple]
-3 -> 1[color=lightblue]
-3 -> 2[color=pink]
-3 -> 4[color=purple]
-4 -> 1[color=lightblue]
-4 -> 2[color=pink]
-4 -> 3[color=purple]
-}
-gap> D := EmptyDigraph(3);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
-gap> vertcolors[3] := "green";;
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];;
-gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=blue, style=filled]
-2[color=red, style=filled]
-3[color=green, style=filled]
-}
-gap> D := Digraph([[2], [1, 3], [2]]);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";;
-gap> vertcolors[2] := "pink";;
-gap> vertcolors[3] := "purple";;
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];;
-gap> edgecolors[1][2] := "green";; edgecolors[2][1] := "green";;
-gap> edgecolors[2][3] := "red";; edgecolors[3][2] := "red";;
-gap> Print(DotSymmetricColoredDigraph(D, vertcolors, edgecolors));
-//dot
-graph hgn{
-node [shape=circle]
-
-1[color=blue, style=filled]
-2[color=pink, style=filled]
-3[color=purple, style=filled]
-1 -- 2[color=green]
-2 -- 3[color=red]
-}
-gap> D := Digraph([[2, 3], [1, 3], [1]]);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
-gap> vertcolors[3] := "green";;
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];;
-gap> edgecolors[1][2] := "orange";; edgecolors[1][3] := "yellow";;
-gap> edgecolors[2][1] := "orange";; edgecolors[2][3] := "pink";;
-gap> edgecolors[3][1] := "yellow";;
-gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));;
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=blue, style=filled]
-2[color=red, style=filled]
-3[color=green, style=filled]
-1 -> 2[color=orange]
-1 -> 3[color=yellow]
-2 -> 1[color=orange]
-2 -> 3[color=pink]
-3 -> 1[color=yellow]
-}
-gap> D := Digraph(IsMutableDigraph, [[2, 3], [1, 3], [1]]);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
-gap> vertcolors[3] := "green";;
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];;
-gap> edgecolors[1][2] := "orange";; edgecolors[1][3] := "yellow";;
-gap> edgecolors[2][1] := "orange";; edgecolors[2][3] := "pink";;
-gap> edgecolors[3][1] := "yellow";;
-gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));;
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=blue, style=filled]
-2[color=red, style=filled]
-3[color=green, style=filled]
-1 -> 2[color=orange]
-1 -> 3[color=yellow]
-2 -> 1[color=orange]
-2 -> 3[color=pink]
-3 -> 1[color=yellow]
-}
-gap> D;
-
-gap> DotSymmetricDigraph(gr2){[12 .. 70]};
-" hgn{\nnode [shape=circle]\n\n1\n2\n3\n4\n1 -- 2\n2 -- 3\n3 -- 3\n3 -"
-gap> DotSymmetricDigraph(gr1);
-Error, the argument must be a symmetric digraph,
-gap> D := CompleteDigraph(4);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
-gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
-gap> Print(DotVertexColoredDigraph(D, vertcolors));
-//dot
-digraph hgn{
-node [shape=circle]
-1[color=blue, style=filled]
-2[color=red, style=filled]
-3[color=green, style=filled]
-4[color=yellow, style=filled]
-1 -> 2
-1 -> 3
-1 -> 4
-2 -> 1
-2 -> 3
-2 -> 4
-3 -> 1
-3 -> 2
-3 -> 4
-4 -> 1
-4 -> 2
-4 -> 3
-}
-gap> D := CompleteDigraph(4);
-
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];; edgecolors[4] := [];;
-gap> edgecolors[1][2] := "lightblue";;
-gap> edgecolors[1][3] := "pink";;
-gap> edgecolors[1][4] := "purple";;
-gap> edgecolors[2][1] := "lightblue";;
-gap> edgecolors[2][3] := "pink";;
-gap> edgecolors[2][4] := "purple";;
-gap> edgecolors[3][1] := "lightblue";;
-gap> edgecolors[3][2] := "pink";;
-gap> edgecolors[3][4] := "purple";;
-gap> edgecolors[4][1] := "lightblue";;
-gap> edgecolors[4][2] := "pink";;
-gap> edgecolors[4][3] := "purple";;
-gap> Print(DotEdgeColoredDigraph(D, edgecolors));
-//dot
-digraph hgn{
-node [shape=circle]
-1
-2
-3
-4
-1 -> 2[color=lightblue]
-1 -> 3[color=pink]
-1 -> 4[color=purple]
-2 -> 1[color=lightblue]
-2 -> 3[color=pink]
-2 -> 4[color=purple]
-3 -> 1[color=lightblue]
-3 -> 2[color=pink]
-3 -> 4[color=purple]
-4 -> 1[color=lightblue]
-4 -> 2[color=pink]
-4 -> 3[color=purple]
-}
-gap> FileString("dot/k4.dot", DotDigraph(gr));
-154]]>
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+
+
+
+
+
+
+
+
+ These functions return mutable &GAP; objects representing graphviz
+ objects, which provide a more flexible means of tailoring pictures of
+ graphs and digraphs to your needs. The Dot variants of these
+ functions are synonymous with, for example,
+ AsString(GraphvizDigraph(D)). It is also possible to use
+ directly on the graphviz objects
+ returned by the Graphviz variants of these functions, i.e.
+ Splash(GraphvizDigraph(D)) does precisely the same thing as
+ Splash(DotDigraph(D)).
<#/GAPDoc>
-<#GAPDoc Label="DotSymmetricDigraph">
+<#GAPDoc Label="GraphvizColoredDigraph">
-
-
-
-
- A string.
+
+
+
+
+
+
+ A &graphviz; object.
- This function produces a graphical representation of the symmetric
- digraph digraph. DotSymmetricDigraph will return an
- error if digraph is not a symmetric digraph. See
- .
-
- The function DotSymmetricColoredDigraph differs from DotDigraph
- only in that the values given in the two lists are used to color the vertices
- and edges of the graph when displayed. The list for vertex colours should be
- a list of length equal to the number of vertices, containing strings that
- are accepted by the graphviz software, which is the one used for graph
- representation. The list for edge colours should be a list of lists
- with the same shape of the outneighbours of the digraph that contains strings
- that correspond to colours accepted by the graphviz software.
- If the list is not the appropriate size, or has holes then the function
- will return an error.
-
- The function DotSymmetricVertexColoredDigraph differs from DotDigraph
- only in that the values in given in the list is used to color the vertices
- of the graph when displayed. The list for vertex colours should be
- a list of length equal to the number of vertices, containing strings that
- are accepted by the graphviz software, which is the one used for graph
- representation. If the list is not the appropriate size, or has holes
- then the function will return an error.
-
- The function DotSymmetricEdgeColoredDigraph differs from DotDigraph
- only in that the values given in the list are used to color the edges
- of the graph when displayed. The list for edge colours should be
- a list of lists with the same shape of the outneighbours, containing strings that
- are accepted by the graphviz software, which is the one used for graph
- representation. If the list is not the appropriate size, or has holes
- then the function will return an error.
-
- Vertices are displayed as circles, numbered consistently with
- digraph. Since digraph is symmetric, for every non-loop
- edge there is a complementary edge with opposite source and range.
- DotSymmetricDigraph displays each pair of complementary edges
- as a single line between the relevant vertices, with no arrowhead.
-
- The output is in dot format (also known as GraphViz)
- format. For details about this file format, and information about how
- to display or edit this format see
- https://www.graphviz.org.
-
- The string returned by DotSymmetricDigraph can be written to a
- file using the command .
-
- star := Digraph([[2, 2, 3, 4], [1, 1], [1], [1, 4]]);
-
-gap> IsSymmetricDigraph(star);
-true
-gap> FileString("dot/star.dot", DotSymmetricDigraph(gr));
-gap> D := Digraph([[2], [1, 3], [2]]);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";;
-gap> vertcolors[2] := "pink";;
-gap> vertcolors[3] := "purple";;
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];;
-gap> edgecolors[1][2] := "green";; edgecolors[2][1] := "green";;
-gap> edgecolors[2][3] := "red";; edgecolors[3][2] := "red";;
-gap> Print(DotSymmetricColoredDigraph(D, vertcolors, edgecolors));
-//dot
-graph hgn{
-node [shape=circle]
-
-1[color=blue, style=filled]
-2[color=pink, style=filled]
-3[color=purple, style=filled]
-1 -- 2[color=green]
-2 -- 3[color=red]
-}
-gap> D := Digraph([[2], [1, 3], [2]]);
-
-gap> vertcolors := [];;
-gap> vertcolors[1] := "blue";;
-gap> vertcolors[2] := "pink";;
-gap> vertcolors[3] := "purple";;
-gap> Print(DotSymmetricVertexColoredDigraph(D, vertcolors));
-//dot
-graph hgn{
-node [shape=circle]
-
-1[color=blue, style=filled]
-2[color=pink, style=filled]
-3[color=purple, style=filled]
-1 -- 2
-2 -- 3
-}
+ These operations produce colored &graphviz; objects representing the
+ digraph D according to the specified colors. For all of these
+ functions valid colors are strings containing:
+
+ RGB
+ -
+ An RGB color code consisting of 6 hexadecimal digits preceded by
+ a #. For example, #ff00ff.
+
+ GraphViz 2.4.11 X11 Color Scheme
+ -
+ One of the color strings specified at:
+ http://graphviz.org/doc/info/colors.html
+
+
+
+ GraphvizVertexColoredDigraph and GraphvizVertexColoredGraph
+ requires its argument colors to be a list of length equal to the
+ number of vertices of D consisting of strings representing colors
+ as described above.
+
+
+ GraphvizEdgeColoredDigraph and GraphvizEdgeColoredGraph
+ requires its argument colors to be a list of lists with the same
+ shape of the out-neighbours of the digraph D consisting of strings
+ representing colors as described above.
+
+
+ GraphvizColoredDigraph and GraphvizColoredGraph requires
+ its arguments:
+
+ vert_colors
+ -
+ to represent vertex colors as described for
+ GraphvizVertexColoredDigraph;
+
+ edge_colors
+ -
+ to represent edge colors as described for
+ GraphvizEdgeColoredDigraph;
+
+
+
+ See the &graphviz; package documentation for more details.
+
+
+ See also
+ D := Digraph([[2], [1, 3], [2]]);
-gap> edgecolors := [];;
-gap> edgecolors[1] := [];; edgecolors[2] := [];;
-gap> edgecolors[3] := [];;
-gap> edgecolors[1][2] := "green";; edgecolors[2][1] := "green";;
-gap> edgecolors[2][3] := "red";; edgecolors[3][2] := "red";;
-gap> Print(DotSymmetricEdgeColoredDigraph(D, edgecolors));
-//dot
-graph hgn{
-node [shape=circle]
-
-1
-2
-3
-1 -- 2[color=green]
-2 -- 3[color=red]
-}
-83]]>
+gap> vert_colors := ["blue", "pink", "purple"];;
+gap> edge_colors := [["green"], ["green", "red"], ["red"]];;
+gap> GraphvizVertexColoredDigraph(D, vert_colors);
+
+gap> GraphvizVertexColoredGraph(D, vert_colors);
+
+gap> GraphvizEdgeColoredDigraph(D, edge_colors);
+
+gap> GraphvizEdgeColoredGraph(D, edge_colors);
+
+gap> GraphvizColoredDigraph(D, vert_colors, edge_colors);
+
+gap> GraphvizColoredGraph(D, vert_colors, edge_colors);
+
+]]>
-<#/GAPDoc>
+ <#/GAPDoc>
<#GAPDoc Label="DotPartialOrderDigraph">
A string.
- This function produces a graphical representation of a partial order
- digraph digraph. DotPartialOrderDigraph will return an error
- if digraph is not a partial order digraph. See .
-
- Since digraph is a partial order, it is both reflexive and
- transitive. The output of DotPartialOrderDigraph is the
- of the
- of digraph.
-
- The output is in dot format (also known as GraphViz)
- format. For details about this file format, and information about how
- to display or edit this format see
- https://www.graphviz.org.
-
- The string returned by DotPartialOrderDigraph can be written to a
- file using the command .
-
- poset := Digraph([[1, 4], [2], [2, 3, 4], [4]);
-gap> IsPartialOrderDigraph(gr);
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+
+
+
+ This function return a mutable &GAP; object representing a graphviz
+ object, which provides a more flexible means of tailoring pictures of
+ graphs and digraphs to your needs. The Dot variants of these
+ functions are synonymous with, for example,
+ AsString(GraphvizDigraph(D)). It is also possible to use
+ directly on the graphviz objects
+ returned by the Graphviz variants of these functions, i.e.
+ Splash(GraphvizDigraph(D)) does precisely the same thing as
+ Splash(DotDigraph(D)).
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="GraphvizPartialOrderDigraph">
+
+
+ A &graphviz; object.
+
+ This function produces a &graphviz; object representing a partial order
+ digraph D. GraphvizPartialOrderDigraph will return an
+ error if D is not a partial order digraph. See .
+
+ Since D is a partial order, it is both reflexive and
+ transitive. The output of GraphvizPartialOrderDigraph is the
+ of the
+ of D.
+
+ See the &graphviz; package documentation for more details.
+
+
+ See also
+ D := Digraph([[1, 4], [2], [2, 3, 4], [4]]);
+
+gap> IsPartialOrderDigraph(D);
true
-gap> FileString("dot/poset.dot", DotPartialOrderDigraph(gr));
-83]]>
+gap> GraphvizPartialOrderDigraph(D);
+]]>
<#/GAPDoc>
@@ -523,65 +287,119 @@ gap> FileString("dot/poset.dot", DotPartialOrderDigraph(gr));
A string.
- This function produces a graphical representation of a preorder
- digraph digraph. DotPreorderDigraph will return an error
- if digraph is not a preorder digraph. See [WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+ ]
+
+
+
+ These functions return mutable &GAP; objects representing graphviz
+ objects, which provide a more flexible means of tailoring pictures of
+ graphs and digraphs to your needs. The Dot variants of these
+ functions are synonymous with, for example,
+ AsString(GraphvizDigraph(D)). It is also possible to use
+ directly on the graphviz objects
+ returned by the Graphviz variants of these functions, i.e.
+ Splash(GraphvizDigraph(D)) does precisely the same thing as
+ Splash(DotDigraph(D)).
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="GraphvizPreorderDigraph">
+
+
+
+ A &graphviz; object.
+
+ These functions produce &graphviz; objects representing a preorder
+ digraph D. These function will give an error
+ if D is not a preorder digraph. See .
A preorder digraph is reflexive and transitive but in general it is
not anti-symmetric and may have strongly connected components
containing more than one vertex. The
- Q obtained by forming the quotient of digraph by the
+ Q obtained by forming the quotient of D by the
partition of its vertices into the strongly connected components
satisfies . Thus every vertex of
- Q corresponds to a strongly connected component of digraph.
- The output of DotPreorderDigraph displays the
+ Q corresponds to a strongly connected component of D.
+ The output of GraphvizPreorderDigraph displays the
of Q with
vertices displayed as rounded rectangles labelled by all of the vertices
- of digraph in the corresponding strongly connected component.
+ of D in the corresponding strongly connected component.
+
- The output is in dot format (also known as GraphViz)
- format. For details about this file format, and information about how
- to display or edit this format see
- https://www.graphviz.org.
+ See the &graphviz; package documentation for more details.
+
- The string returned by DotPreorderDigraph can be written to a
- file using the command .
+ See also
- preset := Digraph([[1, 2, 4, 5], [1, 2, 4, 5], [3, 4], [4], [1, 2, 4, 5]);
-gap> IsPreorderDigraph(gr);
+ D := Digraph([[1, 2, 4, 5], [1, 2, 4, 5], [3, 4], [4],
+> [1, 2, 4, 5]]);
+
+gap> IsPreorderDigraph(D);
true
-gap> FileString("dot/preset.dot", DotProrderDigraph(gr));
-83]]>
+gap> GraphvizPreorderDigraph(D);
+]]>
<#/GAPDoc>
<#GAPDoc Label="DotHighlightedDigraph">
-
+
A string.
- DotHighlightedDigraph produces a graphical representation of the
- digraph digraph, where the vertices in the list verts, and
- edges between them, are drawn with colour colour1 and all other
- vertices and edges in digraph are drawn with colour colour2.
- If colour1 and colour2 are not given then
- DotHighlightedDigraph uses black and grey respectively.
-
- Note that DotHighlightedDigraph does not validate the colours
- colour1 and colour2 - consult the GraphViz documentation to
- see what is available.
-
- See for more details on the output.
-
- digraph := Digraph([[2, 3], [2], [1, 3]]);
-
-gap> FileString("dot/my_digraph.dot",
-> DotHighlightedDigraph(digraph, [1, 2], "red", "black"));
-264]]>
+ WARNING! As of v2.0.0 of &Digraphs; these functions are
+ deprecated in favour of:
+
+
+
+
+ These functions return mutable &GAP; objects representing graphviz
+ objects, which provide a more flexible means of tailoring pictures of
+ graphs and digraphs to your needs. The Dot variants of these
+ functions are synonymous with, for example,
+ AsString(GraphvizDigraph(D)). It is also possible to use
+ directly on the graphviz objects
+ returned by the Graphviz variants of these functions, i.e.
+ Splash(GraphvizDigraph(D)) does precisely the same thing as
+ Splash(DotDigraph(D)).
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="GraphvizHighlightedDigraph">
+
+
+
+ A &graphviz; object.
+
+ These functions produce &graphviz; objects representing the digraph
+ D, where the vertices in the list verts, and edges
+ between them, are drawn with color color1 and all other vertices
+ and edges in D are drawn with color color2. If
+ color1 and color2 are not given, then these functions
+ use \"black\" and \"grey\" respectively.
+
+
+ See and
+ for more details on the output.
+
+ D := Digraph([[2, 3], [2], [1, 3]]);
+
+gap> GraphvizHighlightedDigraph(D, [1, 2], "red", "black");
+
+gap> D := DigraphSymmetricClosure(D);
+
+gap> GraphvizHighlightedGraph(D, [1, 2], "red", "black");
+]]>
<#/GAPDoc>
diff --git a/doc/z-chap9.xml b/doc/z-chap9.xml
index 42adee63f..37891bec0 100644
--- a/doc/z-chap9.xml
+++ b/doc/z-chap9.xml
@@ -1,11 +1,22 @@
Visualising and IO
Visualising a digraph
- <#Include Label="Splash">
+ <#Include Label="GraphvizDigraph">
<#Include Label="DotDigraph">
- <#Include Label="DotSymmetricDigraph">
+
+ <#Include Label="GraphvizColoredDigraph">
+ <#Include Label="DotColoredDigraph">
+
+ <#Include Label="GraphvizVertexLabelledDigraph">
+ <#Include Label="DotVertexLabelledDigraph">
+
+ <#Include Label="GraphvizPartialOrderDigraph">
<#Include Label="DotPartialOrderDigraph">
+
+ <#Include Label="GraphvizPreorderDigraph">
<#Include Label="DotPreorderDigraph">
+
+ <#Include Label="GraphvizHighlightedDigraph">
<#Include Label="DotHighlightedDigraph">
diff --git a/etc/code-coverage-test-c.py b/etc/code-coverage-test-c.py
new file mode 100755
index 000000000..62cd03294
--- /dev/null
+++ b/etc/code-coverage-test-c.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+"""
+"""
+
+# pylint: disable=invalid-name, broad-except
+
+import argparse
+import tempfile
+import subprocess
+import sys
+import os
+import webbrowser
+
+from os.path import exists, isfile
+
+_ERR_PREFIX = '\033[31merror: '
+
+def exec_string(string):
+ 'execute the string in a subprocess.'
+ try:
+ subprocess.check_call(string, shell=True)
+ except KeyboardInterrupt:
+ sys.exit('\033[31m\nKilled!\033[0m')
+ except (subprocess.CalledProcessError, OSError):
+ sys.exit(_ERR_PREFIX + 'executing:\n' + string + '\n failed!\033[0m')
+
+_PARSER = argparse.ArgumentParser(prog='code-coverage-test-c.py',
+ usage='%(prog)s [options]')
+_PARSER.add_argument('files', nargs='+', type=str,
+ help='the test files you want to check code coverage for'
+ + '(must be at least one)')
+_PARSER.add_argument('--gap-root', nargs='?', type=str,
+ help='the gap root directory (default: ~/gap)',
+ default='~/gap/')
+_PARSER.add_argument('--pkg', nargs='?', type=str,
+ help='the package to profile (default: None)',
+ default=None)
+_PARSER.add_argument('--build', dest='build', action='store_true',
+ help='rebuild GAP (default: False)')
+_PARSER.set_defaults(build=False)
+_PARSER.add_argument('--open', nargs='?', type=str,
+ help=('open the lcov html page for this file ' +
+ '(default: None)'),
+ default=None)
+_PARSER.add_argument('--line', nargs='?', type=str,
+ help=('open the html page for the file specified by --open' +
+ ' at this line (default: None)'),
+ default=None)
+_ARGS = _PARSER.parse_args()
+
+if not _ARGS.gap_root[-1] == '/':
+ _ARGS.gap_root += '/'
+
+_ARGS.gap_root = os.path.expanduser(_ARGS.gap_root)
+if _ARGS.pkg != None:
+ _ARGS.pkg = _ARGS.gap_root + '/pkg/' + _ARGS.pkg
+
+if not (os.path.exists(_ARGS.gap_root) and os.path.isdir(_ARGS.gap_root)):
+ sys.exit('\033[31mcode-coverage-test-c.py: error: can\'t find gap root' +
+ ' directory!\033[0m')
+if (_ARGS.pkg != None and not (os.path.exists(_ARGS.pkg) and
+ os.path.isdir(_ARGS.pkg))):
+ sys.exit('\033[31mcode-coverage-test-c.py: error: can\'t find the pkg' +
+ ' directory %s\033[0m' % _ARGS.pkg)
+for f in _ARGS.files:
+ if not (os.path.exists(f) and os.path.isfile(f)):
+ sys.exit('\033[31mcode-coverage-test-c.py: error: ' + f +
+ ' does not exist!\033[0m')
+
+_DIR = tempfile.mkdtemp()
+print('\033[35musing temporary directory: ' + _DIR + '\033[0m')
+
+_COMMANDS = 'echo "'
+for f in _ARGS.files:
+ _COMMANDS += 'Test(\\"' + f + '\\");;'
+_COMMANDS += '"'
+
+# TODO build if files changed since last build or built with the wrong flags,
+# by looking in config.log
+
+# for source in :
+# if time.ctime(os.path.getmtime(file))
+
+if _ARGS.build:
+ cwd = os.getcwd()
+ os.chdir(_ARGS.gap_root)
+ exec_string('''rm -rf bin/ && \
+ make clean && \
+ ./configure CFLAGS="-O0 -g --coverage" \
+ CXXFLAGS="-O0 -g --coverage" \
+ LDFLAGS="-O0 -g --coverage" && \
+ make -j8''')
+ if _ARGS.pkg != None:
+ os.chdir(_ARGS.pkg)
+ exec_string('rm -rf bin/ && \
+ make clean && \
+ ./configure CFLAGS="-O0 -g --coverage" \
+ CXXFLAGS="-O0 -g --coverage" \
+ LDFLAGS="-O0 -g --coverage" && \
+ make -j8''')
+ os.chdir(cwd)
+
+pro1 = subprocess.Popen(_COMMANDS, stdout=subprocess.PIPE, shell=True)
+_RUN_GAP = _ARGS.gap_root + 'bin/gap.sh -A -m 1g -T'
+
+try:
+ pro2 = subprocess.Popen(_RUN_GAP,
+ stdin=pro1.stdout,
+ shell=True)
+ pro2.wait()
+ print('')
+except KeyboardInterrupt:
+ pro1.terminate()
+ pro1.wait()
+ pro2.terminate()
+ pro2.wait()
+ print('\033[31mKilled!\033[0m')
+ sys.exit(1)
+except Exception:
+ sys.exit('\033[31mcode-coverage-test-c.py: error: something went wrong '
+ + 'calling GAP!\033[0m''')
+if _ARGS.pkg != None:
+ exec_string('lcov --capture --directory ' + _ARGS.pkg +
+ '/src --output-file ' + _DIR + '/lcov.info')
+else:
+ exec_string('lcov --capture --directory ' + _ARGS.gap_root +
+ '/src --output-file ' + _DIR + '/lcov.info')
+
+exec_string('genhtml ' + _DIR + '/lcov.info --output-directory ' + _DIR +
+ '/lcov-out')
+
+filename = _DIR + '/lcov-out/'
+if _ARGS.open:
+ filename += _ARGS.open + '.gcov.html'
+else:
+ filename += '/index.html'
+
+if exists(filename) and isfile(filename):
+ if _ARGS.open and _ARGS.line:
+ filename += '#' + _ARGS.line
+ print('file://' + filename)
+ try:
+ webbrowser.get('chrome').open('file://' + filename, new=2)
+ except Exception:
+ webbrowser.open('file://' + filename, new=2)
+else:
+ sys.exit('\n' + _ERR_PREFIX + 'Failed to open file://' + filename +
+ '\033[0m')
+
+print('\n\033[32mSUCCESS!\033[0m')
+sys.exit(0)
diff --git a/etc/code-coverage-test-gap.py b/etc/code-coverage-test-gap.py
index f52bbdf31..11c6e5666 100755
--- a/etc/code-coverage-test-gap.py
+++ b/etc/code-coverage-test-gap.py
@@ -71,7 +71,7 @@
_GAP_COMMANDS.extend(
[
"UncoverageLineByLine();;",
- rf"LoadPackage(\"profiling\", false);;",
+ r"LoadPackage(\"profiling\", false);;",
rf"filesdir := \"{getcwd()}{_PROFILE_DIR}\";;",
rf"outdir := \"{_DIR}\";;",
rf"x := ReadLineByLineProfile(\"{_DIR}/profile.gz\");;",
diff --git a/gap/deprecated.gd b/gap/deprecated.gd
new file mode 100644
index 000000000..d5b6c60c0
--- /dev/null
+++ b/gap/deprecated.gd
@@ -0,0 +1,35 @@
+#############################################################################
+##
+## deprecated.gd
+## Copyright (C) 2024 James D. Mitchell
+##
+## Licensing information can be found in the README file of this package.
+##
+#############################################################################
+##
+
+DeclareAttribute("DotDigraph", IsDigraph);
+DeclareAttribute("DotSymmetricDigraph", IsDigraph);
+
+DeclareOperation("DotSymmetricVertexColoredDigraph", [IsDigraph, IsList]);
+DeclareOperation("DotVertexColoredDigraph", [IsDigraph, IsList]);
+
+DeclareOperation("DotEdgeColoredDigraph", [IsDigraph, IsList]);
+DeclareOperation("DotSymmetricEdgeColoredDigraph", [IsDigraph, IsList]);
+
+DeclareOperation("DotColoredDigraph", [IsDigraph, IsList, IsList]);
+DeclareOperation("DotSymmetricColoredDigraph", [IsDigraph, IsList, IsList]);
+
+DeclareOperation("DotVertexLabelledDigraph", [IsDigraph]);
+
+DeclareAttribute("DotPartialOrderDigraph", IsDigraph);
+DeclareAttribute("DotPreorderDigraph", IsDigraph);
+
+DeclareSynonym("DotQuasiorderDigraph", DotPreorderDigraph);
+
+DeclareOperation("DotHighlightedDigraph", [IsDigraph, IsList]);
+DeclareOperation("DotHighlightedDigraph",
+ [IsDigraph, IsList, IsString, IsString]);
+DeclareOperation("DotHighlightedGraph", [IsDigraph, IsList]);
+DeclareOperation("DotHighlightedGraph",
+ [IsDigraph, IsList, IsString, IsString]);
diff --git a/gap/deprecated.gi b/gap/deprecated.gi
new file mode 100644
index 000000000..f2c800087
--- /dev/null
+++ b/gap/deprecated.gi
@@ -0,0 +1,116 @@
+#############################################################################
+##
+## deprecated.gi
+## Copyright (C) 2024 James D. Mitchell
+##
+## Licensing information can be found in the README file of this package.
+##
+#############################################################################
+##
+
+BindGlobal("_PrintDeprecated", function(old, arg...)
+ Info(InfoWarning, 1, "`", old, "` is deprecated and will be removed in v3",
+ " use `", Concatenation(List(arg, AsString)), "` instead!");
+end);
+
+InstallMethod(DotDigraph, "for a digraph", [IsDigraph],
+function(D)
+ _PrintDeprecated("DotDigraph", "GraphvizDigraph");
+ return AsString(GraphvizDigraph(D));
+end);
+
+InstallMethod(DotSymmetricDigraph, "for a digraph", [IsDigraph],
+function(D)
+ _PrintDeprecated("DotSymmetricDigraph", "GraphvizGraph");
+ return AsString(GraphvizGraph(D));
+end);
+
+InstallMethod(DotSymmetricVertexColoredDigraph,
+"for a digraph and list of colors",
+[IsDigraph, IsHomogeneousList],
+function(D, colors)
+ _PrintDeprecated("DotSymmetricVertexColoredDigraph",
+ "GraphvizVertexColoredGraph");
+ return AsString(GraphvizVertexColoredGraph(D, colors));
+end);
+
+InstallMethod(DotVertexColoredDigraph, "for a digraph and a list",
+[IsDigraph, IsList],
+function(D, colors)
+ _PrintDeprecated("DotVertexColoredDigraph",
+ "GraphvizVertexColoredDigraph");
+ return AsString(GraphvizVertexColoredDigraph(D, colors));
+end);
+
+InstallMethod(DotSymmetricEdgeColoredDigraph,
+"for a digraph and list of colors",
+[IsDigraph, IsHomogeneousList],
+function(D, colors)
+ _PrintDeprecated("DotSymmetricEdgeColoredDigraph",
+ "GraphvizEdgeColoredGraph");
+ return AsString(GraphvizEdgeColoredGraph(D, colors));
+end);
+
+InstallMethod(DotEdgeColoredDigraph, "for a digraph and a list",
+[IsDigraph, IsList],
+function(D, colors)
+ _PrintDeprecated("DotEdgeColoredDigraph",
+ "GraphvizEdgeColoredDigraph");
+ return AsString(GraphvizEdgeColoredDigraph(D, colors));
+end);
+
+InstallMethod(DotSymmetricColoredDigraph,
+"for a digraph, vertex colors, and edge colors",
+[IsDigraph, IsHomogeneousList, IsHomogeneousList],
+function(D, n_colors, e_colors)
+ _PrintDeprecated("DotSymmetricColoredDigraph",
+ "GraphvizColoredGraph");
+ return AsString(GraphvizColoredGraph(D, n_colors, e_colors));
+end);
+
+InstallMethod(DotColoredDigraph,
+"for a digraph, vertex colors, and edge colors",
+[IsDigraph, IsHomogeneousList, IsHomogeneousList],
+function(D, n_colors, e_colors)
+ _PrintDeprecated("DotColoredDigraph",
+ "GraphvizColoredDigraph");
+ return AsString(GraphvizColoredDigraph(D, n_colors, e_colors));
+end);
+
+InstallMethod(DotVertexLabelledDigraph, "for a digraph", [IsDigraph],
+function(D)
+ _PrintDeprecated("DotVertexLabelledDigraph",
+ "GraphvizVertexLabelledDigraph");
+ return AsString(GraphvizVertexLabelledDigraph(D));
+end);
+
+InstallMethod(DotPartialOrderDigraph, "for a digraph", [IsDigraph],
+function(D)
+ _PrintDeprecated("DotPartialOrderDigraph",
+ "GraphvizPartialOrderDigraph");
+ return AsString(GraphvizPartialOrderDigraph(D));
+end);
+
+InstallMethod(DotPreorderDigraph, "for a digraph", [IsDigraph],
+function(D)
+ _PrintDeprecated("DotPreorderDigraph",
+ "GraphvizPreorderDigraph");
+ return AsString(GraphvizPreorderDigraph(D));
+end);
+
+InstallMethod(DotHighlightedDigraph,
+"for a digraph, list, and two strings",
+[IsDigraph, IsList, IsString, IsString],
+function(D, hi_verts, hi, lo)
+ _PrintDeprecated("DotHighlightedDigraph",
+ "GraphvizHighlightedDigraph");
+ return AsString(GraphvizHighlightedDigraph(D, hi_verts, hi, lo));
+end);
+
+InstallMethod(DotHighlightedDigraph, "for a digraph and list",
+[IsDigraph, IsList],
+function(D, list)
+ _PrintDeprecated("DotHighlightedDigraph",
+ "GraphvizHighlightedDigraph");
+ return AsString(GraphvizHighlightedDigraph(D, list, "black", "grey"));
+end);
diff --git a/gap/display.gd b/gap/display.gd
index 5916ef9b9..93a9c937a 100644
--- a/gap/display.gd
+++ b/gap/display.gd
@@ -1,4 +1,4 @@
-#############################################################################
+############################################################################
##
## display.gd
## Copyright (C) 2017-19 James D. Mitchell
@@ -8,18 +8,57 @@
#############################################################################
##
-DeclareAttribute("DotDigraph", IsDigraph);
-DeclareOperation("DotColoredDigraph", [IsDigraph, IsList, IsList]);
-DeclareOperation("DotVertexColoredDigraph", [IsDigraph, IsList]);
-DeclareOperation("DotEdgeColoredDigraph", [IsDigraph, IsList]);
-DeclareOperation("DotVertexLabelledDigraph", [IsDigraph]);
-DeclareAttribute("DotSymmetricDigraph", IsDigraph);
-DeclareOperation("DotSymmetricColoredDigraph", [IsDigraph, IsList, IsList]);
-DeclareOperation("DotSymmetricVertexColoredDigraph", [IsDigraph, IsList]);
-DeclareOperation("DotSymmetricEdgeColoredDigraph", [IsDigraph, IsList]);
-DeclareAttribute("DotPartialOrderDigraph", IsDigraph);
-DeclareAttribute("DotPreorderDigraph", IsDigraph);
-DeclareSynonym("DotQuasiorderDigraph", DotPreorderDigraph);
-DeclareOperation("DotHighlightedDigraph", [IsDigraph, IsList]);
-DeclareOperation("DotHighlightedDigraph",
+#############################################################################
+# Graphs and digraphs
+#############################################################################
+
+DeclareOperation("GraphvizDigraph", [IsDigraph]);
+DeclareOperation("GraphvizGraph", [IsDigraph]);
+
+#############################################################################
+# Vertex coloured graphs and digraphs
+#############################################################################
+
+DeclareOperation("GraphvizVertexColoredDigraph", [IsDigraph, IsList]);
+DeclareOperation("GraphvizVertexColoredGraph", [IsDigraph, IsList]);
+
+#############################################################################
+# Edge coloured graphs and digraphs
+#############################################################################
+
+DeclareOperation("GraphvizEdgeColoredDigraph", [IsDigraph, IsList]);
+DeclareOperation("GraphvizEdgeColoredGraph", [IsDigraph, IsList]);
+
+#############################################################################
+# Vertex and edge coloured graphs and digraphs
+#############################################################################
+
+DeclareOperation("GraphvizColoredDigraph", [IsDigraph, IsList, IsList]);
+DeclareOperation("GraphvizColoredGraph", [IsDigraph, IsList, IsList]);
+
+#############################################################################
+# Vertex labelled graphs and digraphs
+#############################################################################
+
+DeclareOperation("GraphvizVertexLabelledDigraph", [IsDigraph]);
+DeclareOperation("GraphvizVertexLabelledGraph", [IsDigraph]);
+
+#############################################################################
+# Partial and preorder digraphs
+#############################################################################
+
+DeclareAttribute("GraphvizPartialOrderDigraph", IsDigraph);
+DeclareAttribute("GraphvizPreorderDigraph", IsDigraph);
+
+DeclareSynonym("GraphvizQuasiorderDigraph", GraphvizPreorderDigraph);
+
+#############################################################################
+# Highlighted subdigraphs
+#############################################################################
+
+DeclareOperation("GraphvizHighlightedDigraph", [IsDigraph, IsList]);
+DeclareOperation("GraphvizHighlightedDigraph",
+ [IsDigraph, IsList, IsString, IsString]);
+DeclareOperation("GraphvizHighlightedGraph", [IsDigraph, IsList]);
+DeclareOperation("GraphvizHighlightedGraph",
[IsDigraph, IsList, IsString, IsString]);
diff --git a/gap/display.gi b/gap/display.gi
index 44db21e7f..fe7acd3eb 100644
--- a/gap/display.gi
+++ b/gap/display.gi
@@ -1,514 +1,316 @@
#############################################################################
##
## display.gi
-## Copyright (C) 2014-21 James D. Mitchell
+## Copyright (C) 2014-24 James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
-# AN's code, adapted by WW
-
-BindGlobal("DIGRAPHS_DotDigraph",
-function(D, node_funcs, edge_funcs)
- local str, out, i, func, j, l;
- str := "//dot\n";
- Append(str, "digraph hgn{\n");
- Append(str, "node [shape=circle]\n");
- for i in DigraphVertices(D) do
- Append(str, StringFormatted("{}", i));
- for func in node_funcs do
- Append(str, func(i));
- od;
- Append(str, "\n");
+
+# TODO:
+# * add graph6 string or whatever as a comment at the start of the string
+# * check JupyterInterface Splash function
+# * for edge colored non-digraphs, should ensure that the edge colors are
+# symmetric, i.e. the same colors for x -> y and y -> x
+
+#############################################################################
+# Graphs and digraphs
+#############################################################################
+
+InstallOtherMethod(GraphvizDigraph, "for a digraph by out-neighbours",
+[IsDigraphByOutNeighboursRep],
+function(D)
+ local gv, x, y;
+ gv := GraphvizDigraph("hgn");
+ GraphvizSetAttr(gv, "node [shape=circle]");
+ for x in DigraphVertices(D) do
+ GraphvizAddNode(gv, x);
od;
- out := OutNeighbours(D);
- for i in DigraphVertices(D) do
- l := Length(out[i]);
- for j in [1 .. l] do
- Append(str, StringFormatted("{} -> {}", i, out[i][j]));
- for func in edge_funcs do
- Append(str, func(i, j));
- od;
- Append(str, "\n");
+ for x in DigraphVertices(D) do
+ for y in OutNeighboursOfVertexNC(D, x) do
+ GraphvizAddEdge(gv, x, y);
od;
od;
- Append(str, "}\n");
- return str;
-end);
-
-BindGlobal("DIGRAPHS_ValidRGBValue",
-function(str)
- local l, chars, x, i;
- l := Length(str);
- x := 0;
- chars := "0123456789ABCDEFabcdef";
- if l = 7 then
- if str[1] = '#' then
- for i in [2 .. l] do
- if str[i] in chars then
- x := x + 1;
- fi;
- od;
- fi;
- fi;
- return x = (l - 1);
-end);
-
-BindGlobal("DIGRAPHS_GraphvizColorsList", fail);
-
-BindGlobal("DIGRAPHS_GraphvizColors",
-function()
- local f;
- if DIGRAPHS_GraphvizColorsList = fail then
- f := IO_File(Concatenation(DIGRAPHS_Dir(), "/data/colors.p"));
- MakeReadWriteGlobal("DIGRAPHS_GraphvizColorsList");
- DIGRAPHS_GraphvizColorsList := IO_Unpickle(f);
- MakeReadOnlyGlobal("DIGRAPHS_GraphvizColorsList");
- IO_Close(f);
- fi;
- return DIGRAPHS_GraphvizColorsList;
+ return gv;
end);
-BindGlobal("DIGRAPHS_ValidVertColors",
-function(D, verts)
- local v, sum, colors, col;
- v := DigraphVertices(D);
- sum := 0;
- if Length(verts) <> Length(v) then
- ErrorNoReturn("the number of vertex colors must be the same as the number",
- " of vertices, expected ", Length(v), " but found ", Length(verts), "");
+InstallOtherMethod(GraphvizGraph, "for a digraph by out-neighbours",
+[IsDigraphByOutNeighboursRep],
+function(D)
+ local gv, x, y;
+ if not IsSymmetricDigraph(D) then
+ ErrorNoReturn("the argument (a digraph) must be symmetric");
fi;
- colors := DIGRAPHS_GraphvizColors();
- if Length(verts) = Length(v) then
- for col in verts do
- if not IsString(col) then
- ErrorNoReturn("expected a string");
- elif DIGRAPHS_ValidRGBValue(col) = false and
- (col in colors) = false then
- ErrorNoReturn("expected RGB Value or valid color name as defined",
- " by GraphViz 2.44.1 X11 Color Scheme",
- " http://graphviz.org/doc/info/colors.html");
- else
- sum := sum + 1;
+ gv := GraphvizGraph("hgn");
+ GraphvizSetAttr(gv, "node [shape=circle]");
+ for x in DigraphVertices(D) do
+ GraphvizAddNode(gv, x);
+ od;
+ for x in DigraphVertices(D) do
+ for y in OutNeighboursOfVertexNC(D, x) do
+ if x > y then
+ GraphvizAddEdge(gv, x, y);
fi;
od;
- if sum = Length(verts) then
- return true;
- fi;
- fi;
+ od;
+ return gv;
end);
-BindGlobal("DIGRAPHS_ValidEdgeColors",
-function(D, edge)
- local out, l, counter, sum, colors, v, col;
- out := OutNeighbours(D);
- l := Length(edge);
- counter := 0;
- sum := 0;
- colors := DIGRAPHS_GraphvizColors();
- if Length(edge) <> Length(out) then
- ErrorNoReturn("the list of edge colors needs to have the",
- " same shape as the out-neighbours of the digraph");
- else
- for v in [1 .. l] do
- sum := 0;
- if Length(out[v]) <> Length(edge[v]) then
- ErrorNoReturn("the list of edge colors needs to have the",
- " same shape as the out-neighbours of the digraph");
- else
- for col in edge[v] do
- if not IsString(col) then
- ErrorNoReturn("expected a string");
- elif DIGRAPHS_ValidRGBValue(col) = false and
- (col in colors) = false then
- ErrorNoReturn("expected RGB Value or valid color name as defined",
- " by GraphViz 2.44.1 X11 Color Scheme",
- " http://graphviz.org/doc/info/colors.html");
- else
- sum := sum + 1;
- fi;
- od;
- if sum = Length(edge[v]) then
- counter := counter + 1;
- fi;
- fi;
- od;
- if counter = Length(edge) then
- return true;
- fi;
- fi;
-end);
+#############################################################################
+# Vertex coloured graphs and digraphs
+#############################################################################
-InstallMethod(DotDigraph, "for a digraph by out-neighbours",
-[IsDigraphByOutNeighboursRep],
-D -> DIGRAPHS_DotDigraph(D, [], []));
-
-InstallMethod(DotColoredDigraph,
-"for a digraph by out-neighbours and two lists",
-[IsDigraphByOutNeighboursRep, IsList, IsList],
-function(D, vert, edge)
- local vert_func, edge_func;
- if DIGRAPHS_ValidVertColors(D, vert)
- and DIGRAPHS_ValidEdgeColors(D, edge) then
- vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]);
- edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]);
- return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]);
- fi;
-end);
+InstallMethod(GraphvizVertexColoredDigraph, "for a digraph and a list",
+[IsDigraph, IsList],
+{D, colors} -> GraphvizSetNodeColors(GraphvizDigraph(D), colors));
-InstallMethod(DotVertexColoredDigraph,
-"for a digraph by out-neighbours and a list",
-[IsDigraphByOutNeighboursRep, IsList],
-function(D, vert)
- local func;
- if DIGRAPHS_ValidVertColors(D, vert) then
- func := i -> StringFormatted("[color={}, style=filled]", vert[i]);
- return DIGRAPHS_DotDigraph(D, [func], []);
- fi;
-end);
+InstallMethod(GraphvizVertexColoredGraph, "for a digraph and a list",
+[IsDigraph, IsList],
+# IsSymmetricDigraph checked by GraphvizGraph
+{D, colors} -> GraphvizSetNodeColors(GraphvizGraph(D), colors));
-InstallMethod(DotEdgeColoredDigraph,
-"for a digraph by out-neighbours and a list",
-[IsDigraphByOutNeighboursRep, IsList],
-function(D, edge)
- local func;
- if DIGRAPHS_ValidEdgeColors(D, edge) then
- func := {i, j} -> StringFormatted("[color={}]", edge[i][j]);
- return DIGRAPHS_DotDigraph(D, [], [func]);
- fi;
-end);
+#############################################################################
+# Edge coloured graphs and digraphs
+#############################################################################
-InstallMethod(DotVertexLabelledDigraph, "for a digraph by out-neighbours",
-[IsDigraphByOutNeighboursRep],
-function(D)
- local func;
- func := i -> StringFormatted(" [label=\"{}\"]", DigraphVertexLabel(D, i));
- return DIGRAPHS_DotDigraph(D, [func], []);
-end);
+# This function is here rather than graphviz b/c otherwise if D has multiple
+# edges we can't reliably get the corresponding graphviz edge from the head and
+# tail of the edge from gv.
+BindGlobal("DIGRAPHS_ErrorIfNotEdgeColoring",
+function(D, colors)
+ local out, i;
-BindGlobal("DIGRAPHS_DotSymmetricDigraph",
-function(D, node_funcs, edge_funcs)
- local out, str, i, j, func;
- if not IsSymmetricDigraph(D) then
- ErrorNoReturn("the argument must be a symmetric digraph,");
+ out := OutNeighbours(D);
+ if Length(colors) <> Length(out) then
+ ErrorFormatted("the 2nd argument (edge colors) must have ",
+ "the same number of entries as the 1st argument ",
+ "(a digraph) has nodes, expected {} but found {}",
+ Length(out),
+ Length(colors));
fi;
- out := OutNeighbours(D);
- str := "//dot\n";
- Append(str, "graph hgn{\n");
- Append(str, "node [shape=circle]\n\n");
- for i in DigraphVertices(D) do
- Append(str, StringFormatted("{}", i));
- for func in node_funcs do
- Append(str, func(i));
- od;
- Append(str, "\n");
+ for i in [1 .. Length(colors)] do
+ if not IsList(colors[i]) then
+ ErrorFormatted("the 2nd argument (edge colors) must be ",
+ "a list of lists, found {} in position {}",
+ TNAM_OBJ(colors[i]),
+ i);
+ elif Length(out[i]) <> Length(colors[i]) then
+ ErrorFormatted("the 2nd argument (edge colors) must have ",
+ "the same shape as the out neighbours of the 1st ",
+ "argument (a digraph), in position {} expected ",
+ "a list of length {} but found list of length {}",
+ i,
+ Length(out[i]),
+ Length(colors[i]));
+ fi;
+ Perform(colors[i], ErrorIfNotValidColor);
od;
- for i in DigraphVertices(D) do
- for j in [1 .. Length(out[i])] do
- if out[i][j] >= i then
- Append(str, StringFormatted("{} -- {}", i, out[i][j]));
- for func in edge_funcs do
- Append(str, func(i, j));
- od;
- Append(str, "\n");
+end);
+
+BindGlobal("DIGRAPHS_AddEdgesAndColorsNC",
+function(D, gv, colors)
+ local out, e, n, i;
+
+ # This duplicates code in the GraphvizDigraph function because otherwise if D
+ # has multiple edges we can't reliably get the corresponding graphviz edge
+ # from the head and tail of the edge from gv.
+ out := OutNeighbours(D);
+ for n in DigraphVertices(D) do
+ for i in [1 .. Length(out[n])] do
+ if IsGraphvizDigraph(gv) or n > out[n][i] then
+ e := GraphvizAddEdge(gv, n, out[n][i]);
+ GraphvizSetAttr(e, "color", colors[n][i]);
fi;
od;
od;
- Append(str, "}\n");
- return str;
-end);
-
-InstallMethod(DotSymmetricDigraph, "for a digraph by out-neighbours",
-[IsDigraphByOutNeighboursRep],
-D -> DIGRAPHS_DotSymmetricDigraph(D, [], []));
-
-InstallMethod(DotSymmetricColoredDigraph,
-"for a digraph by out-neighbours and two lists",
-[IsDigraphByOutNeighboursRep, IsList, IsList],
-function(D, vert, edge)
- local vert_func, edge_func;
- if DIGRAPHS_ValidVertColors(D, vert)
- and DIGRAPHS_ValidEdgeColors(D, edge) then
- vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]);
- edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]);
- return DIGRAPHS_DotSymmetricDigraph(D, [vert_func], [edge_func]);
- fi;
+ return gv;
end);
-InstallMethod(DotSymmetricVertexColoredDigraph,
+InstallMethod(GraphvizEdgeColoredDigraph,
"for a digraph by out-neighbours and a list",
[IsDigraphByOutNeighboursRep, IsList],
-function(D, vert)
- local func;
- if DIGRAPHS_ValidVertColors(D, vert) then
- func := i -> StringFormatted ("[color={}, style=filled]", vert[i]);
- return DIGRAPHS_DotSymmetricDigraph(D, [func], []);
- fi;
+function(D, colors)
+ local gv;
+ DIGRAPHS_ErrorIfNotEdgeColoring(D, colors);
+ gv := GraphvizDigraph(NullDigraph(DigraphNrVertices(D)));
+ return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors);
end);
-InstallMethod(DotSymmetricEdgeColoredDigraph,
+InstallMethod(GraphvizEdgeColoredGraph,
"for a digraph by out-neighbours and a list",
[IsDigraphByOutNeighboursRep, IsList],
-function(D, edge)
- local func;
- if DIGRAPHS_ValidEdgeColors(D, edge) then
- func := {i, j} -> StringFormatted("[color={}]", edge[i][j]);
- return DIGRAPHS_DotSymmetricDigraph(D, [], [func]);
+function(D, colors)
+ local gv;
+ if not IsSymmetricDigraph(D) then
+ ErrorNoReturn("the argument (a digraph) must be symmetric");
fi;
+ DIGRAPHS_ErrorIfNotEdgeColoring(D, colors);
+ gv := GraphvizGraph(NullDigraph(DigraphNrVertices(D)));
+ return DIGRAPHS_AddEdgesAndColorsNC(D, gv, colors);
end);
-# AN's code
-
-if not IsBound(Splash) then # This function is written by A. Egri-Nagy
- BindGlobal("VizViewers",
- ["xpdf", "xdg-open", "open", "evince", "okular", "gv"]);
-
- BindGlobal("Splash",
- function(arg...)
- local str, opt, path, dir, tdir, file, viewer, type, inn, filetype, out,
- engine;
-
- if not IsString(arg[1]) then
- ErrorNoReturn("the 1st argument must be a string,");
- fi;
- str := arg[1];
-
- opt := rec();
- if IsBound(arg[2]) and IsRecord(arg[2]) then
- opt := arg[2];
- elif IsBound(arg[2]) then
- ErrorNoReturn("the 2nd argument must be a record,");
- fi;
-
- # path
- path := UserHomeExpand("~/"); # default
- if IsBound(opt.path) then
- path := opt.path;
- fi;
-
- # directory
- if IsBound(opt.directory) then
- if not opt.directory in DirectoryContents(path) then
- Exec(Concatenation("mkdir ", path, opt.directory));
- fi;
- dir := Concatenation(path, opt.directory, "/");
- elif IsBound(opt.path) then
- if not "tmp.viz" in DirectoryContents(path) then
- tdir := Directory(Concatenation(path, "/", "tmp.viz"));
- dir := Filename(tdir, "");
- fi;
- else
- tdir := DirectoryTemporary();
- dir := Filename(tdir, "");
- fi;
+#############################################################################
+# Vertex and edge coloured graphs and digraphs
+#############################################################################
- # file
- file := "vizpicture"; # default
- if IsBound(opt.filename) then
- file := opt.filename;
- fi;
+InstallMethod(GraphvizColoredDigraph,
+"for a digraph, list, and list",
+[IsDigraph, IsList, IsList],
+{D, n_colors, e_colors} -> GraphvizSetNodeColors(
+ GraphvizEdgeColoredDigraph(D, e_colors),
+ n_colors));
+
+InstallMethod(GraphvizColoredGraph,
+"for a digraph, list, and list",
+[IsDigraph, IsList, IsList],
+# IsSymmetricDigraph checked by GraphvizEdgeColoredGraph
+{D, n_colors, e_colors} -> GraphvizSetNodeColors(
+ GraphvizEdgeColoredGraph(D, e_colors),
+ n_colors));
- # viewer
- if IsBound(opt.viewer) then
- viewer := opt.viewer;
- if not IsString(viewer) then
- ErrorNoReturn("the option `viewer` must be a string, not an ",
- TNAM_OBJ(viewer), ",");
- elif Filename(DirectoriesSystemPrograms(), viewer) = fail then
- ErrorNoReturn("the viewer \"", viewer, "\" specified in the option ",
- "`viewer` is not available,");
- fi;
- else
- viewer := First(VizViewers, x ->
- Filename(DirectoriesSystemPrograms(), x) <> fail);
- if viewer = fail then
- ErrorNoReturn("none of the default viewers ", VizViewers,
- " is available, please specify an available viewer",
- " in the options record component `viewer`,");
- fi;
- fi;
-
- # type
- if IsBound(opt.type) and (opt.type = "latex" or opt.type = "dot") then
- type := opt.type;
- elif Length(str) >= 6 and str{[1 .. 6]} = "%latex" then
- type := "latex";
- elif Length(str) >= 5 and str{[1 .. 5]} = "//dot" then
- type := "dot";
- else
- ErrorNoReturn("the component \"type\" of the 2nd argument ",
- " must be \"dot\" or \"latex\",");
- fi;
- if type = "latex" then
- inn := Concatenation(dir, file, ".tex");
- else # type = "dot"
- inn := Concatenation(dir, file, ".dot");
- fi;
+#############################################################################
+# Vertex labelled graphs and digraphs
+#############################################################################
- # output type and name
- filetype := "pdf"; # default
- if IsBound(opt.filetype) and IsString(opt.filetype) and type <> "latex" then
- filetype := opt.filetype;
- fi;
- out := Concatenation(dir, file, ".", filetype);
-
- # engine
- engine := "dot"; # default
- if IsBound(opt.engine) then
- engine := opt.engine;
- if not engine in ["dot", "neato", "twopi", "circo",
- "fdp", "sfdp", "patchwork"] then
- ErrorNoReturn("the component \"engine\" of the 2nd argument ",
- " must be one of: \"dot\", \"neato\", ",
- "\"twopi\", \"circo\", \"fdp\", \"sfdp\", ",
- "or \"patchwork\"");
- fi;
- fi;
+InstallMethod(GraphvizVertexLabelledDigraph, "for a digraph",
+[IsDigraph],
+D -> GraphvizSetNodeLabels(GraphvizDigraph(D), DigraphVertexLabels(D)));
- # Write and compile the file
- FileString(inn, str);
- if type = "latex" then
- # Requires GAP >= 4.11:
- # Exec(StringFormatted("cd {}; pdflatex {} 2>/dev/null 1>/dev/null", dir);
- Exec(Concatenation("cd ", dir, ";",
- "pdflatex ", file, " 2>/dev/null 1>/dev/null"));
- else # type = "dot"
- # Requires GAP >= 4.11:
- # Exec(StringFormatted("{} -T {} {} -o {}", engine, filetype, inn, out));
- Exec(Concatenation(engine, " -T", filetype, " ", inn, " -o ", out));
- fi;
- Exec(Concatenation(viewer, " ", out, " 2>/dev/null 1>/dev/null &"));
- end);
-fi;
+InstallMethod(GraphvizVertexLabelledGraph, "for a digraph",
+[IsDigraph],
+# symmetry checked in GraphvizGraph
+D -> GraphvizSetNodeLabels(GraphvizGraph(D), DigraphVertexLabels(D)));
-# CR's code
+#############################################################################
+# Partial and preorder digraphs
+#############################################################################
-InstallMethod(DotPartialOrderDigraph, "for a partial order digraph",
+InstallMethod(GraphvizPartialOrderDigraph, "for a partial order digraph",
[IsDigraph],
function(D)
if not IsPartialOrderDigraph(D) then
- ErrorNoReturn("the argument must be a partial order digraph,");
+ ErrorNoReturn("the argument (a digraph) must be a partial order");
fi;
D := DigraphMutableCopyIfMutable(D);
- return DotDigraph(DigraphReflexiveTransitiveReduction(D));
+ return GraphvizDigraph(DigraphReflexiveTransitiveReduction(D));
end);
-InstallMethod(DotPreorderDigraph, "for a preorder digraph",
+InstallMethod(GraphvizPreorderDigraph, "for a preorder digraph",
[IsDigraph],
function(D)
- local comps, quo, red, str, c, x, e;
+ local comps, gv, label, node, nodes, c, x, e;
+
if not IsPreorderDigraph(D) then
- ErrorNoReturn("the argument must be a preorder digraph,");
+ ErrorNoReturn("the argument (a digraph) must be a preorder");
fi;
# Quotient by the strongly connected components to get a partial order
# D and draw this without loops or edges implied by transitivity.
- D := DigraphMutableCopyIfMutable(D);
- comps := DigraphStronglyConnectedComponents(D).comps;
- quo := DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps));
- red := DigraphReflexiveTransitiveReduction(quo);
+ comps := DigraphStronglyConnectedComponents(D).comps;
+ D := DigraphMutableCopy(D);
+ DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps));
+ DigraphReflexiveTransitiveReduction(D);
- str := "//dot\n";
- Append(str, "digraph graphname {\n");
- Append(str, "node [shape=Mrecord, height=0.5, fixedsize=true]");
- Append(str, "ranksep=1;\n");
+ gv := GraphvizDigraph("graphname");
+ GraphvizSetAttr(gv, "node [shape=\"Mrecord\"]");
+ GraphvizSetAttr(gv, "height=\"0.5\"");
+ GraphvizSetAttr(gv, "fixedsize=\"true\"");
+ GraphvizSetAttr(gv, "ranksep=\"1\"");
- # Each vertex of the quotient D is labelled by its preimage.
for c in [1 .. Length(comps)] do
- Append(str, String(c));
- Append(str, " [label=\"");
- Append(str, String(comps[c][1]));
+
+ label := "\"";
+ Append(label, String(comps[c][1]));
for x in comps[c]{[2 .. Length(comps[c])]} do
- Append(str, "|");
- Append(str, String(x));
+ Append(label, "|");
+ Append(label, String(x));
od;
- Append(str, "\", width=");
- Append(str, String(Float(Length(comps[c]) / 2)));
- Append(str, "]\n");
+ Append(label, "\"");
+
+ node := GraphvizAddNode(gv, c);
+ GraphvizSetAttr(node, "label", label);
+ GraphvizSetAttr(node, "width", Float(Length(comps[c]) / 2));
od;
- # Add the edges of the quotient D.
- for e in DigraphEdges(red) do
- Append(str, Concatenation(String(e[1]), " -> ", String(e[2]), "\n"));
+ nodes := GraphvizNodes(gv);
+ for e in DigraphEdges(D) do
+ GraphvizAddEdge(gv, nodes[e[1]], nodes[e[2]]);
od;
- Append(str, "}");
- return str;
+ return gv;
end);
-InstallMethod(DotHighlightedDigraph, "for a digraph and list",
-[IsDigraph, IsList],
-{D, list} -> DotHighlightedDigraph(D, list, "black", "grey"));
-
-InstallMethod(DotHighlightedDigraph,
-"for a digraph by out-neighbours, list, and two strings",
-[IsDigraphByOutNeighboursRep, IsList, IsString, IsString],
-function(D, highverts, highcolour, lowcolour)
- local lowverts, out, str, i, j;
-
- if not IsSubset(DigraphVertices(D), highverts) then
- ErrorNoReturn("the 2nd argument must be a list of vertices ",
- "of the 1st argument ,");
- elif IsEmpty(highcolour) then
- ErrorNoReturn("the 3rd argument must be a string ",
- "containing the name of a colour,");
- elif IsEmpty(lowcolour) then
- ErrorNoReturn("the 4th argument must be a string ",
- "containing the name of a colour,");
- fi;
-
- lowverts := Difference(DigraphVertices(D), highverts);
- out := OutNeighbours(D);
- str := "//dot\n";
-
- Append(str, "digraph hgn{\n");
-
- Append(str, "subgraph lowverts{\n");
- Append(str, Concatenation("node [shape=circle, color=",
- lowcolour,
- "]\n edge [color=",
- lowcolour,
- "]\n"));
+#############################################################################
+# Highlighted subdigraphs
+#############################################################################
- for i in lowverts do
- Append(str, Concatenation(String(i), "\n"));
- od;
+BindGlobal("DIGRAPHS_GraphvizHighlight",
+function(D, gv, hi_verts, hi, lo)
+ local node, color, out, nodes, edge, v, i, j;
- Append(str, "}\n");
+ if IsMultiDigraph(D) then
+ ErrorNoReturn("the 1st argument (a digraph) must not have multiple edges");
+ elif not IsSubset(DigraphVertices(D), hi_verts) then
+ ErrorNoReturn("the 2nd argument (list) must consist of vertices ",
+ "of the 1st argument (a digraph)");
+ fi;
+ ErrorIfNotValidColor(hi);
+ ErrorIfNotValidColor(lo);
- Append(str, "subgraph highverts{\n");
- Append(str, Concatenation("node [shape=circle, color=",
- highcolour,
- "]\n edge [color=",
- highcolour,
- "]\n"));
+ GraphvizSetAttr(gv, "shape", "circle");
- for i in highverts do
- Append(str, Concatenation(String(i), "\n"));
+ for v in DigraphVertices(D) do
+ node := GraphvizAddNode(gv, v);
+ if v in hi_verts then
+ color := hi;
+ else
+ color := lo;
+ fi;
+ GraphvizSetAttr(node, "color", color);
od;
- Append(str, "}\n");
-
- Append(str, "subgraph lowverts{\n");
- for i in lowverts do
- for j in out[i] do
- Append(str, Concatenation(String(i), " -> ", String(j), "\n"));
- od;
- od;
- Append(str, "}\n");
+ out := OutNeighbours(D);
+ nodes := GraphvizNodes(gv);
- Append(str, "subgraph highverts{\n");
- for i in highverts do
+ for i in DigraphVertices(D) do
for j in out[i] do
- Append(str, Concatenation(String(i), " -> ", String(j)));
- if j in lowverts then
- Append(str, Concatenation(" [color=", lowcolour, "]"));
+ if IsGraphvizDigraph(gv) or i > j then
+ edge := GraphvizAddEdge(gv, nodes[i], nodes[j]);
+ if i in hi_verts and j in hi_verts then
+ color := hi;
+ else
+ color := lo;
+ fi;
+ GraphvizSetAttr(edge, "color", color);
fi;
- Append(str, "\n");
od;
od;
- Append(str, "}\n}\n");
- return str;
+ return gv;
end);
+
+InstallMethod(GraphvizHighlightedDigraph,
+"for a digraph by out-neighbours, list, and two strings",
+[IsDigraphByOutNeighboursRep, IsList, IsString, IsString],
+{D, hi_verts, hi, lo} ->
+DIGRAPHS_GraphvizHighlight(D, GraphvizDigraph(), hi_verts, hi, lo));
+
+InstallMethod(GraphvizHighlightedDigraph, "for a digraph and list",
+[IsDigraph, IsList],
+{D, list} -> GraphvizHighlightedDigraph(D, list, "black", "grey"));
+
+InstallMethod(GraphvizHighlightedGraph,
+"for a digraph by out-neighbours, list, and two strings",
+[IsDigraphByOutNeighboursRep, IsList, IsString, IsString],
+function(D, hi_verts, hi, lo)
+ if not IsSymmetricDigraph(D) then
+ ErrorNoReturn("the argument (a digraph) must be symmetric");
+ fi;
+ return DIGRAPHS_GraphvizHighlight(D, GraphvizGraph(), hi_verts, hi, lo);
+end);
+
+InstallMethod(GraphvizHighlightedGraph, "for a digraph and list",
+[IsDigraph, IsList],
+# IsSymmetricDigraph checked in GraphvizHighlightedGraph
+{D, list} -> GraphvizHighlightedGraph(D, list, "black", "grey"));
diff --git a/init.g b/init.g
index 9edfe8d60..09b5afbb8 100644
--- a/init.g
+++ b/init.g
@@ -71,5 +71,6 @@ ReadPackage("digraphs", "gap/cliques.gd");
ReadPackage("digraphs", "gap/planar.gd");
ReadPackage("digraphs", "gap/examples.gd");
ReadPackage("digraphs", "gap/weights.gd");
+ReadPackage("digraphs", "gap/deprecated.gd");
DeclareInfoClass("InfoDigraphs");
diff --git a/read.g b/read.g
index e04a710fe..0466140d1 100644
--- a/read.g
+++ b/read.g
@@ -53,3 +53,4 @@ ReadPackage("digraphs", "gap/cliques.gi");
ReadPackage("digraphs", "gap/planar.gi");
ReadPackage("digraphs", "gap/examples.gi");
ReadPackage("digraphs", "gap/weights.gi");
+ReadPackage("digraphs", "gap/deprecated.gi");
diff --git a/tst/standard/display.tst b/tst/standard/display.tst
new file mode 100644
index 000000000..0b30d3e74
--- /dev/null
+++ b/tst/standard/display.tst
@@ -0,0 +1,700 @@
+#############################################################################
+##
+#W standard/display.tst
+#Y Copyright (C) 2014-24 James D. Mitchell
+##
+## Licensing information can be found in the README file of this package.
+##
+#############################################################################
+##
+gap> START_TEST("Digraphs package: standard/display.tst");
+gap> LoadPackage("digraphs", false);;
+
+#
+gap> DIGRAPHS_StartTest();
+
+# Display and PrintString and String
+gap> Digraph([]);
+
+gap> Digraph([[]]);
+
+gap> Digraph([[1]]);
+
+gap> Digraph([[2], []]);
+
+gap> gr := Digraph([[1, 2], [2], []]);
+
+gap> PrintString(gr);
+"DigraphFromDigraph6String(\"&Bq?\")"
+gap> String(gr);
+"DigraphFromDigraph6String(\"&Bq?\")"
+gap> gr := Digraph([[2], [1], [], [3]]);
+
+gap> PrintString(gr);
+"DigraphFromDigraph6String(\"&CQ?G\")"
+gap> String(gr);
+"DigraphFromDigraph6String(\"&CQ?G\")"
+gap> r := rec(DigraphVertices := [1, 2, 3],
+> DigraphSource := [1, 2],
+> DigraphRange := [2, 3]);;
+gap> gr := Digraph(r);
+
+gap> PrintString(gr);
+"ChainDigraph(3)"
+gap> String(gr);
+"ChainDigraph(3)"
+
+# DotDigraph and DotSymmetricDigraph
+gap> r := rec(DigraphVertices := [1 .. 3], DigraphSource := [1, 1, 1, 1],
+> DigraphRange := [1, 2, 2, 3]);;
+gap> gr := Digraph(r);
+
+gap> dot := DotDigraph(gr);;
+gap> dot{[1 .. 50]};
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3"
+gap> dot{[51 .. 75]};
+"\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n"
+gap> r := rec(DigraphVertices := [1 .. 8],
+> DigraphSource := [1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 8,
+> 8],
+> DigraphRange := [6, 7, 1, 6, 5, 1, 4, 8, 1, 3, 6, 6, 7, 7, 1, 4, 4, 5, 7, 5,
+> 6]);;
+gap> gr1 := Digraph(r);
+
+gap> DotDigraph(gr1){[50 .. 109]};
+"3\n\t4\n\t5\n\t6\n\t7\n\t8\n\t1 -> 6\n\t1 -> 7\n\t2 -> 1\n\t2 -> 6\n\t3 -> 5\
+\n\t4 "
+gap> adj := [[2], [1, 3], [2, 3, 4], [3]];
+[ [ 2 ], [ 1, 3 ], [ 2, 3, 4 ], [ 3 ] ]
+gap> gr2 := Digraph(adj);
+
+gap> DotDigraph(gr2){[11 .. 75]};
+"aph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2\n\t2 -> 1\n\t\
+2 ->"
+gap> DotSymmetricDigraph(gr2){[12 .. 70]};
+" hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t2 -- 1\n\t3 -- 2\n\t4"
+gap> DotSymmetricDigraph(gr1);
+Error, the argument (a digraph) must be symmetric
+
+#DotColoredDigraph and DotSymmetriColoredDigraph
+# TODO fix the colors here!
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "lightblue";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "lightblue";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+gap> edgecolors[4][3] := "purple";;
+gap> DotColoredDigraph(D, vertcolors, edgecolors){[1 .. 30]};
+"//dot\ndigraph hgn {\n\tnode [sha"
+gap> D := Digraph([[2], [1, 3], [2]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";;
+gap> vertcolors[2] := "pink";;
+gap> vertcolors[3] := "purple";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "green";;
+gap> edgecolors[2][1] := "green";;
+gap> edgecolors[3][1] := "red";; edgecolors[2][2] := "red";;
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\n\
+\t2 [color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t2 -- 1 [co\
+lor=green]\n\t3 -- 2 [color=red]\n}\n"
+gap> D := Digraph([[2, 3], [1, 3], [1]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "yellow";;
+gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "pink";;
+gap> edgecolors[3][1] := "yellow";;
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\
+\n\t2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t1 -> 2 [co\
+lor=orange]\n\t1 -> 3 [color=yellow]\n\t2 -> 1 [color=orange]\n\t2 -> 3 [color\
+=pink]\n\t3 -> 1 [color=yellow]\n}\n"
+gap> D := Digraph(IsMutableDigraph, [[2, 3], [1, 3], [1]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "yellow";;
+gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "pink";;
+gap> edgecolors[3][1] := "yellow";;
+gap> DotColoredDigraph(D, vertcolors, edgecolors);;
+gap> D;
+
+gap> D := Digraph([[2, 4], [1, 3], [2], [1]]);
+
+gap> vertcolors := ["blue", "red", "green", "yellow"];;
+gap> edgecolors := ListWithIdenticalEntries(3,
+> ["orange", "orange", "orange"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st argument (a digraph) has nodes, expected 4 but found 3
+#@else
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st\
+ argument (a digraph) has nodes, expected 4 but found 3
+#@fi
+gap> D := Digraph(IsMutableDigraph, [[2, 4], [1, 3], [2], [1]]);
+
+gap> vertcolors := ["blue", "red", "green", "yellow"];;
+gap> edgecolors := ListWithIdenticalEntries(3,
+> ["orange", "orange", "orange"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st argument (a digraph) has nodes, expected 4 but found 3
+#@else
+gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st\
+ argument (a digraph) has nodes, expected 4 but found 3
+#@fi
+gap> D;
+
+gap> D := CompleteDigraph(4);;
+gap> vertcolors := ["blue", "banana", "green", "yellow"];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/c\
+olors.html
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := ["blue", "red", "green"];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the number of node colors must be the same as the number of nodes, expe\
+cted 4 but found 3
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the number of node colors must be the same as the number of nodes, expe\
+cted 4 but found 3
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [2, 1, 1, 3];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color 2 (integer), valid colors are RGB values or names from th\
+e GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.html
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color 2 (integer), valid colors are RGB values or names from th\
+e GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := ["#AB3487", "#DF4738", "#4BF234", "#AF34C9"];;
+gap> edgecolors := ListWithIdenticalEntries(4,
+> ["lightblue", "pink", "purple"]);;
+gap> Print(DotColoredDigraph(D, vertcolors, edgecolors));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1 [color="#AB3487", style=filled]
+ 2 [color="#DF4738", style=filled]
+ 3 [color="#4BF234", style=filled]
+ 4 [color="#AF34C9", style=filled]
+ 1 -> 2 [color=lightblue]
+ 1 -> 3 [color=pink]
+ 1 -> 4 [color=purple]
+ 2 -> 1 [color=lightblue]
+ 2 -> 3 [color=pink]
+ 2 -> 4 [color=purple]
+ 3 -> 1 [color=lightblue]
+ 3 -> 2 [color=pink]
+ 3 -> 4 [color=purple]
+ 4 -> 1 [color=lightblue]
+ 4 -> 2 [color=pink]
+ 4 -> 3 [color=purple]
+}
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "banana";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "cherry";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+gap> edgecolors[4][3] := "purple";;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/c\
+olors.html
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, invalid color "banana" (list (string)), valid colors are RGB values or \
+names from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "lightblue";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "lightblue";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same shape as the out neig\
+hbours of the 1st argument (a digraph), in position 4 expected a list of lengt\
+h 3 but found list of length 2
+#@else
+gap> DotColoredDigraph(D, vertcolors, edgecolors);
+Error, the 2nd argument (edge colors) must have the same shape as the out neig\
+hbours \
+of the 1st argument (a digraph), in position 4 expected a list of length 3 but\
+ found list of length 2
+#@fi
+
+# DotVertexColoredDigraph
+gap> D := CompleteDigraph(4);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";;
+gap> Print(DotVertexColoredDigraph(D, vertcolors));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1 [color=blue, style=filled]
+ 2 [color=red, style=filled]
+ 3 [color=green, style=filled]
+ 4 [color=yellow, style=filled]
+ 1 -> 2
+ 1 -> 3
+ 1 -> 4
+ 2 -> 1
+ 2 -> 3
+ 2 -> 4
+ 3 -> 1
+ 3 -> 2
+ 3 -> 4
+ 4 -> 1
+ 4 -> 2
+ 4 -> 3
+}
+gap> D := EmptyDigraph(3);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";; vertcolors[2] := "red";;
+gap> vertcolors[3] := "green";;
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> DotVertexColoredDigraph(D, vertcolors);
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\
+\n\t2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n}\n"
+
+# DotEdgeColoredDigraph
+gap> D := CompleteDigraph(4);
+
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];; edgecolors[4] := [];;
+gap> edgecolors[1][1] := "lightblue";;
+gap> edgecolors[1][2] := "pink";;
+gap> edgecolors[1][3] := "purple";;
+gap> edgecolors[2][1] := "lightblue";;
+gap> edgecolors[2][2] := "pink";;
+gap> edgecolors[2][3] := "purple";;
+gap> edgecolors[3][1] := "lightblue";;
+gap> edgecolors[3][2] := "pink";;
+gap> edgecolors[3][3] := "purple";;
+gap> edgecolors[4][1] := "lightblue";;
+gap> edgecolors[4][2] := "pink";;
+gap> edgecolors[4][3] := "purple";;
+gap> DotEdgeColoredDigraph(D, edgecolors);
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2 [c\
+olor=lightblue]\n\t1 -> 3 [color=pink]\n\t1 -> 4 [color=purple]\n\t2 -> 1 [col\
+or=lightblue]\n\t2 -> 3 [color=pink]\n\t2 -> 4 [color=purple]\n\t3 -> 1 [color\
+=lightblue]\n\t3 -> 2 [color=pink]\n\t3 -> 4 [color=purple]\n\t4 -> 1 [color=l\
+ightblue]\n\t4 -> 2 [color=pink]\n\t4 -> 3 [color=purple]\n}\n"
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotEdgeColoredDigraph(CycleDigraph(3), []);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st argument (a digraph) has nodes, expected 3 but found 0
+gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail, fail], [fail], [fail]]);
+Error, the 2nd argument (edge colors) must have the same shape as the out neig\
+hbours of the 1st argument (a digraph), in position 1 expected a list of lengt\
+h 1 but found list of length 2
+#@else
+gap> DotEdgeColoredDigraph(CycleDigraph(3), []);
+Error, the 2nd argument (edge colors) must have the same number of entries as \
+the 1st\
+ argument (a digraph) has nodes, expected 3 but found 0
+#@fi
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]);
+Error, invalid color fail (boolean or fail), valid colors are RGB values or na\
+mes from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/col\
+ors.html
+#@else
+gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]);
+Error, invalid color fail (boolean or fail), valid colors are RGB values or na\
+mes from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+
+# DotSymmetricVertexColoredDigraph
+gap> D := Digraph([[2], [1, 3], [2]]);
+
+gap> vertcolors := [];;
+gap> vertcolors[1] := "blue";;
+gap> vertcolors[2] := "pink";;
+gap> vertcolors[3] := "purple";;
+gap> DotSymmetricVertexColoredDigraph(D, vertcolors);
+"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1 [color=blue, style=filled]\n\
+\t2 [color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t2 -- 1\n\t\
+3 -- 2\n}\n"
+
+# DotSymmetricEdgeColoredDigraph
+gap> D := Digraph([[2], [1, 3], [2]]);
+
+gap> edgecolors := [];;
+gap> edgecolors[1] := [];; edgecolors[2] := [];;
+gap> edgecolors[3] := [];;
+gap> edgecolors[1][1] := "green";; edgecolors[2][1] := "green";;
+gap> edgecolors[2][2] := "red";; edgecolors[3][1] := "red";;
+gap> DotSymmetricEdgeColoredDigraph(D, edgecolors);
+"//dot\ngraph hgn {\n\tnode [shape=circle] \n\t1\n\t2\n\t3\n\t2 -- 1 [color=gr\
+een]\n\t3 -- 2 [color=red]\n}\n"
+
+# DotVertexLabelledDigraph
+gap> r := rec(DigraphVertices := [1 .. 3], DigraphSource := [1, 1, 1, 1],
+> DigraphRange := [1, 2, 2, 3]);;
+gap> gr := Digraph(r);
+
+gap> dot := DotVertexLabelledDigraph(gr);;
+gap> dot;
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [label=1]\n\t2 [label=2]\n\
+\t3 [label=3]\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n\t1 -> 3\n}\n"
+gap> SetDigraphVertexLabel(gr, 1, 2);
+gap> dot := DotVertexLabelledDigraph(gr);;
+gap> dot;
+"//dot\ndigraph hgn {\n\tnode [shape=circle] \n\t1 [label=2]\n\t2 [label=2]\n\
+\t3 [label=3]\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n\t1 -> 3\n}\n"
+
+# Splash
+gap> Splash(1);
+Error, the 1st argument must be a string or graphviz graph, found integer
+gap> Splash("string", 0);
+Error, the 2nd argument must be a record,
+gap> Splash("string");
+Error, the component "type" of the 2nd argument must be "dot" or "\
+latex",
+gap> Splash("string", rec(path := "~/", filename := "filename"));
+Error, the component "type" of the 2nd argument must be "dot" or "\
+latex",
+gap> Splash("string", rec(viewer := "bad"));
+Error, the viewer "bad" specified in the option `viewer` is not available
+gap> Splash("string", rec(type := "dot", engine := "dott"));
+Error, the component "engine" of the 2nd argument must be one of: "\
+dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork"
+gap> tmpdir := Filename(DirectoryTemporary(), "");;
+gap> Splash("string",
+> rec(path := tmpdir,
+> directory := "digraphs_temporary_directory"));
+Error, the component "type" of the 2nd argument must be "dot" or "\
+latex",
+gap> Splash("%latex", rec(filetype := "latex", engine := fail));
+Error, the component "engine" of the 2nd argument must be one of: "\
+dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork"
+gap> Splash("//dot", rec(filetype := "pdf", engine := fail));
+Error, the component "engine" of the 2nd argument must be one of: "\
+dot", "neato", "twopi", "circo", "fdp", "sfdp", or "patchwork"
+gap> MakeReadWriteGlobal("VizViewers");
+gap> VizViewers_backup := ShallowCopy(VizViewers);;
+gap> VizViewers := ["nonexistent-viewer"];;
+gap> Splash("//dot");
+Error, none of the default viewers [ "nonexistent-viewer"
+ ] is available, please specify an available viewer in the options record comp\
+onent `viewer`,
+gap> VizViewers := VizViewers_backup;;
+gap> MakeReadOnlyGlobal("VizViewers");
+
+# DotPartialOrderDigraph
+gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 4], [1 .. 5], [1 .. 6],
+> [1, 2, 3, 4, 5, 7], [1, 8]]);;
+gap> Print(DotPartialOrderDigraph(gr));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 2 -> 1
+ 3 -> 1
+ 4 -> 1
+ 5 -> 2
+ 5 -> 3
+ 5 -> 4
+ 6 -> 5
+ 7 -> 5
+ 8 -> 1
+}
+gap> gr := Digraph([[1], [2], [1, 3], [2, 4], [1, 2, 3, 4, 5], [1, 2, 3, 6]]);;
+gap> Print(DotPartialOrderDigraph(gr));
+//dot
+digraph hgn {
+ node [shape=circle]
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 3 -> 1
+ 4 -> 2
+ 5 -> 3
+ 5 -> 4
+ 6 -> 3
+ 6 -> 2
+}
+gap> gr := Digraph([[1], []]);;
+gap> DotPartialOrderDigraph(gr);
+Error, the argument (a digraph) must be a partial order
+
+# DotPreorderDigraph and DotQuasiorderDigraph
+gap> DotPreorderDigraph(CompleteDigraph(5));
+Error, the argument (a digraph) must be a preorder
+gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 4], [1 .. 5], [1 .. 6],
+> [1, 2, 3, 4, 5, 7], [1, 8]]);;
+gap> Print(DotPreorderDigraph(gr), "\n");
+//dot
+digraph graphname {
+ node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1"
+ 1 [label="1", width=0.5]
+ 2 [label="2", width=0.5]
+ 3 [label="3", width=0.5]
+ 4 [label="4", width=0.5]
+ 5 [label="5", width=0.5]
+ 6 [label="6", width=0.5]
+ 7 [label="7", width=0.5]
+ 8 [label="8", width=0.5]
+ 2 -> 1
+ 3 -> 1
+ 4 -> 1
+ 5 -> 2
+ 5 -> 3
+ 5 -> 4
+ 6 -> 5
+ 7 -> 5
+ 8 -> 1
+}
+
+gap> gr := Concatenation("&X_?_A]|^Vr[nHpmVcy~zy[A????_???G??B]nhtmvcwvJq\\^~",
+> "|m??_AEx]Rb[nHo??__vJy[??A??O_aV~^Zb]njo???_???GZdxMLy}n_");;
+gap> gr := DigraphFromDigraph6String(gr);;
+gap> Print(DotPreorderDigraph(gr){[1 .. 94]}, "\n");
+//dot
+digraph graphname {
+ node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1"
+
+gap> gr := DigraphDisjointUnion(CompleteDigraph(10),
+> CompleteDigraph(5),
+> CycleDigraph(2));;
+gap> gr := DigraphReflexiveTransitiveClosure(DigraphAddEdge(gr, [10, 11]));;
+gap> IsPreorderDigraph(gr);
+true
+gap> Print(DotPreorderDigraph(gr), "\n");
+//dot
+digraph graphname {
+ node [shape="Mrecord"] height="0.5" fixedsize="true" ranksep="1"
+ 1 [label="11|12|13|14|15", width=2.5]
+ 2 [label="1|2|3|4|5|6|7|8|9|10", width=5.]
+ 3 [label="16|17", width=1.]
+ 2 -> 1
+}
+
+
+# DotHighlightedDigraph
+gap> gr := Digraph([[2, 3], [2], [1, 3]]);
+
+gap> Print(DotHighlightedDigraph(gr, [1, 2], "red", "black"));
+//dot
+digraph {
+ shape=circle
+ 1 [color=red]
+ 2 [color=red]
+ 3 [color=black]
+ 1 -> 2 [color=red]
+ 1 -> 3 [color=black]
+ 2 -> 2 [color=red]
+ 3 -> 1 [color=black]
+ 3 -> 3 [color=black]
+}
+gap> D := CycleDigraph(5);;
+gap> DotHighlightedDigraph(D, [10], "black", "grey");
+Error, the 2nd argument (list) must consist of vertices of the 1st argument (a\
+ digraph)
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotHighlightedDigraph(D, [1], "", "grey");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.\
+html
+#@else
+gap> DotHighlightedDigraph(D, [1], "", "grey");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0")
+gap> DotHighlightedDigraph(D, [1], "black", "");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Scheme http://graphviz.org/doc/info/colors.\
+html
+#@else
+gap> DotHighlightedDigraph(D, [1], "black", "");
+Error, invalid color "" (list (string)), valid colors are RGB values or names \
+from the GraphViz 2.44.1 X11 Color Sch\
+eme http://graphviz.org/doc/info/colors.html
+#@fi
+gap> Print(DotHighlightedDigraph(D, Filtered(DigraphVertices(D), IsEvenInt)));
+//dot
+digraph {
+ shape=circle
+ 1 [color=grey]
+ 2 [color=black]
+ 3 [color=grey]
+ 4 [color=black]
+ 5 [color=grey]
+ 1 -> 2 [color=grey]
+ 2 -> 3 [color=grey]
+ 3 -> 4 [color=grey]
+ 4 -> 5 [color=grey]
+ 5 -> 1 [color=grey]
+}
+
+# Splash
+gap> Splash(DotDigraph(RandomDigraph(10)), rec(viewer := 1));
+Error, the option `viewer` must be a string, not an integer
+gap> Splash(DotDigraph(RandomDigraph(10)), rec(viewer := "asdfasfa"));
+Error, the viewer "asdfasfa" specified in the option `viewer` is not available
+
+# Test errors
+gap> GraphvizEdgeColoredGraph(ChainDigraph(3), ["blue"]);
+Error, the argument (a digraph) must be symmetric
+gap> D := DigraphSymmetricClosure(ChainDigraph(3));;
+gap> GraphvizVertexLabelledGraph(D);
+
+gap> GraphvizEdgeColoredGraph(D, List(DigraphVertices(D), ReturnFail));
+Error, the 2nd argument (edge colors) must be a list of lists, found boolean o\
+r fail in position 1
+gap> GraphvizHighlightedDigraph(D, [2]);
+
+gap> GraphvizHighlightedGraph(D, [2]);
+
+gap> Print(AsString(last));
+//dot
+graph {
+ shape=circle
+ 1 [color=grey]
+ 2 [color=black]
+ 3 [color=grey]
+ 2 -- 1 [color=grey]
+ 3 -- 2 [color=grey]
+}
+gap> GraphvizHighlightedGraph(D, [1, 2], "red", "blue");
+
+gap> Print(AsString(last));
+//dot
+graph {
+ shape=circle
+ 1 [color=red]
+ 2 [color=red]
+ 3 [color=blue]
+ 2 -- 1 [color=red]
+ 3 -- 2 [color=blue]
+}
+gap> GraphvizHighlightedGraph(ChainDigraph(3), [1, 2], "red", "blue");
+Error, the argument (a digraph) must be symmetric
+gap> D := Digraph([[], [1, 1]]);;
+gap> GraphvizHighlightedDigraph(D, [2]);
+Error, the 1st argument (a digraph) must not have multiple edges
+
+# DIGRAPHS_UnbindVariables
+gap> Unbind(D);
+gap> Unbind(adj);
+gap> Unbind(backup);
+gap> Unbind(dot);
+gap> Unbind(edgecolors);
+gap> Unbind(gr);
+gap> Unbind(gr1);
+gap> Unbind(gr2);
+gap> Unbind(r);
+gap> Unbind(tmpdir);
+gap> Unbind(vertcolors);
+
+#
+gap> DIGRAPHS_StopTest();
+gap> STOP_TEST("Digraphs package: standard/display.tst", 0);