graphviz - how to create a 'roundtrip' flow - graphviz

I'm trying to create a 'round trip' graph using the graphviz. Given the result below, my objective is to have the PINK squares between the NET and the COM (note from the picture below that they are pushed to the right after the NET).
the COM must be the first node on the LEFT.
the dot code:
digraph {
rankdir = LR;
graph [fontname = "helvetica" ];
node [fontname = "helvetica"];
edge [fontname = "helvetica"];
COM [shape = circle, fillcolor = yellow, style = filled];
NET [shape = circle, fillcolor = yellow, style = filled];
fn1 [shape = BOX, fillcolor = green, style = filled, label = "PORT006"];
clazz1 [shape = BOX, fillcolor = red, style = filled, label = "O"];
ddate1 [shape = BOX, fillcolor = red, style = filled, label = "21-Apr-13"];
status1 [shape = BOX, fillcolor = red, style = filled, label = "OJ3COM6M"];
clazz1exch [shape = BOX, fillcolor = green, style = filled, label = "G"];
ddate1exch [shape = BOX, fillcolor = green, style = filled, label = "13-May-13"];
status1exch [shape = BOX, fillcolor = green, style = filled, label = "GJ3COM6M"];
fn2 [shape = BOX, fillcolor = pink, style = filled, label = "PORT005"];
rbd2 [shape = BOX, fillcolor = pink, style = filled, label = "O"];
ddate2 [shape = BOX, fillcolor = pink, style = filled, label = "29-Apr-13"];
fare2 [shape = BOX, fillcolor = pink, style = filled, label = "OJ3COM6M"];
{ rank=same; clazz1 -> clazz1exch; }
{ rank= same; ddate1 -> ddate1exch; }
{ rank=same; status1 -> status1exch; }
COM -> fn1 -> clazz1exch -> ddate1exch -> status1exch -> NET;
NET -> fn2 -> rbd2 -> ddate2 -> fare2 -> COM;
}

If you simply reverse the direction of the edges going back (dir=back) by changing the line
NET -> fn2 -> rbd2 -> ddate2 -> fare2 -> COM;
into
edge[dir=back];
COM -> fare2 -> ddate2 -> rbd2 -> fn2 -> NET;
you should get:

Related

Forcing the edge between subgraphs to go left or right

I have a PATRICA trie for which I'm generating a GraphViz file. The internal nodes are the skip values and the edges are dotted 0 and solid 1. It is preferred that 0 is to the left of 1, giving an alphabetical order of the leaves. I re-arranged the order I visit the graph so dot gives this result. However, when I group them in trees in a forest using subgraphs, I can't seem to force dot to reliably respect the order for inter-subgraph edges.
digraph {
rankdir=TB;
node [shape = box, style = filled, fillcolor = lightsteelblue];
// forest size 2.
subgraph cluster_tree0 {
style = filled; fillcolor = lightgray; label = "tree 0";
// branches
branch0_0 [label = "3", shape = none, fillcolor = none];
branch0_0 -> branch0_1;
branch0_1 [label = "0", shape = none, fillcolor = none];
branch0_1 -> branch0_2 [style = dashed];
branch0_2 [label = "1", shape = none, fillcolor = none];
branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
branch0_2 -> leaf0_2 [color = royalblue];
branch0_1 -> branch0_3;
branch0_3 [label = "2", shape = none, fillcolor = none];
branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
branch0_3 -> leaf0_4 [color = royalblue];
// leaves
leaf0_1 [label = "u"];
leaf0_2 [label = "v"];
leaf0_3 [label = "x"];
leaf0_4 [label = "y"];
}
branch0_0 -> branch1_0 [lhead = cluster_tree0, ltail = cluster_tree1, color = firebrick, style = dashed];
subgraph cluster_tree1 {
style = filled; fillcolor = lightgray; label = "tree 1";
// branches
branch1_0 [label = "0", shape = none, fillcolor = none];
branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
branch1_0 -> branch1_1;
branch1_1 [label = "1", shape = none, fillcolor = none];
branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
branch1_1 -> branch1_2;
branch1_2 [label = "0", shape = none, fillcolor = none];
branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
branch1_2 -> leaf1_3 [color = royalblue];
// leaves
leaf1_0 [label = "f"];
leaf1_1 [label = "m"];
leaf1_2 [label = "n"];
leaf1_3 [label = "o"];
}
}
On one graph it works fine, but it the subgraphs are reversed to the order I want them.
I reversed the order in the file and it still looks the same. I played around with it and I could get it turned around by rank=same, ordering=out, and invis edges somehow, but I want it to be programmatic. Is there any easy way to draw the red dotted line, representing 0, to the left, instead of to the right, of the solid line, representing 1?
OK, a total kludge, but probably fully scriptable.
First, your input somewhat reworked:
digraph {
rankdir=TB;
newrank=true // helps
graph [splines=false]
node [shape = box, style = filled, fillcolor = lightsteelblue];
// forest size 2.
subgraph cluster_tree1 {
style = filled; fillcolor = lightgray; label = "tree 1";
// branches
branch1_0 [label = "0", shape = none, fillcolor = none];
branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
branch1_0 -> branch1_1;
branch1_1 [label = "1", shape = none, fillcolor = none];
branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
branch1_1 -> branch1_2;
branch1_2 [label = "0", shape = none, fillcolor = none];
branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
branch1_2 -> leaf1_3 [color = royalblue];
// leaves
leaf1_0 [label = "f"];
leaf1_1 [label = "m"];
leaf1_2 [label = "n"];
leaf1_3 [label = "o"];
}
subgraph cluster_tree0 {
style = filled; fillcolor = lightgray; label = "tree 0";
// branches
branch0_0 [label = "3", shape = none, fillcolor = none];
branch0_0 -> branch0_1;
branch0_1 [label = "0", shape = none, fillcolor = none];
branch0_1 -> branch0_2 [style = dashed];
branch0_2 [label = "1", shape = none, fillcolor = none];
branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
branch0_2 -> leaf0_2 [color = royalblue];
branch0_1 -> branch0_3;
branch0_3 [label = "2", shape = none, fillcolor = none];
branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
branch0_3 -> leaf0_4 [color = royalblue];
// leaves
leaf0_1 [label = "u"];
leaf0_2 [label = "v"];
leaf0_3 [label = "x"];
leaf0_4 [label = "y"];
}
// position the clusters (trees)
{rank=same branch1_0 -> branch0_1 [style=invis weight=0]}
// a kludge, we'll add this edge in later
graph [comment="branch0_0 -> branch1_0 [color = firebrick, style = dashed constraint=false weight=0 ];"]
}
The "problem" is the cluster-to-cluster branch, so we remove it (for the first dot pass). And we add the invisible edge to position the clusters where we want them.
Run this input into dot -Tdot >myfile.dot. This sets positions for all nodes & edges.
Run that thru gawk (any language) to un-comment the commented branch(s) and insert into the file.
Finally, neato -n2 -Tpng fixedfile >fixed.png
(yuck, but it works)
f=atrie4.gv;
T=png; F=`basename $f .gv`;dot -Tdot $f >$F.dot;
gawk '
$1~/comment/{
sub(/[\t ]*comment="/,"")
sub(/"[\],;]?[\t ]*$/,"")
add[++a]=$0
next
}
{oline[++o]=$0}
END{
for (i=1;i<o;i++)print oline[i]
for (i=1;i<=a;i++)print add[i]
print oline[o]
}' $F.dot|
neato -n2 -Tpng >$F.$T
firefox $F.$T

how to define a graph with graphviz without overlapping labels

The follow dot file demonstrates the issue I am trying to resolve:
digraph G {
splines=line;
rankdir=LR;
A -> B [label="a long label"];
A -> C [label="a long label"];
A -> A [label="a very long label"];
A -> A [label="a very long label"];
A -> D [label="a long label"];
}
It generates the follow the graph:
The labels are poorly positioned, nearly overlapping.
What can be done to improve the look of this graph?
I would define improve by saying (1) labels do not overlap with each other, (2) labels do not overlap edges, and (3) optionally / ideally labels are drawn along the edge. #3 may not be possible, but #1 and #2 should be sufficient. Using ortho splines would always provide an edge where a which a label could be drawn along and still be read normally, but this I know is not currently supported by graphviz.
"Improve" is in the eye of the beholder, but this uses ports, headlabels, spaces and newlines to rearrange the labels.
digraph G {
splines=line;
rankdir=LR;
// use ports to rearrange edges
// then headlabel, spaces, and newlines (\n)
A:n -> A:w [headlabel="a very long label "];
A:s -> A:w [headlabel="a very long label "];
A -> B [label="a long label"];
A -> C [label="a long label"];
A -> D [label="\n\na long label"];
}
There does not appear to be any supported solution in GraphViz that meet the desired criteria for edge labels. My work around is to split the edges between two nodes and insert another node containing the text of the edge label. The new node is styled to distinguish it from regular nodes.
The GraphViz layout algorithm does a good job of keep nodes separated and not allowing edges to overlap nodes.
Updating the test case with this workaround, I have the following dot file:
digraph G {
splines=ortho;
rankdir=LR;
AA1 [label="a very long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AA2 [label="a very long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AB1 [label="a long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AC1 [label="a long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AD1 [label="a long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
A -> AA1 [arrowhead = "none" ];
AA1 -> A
A -> AA2 [arrowhead = "none" ];
AA2 -> A
A -> AB1 [arrowhead = "none" ];
AB1 -> B
A -> AC1 [arrowhead = "none" ];
AC1 -> C
A -> AD1 [arrowhead = "none" ];
AD1 -> D
}
which produces this

Align nodes in a Graphviz directed graph

I have the following Graphviz code:
digraph {
Technique [shape = box];
Path [shape = box];
KnowledgeObservation [shape = box, label = "Knowledge\nObservation"];
ManagementIntervention [shape = box, label = "Management\nIntervention"];
ResultsModification [shape = box, label = "Results\nModification"];
SharedCode [label = "Shared Code"];
MediatedRelationship [label = "Mediated Relationship"];
Art -> Technique;
Therapy -> Path;
{Technique Path} -> KnowledgeObservation -> ManagementIntervention -> ResultsModification;
{MediatedRelationship SharedCode} -> {KnowledgeObservation ResultsModification}
subgraph {
rank = same
Technique -> Path [dir = none]
}
subgraph {
rank = same
SharedCode
ManagementIntervention
MediatedRelationship
}
}
It currently produces the following output:
How can I vertically align "Management Intervention" with both "Knowledge Observation" and "Results Modification"?
"Shared Code" should be moved to the left of "Management Intervention".
"Mediated Relationship" should be moved to the right of "Management Intervention".
"Shared Code", "Management Intervention" and "Mediated Relationship" should stay horizontally aligned.
How can I accomplish this?
This can be achieved without subgraphs; the most important modification is the line
{ rank = same; SharedCode -> ManagementIntervention -> MediatedRelationship[ style = invis ] }
which keeps the three nodes not only on the right level, but also within the desired order.
Altogether, this code here
digraph
{
// node definition
Art Therapy;
Technique[ shape = box ];
Path[ shape = box ];
KnowledgeObservation[ shape = box, label = "Knowledge\nObservation" ];
ManagementIntervention[ shape = box, label = "Management\nIntervention" ];
ResultsModification[ shape = box, label = "Results\nModification" ];
SharedCode[ label = "Shared Code" ];
MediatedRelationship[ label = "Mediated Relationship" ];
// edges
Art -> Technique;
Therapy -> Path;
{ rank = same; Technique -> Path [dir = none] }
{ Technique Path} -> KnowledgeObservation -> ManagementIntervention -> ResultsModification;
{ rank = same; SharedCode -> ManagementIntervention -> MediatedRelationship[ style = invis ] }
{ MediatedRelationship SharedCode } -> { KnowledgeObservation ResultsModification }
}
gives you
which is, in my understanding, what you are looking for.
Still I would recommend to replace the last line of code with these three
KnowledgeObservation -> { SharedCode MediatedRelationship }[ dir = back ];
SharedCode -> ResultsModification;
MediatedRelationship -> ResultsModification;
Reason is that once your graph gets more complicated, graphviz will recognize and maintain the hierarchical relationships, rather than interpreting ambiguous instructions in surprising ways.
How can I vertically align "Management Intervention" with both "Knowledge Observation" and "Results Modification"?
This can be achieved with increasing the weight of the edge. Edges with higher weight tend to be straighter and shorter than with the lower.
"Mediated Relationship" should be moved to the right of "Management Intervention".
You can control this with the order in which the nodes are defined. If you define "Management Intervention" before the "Shared Code", it (MI) will be drawn first, i. e., to the left of the SI.
"Shared Code", "Management Intervention" and "Mediated Relationship" should stay horizontally aligned.
You did it right, using the rank=same subgraph attribute. Though I would put the subgraph already in the moment of node definitions. This will shorten the source size and limit the rank specification to the place where the nodes are defined, which is good for readability (everything stated in one place).
Your modified example:
digraph {
Technique [shape = box];
Path [shape = box];
KnowledgeObservation [shape = box, label = "Knowledge\nObservation"];
ResultsModification [shape = box, label = "Results\nModification"];
subgraph {
rank=same
ManagementIntervention [shape = box, label = "Management\nIntervention"];
MediatedRelationship [label = "Mediated Relationship"];
SharedCode [label = "Shared Code"];
}
Art -> Technique;
Therapy -> Path;
{Technique Path} -> KnowledgeObservation
KnowledgeObservation -> ManagementIntervention -> ResultsModification [weight=3]
{MediatedRelationship SharedCode} -> {KnowledgeObservation ResultsModification}
subgraph {
rank = same
Technique -> Path [dir = none]
}
}
Result:

How to display identical captions of nodes

I wanted to draw RB-Tree as in Wiki 1,
but I can't find a possibility of display of the identical caption for different nodes(in this case nil - nodes). It is possible?
digraph "rb-tree"{
bgcolor = whitesmoke;
forcelabels = true;
margin = 0;
node [shape = circle,
style = filled,
fontsize = 14,
margin = 0,
fillcolor = black,
fontcolor = white];
edge [fontsize = 10,
arrowhead = vee];
8 [fillcolor = red];
17 [fillcolor = red];
nil_8l [shape = box];
nil_8r [shape = box];
nil_17l [shape = box];
nil_17r [shape = box];
13->8;
13->17;
8->nil_8l;
8->nil_8r;
17->nil_17l;
17->nil_17r;
}
Graphiz has the possibility to set labels. So use:
digraph "rb-tree"{
bgcolor = whitesmoke;
forcelabels = true;
margin = 0;
node [shape = circle,
style = filled,
fontsize = 14,
margin = 0,
fillcolor = black,
fontcolor = white];
edge [fontsize = 10,
arrowhead = vee];
8 [fillcolor = red];
17 [fillcolor = red];
nil_8l [shape = box label="nil"];
nil_8r [shape = box label="nil"];
nil_17l [shape = box label="nil"];
nil_17r [shape = box label="nil"];
13->8;
13->17;
8->nil_8l;
8->nil_8r;
17->nil_17l;
17->nil_17r;
}

Why does Graphviz/Dot act so weirdly to this particular code?

I am using GraphViz 2.28 (the current stable version) on Windows 7, and Graphviz/Dot crashes for the following code.
digraph G {
ranksep = 1.0; size = "10,10";
{
node [shape = plaintext, fontsize = 20];
GAWM1 -> GAWM2 -> 0;
}
node [shape = box];
{rank = same;0;wx1;wx2;rx1;}
wx1 -> wx2;
wx2 -> rx1;
wx1 -> rx1[color = blue];
subgraph struct
{
node [shape = record];
rx11 [shape = record, label = "rx1 | [x=[wx2]]"];
}
{rank = same; GAWM1; "rx11";}
// W'WR Order:
wx2 -> wx1[style = dashed, color = red, label = "1"]; }
Things become weird when I perform some experiments on this example:
It works well when only the last statement "wx2 -> wx1[style = dashed, color = red, label = "1"];" is removed;
It works well when only the eighth line "{rank = same;0;wx1;wx2;rx1;}" is removed;
It also works well when only the label (that is ", label = "1"") in the last statement is removed.
I have reported the problem to Graphviz Issue Tracker, without reply yet. Could you help to find out the reason?
Thank you.
The following variation of your script does not crash:
digraph G {
ranksep = 1.0; size = "10,10";
{
node [shape = plaintext, fontsize = 20];
GAWM1 -> GAWM2 -> 0;
}
node [shape = box];
{rank = same;0;wx1;wx2;rx1;}
wx1 -> wx2;
wx2 -> rx1;
wx1 -> rx1[color = blue];
subgraph struct
{
node [shape = record];
rx11 [shape = record, label = "rx1 | [x=[wx2]]"];
}
{rank = same; GAWM1; "rx11";}
// W'WR Order:
//wx2 -> wx1[style = dashed, color = red, label = "1"];
wx2 -> wx1 [style=dashed, color=red];
}
Looks like a bug with the label of the short edge between wx1 and wx2.

Resources