Skip to content

Commit

Permalink
merged with latest main
Browse files Browse the repository at this point in the history
  • Loading branch information
mpan322 committed Jun 5, 2024
2 parents 1893ed3 + 4df50dd commit 026851b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 24 deletions.
6 changes: 6 additions & 0 deletions gap/dot.gd
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ DeclareOperation("GraphvizNodes", [IsGraphvizGraphDigraphOrContext]);
#! @Description gets the subgraphs of a provided graphviz graph.
DeclareOperation("GraphvizSubgraphs", [IsGraphvizGraphDigraphOrContext]);

#! @Arguments graph
#! @Returns the contexts of the provided graphviz graph, digraph or context.
#! @Description gets the contexts of a provided graphviz graph, digraph
#! or context.
DeclareOperation("GraphvizContexts", [IsGraphvizGraphDigraphOrContext]);

#! @Arguments graph, name
#! @Returns a graph with the provided name.
#! @Description
Expand Down
18 changes: 12 additions & 6 deletions gap/dot.gi
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function(name)
rec(
Name := name,
Subgraphs := GV_Map(),
Contexts := GV_Map(),
Nodes := GV_Map(),
Edges := [],
Attrs := [],
Expand All @@ -34,6 +35,7 @@ function(name)
rec(
Name := name,
Subgraphs := GV_Map(),
Contexts := GV_Map(),
Nodes := GV_Map(),
Edges := [],
Attrs := [],
Expand Down Expand Up @@ -139,6 +141,9 @@ end);
InstallMethod(GraphvizSubgraphs, "for a graphviz (di)graph or context",
[IsGraphvizGraphDigraphOrContext], x -> x!.Subgraphs);

InstallMethod(GraphvizContexts, "for a graphviz (di)graph or context",
[IsGraphvizGraphDigraphOrContext], x -> x!.Contexts);

InstallMethod(GraphvizTail, "for a graphviz edge", [IsGraphvizEdge],
x -> x!.Tail);

Expand Down Expand Up @@ -212,7 +217,8 @@ InstallMethod(\[\], "for a graphviz (di)graph or context and object",
InstallMethod(GraphvizFindSubgraphRecursive,
"for a graphviz (di)graph or context and a string",
[IsGraphvizGraphDigraphOrContext, IsString],
{g, s} -> GV_GraphTreeSearch(g, v -> GraphvizName(v) = s));
{g, s} -> GV_GraphTreeSearch(g, v -> GraphvizName(v) = s and
not IsGraphvizContext(v)));

InstallMethod(GraphvizFindSubgraphRecursive,
"for a graphviz (di)graph or context and a string",
Expand Down Expand Up @@ -444,17 +450,17 @@ InstallMethod(GraphvizAddContext,
"for a graphviz (di)graph or context and a string",
[IsGraphvizGraphDigraphOrContext, IsString],
function(graph, name)
local subgraphs, ctx;
local contexts, ctx;

subgraphs := GraphvizSubgraphs(graph);
if IsBound(subgraphs[name]) then
contexts := GraphvizContexts(graph);
if IsBound(contexts[name]) then
ErrorFormatted("the 1st argument (a graphviz (di)graph/context) ",
"already has a context or subgraph with name \"{}\"",
"already has a context with name \"{}\"",
name);
fi;

ctx := GV_Context(graph, name);
subgraphs[name] := ctx;
contexts[name] := ctx;
return ctx;
end);

Expand Down
31 changes: 24 additions & 7 deletions gap/gv.gi
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ function(parent, name)
rec(
Name := name,
Subgraphs := GV_Map(),
Contexts := GV_Map(),
Nodes := GV_Map(),
Edges := [],
Attrs := [],
Expand Down Expand Up @@ -286,7 +287,7 @@ InstallMethod(GV_GraphTreeSearch,
"for a graphviz graph and a predicate",
[IsGraphvizGraphDigraphOrContext, IsFunction],
function(graph, pred)
local seen, to_visit, g, key, subgraph, parent;
local seen, to_visit, g, key, subgraph, context, parent;
seen := [graph];
to_visit := [graph];

Expand All @@ -307,6 +308,15 @@ function(graph, pred)
fi;
od;

# add contexts to list of to visit if not visited
for key in GV_MapNames(GraphvizContexts(g)) do
context := GraphvizContexts(g)[key];
if not ForAny(seen, s -> IsIdenticalObj(s, context)) then
Add(seen, context);
Add(to_visit, context);
fi;
od;

# add parent if not visited
parent := GV_GetParent(g);
if not IsGraphvizGraphDigraphOrContext(parent) then
Expand All @@ -326,7 +336,7 @@ InstallMethod(GV_GraphSearchChildren,
"for a graphviz graph and a predicate",
[IsGraphvizGraphDigraphOrContext, IsFunction],
function(graph, pred)
local _, curr, queue, count, subs, key;
local _, curr, queue, count, nexts, key;

queue := [graph];
while Length(queue) > 0 do
Expand All @@ -342,9 +352,13 @@ function(graph, pred)
fi;

# Add children
subs := GraphvizSubgraphs(curr);
for key in GV_MapNames(subs) do
Add(queue, subs[key]);
nexts := GraphvizSubgraphs(curr);
for key in GV_MapNames(nexts) do
Add(queue, nexts[key]);
od;
nexts := GraphvizContexts(curr);
for key in GV_MapNames(nexts) do
Add(queue, nexts[key]);
od;
od;
od;
Expand Down Expand Up @@ -628,17 +642,20 @@ InstallMethod(GV_ConstructHistory,
"for a graphviz graph",
[IsGraphvizGraphDigraphOrContext],
function(graph)
local nodes, edges, subs, node_hist, edge_hist, subs_hist, hist;
local ctxs, nodes, edges, subs,
ctxs_hist, node_hist, edge_hist, subs_hist, hist;

nodes := GraphvizNodes(graph);
edges := GraphvizEdges(graph);
subs := GraphvizSubgraphs(graph);
ctxs := GraphvizContexts(graph);

node_hist := List(GV_MapNames(nodes), n -> [GV_GetIdx(nodes[n]), nodes[n]]);
subs_hist := List(GV_MapNames(subs), s -> [GV_GetIdx(subs[s]), subs[s]]);
ctxs_hist := List(GV_MapNames(ctxs), s -> [GV_GetIdx(ctxs[s]), ctxs[s]]);
edge_hist := List(edges, e -> [GV_GetIdx(e), e]);

hist := Concatenation(node_hist, edge_hist, subs_hist);
hist := Concatenation(node_hist, edge_hist, subs_hist, ctxs_hist);
SortBy(hist, v -> v[1]);

Apply(hist, x -> x[2]);
Expand Down
78 changes: 67 additions & 11 deletions tst/subgraph.tst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
##

#@local a, a1, a2, a3, b, b1, b2, b3, c, child, ctx, g, gv, legend, main, n, o
#@local sub1, sub2, ctx1, ctx2
#@local parent, s, s1, s11, s2, sibling
gap> START_TEST("graphviz package: subgraph.tst");
gap> LoadPackage("graphviz", false);;
Expand Down Expand Up @@ -36,13 +37,13 @@ gap> GraphvizAddContext(g);
<graphviz context "no_name_1" with 0 nodes and 0 edges>
#@if CompareVersionNumbers(GAPInfo.Version, "4.12")
gap> GraphvizAddContext(g, "no_name_1");
Error, the 1st argument (a graphviz (di)graph/context) already has a context o\
r subgraph with name "no_name_1"
Error, the 1st argument (a graphviz (di)graph/context) already has a context w\
ith name "no_name_1"
#@else
gap> GraphvizAddContext(g, "no_name_1");
Error, the 1st argument (a graphviz (di)graph/context) already has a context o\
r subgr\
aph with name "no_name_1"
Error, the 1st argument (a graphviz (di)graph/context) already has a context w\
ith nam\
e "no_name_1"
#@fi

# Test no-name constructor graphs' names increment
Expand All @@ -65,13 +66,14 @@ gap> GraphvizAddContext(g);
gap> GraphvizAddContext(g);
<graphviz context "no_name_3" with 0 nodes and 0 edges>

# Test getting subgraphs
# Test getting subgraphs and contexts
gap> g := GraphvizGraph();;
gap> GraphvizAddSubgraph(g, "a");;
gap> GraphvizAddContext(g, "b");;
gap> GraphvizSubgraphs(g);
rec( a := <graphviz graph "a" with 0 nodes and 0 edges>,
b := <graphviz context "b" with 0 nodes and 0 edges> )
rec( a := <graphviz graph "a" with 0 nodes and 0 edges> )
gap> GraphvizContexts(g);
rec( b := <graphviz context "b" with 0 nodes and 0 edges> )

# Test adding a node to a subgraph (does or does not add to parent???)
# TODO need to nail down expected behaviour!
Expand Down Expand Up @@ -294,13 +296,15 @@ gap> GraphvizSubgraphs(g)["b"];
gap> GraphvizSubgraphs(g)["d"];
fail

# Test getting context (subgraph) by name
# Test getting context by name
gap> g := GraphvizDigraph();;
gap> s1 := GraphvizAddSubgraph(g, "a");;
gap> s2 := GraphvizAddContext(g, "c");;
gap> GraphvizSubgraphs(g)["a"];
<graphviz digraph "a" with 0 nodes and 0 edges>
gap> GraphvizSubgraphs(g)["c"];
fail
gap> GraphvizContexts(g)["c"];
<graphviz context "c" with 0 nodes and 0 edges>

# Test adding a nested subgraph
Expand Down Expand Up @@ -331,10 +335,13 @@ gap> g := GraphvizGraph();;
gap> GraphvizAddContext(g, 11);
<graphviz context "11" with 0 nodes and 0 edges>

# Test getting subgraphs with non-string names
# Test getting subgraphs/contexts with non-string names
gap> g := GraphvizGraph();;
gap> GraphvizAddContext(g, ["a"]);;
gap> GraphvizSubgraphs(g)[["a"]];
gap> GraphvizAddSubgraph(g, ["b"]);;
gap> GraphvizSubgraphs(g)[["b"]];
<graphviz graph "[ "b" ]" with 0 nodes and 0 edges>
gap> GraphvizContexts(g)[["a"]];
<graphviz context "[ "a" ]" with 0 nodes and 0 edges>

# Test finding subgraph (parent)
Expand Down Expand Up @@ -478,5 +485,54 @@ gap> GraphvizAddSubgraph(a, "c");;
gap> GraphvizAddSubgraph(b, "c");
<graphviz graph "c" with 0 nodes and 0 edges>

# Test the parent is the object it was added to
gap> g := GraphvizGraph("g");;
gap> sub1 := GraphvizAddSubgraph(g, "sub1");;
gap> sub2 := GraphvizAddSubgraph(sub1, "sub2");;
gap> ctx2 := GraphvizAddContext(sub1, "ctx2");;
gap> GV_GetParent(sub1);
<graphviz graph "g" with 0 nodes and 0 edges>
gap> GV_GetParent(sub2);
<graphviz graph "sub1" with 0 nodes and 0 edges>
gap> GV_GetParent(ctx2);
<graphviz graph "sub1" with 0 nodes and 0 edges>
gap> g := GraphvizGraph("g");;
gap> ctx1 := GraphvizAddSubgraph(g, "ctx1");;
gap> sub2 := GraphvizAddSubgraph(ctx1, "sub2");;
gap> ctx2 := GraphvizAddContext(ctx1, "ctx2");;
gap> GV_GetParent(ctx1);
<graphviz graph "g" with 0 nodes and 0 edges>
gap> GV_GetParent(sub2);
<graphviz graph "ctx1" with 0 nodes and 0 edges>
gap> GV_GetParent(ctx2);
<graphviz graph "ctx1" with 0 nodes and 0 edges>

# Test adding contexts with the same name
gap> g := GraphvizDigraph();;
gap> s1 := GraphvizAddContext(g, "a");;
#@if CompareVersionNumbers(GAPInfo.Version, "4.12")
gap> s2 := GraphvizAddContext(g, "a");
Error, the 1st argument (a graphviz (di)graph/context) already has a context w\
ith name "a"
#@else
gap> s2 := GraphvizAddContext(g, "a");
Error, the 1st argument (a graphviz (di)graph/context) already has a context w\
ith nam\
e "a"
#@fi

# Test adding contexts and subgraphs (different name spaces)
gap> g := GraphvizDigraph();;
gap> s1 := GraphvizAddContext(g, "a");
<graphviz context "a" with 0 nodes and 0 edges>
gap> s2 := GraphvizAddSubgraph(g, "a");
<graphviz digraph "a" with 0 nodes and 0 edges>

# Test finding subgraphs will not return a context instead
gap> g := GraphvizDigraph();;
gap> s1 := GraphvizAddContext(g, "a");;
gap> GraphvizFindSubgraphRecursive(g, "a");
fail

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

0 comments on commit 026851b

Please sign in to comment.