What is the best way to draw large graph using graphvis - graphviz

I need to draw large dataset on image, I used graphvis command lines with all available tools (dot, neato, twopi .. etc) but the result is not readable and contains overlapping.
What I need is display the nodes with labels on the edges, with minimum overlapping so the graph can be readable and also printed on A4 or A3 paper.
I used the options overlap=false, splines=true in neato and same overlapping result.
Here is the dataset:
graph {
graph [ bgcolor=ivory2, overlap=false, splines=true, ranksep ="2.75"]
{node [width=1,height=1,shape=circle,style=filled,color=skyblue] "ECNY" }
edge [ len=2, sep=5]
"DANA" -- "HMRN" -- "ECNY" -- "NORI" -- "MAJZ" -- "RSFH" -- "DANA" [label ="LD1-25-A01", penwidth =3 , color="#156163"]
"DANA" -- "HMRN" -- "ECNY" -- "NORI" -- "MAJZ" -- "RSFH" -- "DANA" [label ="LD1-25-A02", penwidth =3 , color="#30a1f9"]
"DANA" -- "MAJZ" -- "ECNY" -- "HMRN" -- "DANA" [label ="LD1-25-A03", penwidth =3 , color="#ec591d"]
"DANA" -- "MAJZ" -- "ECNY" -- "HMRN" -- "DANA" [label ="LD1-25-A04", penwidth =3 , color="#263a5f"]
"DANA" -- "ECNY" -- "DANA" [label ="LD3-25-A02", penwidth =3 , color="#a3517c"]
"HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "HMRN" [label ="LD1-25-H01", penwidth =3 , color="#800d83"]
"HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" [label ="LD1-25-H02", penwidth =3 , color="#89e15a"]
"HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" [label ="LD3-25-H03", penwidth =3 , color="#74ed0e"]
"HMRN" -- "ECNY" -- "HMRN" [label ="JED-10-H08", penwidth =3 , color="#e8e786"]
"HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "HMRN" [label ="LD1-25-H04", penwidth =3 , color="#e1f559"]
"ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A02", penwidth =3 , color="#8f7964"]
"ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A03", penwidth =3 , color="#9058f0"]
"ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-A04", penwidth =3 , color="#b537b7"]
"ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-A05", penwidth =3 , color="#fc2c2a"]
"ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A06", penwidth =3 , color="#36309c"]
"ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A07", penwidth =3 , color="#25a571"]
"ECNY" -- "OBHR" -- "ECNY" [label ="JED-10-A26", penwidth =3 , color="#1a6077"]
"ECNY" -- "2820" -- "ECNY" [label ="JED-25-A03", penwidth =3 , color="#8bce8c"]
"ECNY" -- "2138" -- "2129" -- "ECNY" [label ="JED-25-A04", penwidth =3 , color="#9b9afa"]
"ECNY" -- "2017" -- "2013" -- "ECNY" [label ="JED-25-A05", penwidth =3 , color="#5ea9aa"]
"ECNY" -- "2027" -- "2128" -- "ECNY" [label ="JED-25-A22", penwidth =3 , color="#c0c4d4"]
"ECNY" -- "2130" -- "2137" -- "ECNY" [label ="JED-25-A27", penwidth =3 , color="#781ce0"]
"ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-A01", penwidth =3 , color="#fd5c5a"]
"ECNY" -- "HMRN" -- "ZJ01" -- "ECNY" [label ="JED-10-H03", penwidth =3 , color="#32e13b"]
"ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-H04", penwidth =3 , color="#487f94"]
"ECNY" -- "2341" -- "2235" -- "2233" -- "ECNY" [label ="JED-10-H05", penwidth =3 , color="#82ae2d"]
"ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-H06", penwidth =3 , color="#f4651c"]
"ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-H07", penwidth =3 , color="#23dd41"]
"ECNY" -- "HMRN" -- "OBHR" -- "ECNY" [label ="JED-10-H37", penwidth =3 , color="#521f43"]
"ECNY" -- "PROJECT" -- "ECNY" [label ="JED-10-H49", penwidth =3 , color="#0a4bf1"]
"ECNY" -- "2234" -- "2246" -- "2245" -- "2320" -- "ECNY" [label ="JED-25-H01", penwidth =3 , color="#6127e4"]
"ECNY" -- "2842" -- "2030" -- "ECNY" [label ="JED-25-H03", penwidth =3 , color="#ce1f98"]
"ECNY" -- "2170" -- "2166" -- "ECNY" [label ="JED-25-H06", penwidth =3 , color="#aeb0ce"]
"ECNY" -- "2158" -- "2144" -- "ECNY" [label ="JED-25-H11", penwidth =3 , color="#9ef618"]
"ECNY" -- "5824" -- "2011" -- "ECNY" [label ="JED-25-H15", penwidth =3 , color="#b2d524"]
"ECNY" -- "2010" -- "2830" -- "2198" -- "ECNY" [label ="JED-25-H16", penwidth =3 , color="#53e7ae"]
"ECNY" -- "2179" -- "ECNY" [label ="JED-25-H17", penwidth =3 , color="#149169"]
"ECNY" -- "2211" -- "ECNY" [label ="JED-25-H19", penwidth =3 , color="#15a51b"]
"ECNY" -- "2316" -- "ECNY" [label ="JED-25-H20", penwidth =3 , color="#e91d18"]
"ECNY" -- "2203" -- "ECNY" [label ="JED-25-H22", penwidth =3 , color="#38a23a"]
"ECNY" -- "SBCB" -- "JFCC" -- "ECNY" [label ="JED-25-H33", penwidth =3 , color="#a1abf4"]
"ECNY" -- "HMRN" -- "ECNY" [label ="JED-25-H41", penwidth =3 , color="#c14ff8"]
"ECNY" -- "TAIF" -- "SNFN" -- "NORI" -- "ECNY" [label ="LD1-10-H04", penwidth =3 , color="#75fb4f"]
"ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" -- "ECNY" [label ="LD1-25-H03", penwidth =3 , color="#52d1c8"]
"ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-H01", penwidth =3 , color="#498a16"]
"ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-H02", penwidth =3 , color="#70f831"]
"ECNY" -- "2310" -- "5880" -- "5301" -- "2248" -- "ECNY" [label ="JED-10-H17", penwidth =3 , color="#ebb4e1"]
"SBCB" -- "ECNY" -- "HMRN" -- "JELS" -- "ROMN" -- "OBHR" -- "SAFA" -- "SBCB" [label ="JED-W40-A01", penwidth =3 , color="#7ff59c"]
"SBCB" -- "SAFA" -- "OBHR" -- "HMRN" -- "ECNY" -- "SBCB" [label ="JED-10-H35", penwidth =3 , color="#e817b9"]
"2171" -- "ECNY" -- "2171" [label ="JED-10-H19", penwidth =3 , color="#bf1252"]
"ABHA" -- "ECNY" -- "DANA" -- "ABHA" [label ="LD3-10-H01", penwidth =3 , color="#8b60ae"]
"MAJZ" -- "ECNY" -- "DANA" -- "2510" -- "MAJZ" [label ="LD1-10-H02", penwidth =3 , color="#1e3c55"]
"2209" -- "2206" -- "ECNY" -- "2209" [label ="JED-25-H02", penwidth =3 , color="#1b6092"]
}
this is one of the output when using these options (in neato):
graph [ bgcolor=ivory2, overlap=false, splines=true, ranksep ="2.75"]
{node [width=1,height=1,shape=circle,style=filled,color=skyblue]
"ECNY" }
edge [ len=2, sep=5]
also this when make overlap=scale but still the image is not readable!
overlap=scale, sep=\"+25,25\", splines=true, rankdir=\"TB\"
so what other attributes can enhance this graph ?

Inevitably, as the number of nodes and edges increase, we will eventually end up without enough space to have a compact but nevertheless clear graph. However, there are some things we can do to improve matters, I think. In this case, we can take advantage of the fact that all the sequences of edges form loops that return to "ECNY".
First, I weighted the edges that are closer to "ECNY" less (so that they are more stretchy) and made them longer by default (so that the middle of the graph was more spread out), and conversely with the edges that are further from "ECNY".
Second, I labelled each loop only once, with the label being on the edge as far away from "ECNY" in the loop as I could get it.
I made these changes programmatically with a Python script adjweight.py as follows:
import sys, re, math
for line in sys.stdin:
line = line.rstrip()
if re.match(' +"',line):
loop, attr = line.split(" [")
loopli = loop.split(" -- ")[1:]
# We take all but the first node, to eliminate repeats
# then we put the list of edges together with "ECNY" first and last.
i = loopli.index('"ECNY"')
loopli = loopli[i:] + loopli[:i] + [loopli[i]]
n = len(loopli)
# Now we write the multi-edge lines as individual lines so that we can
# give each edge an individual weight and length
for i in range(n-1):
# We weight edges that are furthest from the center (i.e. those with
# numbers closest to n/2) highest and those that are closest to the
# center are weighted lowest.
wt = (n/2)/(abs(n/2 - (i+1))+1)
edgelength = 1/wt
if i - n//2 + 1 != 0:
# This edge is the furthest from the center in this loop, so we
# label this edge (but not the other edges in the loop)
attr = ",".join(attr.split(",")[1:])
# We raise the weights and edge lengths to different powers to adjust
# the distribution of nodes across the "diameter" of the graph
print (" %s -- %s [weight = %f, len = %f, %s" % (
loopli[i],loopli[i+1],wt**3,edgelength**2,attr))
else:
print (line)
... which can be run with python adjweight.py <large.dot >large3.dot, where large.dot is the .dot file shown in the question.
Changing the fontsize for the edges to 10 (compared to the default of 14) and running large3.dot through neato gave me the following graph:
This has spread the nodes more evenly around the page and it is much less cluttered by edge labels, so it seems like an improvement to me. Edge labels still overlap a few nodes and (particularly in the top right of the graph) other edge labels because the overlap parameter only affects nodes and edge lines, not edge labels.
Tweaking the relative lengths and weights of edges as they relate to the distance from "ECNY" might help improve the graph a bit more.

i need to visualize all the path form certain node to other nodes, so my problem about visualizing nodes not on the simplification.
all right you already visualize all the path from certain node to other nodes But AS you said ** the result is not readable and contains overlapping**. i think what you need is to make this visualize clear
my next advice to you try visualize your graph by hand on small data using (3 dimension graph) then code it or try to find attributes to visualize it on 3d if it work well on small data.
i just try to think how to help in this problem so all this are just suggestion and open questions to make you find answer on your question.

Why you not try to reduce data on your graph first (i.e:even if you get your implementation - it is hard to follow the graph)and the main idea of representing data on a graph is simplification and you will loss it )So My ADVICE TRY TO REDUCE DATA ON Your GRAPH.

I recommend using software/framework that has the popular force directed layout algorithms (http://en.wikipedia.org/wiki/Force-directed_graph_drawing), the most popular of which are Fruchterman-Reingold and Kamada-Kawai. I've used R (http://www.r-project.org/) with the igraph package. I know this is kind of not answering your question since you said you were using graphvis, but using force-directed algorithms is your best bet.

Related

How do you remove margin/padding from a GraphViz node using an image?

I am using GraphViz with user defined shapes for nodes using the image tag. The images are png files, and contain lines to the edge of the image to link up with edges drawn by GraphViz. But if I try to make a rudimentary graph using neato with a defined layout, you can still see some margin or padding between the images and the graph edges that show up as small gaps in the lines. There is no border in the images themselves. (I also need to re-center some of the images.) How does one remove the gaps?
Here is my .dot, with several attempts inspired by other answers, but nothing seems to remove the gaps.
graph G {
pad = 0.0;
a [ label="", pos="0,0", shape=none, width=0, height=0, image="LnLft.png" ];
b [ label="", pos="100,0", shape=none, width=0, height=0, image="BrkClsHrz.png", penwidth=0 ];
h1 [ label="", pos="200,0", shape=none, width=0, height=0 ];
c [ label="", pos="200,-100", shape=plaintext, width=0, height=0, image="BrkClsVrt.png", penwidth=0 ];
d [ label="", pos="200,-200", shape=plaintext, width=0, height=0, image="BrkOpnVrt.png" ];
h2 [ label="", pos="200,-300", shape=none, width=0, height=0 ];
e [ label="", pos="100,-300", shape=none, width=0, height=0, image="BrkClsHrz.png", margin="0,0"];
f [ label="", pos="0,-300", shape=none, width=0, height=0, image="LnLft.png" ];
a -- b [len=1.5, penwidth=2];
b -- h1 [len=1.5, penwidth=2];
h1 -- c [len=1.5, penwidth=2];
c -- d [len=1.5, penwidth=2];
d -- h2 [len=1.5, penwidth=2];
h2 -- e [len=1.5, penwidth=2];
e -- f [len=1.5, penwidth=2];
}
And here is the output:

graphviz: dotted box around "same"-grouped boxes

I have a number of boxes that are put on the same level as such:
via multiple {rank=same a3 b3_1 b3_2 c3_1 c3_2 d3_1 d3_2}; lines whereas I define my elements with a3 [label = "Assigned"]; lines.
I'd like to get a (dotted, if possible) box around all elements that are on the same level, as such (mockup via editor):
The whole source looks as follows:
digraph customer {
layout=dot
label = "some diagram";
labelloc = "t"; // place the label at the top
node [shape=record];
{rank=same a1 b1 c1 d1};
{rank=same a2 b2 c2 d2};
{rank=same a3 b3_1 b3_2 c3_1 c3_2 d3_1 d3_2};
{rank=same a4 b4_1_1 b4_1_2 b4_2_1 b4_2_2 c4_1_1 c4_1_2 c4_2_1 c4_2_2 d4_1_1 d4_1_2 d4_2_1 d4_2_2};
{rank=same a5 b5_1 b5_2 b5_3 b5_4 c5_1 c5_2 c5_3 c5_4 d5_1 d5_2 d5_3 d5_4};
{rank=same a6 b6_1 b6_2 b6_3 b6_4 c6_1 c6_2 c6_3 c6_4 d6_1 d6_2 d6_3 d6_4};
a1 [label = "Level 1"];
a2 [label = "Level 2"];
a3 [label = "Level 3"];
a4 [label = "Level 4"];
a5 [label = "Level 5"];
a6 [label = "Level 6"];
a1 -> a2 -> a3 -> a4; a4 -> a5 [label = "case ..." ]; a5 -> a6;
b1 [label = "Text A"];
b2 [label = "false"];
b3_1 [label = "no"];
b3_2 [label = "yes"];
b4_1_1 [label = "same"];
b4_1_2 [label = "different"];
b4_2_1 [label = "same"];
b4_2_2 [label = "different"];
b5_1 [label = "no", fillcolor = red, style=filled];
b5_2 [label = "no", fillcolor = red, style=filled];
b5_3 [label = "no", fillcolor = red, style=filled];
b5_4 [label = "yes", fillcolor = green, style=filled];
b6_1 [label = "yes", fillcolor = green, style=filled];
b6_2 [label = "yes", fillcolor = green, style=filled];
b6_3 [label = "yes", fillcolor = green, style=filled];
b6_4 [label = "yes", fillcolor = green, style=filled];
b1 -> b2;
b2 -> b3_1; b3_1 -> b4_1_1; b4_1_1 -> b5_1 [label = "A" ]; b5_1 -> b6_1;
b3_1 -> b4_1_2; b4_1_2 -> b5_2 [label = "B" ]; b5_2 -> b6_2;
b2 -> b3_2; b3_2 -> b4_2_1; b4_2_1 -> b5_3 [label = "C" ]; b5_3 -> b6_3;
b3_2 -> b4_2_2; b4_2_2 -> b5_4 [label = "D" ]; b5_4 -> b6_4;
subgraph clusterone {
a1; b1; c1; d1;
label="level 1";
graph[style=dotted];
}
c1 [label = "Text B"];
c2 [label = "true"];
c3_1 [label = "no"];
c3_2 [label = "yes"];
c4_1_1 [label = "same"];
c4_1_2 [label = "different"];
c4_2_1 [label = "same"];
c4_2_2 [label = "different"];
c5_1 [label = "no", fillcolor = red, style=filled];
c5_2 [label = "no", fillcolor = red, style=filled];
c5_3 [label = "yes", fillcolor = green, style=filled];
c5_4 [label = "yes", fillcolor = green, style=filled];
c6_1 [label = "yes", fillcolor = green, style=filled];
c6_2 [label = "yes", fillcolor = green, style=filled];
c6_3 [label = "yes", fillcolor = green, style=filled];
c6_4 [label = "yes", fillcolor = green, style=filled];
c1 -> c2;
c2 -> c3_1; c3_1 -> c4_1_1; c4_1_1 -> c5_1 [label = "E" ]; c5_1 -> c6_1;
c3_1 -> c4_1_2; c4_1_2 -> c5_2 [label = "F" ]; c5_2 -> c6_2;
c2 -> c3_2; c3_2 -> c4_2_1; c4_2_1 -> c5_3 [label = "G" ]; c5_3 -> c6_3;
c3_2 -> c4_2_2; c4_2_2 -> c5_4 [label = "H" ]; c5_4 -> c6_4;
d1 [label = "(else)"];
d2 [label = "???", fillcolor = yellow, style=filled];
d3_1 [label = "no"];
d3_2 [label = "yes"];
d4_1_1 [label = "same"];
d4_1_2 [label = "different"];
d4_2_1 [label = "same"];
d4_2_2 [label = "different"];
d5_1 [label = "no", fillcolor = red, style=filled];
d5_2 [label = "no", fillcolor = red, style=filled];
d5_3 [label = "no", fillcolor = red, style=filled];
d5_4 [label = "no", fillcolor = red, style=filled];
d6_1 [label = "yes", fillcolor = green, style=filled];
d6_2 [label = "yes", fillcolor = green, style=filled];
d6_3 [label = "yes", fillcolor = green, style=filled];
d6_4 [label = "yes", fillcolor = green, style=filled];
d1 -> d2;
d2 -> d3_1; d3_1 -> d4_1_1; d4_1_1 -> d5_1 [label = "I" ]; d5_1 -> d6_1;
d3_1 -> d4_1_2; d4_1_2 -> d5_2 [label = "J" ]; d5_2 -> d6_2;
d2 -> d3_2; d3_2 -> d4_2_1; d4_2_1 -> d5_3 [label = "K" ]; d5_3 -> d6_3;
d3_2 -> d4_2_2; d4_2_2 -> d5_4 [label = "L" ]; d5_4 -> d6_4;
}
By some reason it conflicts with rank=same declaration.
Try removing it and use cluster instead with rank=same inside, like this:
subgraph cluster_one {
label="cluster one";
rank=same;
style=dotted;
a1 b1 c1 d1
};
subgraph cluster_two {
label="cluster two";
rank=same;
style=dotted;
a2 b2 c2 d2
};
or even shorter (one line):
subgraph cluster_one { label="cluster one" rank=same style=dotted a1 b1 c1 d1 }
Keep in mind, that width of subgraphs will not be the same, as it used to be.

Nested directed subgraphs

I'm trying to obtain nested subgraphs in graphviz.
Graphviz version is 2.38.0 (20140413.2041)
Here is the code:
digraph G {
subgraph cluster_win {
style=filled;
color=lightgrey;
label = "Windows"
subgraph extra_enabled {
fillcolor = "#EDF1F2";
color = "#028d35";
label="Subdirectory extra included";
node [style=filled,color=white];
config_debug1 [label = "Configure Debug"];
config_release1 [label = "Configure Release"];
build_debug1 [label = "Build"];
build_release1 [label = "Build"];
config_debug1 -> build_debug1;
config_release1 -> build_release1;
shape=rect;
style=rounded;
}
subgraph extra_disabled {
label = "Subdirectory extra excluded";
config_debug2 [label = "Configure Debug"];
config_release2 [label = "Configure Release"];
build_debug2 [label = "Build"];
build_release2 [label = "Build"];
config_debug2 -> build_debug2;
config_release2 -> build_release2;
}
checkout [style=filled, color=white];
checkout -> extra_enabled;
checkout -> extra_disabled;
}
start -> checkout;
start [label="git push"; shape=Mdiamond];
}
And this is the result.
Graphviz draws two ordinary nodes "extra_enabled" and "extra_disabled". However, I want them to be subgraphs, containing nodes "Configure Release", "Configure Debug", "Build" and another "Build".
How can I fix it?
You need to do two things:
Connect nodes only, you cannot connect to a cluster
Cluster names need to be prefixed by cluster_
Applying this to your code
digraph G {
subgraph cluster_win {
style=filled;
color=lightgrey;
label = "Windows "
subgraph cluster_extra_enabled {
fillcolor = "#EDF1F2";
color = "#028d35";
label="Subdirectory extra included";
node [style=filled,color=white];
config_debug1 [label = "Configure Debug"];
config_release1 [label = "Configure Release"];
build_debug1 [label = "Build"];
build_release1 [label = "Build"];
config_debug1 -> build_debug1;
config_release1 -> build_release1;
shape=rect;
style=rounded;
}
subgraph cluster_extra_disabled {
label = "Subdirectory extra excluded";
config_debug2 [label = "Configure Debug"];
config_release2 [label = "Configure Release"];
build_debug2 [label = "Build"];
build_release2 [label = "Build"];
config_debug2 -> build_debug2;
config_release2 -> build_release2;
}
checkout [style=filled, color=white];
checkout -> config_debug1;
checkout -> config_release2;
}
start -> checkout;
start [label="git push"; shape=Mdiamond];
}
I get
which is probably close to what you want. Note that I have added a few spaces to the label "Windows " to get it out of the way of the arrow. You could also use labeljust. There are also ways to make the edge end at the boundary of the cluster, but that would have needed a lot more editing on my part which I was not sure you want it.
I just wanted to append to the answer that vaettchen added. While it is correct that you cannot directly connect edges to clusters, edges must travel between nodes, there is a way to do so visually with lhead and ltail.
You can do the following:
node1 -> node2 [lhead=cluster_name_1, ltail=cluster_name_2]
Which will cut the connectors off at the limit of the cluster to connect clusters, this is just visual and is logged as a node connection, but it is a nicer way to visually display connections between whole clusters.

How to set a graph-filling-area?

How to set the graph to try to fill the area allocated to it? With an increase in the number of nodes, it simply decreases in size, but also remains in one line, although the vertical size (40) allows placement down. If you remove the rankdir, then it places vertically, but also in one line.
digraph "test_graph"{
rankdir = LR;
bgcolor = whitesmoke;
graph [size = "15, 40"];
node [shape = circle,
style = filled,
margin = 0,
fontsize = 14,
color = sandybrown];
edge [fontsize = 10,
arrowhead = vee];
1->2 [label = "R"];
2->3 [label = "R"];
3->4 [label = "R"];
3->5 [label = "B"];
4->1 [label = "R"];
5->6 [label = "U"];
6->7 [label = "U"];
7->8 [label = "U"];
7->9 [label = "F"];
8->5 [label = "U"];
9->10 [label = "F"];
10->11 [label = "D"];
11->12 [label = "D"];
12->13 [label = "D"];
13->10 [label = "D"];
13->14 [label = "L"];
14->15 [label = "L"];
15->16 [label = "D"];
16->17 [label = "D"];
17->18 [label = "D"];
17->19 [label = "L"];
18->15 [label = "D"];
19->20 [label = "F"];
20->21 [label = "F"];
21->22 [label = "F"];
21->23 [label = "L"];
22->19 [label = "F"];
23->24 [label = "L"];
24->25 [label = "F"];
}
You will need to select suitable nodes that
are connected by one edge
connect to other nodes in a way that fills the available width as you like it
and then
connect them in the desired order by invisible edges (so that you avoid graphviz reordering them)
ranking them on the same lavel so that they appear one below the other
In concrete terms this means that adding
1 -> 10 -> 19[ style = invis ];
{ rank = same; 1 10 19 }
just before the closing curly brace, as the last two lines, will produce
which is, as far as I understand your requirement, what you want.

Make Graphviz edge labels vertical (or make the tree extend horizontally)

I would like to achieve either a) vertical edge labels or b) a horizontally extending tree in order to fit this graph on a single A4 page. How would I do it?
digraph g {
node[shape=point]
root -> 1 [label = "abcdefghijklmnopqrstuvwxyz$"]
root -> 2 [label = "bcdefghijklmnopqrstuvwxyz$"]
root -> 3 [label = "cdefghijklmnopqrstuvwxyz$"]
root -> 4 [label = "defghijklmnopqrstuvwxyz$"]
root -> 5 [label = "efghijklmnopqrstuvwxyz$"]
root -> 6 [label = "fghijklmnopqrstuvwxyz$"]
root -> 7 [label = "ghijklmnopqrstuvwxyz$"]
root -> 8 [label = "hijklmnopqrstuvwxyz$"]
root -> 9 [label = "ijklmnopqrstuvwxyz$"]
root -> 10 [label = "jklmnopqrstuvwxyz$"]
root -> 11 [label = "klmnopqrstuvwxyz$"]
root -> 12 [label = "lmnopqrstuvwxyz$"]
root -> 13 [label = "mnopqrstuvwxyz$"]
root -> 14 [label = "nopqrstuvwxyz$"]
root -> 15 [label = "opqrstuvwxyz$"]
root -> 16 [label = "pqrstuvwxyz$"]
root -> 17 [label = "qrstuvwxyz$"]
root -> 18 [label = "rstuvwxyz$"]
root -> 19 [label = "stuvwxyz$"]
root -> 20 [label = "tuvwxyz$"]
root -> 21 [label = "uvwxyz$"]
root -> 22 [label = "vwxyz$"]
root -> 23 [label = "wxyz$"]
root -> 24 [label = "xyz$"]
root -> 25 [label = "yz$"]
root -> 26 [label = "z$"]
root -> 27 [label = "$"]
}
rankdir=LR can let you fit it on one page
digraph g {
graph[rankdir=LR]
node[shape=point]
root -> 1 [label = "abcdefghijklmnopqrstuvwxyz$"]
root -> 2 [label = "bcdefghijklmnopqrstuvwxyz$"]
...
}
http://www.graphviz.org/doc/info/attrs.html#d:rankdir
One work-around I just discovered on the net was to seperate every character with a '\n' (eg. a newline character). It's not pretty, but it basically achieves vertical edge labels:
For example:
root -> 1 [label = "f\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n$"]
One possibility is to use the unflatten utility.
For example:
unflatten -l 8 yourdotfile.gv | dot | neato -s -n2 -Tpng -o result.png
The resulting graph is not as wide as before.

Resources