Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 72 additions & 7 deletions gap/dot.gi
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ function(arg...)
[msg]);
end);

DeclareOperation("GV_GraphSearchChildren", [IsGVGraph, IsFunction]);
DeclareOperation("GV_GraphTreeSearch", [IsGVGraph, IsFunction]);
DeclareOperation("GV_GetCounter", [IsGVGraph]);
DeclareOperation("GV_IncCounter", [IsGVGraph]);
DeclareCategory("IsGV_Map", IsObject);
Expand Down Expand Up @@ -549,9 +551,14 @@ function(g)
local result, edges, nodes, kind;

result := "";
edges := Length(GraphvizEdges(g));
nodes :=
Length(GV_MapNames(GraphvizNodes(g)));
edges := 0;
nodes := 0;

GV_GraphSearchChildren(g, function(s)
nodes := nodes + Length(GV_MapNames(GraphvizNodes(s)));
edges := edges + Length(GraphvizEdges(s));
return false;
end);

if IsGVDigraph(g) then
kind := "digraph";
Expand Down Expand Up @@ -724,7 +731,36 @@ InstallMethod(GV_GetParent,
"for a graphviz graph",
[IsGVGraph], graph -> graph!.Parent);

DeclareOperation("GV_GraphTreeSearch", [IsGVGraph, IsFunction]);
# tree search only on the children of the graph
InstallMethod(GV_GraphSearchChildren,
"for a graphviz graph and a predicate",
[IsGVGraph, IsFunction],
function(graph, pred)
local _, curr, queue, count, subs, key;

queue := [graph];
while Length(queue) > 0 do
count := Length(queue);

for _ in [1 .. count] do
# TODO: make sure this is using a linked list rather than an array list
curr := Remove(queue, 1);

# Check this graph (visit)
if pred(curr) then
return curr;
fi;

# Add children
subs := GraphvizSubgraphs(curr);
for key in GV_MapNames(subs) do
Add(queue, subs[key]);
od;
od;
od;

return fail;
end);

InstallMethod(GV_GraphTreeSearch,
"for a graphviz graph and a predicate",
Expand Down Expand Up @@ -1189,9 +1225,38 @@ end);
InstallMethod(GraphvizRemoveAttr, "for a graphviz graph and an object",
[IsGVGraph, IsObject],
function(obj, attr)
local attrs;
attrs := GraphvizAttrs(obj);
obj!.Attrs := Filtered(attrs, item -> item[1] <> String(attr));
local attrs, i, k, str, match;

attrs := GraphvizAttrs(obj);
attr := String(attr);

# remove by value
if '=' in attr then
obj!.Attrs := Filtered(attrs, item -> item <> attr);
else

for k in [1 .. Length(attrs)] do
str := attrs[k];

# check if the string is of the form '`attr`=...'
match := true;
for i in [1 .. Length(attr)] do
if i > Length(str) or attr[i] <> str[i] then
match := false;
break;
fi;
od;
match := match and i + 1 <= Length(str) and str[i + 1] = '=';

# if so remove it
if match then
RemoveElmList(attrs, k);
else
k := k + 1;
fi;
od;

fi;
return obj;
end);

Expand Down
4 changes: 2 additions & 2 deletions tst/examples/er.tst
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ gap> GraphvizSetAttrs(GraphvizAddEdge(e, "course", "S-C"),

#
gap> GraphvizSetAttr(e, "label=\"Entity Relation Diagram\ndrawn by NEATO\"");
<graphviz graph ER with 0 nodes and 12 edges>
<graphviz graph ER with 12 nodes and 12 edges>
gap> GraphvizSetAttr(e, "fontsize=\"20\"");
<graphviz graph ER with 0 nodes and 12 edges>
<graphviz graph ER with 12 nodes and 12 edges>

#
gap> AsString(e);
Expand Down
6 changes: 3 additions & 3 deletions tst/examples/traffic_lights.tst
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ gap> for pair in [[2, 1], [1, 2]] do

#
gap> GraphvizSetAttr(t, "overlap=\"false\"");
<graphviz digraph TrafficLights with 0 nodes and 16 edges>
<graphviz digraph TrafficLights with 14 nodes and 16 edges>
gap> GraphvizSetAttr(t,
> """label="PetriNet Model TrafficLights
> Extracted from ConceptBase and laid out by Graphviz"
> """);
<graphviz digraph TrafficLights with 0 nodes and 16 edges>
<graphviz digraph TrafficLights with 14 nodes and 16 edges>
gap> GraphvizSetAttr(t, "fontsize=12");
<graphviz digraph TrafficLights with 0 nodes and 16 edges>
<graphviz digraph TrafficLights with 14 nodes and 16 edges>

#
gap> AsString(t);
Expand Down
36 changes: 36 additions & 0 deletions tst/graph.tst
Original file line number Diff line number Diff line change
Expand Up @@ -241,5 +241,41 @@ gap> GraphvizSetColor(g, "red");;
gap> GraphvizAttrs(g);
[ "color=red" ]

# testing removing attributes from graphs by value
gap> g := GraphvizGraph();;
gap> GraphvizSetAttr(g, "label", "test");;
gap> GraphvizAttrs(g);
[ "label=test" ]
gap> GraphvizSetAttr(g, 1, 2);
#I unknown attribute "1", the graphviz object may no longer be valid, it can be removed using GraphvizRemoveAttr
<graphviz graph with 0 nodes and 0 edges>
gap> GraphvizAttrs(g);
[ "label=test", "1=2" ]
gap> GraphvizRemoveAttr(g, "1=2");
<graphviz graph with 0 nodes and 0 edges>
gap> GraphvizAttrs(g);
[ "label=test" ]

# testing removing attributes from graphs by key
gap> g := GraphvizGraph();;
gap> GraphvizSetAttr(g, "label", "test");;
gap> GraphvizAttrs(g);
[ "label=test" ]
gap> GraphvizSetAttr(g, 1, 2);;
#I unknown attribute "1", the graphviz object may no longer be valid, it can be removed using GraphvizRemoveAttr
gap> GraphvizAttrs(g);
[ "label=test", "1=2" ]
gap> GraphvizRemoveAttr(g, 1);;
gap> GraphvizAttrs(g);
[ "label=test" ]
gap> GraphvizRemoveAttr(g, "label");;
gap> GraphvizAttrs(g);
[ ]
gap> GraphvizSetAttr(g, 1, 2);;
#I unknown attribute "1", the graphviz object may no longer be valid, it can be removed using GraphvizRemoveAttr
gap> GraphvizRemoveAttr(g, "label");;
gap> GraphvizAttrs(g);
[ "1=2" ]

#
gap> STOP_TEST("graphviz package: graph.tst", 0);
59 changes: 59 additions & 0 deletions tst/node.tst
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,64 @@ gap> s := GraphvizGraph();;
gap> GraphvizAddNode(s, n);
Error, Cannot add node objects directly to graphs. Please use the node's name.

# Test updating an attribute
gap> g := GraphvizGraph();;
gap> n := GraphvizAddNode(g, "n");;
gap> GraphvizSetAttr(n, "label", "a");;
gap> AsString(g);
"//dot\ngraph {\n\tn [label=a]\n}\n"
gap> GraphvizSetAttr(n, "label", "b");;
gap> AsString(g);
"//dot\ngraph {\n\tn [label=b]\n}\n"
gap> GraphvizSetAttr(n, "color", "red");;
gap> AsString(g);
"//dot\ngraph {\n\tn [color=red, label=b]\n}\n"
gap> GraphvizSetAttr(n, "color", "blue");;
gap> AsString(g);
"//dot\ngraph {\n\tn [color=blue, label=b]\n}\n"

# test changing labels functions properly
gap> g := GraphvizGraph("xxx");;
gap> GraphvizAddNode(g, 1);;
gap> GraphvizAddNode(g, 2);;
gap> GraphvizAddNode(g, 3);;
gap> GraphvizSetNodeLabels(g, ["i", "ii", "iii"]);
<graphviz graph xxx with 3 nodes and 0 edges>
gap> AsString(g);
"//dot\ngraph xxx {\n\t1 [label=i]\n\t2 [label=ii]\n\t3 [label=iii]\n}\n"
gap> GraphvizSetNodeLabels(g, ["a", "b", "c"]);
<graphviz graph xxx with 3 nodes and 0 edges>
gap> AsString(g);
"//dot\ngraph xxx {\n\t1 [label=a]\n\t2 [label=b]\n\t3 [label=c]\n}\n"

# test changing labels and colors functions properly
gap> g := GraphvizGraph("xxx");
<graphviz graph xxx with 0 nodes and 0 edges>
gap> GraphvizAddNode(g, 1);
<graphviz node 1>
gap> GraphvizAddNode(g, 2);
<graphviz node 2>
gap> GraphvizAddNode(g, 3);
<graphviz node 3>
gap> GraphvizSetNodeColors(g, ["i", "ii", "iii"]);
Error, invalid color "i" (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
gap> GraphvizSetNodeColors(g, ["red", "green", "blue"]);
<graphviz graph xxx with 3 nodes and 0 edges>
gap> AsString(g);
"//dot\ngraph xxx {\n\t1 [color=red, style=filled]\n\t2 [color=green, style=fi\
lled]\n\t3 [color=blue, style=filled]\n}\n"
gap> GraphvizSetNodeColors(g, ["red", "#00FF00", "blue"]);
<graphviz graph xxx with 3 nodes and 0 edges>
gap> AsString(g);
"//dot\ngraph xxx {\n\t1 [color=red, style=filled]\n\t2 [color=\"#00FF00\", st\
yle=filled]\n\t3 [color=blue, style=filled]\n}\n"
gap> GraphvizSetNodeColors(g, ["#FF0000", "#00FF00", "#0000FF"]);
<graphviz graph xxx with 3 nodes and 0 edges>
gap> AsString(g);
"//dot\ngraph xxx {\n\t1 [color=\"#FF0000\", style=filled]\n\t2 [color=\"#00FF\
00\", style=filled]\n\t3 [color=\"#0000FF\", style=filled]\n}\n"

#
gap> STOP_TEST("graphviz package: node.tst", 0);
36 changes: 36 additions & 0 deletions tst/subgraph.tst
Original file line number Diff line number Diff line change
Expand Up @@ -380,5 +380,41 @@ gap> o := GraphvizFindGraph(g, 1);
gap> IsIdenticalObj(o, s);
true

# Test edge and node numbers when subgraphs are present
gap> g := GraphvizGraph("main");;
gap> a := GraphvizAddSubgraph(g, 1);;
gap> b := GraphvizAddSubgraph(g, 2);;
gap> c := GraphvizAddSubgraph(a, 3);; # nested subgraph
gap> GraphvizAddNode(g, 1);;
gap> GraphvizAddNode(a, 2);;
gap> GraphvizAddNode(a, 3);;
gap> GraphvizAddNode(b, 4);;
gap> GraphvizAddNode(b, 5);;
gap> GraphvizAddNode(b, 6);;
gap> GraphvizAddNode(c, 7);;
gap> GraphvizAddNode(c, 8);;
gap> GraphvizAddNode(c, 9);;
gap> GraphvizAddNode(c, 10);;
gap> g;
<graphviz graph main with 10 nodes and 0 edges>
gap> GraphvizAddEdge(g, 1, 2);;
gap> GraphvizAddEdge(a, 2, 3);;
gap> GraphvizAddEdge(a, 3, 4);;
gap> GraphvizAddEdge(b, 4, 5);;
gap> GraphvizAddEdge(b, 5, 6);;
gap> GraphvizAddEdge(b, 6, 7);;
gap> GraphvizAddEdge(c, 7, 8);;
gap> GraphvizAddEdge(c, 8, 9);;
gap> GraphvizAddEdge(c, 9, 10);;
gap> GraphvizAddEdge(c, 10, 1);;
gap> g;
<graphviz graph main with 10 nodes and 10 edges>
gap> a;
<graphviz graph 1 with 6 nodes and 6 edges>
gap> b;
<graphviz graph 2 with 3 nodes and 3 edges>
gap> c;
<graphviz graph 3 with 4 nodes and 4 edges>

#
gap> STOP_TEST("graphviz package: subgraph.tst", 0);