From 1f7a149e844c1087147f96130ad2d12d3892e5fd Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 3 May 2024 10:37:43 +0100 Subject: [PATCH 1/5] Checkout files from mpan322/main --- PackageInfo.g | 1 + gap/display.gd | 21 +- gap/display.gi | 427 ++++++++++++++------------------ tst/standard/display.tst | 514 +++++++++++++++------------------------ 4 files changed, 391 insertions(+), 572 deletions(-) diff --git a/PackageInfo.g b/PackageInfo.g index 977a2f72d..1351419c0 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -390,6 +390,7 @@ Dependencies := rec( GAP := ">=4.10.0", NeededOtherPackages := [["io", ">=4.5.1"], ["orb", ">=4.8.2"], + ["graphviz", "*"], ["datastructures", ">=0.2.5"]], SuggestedOtherPackages := [["GAPDoc", ">=1.6.3"], ["grape", ">=4.8.1"], diff --git a/gap/display.gd b/gap/display.gd index 5916ef9b9..808775f91 100644 --- a/gap/display.gd +++ b/gap/display.gd @@ -1,4 +1,4 @@ -############################################################################# +############################################################################ ## ## display.gd ## Copyright (C) 2017-19 James D. Mitchell @@ -8,6 +8,24 @@ ############################################################################# ## +DeclareAttribute("GraphvizDotDigraph", IsDigraph); +DeclareOperation("GraphvizDotColoredDigraph", [IsDigraph, IsList, IsList]); +DeclareOperation("GraphvizDotVertexColoredDigraph", [IsDigraph, IsList]); +DeclareOperation("GraphvizDotEdgeColoredDigraph", [IsDigraph, IsList]); +DeclareOperation("GraphvizDotVertexLabelledDigraph", [IsDigraph]); +DeclareAttribute("GraphvizDotSymmetricDigraph", IsDigraph); +DeclareOperation("GraphvizDotSymmetricColoredDigraph", + [IsDigraph, IsList, IsList]); +DeclareOperation("GraphvizDotSymmetricVertexColoredDigraph", + [IsDigraph, IsList]); +DeclareOperation("GraphvizDotSymmetricEdgeColoredDigraph", [IsDigraph, IsList]); +DeclareAttribute("GraphvizDotPartialOrderDigraph", IsDigraph); +DeclareAttribute("GraphvizDotPreorderDigraph", IsDigraph); +DeclareSynonym("GraphvizDotQuasiorderDigraph", GraphvizDotPreorderDigraph); +DeclareOperation("GraphvizDotHighlightedDigraph", [IsDigraph, IsList]); +DeclareOperation("GraphvizDotHighlightedDigraph", + [IsDigraph, IsList, IsString, IsString]); + DeclareAttribute("DotDigraph", IsDigraph); DeclareOperation("DotColoredDigraph", [IsDigraph, IsList, IsList]); DeclareOperation("DotVertexColoredDigraph", [IsDigraph, IsList]); @@ -23,3 +41,4 @@ DeclareSynonym("DotQuasiorderDigraph", DotPreorderDigraph); DeclareOperation("DotHighlightedDigraph", [IsDigraph, IsList]); DeclareOperation("DotHighlightedDigraph", [IsDigraph, IsList, IsString, IsString]); + diff --git a/gap/display.gi b/gap/display.gi index f55429169..c4d919ad3 100644 --- a/gap/display.gi +++ b/gap/display.gi @@ -9,35 +9,37 @@ ## # AN's code, adapted by WW -BindGlobal("DIGRAPHS_DotDigraph", +BindGlobal("GV_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"); + local out, nodes, tail, head, node, edge, graph, i, func, j, l; + + graph := GraphvizDigraph("hgn"); + GraphvizSetAttr(graph, "node [shape=\"circle\"]"); + for i in DigraphVertices(D) do - Append(str, StringFormatted("{}", i)); + node := GraphvizAddNode(graph, StringFormatted("{}", i)); for func in node_funcs do - Append(str, func(i)); + func(graph, node, i); od; - Append(str, "\n"); od; + + nodes := GraphvizNodes(graph); 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])); + tail := nodes[String(i)]; + head := nodes[String(out[i][j])]; + edge := GraphvizAddEdge(graph, tail, head); for func in edge_funcs do - Append(str, func(i, j)); + func(graph, edge, i, j); od; - Append(str, "\n"); od; od; - Append(str, "}\n"); - return str; + return graph; end); -BindGlobal("DIGRAPHS_ValidRGBValue", +BindGlobal("GV_DIGRAPHS_ValidRGBValue", function(str) local l, chars, x, i; l := Length(str); @@ -59,22 +61,22 @@ function(str) fi; end); -BindGlobal("DIGRAPHS_GraphvizColorsList", fail); +BindGlobal("GV_DIGRAPHS_GraphvizColorsList", fail); -BindGlobal("DIGRAPHS_GraphvizColors", +BindGlobal("GV_DIGRAPHS_GraphvizColors", function() local f; - if DIGRAPHS_GraphvizColorsList = fail then + if GV_DIGRAPHS_GraphvizColorsList = fail then f := IO_File(Concatenation(DIGRAPHS_Dir(), "/data/colors.p")); - MakeReadWriteGlobal("DIGRAPHS_GraphvizColorsList"); - DIGRAPHS_GraphvizColorsList := IO_Unpickle(f); - MakeReadOnlyGlobal("DIGRAPHS_GraphvizColorsList"); + MakeReadWriteGlobal("GV_DIGRAPHS_GraphvizColorsList"); + GV_DIGRAPHS_GraphvizColorsList := IO_Unpickle(f); + MakeReadOnlyGlobal("GV_DIGRAPHS_GraphvizColorsList"); IO_Close(f); fi; - return DIGRAPHS_GraphvizColorsList; + return GV_DIGRAPHS_GraphvizColorsList; end); -BindGlobal("DIGRAPHS_ValidVertColors", +BindGlobal("GV_DIGRAPHS_ValidVertColors", function(D, verts) local v, sum, colors, col; v := DigraphVertices(D); @@ -83,12 +85,12 @@ function(D, verts) ErrorNoReturn("the number of vertex colors must be the same as the number", " of vertices, expected ", Length(v), " but found ", Length(verts), ""); fi; - colors := DIGRAPHS_GraphvizColors(); + colors := GV_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 + elif GV_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", @@ -103,14 +105,14 @@ function(D, verts) fi; end); -BindGlobal("DIGRAPHS_ValidEdgeColors", +BindGlobal("GV_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(); + colors := GV_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"); @@ -124,7 +126,7 @@ function(D, edge) for col in edge[v] do if not IsString(col) then ErrorNoReturn("expected a string"); - elif DIGRAPHS_ValidRGBValue(col) = false and + elif GV_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", @@ -144,261 +146,185 @@ function(D, edge) fi; end); +InstallMethod(GraphvizDotDigraph, "for a digraph by out-neighbours", +[IsDigraphByOutNeighboursRep], +D -> GV_DIGRAPHS_DotDigraph(D, [], [])); + InstallMethod(DotDigraph, "for a digraph by out-neighbours", [IsDigraphByOutNeighboursRep], -D -> DIGRAPHS_DotDigraph(D, [], [])); +D -> AsString(GraphvizDotDigraph(D))); -InstallMethod(DotColoredDigraph, "for a digraph by out-neighbours and two lists", +InstallMethod(GraphvizDotColoredDigraph, +"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]); + local vert_func, cond, edge_func; + cond := GV_DIGRAPHS_ValidVertColors(D, vert); + cond := cond and GV_DIGRAPHS_ValidEdgeColors(D, edge); + if cond then + vert_func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], + style := "filled")); + edge_func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); + return GV_DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]); fi; end); -InstallMethod(DotVertexColoredDigraph, +InstallMethod(DotColoredDigraph, "for a digraph by out-neighbours and two lists", +[IsDigraphByOutNeighboursRep, IsList, IsList], +{D, vert, edge} -> AsString(GraphvizDotColoredDigraph(D, vert, edge))); + +InstallMethod(GraphvizDotVertexColoredDigraph, "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], []); + if GV_DIGRAPHS_ValidVertColors(D, vert) then + func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], + style := "filled")); + return GV_DIGRAPHS_DotDigraph(D, [func], []); fi; end); -InstallMethod(DotEdgeColoredDigraph, +InstallMethod(DotVertexColoredDigraph, +"for a digraph by out-neighbours and a list", +[IsDigraphByOutNeighboursRep, IsList], +{D, vert} -> AsString(GraphvizDotVertexColoredDigraph(D, vert))); + +InstallMethod(GraphvizDotEdgeColoredDigraph, "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]); + if GV_DIGRAPHS_ValidEdgeColors(D, edge) then + func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); + return GV_DIGRAPHS_DotDigraph(D, [], [func]); fi; end); -InstallMethod(DotVertexLabelledDigraph, "for a digraph by out-neighbours", +InstallMethod(DotEdgeColoredDigraph, +"for a digraph by out-neighbours and a list", +[IsDigraphByOutNeighboursRep, IsList], +{D, edge} -> AsString(GraphvizDotEdgeColoredDigraph(D, edge))); + +InstallMethod(GraphvizDotVertexLabelledDigraph, +"for a digraph by out-neighbours", [IsDigraphByOutNeighboursRep], function(D) local func; - func := i -> StringFormatted(" [label=\"{}\"]", DigraphVertexLabel(D, i)); - return DIGRAPHS_DotDigraph(D, [func], []); + func := {g, n, i} -> GraphvizSetAttrs(n, rec(label := + DigraphVertexLabel(D, i))); + return GV_DIGRAPHS_DotDigraph(D, [func], []); end); -BindGlobal("DIGRAPHS_DotSymmetricDigraph", +InstallMethod(DotVertexLabelledDigraph, "for a digraph by out-neighbours", +[IsDigraphByOutNeighboursRep], +{D} -> AsString(GraphvizDotVertexLabelledDigraph(D))); + +BindGlobal("GV_DIGRAPHS_DotSymmetricDigraph", function(D, node_funcs, edge_funcs) - local out, str, i, j, func; + local graph, node, nodes, edge, out, n1, n2, 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"); + + out := OutNeighbours(D); + + graph := GraphvizGraph("hgn"); + GraphvizSetAttr(graph, "node [shape=\"circle\"]"); for i in DigraphVertices(D) do - Append(str, StringFormatted("{}", i)); + node := GraphvizAddNode(graph, StringFormatted("{}", i)); for func in node_funcs do - Append(str, func(i)); + func(graph, node, i); od; - Append(str, "\n"); od; + + nodes := GraphvizNodes(graph); 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])); + n1 := nodes[String(i)]; + n2 := nodes[String(out[i][j])]; + edge := GraphvizAddEdge(graph, n1, n2); for func in edge_funcs do - Append(str, func(i, j)); + func(graph, edge, i, j); od; - Append(str, "\n"); fi; od; od; - Append(str, "}\n"); - return str; + return graph; end); +InstallMethod(GraphvizDotSymmetricDigraph, "for a digraph by out-neighbours", +[IsDigraphByOutNeighboursRep], +D -> GV_DIGRAPHS_DotSymmetricDigraph(D, [], [])); + InstallMethod(DotSymmetricDigraph, "for a digraph by out-neighbours", [IsDigraphByOutNeighboursRep], -D -> DIGRAPHS_DotSymmetricDigraph(D, [], [])); +D -> AsString(GraphvizDotSymmetricDigraph(D))); -InstallMethod(DotSymmetricColoredDigraph, +InstallMethod(GraphvizDotSymmetricColoredDigraph, "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]); + local vert_func, cond, edge_func; + cond := GV_DIGRAPHS_ValidVertColors(D, vert); + cond := cond and GV_DIGRAPHS_ValidEdgeColors(D, edge); + if cond then + vert_func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], + style := "filled")); + edge_func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); + return GV_DIGRAPHS_DotSymmetricDigraph(D, [vert_func], [edge_func]); fi; end); -InstallMethod(DotSymmetricVertexColoredDigraph, +InstallMethod(GraphvizDotSymmetricVertexColoredDigraph, "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], []); + if GV_DIGRAPHS_ValidVertColors(D, vert) then + func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], + style := "filled")); + return GV_DIGRAPHS_DotSymmetricDigraph(D, [func], []); fi; end); -InstallMethod(DotSymmetricEdgeColoredDigraph, +InstallMethod(GraphvizDotSymmetricEdgeColoredDigraph, "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]); + if GV_DIGRAPHS_ValidEdgeColors(D, edge) then + func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); + return GV_DIGRAPHS_DotSymmetricDigraph(D, [], [func]); fi; end); -# AN's code - -if not IsBound(Splash) then # This function is written by A. Egri-Nagy - BindGlobal("VizViewers", - ["xpdf", "xdg-open", "open", "evince", "okular", "gv"]); - - BindGlobal("Splash", - function(arg) - local str, opt, path, dir, tdir, file, viewer, type, inn, filetype, out, - engine; - - if not IsString(arg[1]) then - ErrorNoReturn("the 1st argument must be a string,"); - fi; - str := arg[1]; - - opt := rec(); - if IsBound(arg[2]) and IsRecord(arg[2]) then - opt := arg[2]; - elif IsBound(arg[2]) then - ErrorNoReturn("the 2nd argument must be a record,"); - fi; - - # path - path := UserHomeExpand("~/"); # default - if IsBound(opt.path) then - path := opt.path; - fi; - - # directory - if IsBound(opt.directory) then - if not opt.directory in DirectoryContents(path) then - Exec(Concatenation("mkdir ", path, opt.directory)); - fi; - dir := Concatenation(path, opt.directory, "/"); - elif IsBound(opt.path) then - if not "tmp.viz" in DirectoryContents(path) then - tdir := Directory(Concatenation(path, "/", "tmp.viz")); - dir := Filename(tdir, ""); - fi; - else - tdir := DirectoryTemporary(); - dir := Filename(tdir, ""); - fi; - - # file - file := "vizpicture"; # default - if IsBound(opt.filename) then - file := opt.filename; - fi; - - # 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; - - # 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; - - # 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(DotSymmetricEdgeColoredDigraph, +"for a digraph by out-neighbours and a list", +[IsDigraphByOutNeighboursRep, IsList], +{D, edge} -> AsString(GraphvizDotSymmetricEdgeColoredDigraph(D, edge))); # CR's code -InstallMethod(DotPartialOrderDigraph, "for a partial order digraph", +InstallMethod(GraphvizDotPartialOrderDigraph, "for a partial order digraph", [IsDigraph], function(D) if not IsPartialOrderDigraph(D) then ErrorNoReturn("the argument must be a partial order digraph,"); fi; D := DigraphMutableCopyIfMutable(D); - return DotDigraph(DigraphReflexiveTransitiveReduction(D)); + return GraphvizDotDigraph(DigraphReflexiveTransitiveReduction(D)); end); -InstallMethod(DotPreorderDigraph, "for a preorder digraph", +InstallMethod(DotPartialOrderDigraph, "for a partial order digraph", +[IsDigraph], +{D} -> AsString(GraphvizDotPartialOrderDigraph(D))); + +InstallMethod(GraphvizDotPreorderDigraph, "for a preorder digraph", [IsDigraph], function(D) - local comps, quo, red, str, c, x, e; + local comps, quo, red, c, x, e, node, graph, label, head, tail, nodes; if not IsPreorderDigraph(D) then ErrorNoReturn("the argument must be a preorder digraph,"); fi; @@ -410,43 +336,57 @@ function(D) quo := DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps)); red := DigraphReflexiveTransitiveReduction(quo); - str := "//dot\n"; - Append(str, "digraph graphname {\n"); - Append(str, "node [shape=Mrecord, height=0.5, fixedsize=true]"); - Append(str, "ranksep=1;\n"); + graph := GraphvizDigraph("graphname"); + GraphvizSetAttr(graph, "node [shape=\"Mrecord\"]"); + GraphvizSetAttr(graph, "height=\"0.5\""); + GraphvizSetAttr(graph, "fixedsize=\"true\""); + GraphvizSetAttr(graph, "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])); + + # create node w/ label + 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(graph, String(c)); + GraphvizSetAttr(node, "label", label); + GraphvizSetAttr(node, "width", String(Float(Length(comps[c]) / 2))); od; # Add the edges of the quotient D. + nodes := GraphvizNodes(graph); for e in DigraphEdges(red) do - Append(str, Concatenation(String(e[1]), " -> ", String(e[2]), "\n")); + tail := nodes[String(e[1])]; + head := nodes[String(e[2])]; + GraphvizAddEdge(graph, tail, head); od; - Append(str, "}"); - return str; + return graph; end); +InstallMethod(DotPreorderDigraph, "for a preorder digraph", +[IsDigraph], +{D} -> AsString(GraphvizDotPreorderDigraph(D))); + +InstallMethod(GraphvizDotHighlightedDigraph, "for a digraph and list", +[IsDigraph, IsList], +{D, list} -> GraphvizDotHighlightedDigraph(D, list, "black", "grey")); + InstallMethod(DotHighlightedDigraph, "for a digraph and list", [IsDigraph, IsList], -{D, list} -> DotHighlightedDigraph(D, list, "black", "grey")); +{D, list} -> AsString(GraphvizDotHighlightedDigraph(D, list, "black", "grey"))); -InstallMethod(DotHighlightedDigraph, +InstallMethod(GraphvizDotHighlightedDigraph, "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; + local lowverts, graph, node, edge, nodes, out, i, j; if not IsSubset(DigraphVertices(D), highverts) then ErrorNoReturn("the 2nd argument must be a list of vertices ", @@ -461,55 +401,42 @@ function(D, highverts, highcolour, lowcolour) 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")); + graph := GraphvizDigraph("hgn"); for i in lowverts do - Append(str, Concatenation(String(i), "\n")); + node := GraphvizAddNode(graph, String(i)); + GraphvizSetAttrs(node, rec(shape := "circle", color := lowcolour)); od; - Append(str, "}\n"); - - Append(str, "subgraph highverts{\n"); - Append(str, Concatenation("node [shape=circle, color=", - highcolour, - "]\n edge [color=", - highcolour, - "]\n")); - for i in highverts do - Append(str, Concatenation(String(i), "\n")); + node := GraphvizAddNode(graph, String(i)); + GraphvizSetAttrs(node, rec(shape := "circle", color := highcolour)); od; - Append(str, "}\n"); - - Append(str, "subgraph lowverts{\n"); + nodes := GraphvizNodes(graph); for i in lowverts do for j in out[i] do - Append(str, Concatenation(String(i), " -> ", String(j), "\n")); + edge := GraphvizAddEdge(graph, nodes[String(i)], nodes[String(j)]); + GraphvizSetAttr(edge, "color", lowcolour); od; od; - Append(str, "}\n"); - Append(str, "subgraph highverts{\n"); for i in highverts do for j in out[i] do - Append(str, Concatenation(String(i), " -> ", String(j))); + edge := GraphvizAddEdge(graph, nodes[String(i)], nodes[String(j)]); + GraphvizSetAttr(edge, "color", highcolour); if j in lowverts then - Append(str, Concatenation(" [color=", lowcolour, "]")); + GraphvizSetAttr(edge, "color", lowcolour); fi; - Append(str, "\n"); od; od; - Append(str, "}\n}\n"); - return str; + return graph; end); + +InstallMethod(DotHighlightedDigraph, +"for a digraph by out-neighbours, list, and two strings", +[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], +{D, highverts, highcolour, lowcolour} -> + AsString(GraphvizDotHighlightedDigraph(D, highverts, highcolour, lowcolour))); diff --git a/tst/standard/display.tst b/tst/standard/display.tst index 76b7ef493..a87483c7d 100644 --- a/tst/standard/display.tst +++ b/tst/standard/display.tst @@ -4,6 +4,7 @@ #Y Copyright (C) 2014-15 James D. Mitchell ## ## Licensing information can be found in the README file of this package. +## Taken from the old digraphs display package ## ############################################################################# ## @@ -13,70 +14,40 @@ 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{\nnode [shape=circle]\n1\n2\n3\n1 -> " -gap> dot{[51 .. 75]}; -"1\n1 -> 2\n1 -> 2\n1 -> 3\n}\n" +gap> gr := Digraph(r);; +gap> dot := GraphvizDotDigraph(gr);; +gap> AsString(dot); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t1 -> 1\n\t1 -> 2\ +\n\t1 -> 2\n\t1 -> 3\n}\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]}; -"6\n7\n8\n1 -> 6\n1 -> 7\n2 -> 1\n2 -> 6\n3 -> 5\n4 -> 1\n4 -> 4\n4 -> " +gap> gr1 := Digraph(r);; +gap> dot1 := GraphvizDotDigraph(gr1);; +gap> AsString(dot1); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\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 -> 1\n\t4 -> 4\n\ +\t4 -> 8\n\t5 -> 1\n\t5 -> 3\n\t5 -> 6\n\t5 -> 6\n\t5 -> 7\n\t6 -> 7\n\t7 -> 1\ +\n\t7 -> 4\n\t7 -> 4\n\t7 -> 5\n\t7 -> 7\n\t8 -> 5\n\t8 -> 6\n}\n" gap> adj := [[2], [1, 3], [2, 3, 4], [3]]; [ [ 2 ], [ 1, 3 ], [ 2, 3, 4 ], [ 3 ] ] -gap> gr2 := Digraph(adj); - -gap> DotDigraph(gr2){[11 .. 75]}; -"aph hgn{\nnode [shape=circle]\n1\n2\n3\n4\n1 -> 2\n2 -> 1\n2 -> 3\n3 -> 2\n" -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> gr2 := Digraph(adj);; +gap> dot2 := GraphvizDotDigraph(gr2);; +gap> AsString(dot2); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2\n\t2 \ +-> 1\n\t2 -> 3\n\t3 -> 2\n\t3 -> 3\n\t3 -> 4\n\t4 -> 3\n}\n" +gap> dot3 := GraphvizDotSymmetricDigraph(gr2);; +gap> AsString(dot3); +"graph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t1 -- 2\n\t2 --\ + 3\n\t3 -- 3\n\t3 -- 4\n}\n" #DotColoredDigraph and DotSymmetriColoredDigraph -gap> D := CompleteDigraph(4); - +gap> D := CompleteDigraph(4);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; @@ -95,10 +66,16 @@ 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{\nnode [shape" -gap> D := Digraph([[2], [1, 3], [2]]); - +gap> dot1 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; +gap> AsString(dot1); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ +2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yello\ +w, style=filled]\n\t1 -> 2 [color=lightblue]\n\t1 -> 3 [color=pink]\n\t1 -> 4 \ +[color=purple]\n\t2 -> 1 [color=lightblue]\n\t2 -> 3 [color=pink]\n\t2 -> 4 [c\ +olor=purple]\n\t3 -> 1 [color=lightblue]\n\t3 -> 2 [color=pink]\n\t3 -> 4 [col\ +or=purple]\n\t4 -> 1 [color=lightblue]\n\t4 -> 2 [color=pink]\n\t4 -> 3 [color\ +=purple]\n}\n" +gap> D := Digraph([[2], [1, 3], [2]]);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; gap> vertcolors[2] := "pink";; @@ -109,12 +86,12 @@ 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{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=pink, style=filled]\n3[color=purple, style=filled]\n1 -- 2[color=green]\n2 -\ -- 3[color=red]\n}\n" -gap> D := Digraph([[2, 3], [1, 3], [1]]); - +gap> dot2 := GraphvizDotSymmetricColoredDigraph(D, vertcolors, edgecolors);; +gap> AsString(dot2); +"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ +[color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t1 -- 2 [color=\ +green]\n\t2 -- 3 [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";; @@ -124,13 +101,13 @@ 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{\nnode [shape=circle]\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n1 -> 2[color=orange]\n1 ->\ - 3[color=yellow]\n2 -> 1[color=orange]\n2 -> 3[color=pink]\n3 -> 1[color=yello\ -w]\n}\n" -gap> D := Digraph(IsMutableDigraph, [[2, 3], [1, 3], [1]]); - +gap> dot3 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; +gap> AsString(dot3); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ +2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t1 -> 2 [color=\ +orange]\n\t1 -> 3 [color=yellow]\n\t2 -> 1 [color=orange]\n\t2 -> 3 [color=pin\ +k]\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";; @@ -140,11 +117,13 @@ 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> dot4 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; +gap> AsString(dot4); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ +2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t1 -> 2 [color=\ +orange]\n\t1 -> 3 [color=yellow]\n\t2 -> 1 [color=orange]\n\t2 -> 3 [color=pin\ +k]\n\t3 -> 1 [color=yellow]\n}\n" +gap> D := Digraph([[2, 4], [1, 3], [2], [1]]);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; @@ -154,12 +133,13 @@ gap> edgecolors[3] := [];; edgecolors[4] := [];; gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "orange";; gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "orange";; gap> edgecolors[3][1] := "orange";; edgecolors[4][1] := "orange";; -gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors); -"//dot\ngraph hgn{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n4[color=yellow, style=fill\ -ed]\n1 -- 2[color=orange]\n1 -- 4[color=orange]\n2 -- 3[color=orange]\n}\n" -gap> D := Digraph(IsMutableDigraph, [[2, 4], [1, 3], [2], [1]]); - +gap> dot5 := GraphvizDotSymmetricColoredDigraph(D, vertcolors, edgecolors);; +gap> AsString(dot5); +"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ +[color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yellow,\ + style=filled]\n\t1 -- 2 [color=orange]\n\t1 -- 4 [color=orange]\n\t2 -- 3 [co\ +lor=orange]\n}\n" +gap> D := Digraph(IsMutableDigraph, [[2, 4], [1, 3], [2], [1]]);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; @@ -169,14 +149,13 @@ gap> edgecolors[3] := [];; edgecolors[4] := [];; gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "orange";; gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "orange";; gap> edgecolors[3][1] := "orange";; edgecolors[4][1] := "orange";; -gap> DotSymmetricColoredDigraph(D, vertcolors, edgecolors); -"//dot\ngraph hgn{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n4[color=yellow, style=fill\ -ed]\n1 -- 2[color=orange]\n1 -- 4[color=orange]\n2 -- 3[color=orange]\n}\n" -gap> D; - -gap> D := CompleteDigraph(4); - +gap> dot6 := GraphvizDotSymmetricColoredDigraph(D, vertcolors, edgecolors);; +gap> AsString(dot6); +"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ +[color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yellow,\ + style=filled]\n\t1 -- 2 [color=orange]\n\t1 -- 4 [color=orange]\n\t2 -- 3 [co\ +lor=orange]\n}\n" +gap> D := CompleteDigraph(4);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "banana";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; @@ -195,11 +174,10 @@ gap> edgecolors[3][3] := "purple";; gap> edgecolors[4][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; gap> edgecolors[4][3] := "purple";; -gap> DotColoredDigraph(D, vertcolors, edgecolors){[5 .. 35]}; +gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors){[5 .. 35]}; Error, expected RGB Value or valid color name as defined by GraphViz 2.44.1 X1\ 1 Color Scheme http://graphviz.org/doc/info/colors.html -gap> D := CompleteDigraph(4); - +gap> D := CompleteDigraph(4);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; @@ -218,11 +196,10 @@ 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); +gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); Error, the number of vertex colors must be the same as the number of vertices,\ expected 4 but found 3 -gap> D := CompleteDigraph(4); - +gap> D := CompleteDigraph(4);; gap> vertcolors := [];; gap> vertcolors[1] := 2;; vertcolors[2] := 1;; gap> vertcolors[3] := 1;; vertcolors[4] := 3;; @@ -241,10 +218,9 @@ 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); +gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); Error, expected a string -gap> D := CompleteDigraph(4); - +gap> D := CompleteDigraph(4);; gap> vertcolors := [];; gap> vertcolors[1] := "#AB3487";; vertcolors[2] := "#DF4738";; gap> vertcolors[3] := "#4BF234";; vertcolors[4] := "#AF34C9";; @@ -263,15 +239,16 @@ gap> edgecolors[3][3] := "purple";; gap> edgecolors[4][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; gap> edgecolors[4][3] := "purple";; -gap> DotColoredDigraph(D, vertcolors, edgecolors); -"//dot\ndigraph hgn{\nnode [shape=circle]\n1[color=#AB3487, style=filled]\n2[c\ -olor=#DF4738, style=filled]\n3[color=#4BF234, style=filled]\n4[color=#AF34C9, \ -style=filled]\n1 -> 2[color=lightblue]\n1 -> 3[color=pink]\n1 -> 4[color=purpl\ -e]\n2 -> 1[color=lightblue]\n2 -> 3[color=pink]\n2 -> 4[color=purple]\n3 -> 1[\ -color=lightblue]\n3 -> 2[color=pink]\n3 -> 4[color=purple]\n4 -> 1[color=light\ -blue]\n4 -> 2[color=pink]\n4 -> 3[color=purple]\n}\n" -gap> D := CompleteDigraph(4); - +gap> x1 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; +gap> AsString(x1); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=#AB3487, style=filled]\ +\n\t2 [color=#DF4738, style=filled]\n\t3 [color=#4BF234, style=filled]\n\t4 [c\ +olor=#AF34C9, style=filled]\n\t1 -> 2 [color=lightblue]\n\t1 -> 3 [color=pink]\ +\n\t1 -> 4 [color=purple]\n\t2 -> 1 [color=lightblue]\n\t2 -> 3 [color=pink]\n\ +\t2 -> 4 [color=purple]\n\t3 -> 1 [color=lightblue]\n\t3 -> 2 [color=pink]\n\t\ +3 -> 4 [color=purple]\n\t4 -> 1 [color=lightblue]\n\t4 -> 2 [color=pink]\n\t4 \ +-> 3 [color=purple]\n}\n" +gap> D := CompleteDigraph(4);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; @@ -290,11 +267,10 @@ 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); +gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); Error, expected RGB Value or valid color name as defined by GraphViz 2.44.1 X1\ 1 Color Scheme http://graphviz.org/doc/info/colors.html -gap> D := CompleteDigraph(4); - +gap> D := CompleteDigraph(4);; gap> vertcolors := [];; gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; @@ -312,52 +288,35 @@ gap> edgecolors[3][2] := "pink";; gap> edgecolors[3][3] := "purple";; gap> edgecolors[4][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; -gap> DotColoredDigraph(D, vertcolors, edgecolors); +gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); Error, the list of edge colors needs to have the same shape as the out-neighbo\ urs of the digraph # DotVertexColoredDigraph -gap> D := CompleteDigraph(4); - +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> out1 := GraphvizDotVertexColoredDigraph(D, vertcolors);; +gap> AsString(out1); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ +2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yello\ +w, style=filled]\n\t1 -> 2\n\t1 -> 3\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" +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{\nnode [shape=circle]\n1[color=blue, style=filled]\n2[colo\ -r=red, style=filled]\n3[color=green, style=filled]\n}\n" +gap> out2 := GraphvizDotVertexColoredDigraph(D, vertcolors);; +gap> AsString(out2); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ +2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n}\n" # DotEdgeColoredDigraph -gap> D := CompleteDigraph(4); - +gap> D := CompleteDigraph(4);; gap> edgecolors := [];; gap> edgecolors[1] := [];; edgecolors[2] := [];; gap> edgecolors[3] := [];; edgecolors[4] := [];; @@ -373,62 +332,63 @@ 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{\nnode [shape=circle]\n1\n2\n3\n4\n1 -> 2[color=lightblue]\ -\n1 -> 3[color=pink]\n1 -> 4[color=purple]\n2 -> 1[color=lightblue]\n2 -> 3[co\ -lor=pink]\n2 -> 4[color=purple]\n3 -> 1[color=lightblue]\n3 -> 2[color=pink]\n\ -3 -> 4[color=purple]\n4 -> 1[color=lightblue]\n4 -> 2[color=pink]\n4 -> 3[colo\ -r=purple]\n}\n" -gap> DotEdgeColoredDigraph(CycleDigraph(3), []); +gap> out1 := GraphvizDotEdgeColoredDigraph(D, edgecolors);; +gap> AsString(out1){[1 .. 300]}; +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2 [colo\ +r=lightblue]\n\t1 -> 3 [color=pink]\n\t1 -> 4 [color=purple]\n\t2 -> 1 [color=\ +lightblue]\n\t2 -> 3 [color=pink]\n\t2 -> 4 [color=purple]\n\t3 -> 1 [color=li\ +ghtblue]\n\t3 -> 2 [color=pink]\n\t3 -> 4 [color=purple]\n\t4 -> 1 [color=ligh\ +tblue]\n\t4 -> 2 [color" +gap> GraphvizDotEdgeColoredDigraph(CycleDigraph(3), []); Error, the list of edge colors needs to have the same shape as the out-neighbo\ urs of the digraph -gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail, fail], [fail], [fail]]); +gap> GraphvizDotEdgeColoredDigraph(CycleDigraph(3), [[fail, fail], [fail], [fail]]); Error, the list of edge colors needs to have the same shape as the out-neighbo\ urs of the digraph -gap> DotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]); +gap> GraphvizDotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]); Error, expected a string # DotSymmetricVertexColoredDigraph -gap> D := Digraph([[2], [1, 3], [2]]); - +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{\nnode [shape=circle]\n\n1[color=blue, style=filled]\n2[colo\ -r=pink, style=filled]\n3[color=purple, style=filled]\n1 -- 2\n2 -- 3\n}\n" +gap> out1 := GraphvizDotSymmetricVertexColoredDigraph(D, vertcolors);; +gap> AsString(out1); +"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ +[color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t1 -- 2\n\t2 --\ + 3\n}\n" # DotSymmetricEdgeColoredDigraph -gap> D := Digraph([[2], [1, 3], [2]]); - +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{\nnode [shape=circle]\n\n1\n2\n3\n1 -- 2[color=green]\n2 -- \ -3[color=red]\n}\n" +gap> out1 := GraphvizDotSymmetricEdgeColoredDigraph(D, edgecolors);; +gap> AsString(out1); +"graph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t1 -- 2 [color=green\ +]\n\t2 -- 3 [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{\nnode [shape=circle]\n1 [label=\"1\"]\n2 [label=\"2\"]\n3\ - [label=\"3\"]\n1 -> 1\n1 -> 2\n1 -> 2\n1 -> 3\n}\n" +gap> gr := Digraph(r);; +gap> dot1 := GraphvizDotVertexLabelledDigraph(gr);; +gap> AsString(dot1); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [label=1]\n\t2 [label=2]\n\t3 \ +[label=3]\n\t1 -> 1\n\t1 -> 2\n\t1 -> 2\n\t1 -> 3\n}\n" gap> SetDigraphVertexLabel(gr, 1, 2); -gap> dot := DotVertexLabelledDigraph(gr);; -gap> dot; -"//dot\ndigraph hgn{\nnode [shape=circle]\n1 [label=\"2\"]\n2 [label=\"2\"]\n3\ - [label=\"3\"]\n1 -> 1\n1 -> 2\n1 -> 2\n1 -> 3\n}\n" +gap> dot2 := GraphvizDotVertexLabelledDigraph(gr);; +gap> AsString(dot2); +"digraph 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, +Error, the 1st argument must be a string or graphviz graph. gap> Splash("string", 0); Error, the 2nd argument must be a record, gap> Splash("string"); @@ -437,8 +397,8 @@ 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(viewer := "xpdf")); +Error, the viewer "xpdf" 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" @@ -463,132 +423,84 @@ Error, none of the default viewers [ "nonexistent-viewer" onent `viewer`, gap> VizViewers := VizViewers_backup;; gap> MakeReadOnlyGlobal("VizViewers"); +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\ +, # 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> out1 := GraphvizDotPartialOrderDigraph(gr);; +gap> AsString(out1); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t5\n\t6\n\t7\ +\n\t8\n\t2 -> 1\n\t3 -> 1\n\t4 -> 1\n\t5 -> 2\n\t5 -> 3\n\t5 -> 4\n\t6 -> 5\n\ +\t7 -> 5\n\t8 -> 1\n}\n" 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> out2 := GraphvizDotPartialOrderDigraph(gr);; +gap> AsString(out2); +"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t5\n\t6\n\t3 \ +-> 1\n\t4 -> 2\n\t5 -> 3\n\t5 -> 4\n\t6 -> 3\n\t6 -> 2\n}\n" gap> gr := Digraph([[1], []]);; -gap> DotPartialOrderDigraph(gr); +gap> GraphvizDotPartialOrderDigraph(gr);; Error, the argument must be a partial order digraph, +# +gap> DIGRAPHS_StopTest(); +gap> STOP_TEST("Digraphs package: standard/display.tst", 0); + # DotPreorderDigraph and DotQuasiorderDigraph -gap> DotPreorderDigraph(CompleteDigraph(5)); +gap> GraphvizDotPreorderDigraph(CompleteDigraph(5));; Error, the argument must be a preorder digraph, 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> out1 := GraphvizDotPreorderDigraph(gr);; +gap> AsString(out1); +"digraph graphname {\n\tnode [shape=\"Mrecord\"] height=\"0.5\" fixedsize=\"tr\ +ue\" ranksep=\"1\" \n\t1 [label=\"1\", width=0.5]\n\t2 [label=\"2\", width=0.5\ +]\n\t3 [label=\"3\", width=0.5]\n\t4 [label=\"4\", width=0.5]\n\t5 [label=\"5\ +\", width=0.5]\n\t6 [label=\"6\", width=0.5]\n\t7 [label=\"7\", width=0.5]\n\t\ +8 [label=\"8\", width=0.5]\n\t2 -> 1\n\t3 -> 1\n\t4 -> 1\n\t5 -> 2\n\t5 -> 3\n\ +\t5 -> 4\n\t6 -> 5\n\t7 -> 5\n\t8 -> 1\n}\n" gap> gr := Concatenation("&X_?_A]|^Vr[nHpmVcy~zy[A????_???G??B]nhtmvcwvJq\\^~", > "|m??_AEx]Rb[nHo??__vJy[??A??O_aV~^Zb]njo???_???GZdxMLy}n_");; gap> gr := DigraphFromDigraph6String(gr);; -gap> Print(DotPreorderDigraph(gr){[1 .. 94]}, "\n"); -//dot -digraph graphname { -node [shape=Mrecord, height=0.5, fixedsize=true]ranksep=1; -1 [label= +gap> out2 := GraphvizDotPreorderDigraph(gr);; +gap> AsString(out2); +"digraph graphname {\n\tnode [shape=\"Mrecord\"] height=\"0.5\" fixedsize=\"tr\ +ue\" ranksep=\"1\" \n\t1 [label=\"23\", width=0.5]\n\t2 [label=\"13\", width=0\ +.5]\n\t3 [label=\"1\", width=0.5]\n\t4 [label=\"8\", width=0.5]\n\t5 [label=\"\ +7\", width=0.5]\n\t6 [label=\"6\", width=0.5]\n\t7 [label=\"22\", width=0.5]\n\ +\t8 [label=\"16\", width=0.5]\n\t9 [label=\"19\", width=0.5]\n\t10 [label=\"4|\ +3|15|14|11|24\", width=3.]\n\t11 [label=\"17\", width=0.5]\n\t12 [label=\"9\",\ + width=0.5]\n\t13 [label=\"21\", width=0.5]\n\t14 [label=\"25\", width=0.5]\n\ +\t15 [label=\"2\", width=0.5]\n\t16 [label=\"10\", width=0.5]\n\t17 [label=\"5\ +\", width=0.5]\n\t18 [label=\"20\", width=0.5]\n\t19 [label=\"12\", width=0.5]\ +\n\t20 [label=\"18\", width=0.5]\n\t2 -> 1\n\t3 -> 2\n\t8 -> 7\n\t9 -> 2\n\t9 \ +-> 4\n\t10 -> 9\n\t10 -> 5\n\t10 -> 6\n\t10 -> 8\n\t11 -> 10\n\t12 -> 11\n\t13\ + -> 12\n\t14 -> 13\n\t15 -> 3\n\t15 -> 14\n\t16 -> 3\n\t16 -> 10\n\t17 -> 16\n\ +\t17 -> 12\n\t18 -> 17\n\t19 -> 18\n}\n" 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 -} +gap> out3 := GraphvizDotPreorderDigraph(gr);; +gap> AsString(out3); +"digraph graphname {\n\tnode [shape=\"Mrecord\"] height=\"0.5\" fixedsize=\"tr\ +ue\" ranksep=\"1\" \n\t1 [label=\"11|12|13|14|15\", width=2.5]\n\t2 [label=\"1\ +|2|3|4|5|6|7|8|9|10\", width=5.]\n\t3 [label=\"16|17\", width=1.]\n\t2 -> 1\n}\ +\n" # DotHighlightedDigraph -gap> gr := Digraph([[2, 3], [2], [1, 3]]); - -gap> Print(DotHighlightedDigraph(gr, [1, 2], "red", "black")); -//dot -digraph hgn{ -subgraph lowverts{ -node [shape=circle, color=black] - edge [color=black] -3 -} -subgraph highverts{ -node [shape=circle, color=red] - edge [color=red] -1 -2 -} -subgraph lowverts{ -3 -> 1 -3 -> 3 -} -subgraph highverts{ -1 -> 2 -1 -> 3 [color=black] -2 -> 2 -} -} +gap> gr := Digraph([[2, 3], [2], [1, 3]]);; +gap> out1 := GraphvizDotHighlightedDigraph(gr, [1, 2], "red", "black");; +gap> ReplacedString(AsString(out1), ">", "<"); +"digraph hgn {\n\t3 [color=black, shape=circle]\n\t1 [color=red, shape=circle]\ +\n\t2 [color=red, shape=circle]\n\t3 -< 1 [color=black]\n\t3 -< 3 [color=black\ +]\n\t1 -< 2 [color=red]\n\t1 -< 3 [color=black]\n\t2 -< 2 [color=red]\n}\n" gap> D := CycleDigraph(5);; gap> DotHighlightedDigraph(D, [10], "black", "grey"); Error, the 2nd argument must be a list of vertices of the 1st argu\ @@ -599,52 +511,12 @@ Error, the 3rd argument must be a string containing the name of a\ gap> DotHighlightedDigraph(D, [1], "black", ""); Error, the 4th argument must be a string containing the name of a \ colour, -gap> Print(DotHighlightedDigraph(D, Filtered(DigraphVertices(D), IsEvenInt))); -//dot -digraph hgn{ -subgraph lowverts{ -node [shape=circle, color=grey] - edge [color=grey] -1 -3 -5 -} -subgraph highverts{ -node [shape=circle, color=black] - edge [color=black] -2 -4 -} -subgraph lowverts{ -1 -> 2 -3 -> 4 -5 -> 1 -} -subgraph highverts{ -2 -> 3 [color=grey] -4 -> 5 [color=grey] -} -} - -# 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\ -, - -# 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> out2 := GraphvizDotHighlightedDigraph(D, Filtered(DigraphVertices(D), IsEvenInt));; +gap> AsString(out2); +"digraph hgn {\n\t1 [color=grey, shape=circle]\n\t3 [color=grey, shape=circle]\ +\n\t5 [color=grey, shape=circle]\n\t2 [color=black, shape=circle]\n\t4 [color=\ +black, shape=circle]\n\t1 -> 2 [color=grey]\n\t3 -> 4 [color=grey]\n\t5 -> 1 [\ +color=grey]\n\t2 -> 3 [color=grey]\n\t4 -> 5 [color=grey]\n}\n" # gap> DIGRAPHS_StopTest(); From dc60352d42280f248468d0d086d9f4a19189f265 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Tue, 7 May 2024 17:41:46 +0100 Subject: [PATCH 2/5] etc: add scripts for generating code coverage --- etc/code-coverage-test-c.py | 151 ++++++++++++++++++++++++++++++++++ etc/code-coverage-test-gap.py | 107 ++++++++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100755 etc/code-coverage-test-c.py create mode 100755 etc/code-coverage-test-gap.py diff --git a/etc/code-coverage-test-c.py b/etc/code-coverage-test-c.py new file mode 100755 index 000000000..62cd03294 --- /dev/null +++ b/etc/code-coverage-test-c.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +""" +""" + +# pylint: disable=invalid-name, broad-except + +import argparse +import tempfile +import subprocess +import sys +import os +import webbrowser + +from os.path import exists, isfile + +_ERR_PREFIX = '\033[31merror: ' + +def exec_string(string): + 'execute the string in a subprocess.' + try: + subprocess.check_call(string, shell=True) + except KeyboardInterrupt: + sys.exit('\033[31m\nKilled!\033[0m') + except (subprocess.CalledProcessError, OSError): + sys.exit(_ERR_PREFIX + 'executing:\n' + string + '\n failed!\033[0m') + +_PARSER = argparse.ArgumentParser(prog='code-coverage-test-c.py', + usage='%(prog)s [options]') +_PARSER.add_argument('files', nargs='+', type=str, + help='the test files you want to check code coverage for' + + '(must be at least one)') +_PARSER.add_argument('--gap-root', nargs='?', type=str, + help='the gap root directory (default: ~/gap)', + default='~/gap/') +_PARSER.add_argument('--pkg', nargs='?', type=str, + help='the package to profile (default: None)', + default=None) +_PARSER.add_argument('--build', dest='build', action='store_true', + help='rebuild GAP (default: False)') +_PARSER.set_defaults(build=False) +_PARSER.add_argument('--open', nargs='?', type=str, + help=('open the lcov html page for this file ' + + '(default: None)'), + default=None) +_PARSER.add_argument('--line', nargs='?', type=str, + help=('open the html page for the file specified by --open' + + ' at this line (default: None)'), + default=None) +_ARGS = _PARSER.parse_args() + +if not _ARGS.gap_root[-1] == '/': + _ARGS.gap_root += '/' + +_ARGS.gap_root = os.path.expanduser(_ARGS.gap_root) +if _ARGS.pkg != None: + _ARGS.pkg = _ARGS.gap_root + '/pkg/' + _ARGS.pkg + +if not (os.path.exists(_ARGS.gap_root) and os.path.isdir(_ARGS.gap_root)): + sys.exit('\033[31mcode-coverage-test-c.py: error: can\'t find gap root' + + ' directory!\033[0m') +if (_ARGS.pkg != None and not (os.path.exists(_ARGS.pkg) and + os.path.isdir(_ARGS.pkg))): + sys.exit('\033[31mcode-coverage-test-c.py: error: can\'t find the pkg' + + ' directory %s\033[0m' % _ARGS.pkg) +for f in _ARGS.files: + if not (os.path.exists(f) and os.path.isfile(f)): + sys.exit('\033[31mcode-coverage-test-c.py: error: ' + f + + ' does not exist!\033[0m') + +_DIR = tempfile.mkdtemp() +print('\033[35musing temporary directory: ' + _DIR + '\033[0m') + +_COMMANDS = 'echo "' +for f in _ARGS.files: + _COMMANDS += 'Test(\\"' + f + '\\");;' +_COMMANDS += '"' + +# TODO build if files changed since last build or built with the wrong flags, +# by looking in config.log + +# for source in : +# if time.ctime(os.path.getmtime(file)) + +if _ARGS.build: + cwd = os.getcwd() + os.chdir(_ARGS.gap_root) + exec_string('''rm -rf bin/ && \ + make clean && \ + ./configure CFLAGS="-O0 -g --coverage" \ + CXXFLAGS="-O0 -g --coverage" \ + LDFLAGS="-O0 -g --coverage" && \ + make -j8''') + if _ARGS.pkg != None: + os.chdir(_ARGS.pkg) + exec_string('rm -rf bin/ && \ + make clean && \ + ./configure CFLAGS="-O0 -g --coverage" \ + CXXFLAGS="-O0 -g --coverage" \ + LDFLAGS="-O0 -g --coverage" && \ + make -j8''') + os.chdir(cwd) + +pro1 = subprocess.Popen(_COMMANDS, stdout=subprocess.PIPE, shell=True) +_RUN_GAP = _ARGS.gap_root + 'bin/gap.sh -A -m 1g -T' + +try: + pro2 = subprocess.Popen(_RUN_GAP, + stdin=pro1.stdout, + shell=True) + pro2.wait() + print('') +except KeyboardInterrupt: + pro1.terminate() + pro1.wait() + pro2.terminate() + pro2.wait() + print('\033[31mKilled!\033[0m') + sys.exit(1) +except Exception: + sys.exit('\033[31mcode-coverage-test-c.py: error: something went wrong ' + + 'calling GAP!\033[0m''') +if _ARGS.pkg != None: + exec_string('lcov --capture --directory ' + _ARGS.pkg + + '/src --output-file ' + _DIR + '/lcov.info') +else: + exec_string('lcov --capture --directory ' + _ARGS.gap_root + + '/src --output-file ' + _DIR + '/lcov.info') + +exec_string('genhtml ' + _DIR + '/lcov.info --output-directory ' + _DIR + + '/lcov-out') + +filename = _DIR + '/lcov-out/' +if _ARGS.open: + filename += _ARGS.open + '.gcov.html' +else: + filename += '/index.html' + +if exists(filename) and isfile(filename): + if _ARGS.open and _ARGS.line: + filename += '#' + _ARGS.line + print('file://' + filename) + try: + webbrowser.get('chrome').open('file://' + filename, new=2) + except Exception: + webbrowser.open('file://' + filename, new=2) +else: + sys.exit('\n' + _ERR_PREFIX + 'Failed to open file://' + filename + + '\033[0m') + +print('\n\033[32mSUCCESS!\033[0m') +sys.exit(0) diff --git a/etc/code-coverage-test-gap.py b/etc/code-coverage-test-gap.py new file mode 100755 index 000000000..e50ea5a89 --- /dev/null +++ b/etc/code-coverage-test-gap.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +""" +This is a simple script to run code coverage for some test files. +""" +# pylint: disable=invalid-name + +import argparse +import os +import re +import subprocess +import sys +import tempfile + +from os.path import exists, isdir, isfile +from os import getcwd + +_ERR_PREFIX = "\033[31mcode-coverage-test-gap.py: error: " +_INFO_PREFIX = "\033[0m\033[1m" + +_PARSER = argparse.ArgumentParser( + prog="code-coverage-test-gap.py", usage="%(prog)s [options]" +) +_PARSER.add_argument( + "tstfiles", + nargs="+", + type=str, + help="the test files you want to check code coverage for" + + "(must be at least one)", +) +_PARSER.add_argument( + "--gap-root", + nargs="?", + type=str, + help="the gap root directory (default: ~/gap)", + default="~/gap/", +) +_PARSER.add_argument( + "--open", + nargs="?", + type=str, + help=("open the html page for this file (default: None)"), + default=None, +) + +_ARGS = _PARSER.parse_args() +if not _ARGS.gap_root[-1] == "/": + _ARGS.gap_root += "/" + +if exists("gap") and isdir("gap"): + _PROFILE_DIR = "/gap/" +elif exists("lib") and isdir("lib"): + _PROFILE_DIR = "/lib/" +else: + sys.exit(f"{_ERR_PREFIX}no directory gap or lib to profile!\033[0m") + +_ARGS.gap_root = os.path.expanduser(_ARGS.gap_root) +if not (exists(_ARGS.gap_root) and isdir(_ARGS.gap_root)): + sys.exit(f"{_ERR_PREFIX}can't find GAP root directory!\033[0m") + +for f in _ARGS.tstfiles: + if not (exists(f) and isfile(f)): + sys.exit(f"{_ERR_PREFIX}{f} does not exist!\033[0m") + +_DIR = tempfile.mkdtemp() +print(f"{_INFO_PREFIX}Using temporary directory: {_DIR}\033[0m") + +_COMMANDS = 'echo "' +_COMMANDS += "".join(rf"Test(\"{f}\");;\n" for f in _ARGS.tstfiles) +_COMMANDS += rf"""UncoverageLineByLine();; +LoadPackage(\"profiling\", false);; +filesdir := \"{getcwd()}{_PROFILE_DIR}\";;\n""" + +_COMMANDS += rf"outdir := \"{_DIR}\";;\n" +_COMMANDS += rf"x := ReadLineByLineProfile(\"{_DIR}/profile.gz\");;\n" +_COMMANDS += 'OutputAnnotatedCodeCoverageFiles(x, filesdir, outdir);"' + +_RUN_GAP = f"{_ARGS.gap_root}/gap -A -m 1g -T --cover {_DIR}/profile.gz" + +with subprocess.Popen(_COMMANDS, stdout=subprocess.PIPE, shell=True) as pro1: + try: + with subprocess.Popen(_RUN_GAP, stdin=pro1.stdout, shell=True) as pro2: + pro2.wait() + except KeyboardInterrupt: + pro1.terminate() + pro1.wait() + sys.exit("\033[31mKilled!\033[0m") + except (subprocess.CalledProcessError, IOError, OSError): + sys.exit(_ERR_PREFIX + "Something went wrong calling GAP!\033[0m") + + +def rewrite_fname(fname: str) -> str: + return fname.replace("/", "_") + + +suffix = "" +if _ARGS.open: + filename = f"{_DIR}/{rewrite_fname(getcwd())}/{rewrite_fname(_ARGS.open)}.html" + p = re.compile(r"") + with open(filename, "r", encoding="utf-8") as f: + m = p.search(f.read()) + if m: + suffix += "#line" + m.group(1) +else: + filename = _DIR + "/index.html" +print(f"{_INFO_PREFIX}\nSUCCESS!\033[0m") +print(f"{_INFO_PREFIX} See {filename}") +sys.exit(0) From db915089f277ffb5329dddee18c2f7e7cce8c17b Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 3 May 2024 17:47:06 +0100 Subject: [PATCH 3/5] Replace Dot -> Graphviz --- .codespellrc | 2 +- PackageInfo.g | 3 +- doc/display.xml | 846 +++++++++++++++------------------------ doc/main.xml | 5 +- doc/z-chap9.xml | 15 +- gap/deprecated.gd | 35 ++ gap/deprecated.gi | 116 ++++++ gap/display.gd | 84 ++-- gap/display.gi | 568 ++++++++++---------------- init.g | 1 + read.g | 1 + tst/standard/display.tst | 845 ++++++++++++++++++++++---------------- 12 files changed, 1289 insertions(+), 1232 deletions(-) create mode 100644 gap/deprecated.gd create mode 100644 gap/deprecated.gi diff --git a/.codespellrc b/.codespellrc index 1816cb1ef..6520d3fde 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,3 +1,3 @@ [codespell] -skip = ./.git,./tmp,./data,./extern,./tst,./bin,./libtool,configure,configure~,./gh-pages,./autom4te.cache,./cnf,aclocal.m4,./m4,./doc/*.log,./doc/*.html,./doc/*.txt,./doc/*.six,./doc/*.js,./doc/*.bbl,./doc/*.tex,./doc/*.bib +skip = ./.git,./tmp,./data,./extern,./tst,./bin,./libtool,configure,configure~,./gh-pages,./autom4te.cache,./cnf,aclocal.m4,./m4,./doc/*.log,./doc/*.html,./doc/*.txt,./doc/*.six,./doc/*.js,./doc/*.bbl,./doc/*.tex,./doc/*.bib,./digraphs-lib/* ignore-words-list=ist,manuel,MIS,mis diff --git a/PackageInfo.g b/PackageInfo.g index 1351419c0..dbbf820ec 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -16,6 +16,7 @@ ## ## ## +## ## ## ## <#/GAPDoc> @@ -390,7 +391,7 @@ Dependencies := rec( GAP := ">=4.10.0", NeededOtherPackages := [["io", ">=4.5.1"], ["orb", ">=4.8.2"], - ["graphviz", "*"], + ["graphviz", ">=0.0.0"], ["datastructures", ">=0.2.5"]], SuggestedOtherPackages := [["GAPDoc", ">=1.6.3"], ["grape", ">=4.8.1"], diff --git a/doc/display.xml b/doc/display.xml index f064d9a05..7086f1929 100644 --- a/doc/display.xml +++ b/doc/display.xml @@ -1,518 +1,282 @@ ############################################################################# ## #W display.xml -#Y Copyright (C) 2011-17 James D. Mitchell +#Y Copyright (C) 2014-24 James D. Mitchell ## ## Licensing information can be found in the README file of this package. ## ############################################################################# ## +<#GAPDoc Label="DotDigraph"> + + + + A string. + + WARNING! As of v2.0.0 of &Digraphs; these functions are + deprecated in favour of: + + + + + and return + mutable &GAP; objects representing graphviz objects, which provide a + more flexible means of tailoring pictures of graphs and digraphs to your + needs. The function DotDigraph is synonymous with + AsString(GraphvizDigraph(D)). It is also possible to use + directly on the graphviz objects + returned by the function , i.e. + Splash(GraphvizDigraph(D)) does precisely the same thing as + Splash(DotDigraph(D)). + + +<#/GAPDoc> -<#GAPDoc Label="Splash"> +<#GAPDoc Label="GraphvizDigraph"> - - Nothing. + + + A &graphviz; object. - This function attempts to convert the string str into a pdf - document and open this document, i.e. to splash it all over your monitor.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ of D in the corresponding strongly connected component. +

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

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

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

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

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

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

+ + See and + for more details on the output. + + D := Digraph([[2, 3], [2], [1, 3]]); + +gap> GraphvizHighlightedDigraph(D, [1, 2], "red", "black"); + +gap> D := DigraphSymmetricClosure(D); + +gap> GraphvizHighlightedGraph(D, [1, 2], "red", "black"); +]]> <#/GAPDoc> diff --git a/doc/main.xml b/doc/main.xml index 95ee02d6b..e5c287f5a 100644 --- a/doc/main.xml +++ b/doc/main.xml @@ -3,10 +3,13 @@ https://gap-packages.github.io/grapeGrape"> + https://digraphs.github.io/graphvizGraphviz"> http://www.tcs.tkk.fi/Software/bliss/bliss"> - https://github.com/graph-algorithms/edge-addition-planarity-suiteedge-addition-planarity-suite"> Visualising and IO

Visualising a digraph - <#Include Label="Splash"> + <#Include Label="GraphvizDigraph"> <#Include Label="DotDigraph"> - <#Include Label="DotSymmetricDigraph"> + + <#Include Label="GraphvizColoredDigraph"> + <#Include Label="DotColoredDigraph"> + + <#Include Label="GraphvizVertexLabelledDigraph"> + <#Include Label="DotVertexLabelledDigraph"> + + <#Include Label="GraphvizPartialOrderDigraph"> <#Include Label="DotPartialOrderDigraph"> + + <#Include Label="GraphvizPreorderDigraph"> <#Include Label="DotPreorderDigraph"> + + <#Include Label="GraphvizHighlightedDigraph"> <#Include Label="DotHighlightedDigraph">
diff --git a/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..28bbfdfa4 --- /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, 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); diff --git a/gap/display.gd b/gap/display.gd index 808775f91..93a9c937a 100644 --- a/gap/display.gd +++ b/gap/display.gd @@ -8,37 +8,57 @@ ############################################################################# ## -DeclareAttribute("GraphvizDotDigraph", IsDigraph); -DeclareOperation("GraphvizDotColoredDigraph", [IsDigraph, IsList, IsList]); -DeclareOperation("GraphvizDotVertexColoredDigraph", [IsDigraph, IsList]); -DeclareOperation("GraphvizDotEdgeColoredDigraph", [IsDigraph, IsList]); -DeclareOperation("GraphvizDotVertexLabelledDigraph", [IsDigraph]); -DeclareAttribute("GraphvizDotSymmetricDigraph", IsDigraph); -DeclareOperation("GraphvizDotSymmetricColoredDigraph", - [IsDigraph, IsList, IsList]); -DeclareOperation("GraphvizDotSymmetricVertexColoredDigraph", - [IsDigraph, IsList]); -DeclareOperation("GraphvizDotSymmetricEdgeColoredDigraph", [IsDigraph, IsList]); -DeclareAttribute("GraphvizDotPartialOrderDigraph", IsDigraph); -DeclareAttribute("GraphvizDotPreorderDigraph", IsDigraph); -DeclareSynonym("GraphvizDotQuasiorderDigraph", GraphvizDotPreorderDigraph); -DeclareOperation("GraphvizDotHighlightedDigraph", [IsDigraph, IsList]); -DeclareOperation("GraphvizDotHighlightedDigraph", - [IsDigraph, IsList, IsString, IsString]); +############################################################################# +# Graphs and digraphs +############################################################################# -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", - [IsDigraph, IsList, IsString, IsString]); +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 c4d919ad3..890d29ab5 100644 --- a/gap/display.gi +++ b/gap/display.gi @@ -1,351 +1,225 @@ ############################################################################# ## ## 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("GV_DIGRAPHS_DotDigraph", -function(D, node_funcs, edge_funcs) - local out, nodes, tail, head, node, edge, graph, i, func, j, l; +# 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 - graph := GraphvizDigraph("hgn"); - GraphvizSetAttr(graph, "node [shape=\"circle\"]"); +############################################################################# +# Graphs and digraphs +############################################################################# - for i in DigraphVertices(D) do - node := GraphvizAddNode(graph, StringFormatted("{}", i)); - for func in node_funcs do - func(graph, node, i); - od; +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; - - nodes := GraphvizNodes(graph); - out := OutNeighbours(D); - for i in DigraphVertices(D) do - l := Length(out[i]); - for j in [1 .. l] do - tail := nodes[String(i)]; - head := nodes[String(out[i][j])]; - edge := GraphvizAddEdge(graph, tail, head); - for func in edge_funcs do - func(graph, edge, i, j); - od; + for x in DigraphVertices(D) do + for y in OutNeighboursOfVertexNC(D, x) do + GraphvizAddEdge(gv, x, y); od; od; - return graph; -end); - -BindGlobal("GV_DIGRAPHS_ValidRGBValue", -function(str) - local l, chars, x, i; - l := Length(str); - x := 0; - chars := "0123456789ABCDEFabcdef"; - if l = 7 then - if str[1] = '#' then - for i in [2 .. l] do - if str[i] in chars then - x := x + 1; - fi; - od; - fi; - fi; - if x = (l - 1) then - return true; - else - return false; - fi; -end); - -BindGlobal("GV_DIGRAPHS_GraphvizColorsList", fail); - -BindGlobal("GV_DIGRAPHS_GraphvizColors", -function() - local f; - if GV_DIGRAPHS_GraphvizColorsList = fail then - f := IO_File(Concatenation(DIGRAPHS_Dir(), "/data/colors.p")); - MakeReadWriteGlobal("GV_DIGRAPHS_GraphvizColorsList"); - GV_DIGRAPHS_GraphvizColorsList := IO_Unpickle(f); - MakeReadOnlyGlobal("GV_DIGRAPHS_GraphvizColorsList"); - IO_Close(f); - fi; - return GV_DIGRAPHS_GraphvizColorsList; + return gv; end); -BindGlobal("GV_DIGRAPHS_ValidVertColors", -function(D, verts) - local v, sum, colors, col; - v := DigraphVertices(D); - sum := 0; - if Length(verts) <> Length(v) then - ErrorNoReturn("the number of vertex colors must be the same as the number", - " of vertices, expected ", Length(v), " but found ", Length(verts), ""); - fi; - colors := GV_DIGRAPHS_GraphvizColors(); - if Length(verts) = Length(v) then - for col in verts do - if not IsString(col) then - ErrorNoReturn("expected a string"); - elif GV_DIGRAPHS_ValidRGBValue(col) = false and - (col in colors) = false then - ErrorNoReturn("expected RGB Value or valid color name as defined", - " by GraphViz 2.44.1 X11 Color Scheme", - " http://graphviz.org/doc/info/colors.html"); - else - sum := sum + 1; - fi; - od; - if sum = Length(verts) then - return true; - fi; +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; -end); - -BindGlobal("GV_DIGRAPHS_ValidEdgeColors", -function(D, edge) - local out, l, counter, sum, colors, v, col; - out := OutNeighbours(D); - l := Length(edge); - counter := 0; - sum := 0; - colors := GV_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 GV_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; + 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 counter = Length(edge) then - return true; - fi; - fi; + od; + return gv; end); -InstallMethod(GraphvizDotDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -D -> GV_DIGRAPHS_DotDigraph(D, [], [])); +############################################################################# +# Vertex coloured graphs and digraphs +############################################################################# -InstallMethod(DotDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -D -> AsString(GraphvizDotDigraph(D))); - -InstallMethod(GraphvizDotColoredDigraph, -"for a digraph by out-neighbours and two lists", -[IsDigraphByOutNeighboursRep, IsList, IsList], -function(D, vert, edge) - local vert_func, cond, edge_func; - cond := GV_DIGRAPHS_ValidVertColors(D, vert); - cond := cond and GV_DIGRAPHS_ValidEdgeColors(D, edge); - if cond then - vert_func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], - style := "filled")); - edge_func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); - return GV_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(DotColoredDigraph, "for a digraph by out-neighbours and two lists", -[IsDigraphByOutNeighboursRep, IsList, IsList], -{D, vert, edge} -> AsString(GraphvizDotColoredDigraph(D, vert, edge))); +InstallMethod(GraphvizVertexColoredGraph, "for a digraph and a list", +[IsDigraph, IsList], +# IsSymmetricDigraph checked by GraphvizGraph +{D, colors} -> GraphvizSetNodeColors(GraphvizGraph(D), colors)); -InstallMethod(GraphvizDotVertexColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, vert) - local func; - if GV_DIGRAPHS_ValidVertColors(D, vert) then - func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], - style := "filled")); - return GV_DIGRAPHS_DotDigraph(D, [func], []); - fi; -end); +############################################################################# +# Edge coloured graphs and digraphs +############################################################################# -InstallMethod(DotVertexColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -{D, vert} -> AsString(GraphvizDotVertexColoredDigraph(D, vert))); +# 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; -InstallMethod(GraphvizDotEdgeColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -function(D, edge) - local func; - if GV_DIGRAPHS_ValidEdgeColors(D, edge) then - func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); - return GV_DIGRAPHS_DotDigraph(D, [], [func]); + 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], GV_ErrorIfNotValidColor); + od; end); -InstallMethod(DotEdgeColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -{D, edge} -> AsString(GraphvizDotEdgeColoredDigraph(D, edge))); - -InstallMethod(GraphvizDotVertexLabelledDigraph, -"for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -function(D) - local func; - func := {g, n, i} -> GraphvizSetAttrs(n, rec(label := - DigraphVertexLabel(D, i))); - return GV_DIGRAPHS_DotDigraph(D, [func], []); -end); - -InstallMethod(DotVertexLabelledDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -{D} -> AsString(GraphvizDotVertexLabelledDigraph(D))); - -BindGlobal("GV_DIGRAPHS_DotSymmetricDigraph", -function(D, node_funcs, edge_funcs) - local graph, node, nodes, edge, out, n1, n2, i, j, func; - if not IsSymmetricDigraph(D) then - ErrorNoReturn("the argument must be a symmetric digraph,"); - fi; +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); - - graph := GraphvizGraph("hgn"); - GraphvizSetAttr(graph, "node [shape=\"circle\"]"); - for i in DigraphVertices(D) do - node := GraphvizAddNode(graph, StringFormatted("{}", i)); - for func in node_funcs do - func(graph, node, i); - od; - od; - - nodes := GraphvizNodes(graph); - for i in DigraphVertices(D) do - for j in [1 .. Length(out[i])] do - if out[i][j] >= i then - n1 := nodes[String(i)]; - n2 := nodes[String(out[i][j])]; - edge := GraphvizAddEdge(graph, n1, n2); - for func in edge_funcs do - func(graph, edge, i, j); - od; + for n in DigraphVertices(D) do + for i in [1 .. Length(out[n])] do + if IsGVDigraph(gv) or n > out[n][i] then + e := GraphvizAddEdge(gv, n, out[n][i]); + GraphvizSetAttr(e, "color", colors[n][i]); fi; od; od; - return graph; + return gv; end); -InstallMethod(GraphvizDotSymmetricDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -D -> GV_DIGRAPHS_DotSymmetricDigraph(D, [], [])); - -InstallMethod(DotSymmetricDigraph, "for a digraph by out-neighbours", -[IsDigraphByOutNeighboursRep], -D -> AsString(GraphvizDotSymmetricDigraph(D))); - -InstallMethod(GraphvizDotSymmetricColoredDigraph, -"for a digraph by out-neighbours and two lists", -[IsDigraphByOutNeighboursRep, IsList, IsList], -function(D, vert, edge) - local vert_func, cond, edge_func; - cond := GV_DIGRAPHS_ValidVertColors(D, vert); - cond := cond and GV_DIGRAPHS_ValidEdgeColors(D, edge); - if cond then - vert_func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], - style := "filled")); - edge_func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); - return GV_DIGRAPHS_DotSymmetricDigraph(D, [vert_func], [edge_func]); - fi; -end); - -InstallMethod(GraphvizDotSymmetricVertexColoredDigraph, +InstallMethod(GraphvizEdgeColoredDigraph, "for a digraph by out-neighbours and a list", [IsDigraphByOutNeighboursRep, IsList], -function(D, vert) - local func; - if GV_DIGRAPHS_ValidVertColors(D, vert) then - func := {g, n, i} -> GraphvizSetAttrs(n, rec(color := vert[i], - style := "filled")); - return GV_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(GraphvizDotSymmetricEdgeColoredDigraph, +InstallMethod(GraphvizEdgeColoredGraph, "for a digraph by out-neighbours and a list", [IsDigraphByOutNeighboursRep, IsList], -function(D, edge) - local func; - if GV_DIGRAPHS_ValidEdgeColors(D, edge) then - func := {g, e, i, j} -> GraphvizSetAttrs(e, rec(color := edge[i][j])); - return GV_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); -InstallMethod(DotSymmetricEdgeColoredDigraph, -"for a digraph by out-neighbours and a list", -[IsDigraphByOutNeighboursRep, IsList], -{D, edge} -> AsString(GraphvizDotSymmetricEdgeColoredDigraph(D, edge))); +############################################################################# +# Vertex and edge coloured graphs and digraphs +############################################################################# -# CR's code +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)); -InstallMethod(GraphvizDotPartialOrderDigraph, "for a partial order digraph", +############################################################################# +# Vertex labelled graphs and digraphs +############################################################################# + +InstallMethod(GraphvizVertexLabelledDigraph, "for a digraph", +[IsDigraph], +D -> GraphvizSetNodeLabels(GraphvizDigraph(D), DigraphVertexLabels(D))); + +InstallMethod(GraphvizVertexLabelledGraph, "for a digraph", +[IsDigraph], +# symmetry checked in GraphvizGraph +D -> GraphvizSetNodeLabels(GraphvizGraph(D), DigraphVertexLabels(D))); + +############################################################################# +# Partial and preorder digraphs +############################################################################# + +InstallMethod(GraphvizPartialOrderDigraph, "for a partial order digraph", [IsDigraph], function(D) if not IsPartialOrderDigraph(D) then - ErrorNoReturn("the argument must be a partial order digraph,"); + ErrorNoReturn("the argument (a digraph) must be a partial order"); fi; D := DigraphMutableCopyIfMutable(D); - return GraphvizDotDigraph(DigraphReflexiveTransitiveReduction(D)); + return GraphvizDigraph(DigraphReflexiveTransitiveReduction(D)); end); -InstallMethod(DotPartialOrderDigraph, "for a partial order digraph", -[IsDigraph], -{D} -> AsString(GraphvizDotPartialOrderDigraph(D))); - -InstallMethod(GraphvizDotPreorderDigraph, "for a preorder digraph", +InstallMethod(GraphvizPreorderDigraph, "for a preorder digraph", [IsDigraph], function(D) - local comps, quo, red, c, x, e, node, graph, label, head, tail, nodes; + 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); - - graph := GraphvizDigraph("graphname"); - GraphvizSetAttr(graph, "node [shape=\"Mrecord\"]"); - GraphvizSetAttr(graph, "height=\"0.5\""); - GraphvizSetAttr(graph, "fixedsize=\"true\""); - GraphvizSetAttr(graph, "ranksep=\"1\""); - - # Each vertex of the quotient D is labelled by its preimage. + comps := DigraphStronglyConnectedComponents(D).comps; + D := DigraphMutableCopy(D); + DigraphRemoveAllMultipleEdges(QuotientDigraph(D, comps)); + DigraphReflexiveTransitiveReduction(D); + + gv := GraphvizDigraph("graphname"); + GraphvizSetAttr(gv, "node [shape=\"Mrecord\"]"); + GraphvizSetAttr(gv, "height=\"0.5\""); + GraphvizSetAttr(gv, "fixedsize=\"true\""); + GraphvizSetAttr(gv, "ranksep=\"1\""); + for c in [1 .. Length(comps)] do - # create node w/ label label := "\""; Append(label, String(comps[c][1])); for x in comps[c]{[2 .. Length(comps[c])]} do @@ -354,89 +228,89 @@ function(D) od; Append(label, "\""); - node := GraphvizAddNode(graph, String(c)); + node := GraphvizAddNode(gv, c); GraphvizSetAttr(node, "label", label); - GraphvizSetAttr(node, "width", String(Float(Length(comps[c]) / 2))); + GraphvizSetAttr(node, "width", Float(Length(comps[c]) / 2)); od; - # Add the edges of the quotient D. - nodes := GraphvizNodes(graph); - for e in DigraphEdges(red) do - tail := nodes[String(e[1])]; - head := nodes[String(e[2])]; - GraphvizAddEdge(graph, tail, head); + nodes := GraphvizNodes(gv); + for e in DigraphEdges(D) do + GraphvizAddEdge(gv, nodes[e[1]], nodes[e[2]]); od; - return graph; + return gv; end); -InstallMethod(DotPreorderDigraph, "for a preorder digraph", -[IsDigraph], -{D} -> AsString(GraphvizDotPreorderDigraph(D))); - -InstallMethod(GraphvizDotHighlightedDigraph, "for a digraph and list", -[IsDigraph, IsList], -{D, list} -> GraphvizDotHighlightedDigraph(D, list, "black", "grey")); +############################################################################# +# Highlighted subdigraphs +############################################################################# -InstallMethod(DotHighlightedDigraph, "for a digraph and list", -[IsDigraph, IsList], -{D, list} -> AsString(GraphvizDotHighlightedDigraph(D, list, "black", "grey"))); +BindGlobal("DIGRAPHS_GraphvizHighlight", +function(D, gv, hi_verts, hi, lo) + local node, color, out, nodes, edge, v, i, j; -InstallMethod(GraphvizDotHighlightedDigraph, -"for a digraph by out-neighbours, list, and two strings", -[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], -function(D, highverts, highcolour, lowcolour) - local lowverts, graph, node, edge, nodes, out, 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,"); + 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; + GV_ErrorIfNotValidColor(hi); + GV_ErrorIfNotValidColor(lo); - lowverts := Difference(DigraphVertices(D), highverts); - out := OutNeighbours(D); + GraphvizSetAttr(gv, "shape", "circle"); - graph := GraphvizDigraph("hgn"); - - for i in lowverts do - node := GraphvizAddNode(graph, String(i)); - GraphvizSetAttrs(node, rec(shape := "circle", color := lowcolour)); + 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; - for i in highverts do - node := GraphvizAddNode(graph, String(i)); - GraphvizSetAttrs(node, rec(shape := "circle", color := highcolour)); - od; + out := OutNeighbours(D); + nodes := GraphvizNodes(gv); - nodes := GraphvizNodes(graph); - for i in lowverts do - for j in out[i] do - edge := GraphvizAddEdge(graph, nodes[String(i)], nodes[String(j)]); - GraphvizSetAttr(edge, "color", lowcolour); - od; - od; - - for i in highverts do + for i in DigraphVertices(D) do for j in out[i] do - edge := GraphvizAddEdge(graph, nodes[String(i)], nodes[String(j)]); - GraphvizSetAttr(edge, "color", highcolour); - if j in lowverts then - GraphvizSetAttr(edge, "color", lowcolour); + if IsGVDigraph(gv) or i > j then + edge := GraphvizAddEdge(gv, nodes[i], nodes[j]); + if i in hi_verts and j in hi_verts then + color := hi; + else + color := lo; + fi; + GraphvizSetAttr(edge, "color", color); fi; od; od; - return graph; + return gv; end); -InstallMethod(DotHighlightedDigraph, +InstallMethod(GraphvizHighlightedDigraph, "for a digraph by out-neighbours, list, and two strings", [IsDigraphByOutNeighboursRep, IsList, IsString, IsString], -{D, highverts, highcolour, lowcolour} -> - AsString(GraphvizDotHighlightedDigraph(D, highverts, highcolour, lowcolour))); +{D, hi_verts, hi, lo} -> +DIGRAPHS_GraphvizHighlight(D, GraphvizDigraph(), hi_verts, hi, lo)); + +InstallMethod(GraphvizHighlightedDigraph, "for a digraph and list", +[IsDigraph, IsList], +{D, list} -> GraphvizHighlightedDigraph(D, list, "black", "grey")); + +InstallMethod(GraphvizHighlightedGraph, +"for a digraph by out-neighbours, list, and two strings", +[IsDigraphByOutNeighboursRep, IsList, IsString, IsString], +function(D, hi_verts, hi, lo) + if not IsSymmetricDigraph(D) then + ErrorNoReturn("the argument (a digraph) must be symmetric"); + fi; + return DIGRAPHS_GraphvizHighlight(D, GraphvizGraph(), hi_verts, hi, lo); +end); + +InstallMethod(GraphvizHighlightedGraph, "for a digraph and list", +[IsDigraph, IsList], +# IsSymmetricDigraph checked in GraphvizHighlightedGraph +{D, list} -> GraphvizHighlightedGraph(D, list, "black", "grey")); diff --git a/init.g b/init.g index beae97a2f..261f3369d 100644 --- a/init.g +++ b/init.g @@ -63,5 +63,6 @@ ReadPackage("digraphs", "gap/cliques.gd"); ReadPackage("digraphs", "gap/planar.gd"); ReadPackage("digraphs", "gap/examples.gd"); ReadPackage("digraphs", "gap/weights.gd"); +ReadPackage("digraphs", "gap/deprecated.gd"); DeclareInfoClass("InfoDigraphs"); diff --git a/read.g b/read.g index 3dfbecb7e..f374567f4 100644 --- a/read.g +++ b/read.g @@ -41,3 +41,4 @@ ReadPackage("digraphs", "gap/cliques.gi"); ReadPackage("digraphs", "gap/planar.gi"); ReadPackage("digraphs", "gap/examples.gi"); ReadPackage("digraphs", "gap/weights.gi"); +ReadPackage("digraphs", "gap/deprecated.gi"); diff --git a/tst/standard/display.tst b/tst/standard/display.tst index a87483c7d..0b30d3e74 100644 --- a/tst/standard/display.tst +++ b/tst/standard/display.tst @@ -1,10 +1,9 @@ ############################################################################# ## #W standard/display.tst -#Y Copyright (C) 2014-15 James D. Mitchell +#Y Copyright (C) 2014-24 James D. Mitchell ## ## Licensing information can be found in the README file of this package. -## Taken from the old digraphs display package ## ############################################################################# ## @@ -14,68 +13,95 @@ 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 := GraphvizDotDigraph(gr);; -gap> AsString(dot); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t1 -> 1\n\t1 -> 2\ -\n\t1 -> 2\n\t1 -> 3\n}\n" +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> dot1 := GraphvizDotDigraph(gr1);; -gap> AsString(dot1); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\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 -> 1\n\t4 -> 4\n\ -\t4 -> 8\n\t5 -> 1\n\t5 -> 3\n\t5 -> 6\n\t5 -> 6\n\t5 -> 7\n\t6 -> 7\n\t7 -> 1\ -\n\t7 -> 4\n\t7 -> 4\n\t7 -> 5\n\t7 -> 7\n\t8 -> 5\n\t8 -> 6\n}\n" +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> dot2 := GraphvizDotDigraph(gr2);; -gap> AsString(dot2); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2\n\t2 \ --> 1\n\t2 -> 3\n\t3 -> 2\n\t3 -> 3\n\t3 -> 4\n\t4 -> 3\n}\n" -gap> dot3 := GraphvizDotSymmetricDigraph(gr2);; -gap> AsString(dot3); -"graph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t1 -- 2\n\t2 --\ - 3\n\t3 -- 3\n\t3 -- 4\n}\n" +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 -gap> D := CompleteDigraph(4);; +# TODO fix the colors here! +gap> D := CompleteDigraph(4); + gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; gap> edgecolors := [];; gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; +gap> edgecolors[3] := [];; edgecolors[4] := [];; gap> edgecolors[1][1] := "lightblue";; gap> edgecolors[1][2] := "pink";; gap> edgecolors[1][3] := "purple";; gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][2] := "pink";; -gap> edgecolors[2][3] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; +gap> edgecolors[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "lightblue";; +gap> edgecolors[3][2] := "pink";; gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; gap> edgecolors[4][3] := "purple";; -gap> dot1 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; -gap> AsString(dot1); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ -2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yello\ -w, style=filled]\n\t1 -> 2 [color=lightblue]\n\t1 -> 3 [color=pink]\n\t1 -> 4 \ -[color=purple]\n\t2 -> 1 [color=lightblue]\n\t2 -> 3 [color=pink]\n\t2 -> 4 [c\ -olor=purple]\n\t3 -> 1 [color=lightblue]\n\t3 -> 2 [color=pink]\n\t3 -> 4 [col\ -or=purple]\n\t4 -> 1 [color=lightblue]\n\t4 -> 2 [color=pink]\n\t4 -> 3 [color\ -=purple]\n}\n" -gap> D := Digraph([[2], [1, 3], [2]]);; +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";; @@ -86,12 +112,12 @@ gap> edgecolors[3] := [];; gap> edgecolors[1][1] := "green";; gap> edgecolors[2][1] := "green";; gap> edgecolors[3][1] := "red";; edgecolors[2][2] := "red";; -gap> dot2 := GraphvizDotSymmetricColoredDigraph(D, vertcolors, edgecolors);; -gap> AsString(dot2); -"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ -[color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t1 -- 2 [color=\ -green]\n\t2 -- 3 [color=red]\n}\n" -gap> D := Digraph([[2, 3], [1, 3], [1]]);; +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";; @@ -101,13 +127,13 @@ 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> dot3 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; -gap> AsString(dot3); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ -2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t1 -> 2 [color=\ -orange]\n\t1 -> 3 [color=yellow]\n\t2 -> 1 [color=orange]\n\t2 -> 3 [color=pin\ -k]\n\t3 -> 1 [color=yellow]\n}\n" -gap> D := Digraph(IsMutableDigraph, [[2, 3], [1, 3], [1]]);; +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";; @@ -117,278 +143,305 @@ 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> dot4 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; -gap> AsString(dot4); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ -2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t1 -> 2 [color=\ -orange]\n\t1 -> 3 [color=yellow]\n\t2 -> 1 [color=orange]\n\t2 -> 3 [color=pin\ -k]\n\t3 -> 1 [color=yellow]\n}\n" -gap> D := Digraph([[2, 4], [1, 3], [2], [1]]);; -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; -gap> edgecolors[1][1] := "orange";; edgecolors[1][2] := "orange";; -gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "orange";; -gap> edgecolors[3][1] := "orange";; edgecolors[4][1] := "orange";; -gap> dot5 := GraphvizDotSymmetricColoredDigraph(D, vertcolors, edgecolors);; -gap> AsString(dot5); -"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ -[color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yellow,\ - style=filled]\n\t1 -- 2 [color=orange]\n\t1 -- 4 [color=orange]\n\t2 -- 3 [co\ -lor=orange]\n}\n" -gap> D := Digraph(IsMutableDigraph, [[2, 4], [1, 3], [2], [1]]);; +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] := "orange";; edgecolors[1][2] := "orange";; -gap> edgecolors[2][1] := "orange";; edgecolors[2][2] := "orange";; -gap> edgecolors[3][1] := "orange";; edgecolors[4][1] := "orange";; -gap> dot6 := GraphvizDotSymmetricColoredDigraph(D, vertcolors, edgecolors);; -gap> AsString(dot6); -"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ -[color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yellow,\ - style=filled]\n\t1 -- 2 [color=orange]\n\t1 -- 4 [color=orange]\n\t2 -- 3 [co\ -lor=orange]\n}\n" -gap> D := CompleteDigraph(4);; -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "banana";; -gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; -gap> edgecolors[1][1] := "lightblue";; -gap> edgecolors[1][2] := "pink";; -gap> edgecolors[1][3] := "purple";; -gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][2] := "pink";; -gap> edgecolors[2][3] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; -gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; -gap> edgecolors[4][2] := "pink";; -gap> edgecolors[4][3] := "purple";; -gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors){[5 .. 35]}; -Error, expected RGB Value or valid color name as defined by GraphViz 2.44.1 X1\ -1 Color Scheme http://graphviz.org/doc/info/colors.html -gap> D := CompleteDigraph(4);; -gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; -gap> vertcolors[3] := "green";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; -gap> edgecolors[1][1] := "lightblue";; -gap> edgecolors[1][2] := "pink";; -gap> edgecolors[1][3] := "purple";; -gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][2] := "pink";; -gap> edgecolors[2][3] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; -gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; -gap> edgecolors[4][2] := "pink";; -gap> edgecolors[4][3] := "purple";; -gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); -Error, the number of vertex colors must be the same as the number of vertices,\ - expected 4 but found 3 -gap> D := CompleteDigraph(4);; -gap> vertcolors := [];; -gap> vertcolors[1] := 2;; vertcolors[2] := 1;; -gap> vertcolors[3] := 1;; vertcolors[4] := 3;; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; -gap> edgecolors[1][1] := "lightblue";; -gap> edgecolors[1][2] := "pink";; -gap> edgecolors[1][3] := "purple";; -gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][2] := "pink";; -gap> edgecolors[2][3] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; -gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; -gap> edgecolors[4][2] := "pink";; -gap> edgecolors[4][3] := "purple";; -gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); -Error, expected a string -gap> D := CompleteDigraph(4);; -gap> vertcolors := [];; -gap> vertcolors[1] := "#AB3487";; vertcolors[2] := "#DF4738";; -gap> vertcolors[3] := "#4BF234";; vertcolors[4] := "#AF34C9";; -gap> edgecolors := [];; -gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; -gap> edgecolors[1][1] := "lightblue";; -gap> edgecolors[1][2] := "pink";; -gap> edgecolors[1][3] := "purple";; -gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][2] := "pink";; -gap> edgecolors[2][3] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; -gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; -gap> edgecolors[4][2] := "pink";; -gap> edgecolors[4][3] := "purple";; -gap> x1 := GraphvizDotColoredDigraph(D, vertcolors, edgecolors);; -gap> AsString(x1); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=#AB3487, style=filled]\ -\n\t2 [color=#DF4738, style=filled]\n\t3 [color=#4BF234, style=filled]\n\t4 [c\ -olor=#AF34C9, style=filled]\n\t1 -> 2 [color=lightblue]\n\t1 -> 3 [color=pink]\ -\n\t1 -> 4 [color=purple]\n\t2 -> 1 [color=lightblue]\n\t2 -> 3 [color=pink]\n\ -\t2 -> 4 [color=purple]\n\t3 -> 1 [color=lightblue]\n\t3 -> 2 [color=pink]\n\t\ -3 -> 4 [color=purple]\n\t4 -> 1 [color=lightblue]\n\t4 -> 2 [color=pink]\n\t4 \ --> 3 [color=purple]\n}\n" -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[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "cherry";; +gap> edgecolors[3][2] := "pink";; gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; gap> edgecolors[4][3] := "purple";; -gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); -Error, expected RGB Value or valid color name as defined by GraphViz 2.44.1 X1\ -1 Color Scheme http://graphviz.org/doc/info/colors.html -gap> D := CompleteDigraph(4);; +#@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[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; gap> edgecolors := [];; gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; +gap> edgecolors[3] := [];; edgecolors[4] := [];; gap> edgecolors[1][1] := "lightblue";; gap> edgecolors[1][2] := "pink";; gap> edgecolors[1][3] := "purple";; gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][2] := "pink";; -gap> edgecolors[2][3] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; +gap> edgecolors[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "lightblue";; +gap> edgecolors[3][2] := "pink";; gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; -gap> GraphvizDotColoredDigraph(D, vertcolors, edgecolors); -Error, the list of edge colors needs to have the same shape as the out-neighbo\ -urs of the digraph +#@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> D := CompleteDigraph(4); + gap> vertcolors := [];; -gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; +gap> vertcolors[1] := "blue";; vertcolors[2] := "red";; gap> vertcolors[3] := "green";; vertcolors[4] := "yellow";; -gap> out1 := GraphvizDotVertexColoredDigraph(D, vertcolors);; -gap> AsString(out1); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ -2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n\t4 [color=yello\ -w, style=filled]\n\t1 -> 2\n\t1 -> 3\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" -gap> D := EmptyDigraph(3);; +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[1] := [];; edgecolors[2] := [];; gap> edgecolors[3] := [];; -gap> out2 := GraphvizDotVertexColoredDigraph(D, vertcolors);; -gap> AsString(out2); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t\ -2 [color=red, style=filled]\n\t3 [color=green, style=filled]\n}\n" +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> D := CompleteDigraph(4); + gap> edgecolors := [];; gap> edgecolors[1] := [];; edgecolors[2] := [];; -gap> edgecolors[3] := [];; edgecolors[4] := [];; +gap> edgecolors[3] := [];; edgecolors[4] := [];; gap> edgecolors[1][1] := "lightblue";; gap> edgecolors[1][2] := "pink";; gap> edgecolors[1][3] := "purple";; gap> edgecolors[2][1] := "lightblue";; -gap> edgecolors[2][2] := "pink";; -gap> edgecolors[2][3] := "purple";; -gap> edgecolors[3][1] := "lightblue";; -gap> edgecolors[3][2] := "pink";; +gap> edgecolors[2][2] := "pink";; +gap> edgecolors[2][3] := "purple";; +gap> edgecolors[3][1] := "lightblue";; +gap> edgecolors[3][2] := "pink";; gap> edgecolors[3][3] := "purple";; -gap> edgecolors[4][1] := "lightblue";; +gap> edgecolors[4][1] := "lightblue";; gap> edgecolors[4][2] := "pink";; gap> edgecolors[4][3] := "purple";; -gap> out1 := GraphvizDotEdgeColoredDigraph(D, edgecolors);; -gap> AsString(out1){[1 .. 300]}; -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t1 -> 2 [colo\ -r=lightblue]\n\t1 -> 3 [color=pink]\n\t1 -> 4 [color=purple]\n\t2 -> 1 [color=\ -lightblue]\n\t2 -> 3 [color=pink]\n\t2 -> 4 [color=purple]\n\t3 -> 1 [color=li\ -ghtblue]\n\t3 -> 2 [color=pink]\n\t3 -> 4 [color=purple]\n\t4 -> 1 [color=ligh\ -tblue]\n\t4 -> 2 [color" -gap> GraphvizDotEdgeColoredDigraph(CycleDigraph(3), []); -Error, the list of edge colors needs to have the same shape as the out-neighbo\ -urs of the digraph -gap> GraphvizDotEdgeColoredDigraph(CycleDigraph(3), [[fail, fail], [fail], [fail]]); -Error, the list of edge colors needs to have the same shape as the out-neighbo\ -urs of the digraph -gap> GraphvizDotEdgeColoredDigraph(CycleDigraph(3), [[fail], [fail], [fail]]); -Error, expected a string +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> D := Digraph([[2], [1, 3], [2]]); + gap> vertcolors := [];; gap> vertcolors[1] := "blue";; gap> vertcolors[2] := "pink";; gap> vertcolors[3] := "purple";; -gap> out1 := GraphvizDotSymmetricVertexColoredDigraph(D, vertcolors);; -gap> AsString(out1); -"graph hgn {\n\tnode [shape=\"circle\"] \n\t1 [color=blue, style=filled]\n\t2 \ -[color=pink, style=filled]\n\t3 [color=purple, style=filled]\n\t1 -- 2\n\t2 --\ - 3\n}\n" +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> 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> out1 := GraphvizDotSymmetricEdgeColoredDigraph(D, edgecolors);; -gap> AsString(out1); -"graph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t1 -- 2 [color=green\ -]\n\t2 -- 3 [color=red]\n}\n" +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> dot1 := GraphvizDotVertexLabelledDigraph(gr);; -gap> AsString(dot1); -"digraph 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> 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> dot2 := GraphvizDotVertexLabelledDigraph(gr);; -gap> AsString(dot2); -"digraph 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" +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 +# Splash gap> Splash(1); -Error, the 1st argument must be a string or graphviz graph. +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"); @@ -397,8 +450,8 @@ 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 := "xpdf")); -Error, the viewer "xpdf" specified in the option `viewer` is not available, +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" @@ -423,100 +476,224 @@ Error, none of the default viewers [ "nonexistent-viewer" onent `viewer`, gap> VizViewers := VizViewers_backup;; gap> MakeReadOnlyGlobal("VizViewers"); -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\ -, # DotPartialOrderDigraph gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 4], [1 .. 5], [1 .. 6], > [1, 2, 3, 4, 5, 7], [1, 8]]);; -gap> out1 := GraphvizDotPartialOrderDigraph(gr);; -gap> AsString(out1); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t5\n\t6\n\t7\ -\n\t8\n\t2 -> 1\n\t3 -> 1\n\t4 -> 1\n\t5 -> 2\n\t5 -> 3\n\t5 -> 4\n\t6 -> 5\n\ -\t7 -> 5\n\t8 -> 1\n}\n" +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> out2 := GraphvizDotPartialOrderDigraph(gr);; -gap> AsString(out2); -"digraph hgn {\n\tnode [shape=\"circle\"] \n\t1\n\t2\n\t3\n\t4\n\t5\n\t6\n\t3 \ --> 1\n\t4 -> 2\n\t5 -> 3\n\t5 -> 4\n\t6 -> 3\n\t6 -> 2\n}\n" +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> GraphvizDotPartialOrderDigraph(gr);; -Error, the argument must be a partial order digraph, - -# -gap> DIGRAPHS_StopTest(); -gap> STOP_TEST("Digraphs package: standard/display.tst", 0); +gap> DotPartialOrderDigraph(gr); +Error, the argument (a digraph) must be a partial order # DotPreorderDigraph and DotQuasiorderDigraph -gap> GraphvizDotPreorderDigraph(CompleteDigraph(5));; -Error, the argument must be a preorder digraph, +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> out1 := GraphvizDotPreorderDigraph(gr);; -gap> AsString(out1); -"digraph graphname {\n\tnode [shape=\"Mrecord\"] height=\"0.5\" fixedsize=\"tr\ -ue\" ranksep=\"1\" \n\t1 [label=\"1\", width=0.5]\n\t2 [label=\"2\", width=0.5\ -]\n\t3 [label=\"3\", width=0.5]\n\t4 [label=\"4\", width=0.5]\n\t5 [label=\"5\ -\", width=0.5]\n\t6 [label=\"6\", width=0.5]\n\t7 [label=\"7\", width=0.5]\n\t\ -8 [label=\"8\", width=0.5]\n\t2 -> 1\n\t3 -> 1\n\t4 -> 1\n\t5 -> 2\n\t5 -> 3\n\ -\t5 -> 4\n\t6 -> 5\n\t7 -> 5\n\t8 -> 1\n}\n" +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> out2 := GraphvizDotPreorderDigraph(gr);; -gap> AsString(out2); -"digraph graphname {\n\tnode [shape=\"Mrecord\"] height=\"0.5\" fixedsize=\"tr\ -ue\" ranksep=\"1\" \n\t1 [label=\"23\", width=0.5]\n\t2 [label=\"13\", width=0\ -.5]\n\t3 [label=\"1\", width=0.5]\n\t4 [label=\"8\", width=0.5]\n\t5 [label=\"\ -7\", width=0.5]\n\t6 [label=\"6\", width=0.5]\n\t7 [label=\"22\", width=0.5]\n\ -\t8 [label=\"16\", width=0.5]\n\t9 [label=\"19\", width=0.5]\n\t10 [label=\"4|\ -3|15|14|11|24\", width=3.]\n\t11 [label=\"17\", width=0.5]\n\t12 [label=\"9\",\ - width=0.5]\n\t13 [label=\"21\", width=0.5]\n\t14 [label=\"25\", width=0.5]\n\ -\t15 [label=\"2\", width=0.5]\n\t16 [label=\"10\", width=0.5]\n\t17 [label=\"5\ -\", width=0.5]\n\t18 [label=\"20\", width=0.5]\n\t19 [label=\"12\", width=0.5]\ -\n\t20 [label=\"18\", width=0.5]\n\t2 -> 1\n\t3 -> 2\n\t8 -> 7\n\t9 -> 2\n\t9 \ --> 4\n\t10 -> 9\n\t10 -> 5\n\t10 -> 6\n\t10 -> 8\n\t11 -> 10\n\t12 -> 11\n\t13\ - -> 12\n\t14 -> 13\n\t15 -> 3\n\t15 -> 14\n\t16 -> 3\n\t16 -> 10\n\t17 -> 16\n\ -\t17 -> 12\n\t18 -> 17\n\t19 -> 18\n}\n" +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> out3 := GraphvizDotPreorderDigraph(gr);; -gap> AsString(out3); -"digraph graphname {\n\tnode [shape=\"Mrecord\"] height=\"0.5\" fixedsize=\"tr\ -ue\" ranksep=\"1\" \n\t1 [label=\"11|12|13|14|15\", width=2.5]\n\t2 [label=\"1\ -|2|3|4|5|6|7|8|9|10\", width=5.]\n\t3 [label=\"16|17\", width=1.]\n\t2 -> 1\n}\ -\n" +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> out1 := GraphvizDotHighlightedDigraph(gr, [1, 2], "red", "black");; -gap> ReplacedString(AsString(out1), ">", "<"); -"digraph hgn {\n\t3 [color=black, shape=circle]\n\t1 [color=red, shape=circle]\ -\n\t2 [color=red, shape=circle]\n\t3 -< 1 [color=black]\n\t3 -< 3 [color=black\ -]\n\t1 -< 2 [color=red]\n\t1 -< 3 [color=black]\n\t2 -< 2 [color=red]\n}\n" +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 must be a list of vertices of the 1st argu\ -ment , +Error, the 2nd argument (list) must consist of vertices of the 1st argument (a\ + digraph) +#@if CompareVersionNumbers(GAPInfo.Version, "4.12.0") gap> DotHighlightedDigraph(D, [1], "", "grey"); -Error, the 3rd argument must be a string containing the name of a\ - colour, +Error, invalid color "" (list (string)), valid colors are RGB values or names \ +from the GraphViz 2.44.1 X11 Color 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, the 4th argument must be a string containing the name of a \ -colour, -gap> out2 := GraphvizDotHighlightedDigraph(D, Filtered(DigraphVertices(D), IsEvenInt));; -gap> AsString(out2); -"digraph hgn {\n\t1 [color=grey, shape=circle]\n\t3 [color=grey, shape=circle]\ -\n\t5 [color=grey, shape=circle]\n\t2 [color=black, shape=circle]\n\t4 [color=\ -black, shape=circle]\n\t1 -> 2 [color=grey]\n\t3 -> 4 [color=grey]\n\t5 -> 1 [\ -color=grey]\n\t2 -> 3 [color=grey]\n\t4 -> 5 [color=grey]\n}\n" +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(); From b81ebc6c6b0b9eaa63b314534b8fbe94cb2fcc1e Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Thu, 9 May 2024 12:15:39 +0100 Subject: [PATCH 4/5] ci: checkout from main branch --- .github/workflows/gap.yml | 133 ++++++++++++++++++++++++++++++++++++++ PackageInfo.g | 4 +- gap/display.gi | 10 +-- 3 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/gap.yml diff --git a/.github/workflows/gap.yml b/.github/workflows/gap.yml new file mode 100644 index 000000000..9ec6f1a19 --- /dev/null +++ b/.github/workflows/gap.yml @@ -0,0 +1,133 @@ +name: "GAP" +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + - stable-*.* + schedule: + # Every day at 3:30 AM UTC + - cron: '30 3 * * *' + +env: + DIGRAPHS_LIB: digraphs-lib-0.6 + +jobs: + test-unix: + name: "${{ matrix.os }}${{ matrix.ABI }} / GAP ${{ matrix.gap-branch }}" + runs-on: "${{ matrix.os }}-latest" + strategy: + fail-fast: false + matrix: + os: + - ubuntu + gap-branch: + - master + - stable-4.11 + - stable-4.12 + - stable-4.13 + ABI: [''] + pkgs-to-clone: + - NautyTracesInterface + + include: + - gap-branch: master + os: macos + pkgs-to-clone: "NautyTracesInterface" + - gap-branch: master + os: ubuntu + ABI: 32 + + steps: + - uses: actions/checkout@v4 + - name: "Install dependencies" + if: ${{ runner.os == 'macOS' }} + run: brew install automake + - name: "Install GAP and clone/compile necessary packages" + uses: gap-actions/setup-gap@v2 + with: + GAP_PKGS_TO_CLONE: "${{ matrix.pkgs-to-clone }} digraphs/graphviz" + GAP_PKGS_TO_BUILD: "io orb profiling grape NautyTracesInterface datastructures" + GAPBRANCH: ${{ matrix.gap-branch }} + ABI: ${{ matrix.ABI }} + - name: "Build Digraphs" + uses: gap-actions/build-pkg@v1 + with: + ABI: ${{ matrix.ABI }} + - name: "Install digraphs-lib" + run: | + curl --retry 5 -L -O "https://digraphs.github.io/Digraphs/${{ env.DIGRAPHS_LIB }}.tar.gz" + tar xf "${{ env.DIGRAPHS_LIB }}.tar.gz" + - name: "Run DigraphsTestInstall" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/install.g" + - name: "Run DigraphsTestStandard" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/standard.g" + - name: "Run DigraphsTestManualExamples" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/examples.g" + - name: "Run DigraphsTestExtreme" + uses: gap-actions/run-pkg-tests@v2 + with: + GAP_TESTFILE: "tst/github_actions/extreme.g" + - uses: gap-actions/process-coverage@v2 + - uses: codecov/codecov-action@v3 + + test-cygwin: + name: "cygwin / GAP master" + runs-on: windows-2019 + env: + CHERE_INVOKING: 1 + steps: + - uses: actions/checkout@v4 + - uses: gap-actions/setup-cygwin@v1 + - uses: gap-actions/setup-gap@cygwin-v2 + with: + GAP_PKGS_TO_BUILD: "io orb profiling grape datastructures" + GAP_PKGS_TO_CLONE: "digraphs/graphviz" + - uses: gap-actions/build-pkg@cygwin-v1 + - name: "Install digraphs-lib" + run: | + curl --retry 5 -L -O "https://digraphs.github.io/Digraphs/${{ env.DIGRAPHS_LIB }}.tar.gz" + tar xf "${{ env.DIGRAPHS_LIB }}.tar.gz" + - uses: gap-actions/run-pkg-tests@cygwin-v2 + - uses: gap-actions/process-coverage@cygwin-v2 + - uses: codecov/codecov-action@v3 + + with-external-planarity-bliss: + runs-on: "ubuntu-latest" + env: + GAPBRANCH: "stable-4.12" + ABI: 64 + PKG_CONFIG_PATH: "/home/runner/micromamba/envs/digraphs/lib/pkgconfig:/home/runner/micromamba/envs/digraphs/share/pkgconfig/" + LD_LIBRARY_PATH: "/home/runner/micromamba/envs/digraphs/lib" + CFLAGS: "-I/home/runner/micromamba/envs/digraphs/include" + LDFLAGS: "-L/home/runner/micromamba/envs/digraphs/lib" + defaults: + run: + shell: bash -l {0} + steps: + - uses: actions/checkout@v4 + - name: "Install micromamba environment from environment.yml . . ." + uses: mamba-org/setup-micromamba@v1 + with: + environment-file: environment.yml + cache-environment: true + - name: "Activate \"digraphs\" environment . . ." + run: micromamba activate digraphs + - name: "Install GAP and clone/compile necessary packages" + uses: gap-actions/setup-gap@v2 + with: + GAP_PKGS_TO_BUILD: "io orb profiling grape datastructures" + GAP_PKGS_TO_CLONE: "digraphs/graphviz" + - name: "Build Digraphs" + uses: gap-actions/build-pkg@v1 + with: + CONFIGFLAGS: --with-external-planarity --with-external-bliss + - name: "Run Digraphs package's tst/teststandard.g" + uses: gap-actions/run-pkg-tests@v2 diff --git a/PackageInfo.g b/PackageInfo.g index dbbf820ec..cb4de63c8 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -10,7 +10,7 @@ ## <#GAPDoc Label="PKGVERSIONDATA"> ## -## +## ## ## ## @@ -388,7 +388,7 @@ 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"], diff --git a/gap/display.gi b/gap/display.gi index 890d29ab5..fe7acd3eb 100644 --- a/gap/display.gi +++ b/gap/display.gi @@ -104,7 +104,7 @@ function(D, colors) Length(out[i]), Length(colors[i])); fi; - Perform(colors[i], GV_ErrorIfNotValidColor); + Perform(colors[i], ErrorIfNotValidColor); od; end); @@ -118,7 +118,7 @@ function(D, gv, colors) out := OutNeighbours(D); for n in DigraphVertices(D) do for i in [1 .. Length(out[n])] do - if IsGVDigraph(gv) or n > out[n][i] then + if IsGraphvizDigraph(gv) or n > out[n][i] then e := GraphvizAddEdge(gv, n, out[n][i]); GraphvizSetAttr(e, "color", colors[n][i]); fi; @@ -255,8 +255,8 @@ function(D, gv, hi_verts, hi, lo) ErrorNoReturn("the 2nd argument (list) must consist of vertices ", "of the 1st argument (a digraph)"); fi; - GV_ErrorIfNotValidColor(hi); - GV_ErrorIfNotValidColor(lo); + ErrorIfNotValidColor(hi); + ErrorIfNotValidColor(lo); GraphvizSetAttr(gv, "shape", "circle"); @@ -275,7 +275,7 @@ function(D, gv, hi_verts, hi, lo) for i in DigraphVertices(D) do for j in out[i] do - if IsGVDigraph(gv) or i > j then + 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; From 5416f889b6ecedfbd9c69e22360465b0e30101ac Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Wed, 15 May 2024 11:30:18 +0100 Subject: [PATCH 5/5] Fixes for upstream changes --- gap/deprecated.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/deprecated.gi b/gap/deprecated.gi index 28bbfdfa4..f2c800087 100644 --- a/gap/deprecated.gi +++ b/gap/deprecated.gi @@ -10,7 +10,7 @@ BindGlobal("_PrintDeprecated", function(old, arg...) Info(InfoWarning, 1, "`", old, "` is deprecated and will be removed in v3", - " use `", Concatenation(List(arg, String)), "` instead!"); + " use `", Concatenation(List(arg, AsString)), "` instead!"); end); InstallMethod(DotDigraph, "for a digraph", [IsDigraph],