Skip to content
Open
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
10 changes: 10 additions & 0 deletions doc/display.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ gap> Splash(DotDigraph(RandomDigraph(4)));
<ManSection>
<Attr Name="DotDigraph" Arg="digraph"/>
<Oper Name="DotColoredDigraph" Arg="digraph, vert, edge"/>
<Oper Name="DotColoredEdgeLabelledDigraph" Arg="digraph, vert, edge, labels"/>
<Oper Name="DotVertexLabelledDigraph" Arg="digraph"/>
<Oper Name="DotVertexColoredDigraph" Arg="digraph, vert"/>
<Oper Name="DotEdgeColoredDigraph" Arg="digraph, edge"/>
Expand All @@ -124,6 +125,13 @@ gap> Splash(DotDigraph(RandomDigraph(4)));
are not the appropriate size, or have holes then the function will return
an error.<P/>

<C>DotColoredEdgeLabelledDigraph</C> differs from <C>DotColoredDigraph</C>
only in that the values given in the third list <A>labels</A> is used to
label the edges of the graph when displayed. The list <A>labels</A> should
be a list of equal length to the lists for vertex and edge colours. If the
lists are not the appropriate size, or have holes, then the function will
return an error.<P/>

<C>DotVertexColoredDigraph</C> differs from <C>DotDigraph</C> 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
Expand Down Expand Up @@ -152,6 +160,8 @@ gap> Splash(DotDigraph(RandomDigraph(4)));
The string returned by <C>DotDigraph</C> or
<C>DotVertexLabelledDigraph</C> can be written to a file using
the command <Ref Func="FileString" BookName="GAPDoc"/>.<P/>

See also <Ref Oper="DotEdgeWeightedDigraph"/>. <P/>
<Example><![CDATA[
gap> D := CompleteDigraph(4);
<immutable complete digraph with 4 vertices>
Expand Down
67 changes: 67 additions & 0 deletions doc/weights.xml
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,70 @@ gap> RandomUniqueEdgeWeightedDigraph(IsEulerianDigraph, 5, 1 / 3);
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DotEdgeWeightedDigraph">
<ManSection>
<Oper Name="DotEdgeWeightedDigraph" Arg="digraph[, path][, colors]"/>
<Returns>A string.</Returns>
<Description>
This operation produces a graphical representation of the edge-weighted
digraph <A>digraph</A>, in <E>dot</E> format. Its output will be similar to
that of <Ref Attr="DotDigraph"/>, but the diagram will also show the weights
of the digraph's edges. <P/>

If the optional argument <A>path</A> is specified, it should be a list of
lists describing a path in <A>digraph</A>, in the format described in <Ref
Oper="DigraphPath"/>. If specified, the path's edges will be highlighted in
the diagram, as will its start and end vertices. <P/>

If the optional argument <A>colors</A> is specified, it should be a record
containing any of the following components:

<List>
<Item>
<A>vert</A>: the colour of ordinary vertices (default "grey");
</Item>
<Item>
<A>edge</A>: the colour of ordinary edges (default "black");
</Item>
<Item>
<A>highlight</A>: the colour of any edges on <A>path</A>, if any
(default "blue");
</Item>
<Item>
<A>source</A>: the colour of the first vertex in <A>path</A>, if any
(default "yellowgreen");
</Item>
<Item>
<A>dest</A>: the colour of the final vertex in <A>path</A>, if any
(default "lightpink").
</Item>
</List>

Each value in the record should be a string representing a colour understood
by the <C>GraphViz</C> software. For details about this format, see
<URL>https://www.graphviz.org</URL>. If any of the above components are not
specified, or if no <A>colors</A> argument is given, the default value will
be used. <P/>

The output of this operation can be passed to <Ref Func="Splash"/> to
attempt to display it graphically on the computer's screen. <P/>

<Example><![CDATA[
gap> gr := EdgeWeightedDigraph([[2], [3], []], [[10], [15], []]);
<immutable edge-weighted digraph with 3 vertices, 2 edges>
gap> path := EdgeWeightedDigraphShortestPath(g, 2, 3);
[ [ 2, 3 ], [ 1 ] ]
gap> Print(DotEdgeWeightedDigraph(gr, path));
//dot
digraph hgn{
node [shape=circle]
1[color=gray, style=filled]
2[color=yellowgreen, style=filled]
3[color=lightpink, style=filled]
1 -> 2[color=black, label=10]
2 -> 3[color=blue, label=15]
}]]></Example>
</Description>
</ManSection>
<#/GAPDoc>
1 change: 1 addition & 0 deletions doc/z-chap5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<#Include Label="DigraphMinimumCut">
<#Include Label="DigraphMinimumCutSet">
<#Include Label="RandomUniqueEdgeWeightedDigraph">
<#Include Label="DotEdgeWeightedDigraph">
</Section>

<Section><Heading>Orders</Heading>
Expand Down
2 changes: 2 additions & 0 deletions gap/display.gd
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

DeclareAttribute("DotDigraph", IsDigraph);
DeclareOperation("DotColoredDigraph", [IsDigraph, IsList, IsList]);
DeclareOperation("DotColoredEdgeLabelledDigraph",
[IsDigraph, IsList, IsList, IsList]);
DeclareOperation("DotVertexColoredDigraph", [IsDigraph, IsList]);
DeclareOperation("DotEdgeColoredDigraph", [IsDigraph, IsList]);
DeclareOperation("DotVertexLabelledDigraph", [IsDigraph]);
Expand Down
15 changes: 15 additions & 0 deletions gap/display.gi
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,21 @@ function(D, vert, edge)
fi;
end);

InstallMethod(DotColoredEdgeLabelledDigraph,
"for a digraph by out-neighbours and three lists",
[IsDigraphByOutNeighboursRep, IsList, IsList, IsList],
function(D, vert, edge, weight)
local vert_func, edge_func;
# See https://graphs.grevian.org/example
if DIGRAPHS_ValidVertColors(D, vert)
and DIGRAPHS_ValidEdgeColors(D, edge) then
vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]);
edge_func := {i, j} -> StringFormatted("[color={}, label={}]",
edge[i][j], weight[i][j]);
return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]);
fi;
end);

InstallMethod(DotVertexColoredDigraph,
"for a digraph by out-neighbours and a list",
[IsDigraphByOutNeighboursRep, IsList],
Expand Down
6 changes: 6 additions & 0 deletions gap/weights.gd
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ DeclareOperation("RandomUniqueEdgeWeightedDigraph",
[IsFunction, IsPosInt, IsFloat]);
DeclareOperation("RandomUniqueEdgeWeightedDigraph",
[IsFunction, IsPosInt, IsRat]);

# 7. Drawing edge weighted digraphs
DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph]);
DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsList]);
DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsRecord]);
DeclareOperation("DotEdgeWeightedDigraph", [IsDigraph, IsList, IsRecord]);
60 changes: 60 additions & 0 deletions gap/weights.gi
Original file line number Diff line number Diff line change
Expand Up @@ -895,3 +895,63 @@ DIGRAPHS_RandomEdgeWeightedDigraphFilt);
InstallMethod(RandomUniqueEdgeWeightedDigraph,
"for a function, a pos int, and a rational", [IsFunction, IsPosInt, IsRat],
DIGRAPHS_RandomEdgeWeightedDigraphFilt);

#############################################################################
# 7. Drawing edge weighted digraphs
#############################################################################

InstallMethod(DotEdgeWeightedDigraph, "for a digraph",
[IsDigraph],
digraph -> DotEdgeWeightedDigraph(digraph, [[], []], rec()));

InstallMethod(DotEdgeWeightedDigraph, "for a digraph and a list",
[IsDigraph, IsList],
{digraph, path} -> DotEdgeWeightedDigraph(digraph, path, rec()));

InstallMethod(DotEdgeWeightedDigraph, "for a digraph and a record",
[IsDigraph, IsRecord],
{digraph, colors} -> DotEdgeWeightedDigraph(digraph, [[], []], colors));

InstallMethod(DotEdgeWeightedDigraph, "for a digraph, a list, and a record",
[IsDigraph, IsList, IsRecord],
function(digraph, path, colors)
local default_colors, edge, vert, source, dest, name, vertColours,
edgeColours, path_verts, path_edge_indices, path_length, i;

# Use default colours for any that aren't specified
default_colors := rec(highlight := "blue",
edge := "black",
vert := "gray",
source := "yellowgreen",
dest := "lightpink");
for name in RecNames(colors) do
if IsBound(default_colors.(name)) then
default_colors.(name) := colors.(name);
else
Error("3rd arg <colors> contains unsupported option named '", name, "'");
fi;
od;
colors := default_colors;

# fill with basic colours
vertColours := ListWithIdenticalEntries(DigraphNrVertices(digraph),
colors.vert);
edgeColours := List(OutNeighbours(digraph),
outs_u -> List(outs_u, _ -> colors.edge));

# highlight the path
path_verts := path[1];
path_edge_indices := path[2];
path_length := Length(path_edge_indices);
if not IsEmpty(path_verts) then
for i in [1 .. path_length] do
edgeColours[path_verts[i]][path_edge_indices[i]] := colors.highlight;
od;
vertColours[path_verts[1]] := colors.source;
vertColours[path_verts[path_length + 1]] := colors.dest;
fi;

# draw with the weights as labels
return DotColoredEdgeLabelledDigraph(digraph, vertColours, edgeColours,
EdgeWeights(digraph));
end);
70 changes: 69 additions & 1 deletion tst/standard/weights.tst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#############################################################################
##

#@local D, d, distances, edges, gr, m, parents, r, tree
#@local D, d, distances, edges, gr, m, parents, path, r, tree
gap> START_TEST("Digraphs package: standard/weights.tst");
gap> LoadPackage("digraphs", false);;

Expand Down Expand Up @@ -503,6 +503,74 @@ true
gap> SortedList(Flat(EdgeWeights(D))) = [1 .. DigraphNrEdges(D)];
true

#############################################################################
# 7. Drawing edge-weighted digraphs
#############################################################################

# Trivial example
gap> gr := EdgeWeightedDigraph([[2], []], [[10], []]);;
gap> Print(DotEdgeWeightedDigraph(gr));
//dot
digraph hgn{
node [shape=circle]
1[color=gray, style=filled]
2[color=gray, style=filled]
1 -> 2[color=black, label=10]
}

# Cycle example
gap> gr := EdgeWeightedDigraph(CycleDigraph(5), [[10], [4], [8], [2], [8]]);;
gap> path := DigraphPath(gr, 3, 1);
[ [ 3, 4, 5, 1 ], [ 1, 1, 1 ] ]
gap> Print(DotEdgeWeightedDigraph(gr, path, rec(highlight := "red")));
//dot
digraph hgn{
node [shape=circle]
1[color=lightpink, style=filled]
2[color=gray, style=filled]
3[color=yellowgreen, style=filled]
4[color=gray, style=filled]
5[color=gray, style=filled]
1 -> 2[color=black, label=10]
2 -> 3[color=black, label=4]
3 -> 4[color=red, label=8]
4 -> 5[color=red, label=2]
5 -> 1[color=red, label=8]
}

# Large example
gap> gr := EdgeWeightedDigraph(
> [[5, 7], [5], [1, 3, 6], [1, 3], [4, 5], [1, 2], [6]],
> [[8, 4], [12], [11, 2, 10], [3, 7], [9, 13], [1, 6], [5]]);
<immutable edge-weighted digraph with 7 vertices, 13 edges>
gap> path := EdgeWeightedDigraphShortestPath(gr, 1, 2);
[ [ 1, 7, 6, 2 ], [ 2, 1, 2 ] ]
gap> Print(DotEdgeWeightedDigraph(gr, path));
//dot
digraph hgn{
node [shape=circle]
1[color=yellowgreen, style=filled]
2[color=lightpink, style=filled]
3[color=gray, style=filled]
4[color=gray, style=filled]
5[color=gray, style=filled]
6[color=gray, style=filled]
7[color=gray, style=filled]
1 -> 5[color=black, label=8]
1 -> 7[color=blue, label=4]
2 -> 5[color=black, label=12]
3 -> 1[color=black, label=11]
3 -> 3[color=black, label=2]
3 -> 6[color=black, label=10]
4 -> 1[color=black, label=3]
4 -> 3[color=black, label=7]
5 -> 4[color=black, label=9]
5 -> 5[color=black, label=13]
6 -> 1[color=black, label=1]
6 -> 2[color=blue, label=6]
7 -> 6[color=blue, label=5]
}

#
gap> DIGRAPHS_StopTest();
gap> STOP_TEST("Digraphs package: standard/weights.tst", 0);
Loading