I've reduced my problem to the following simple example:
digraph {
subgraph {rank=same; 0 -> 1 -> 2;}
0 -> 2 [label="A"];
2 -> 0 [label="B"];
}
which produces
While keeping 0, 1 and 2 in the same rank (the original example is in the context of a larger graph), I need A and B edges to be discernible. i.e. the edges to clearly match to labels and the labels to be readable.
One solution I imagined was using ports on the edge connections specified by
0:ne -> 2:nw [label="A"];
2:sw -> 0:se [label="B"];
however this produces
Other ideas? I am generating larger graphs with the same issue so a best solution would not be a completely ad-hoc manual placement of edges/labels.
Edit: A (still simplified) example of the larger generated graph is the following.
digraph {
size = "6,8.5";
ratio = "fill";
node [shape = circle];
node [fontsize = 24];
edge [fontsize = 24];
{graph [rank=same]; edge[color=invis];1;}
{graph [rank=same]; edge[color=invis];2 -> 0 -> 3 -> 4;}
0 -> 0 [label="6: 0.1764"];
0 -> 4 [label="4: 0.1304"];
0 -> 3 [label="5: 0.1551"];
0 -> 2 [label="7: 0.1489"];
0 -> 1 [label="Z: 0.3893"];
4 -> 0 [label="6: 0.1237"];
4 -> 3 [label="5: 0.05201"];
4 -> 2 [label="7: 0.15 "];
4 -> 1 [label="Z: 0.4585"];
3 -> 0 [label="6: 0.1658"];
3 -> 4 [label="4: 0.13 "];
3 -> 3 [label="5: 0.1038"];
3 -> 2 [label="7: 0.1616"];
3 -> 1 [label="Z: 0.4388"];
2 -> 0 [label="6: 0.1661"];
2 -> 4 [label="4: 0.1295"];
2 -> 3 [label="5: 0.2078"];
2 -> 2 [label="7: 0.1406"];
2 -> 1 [label="Z: 0.356 "];
1 -> 0 [label="6: 0.1103"];
1 -> 4 [label="4: 0.2591"];
1 -> 3 [label="5: 0.1382"];
1 -> 2 [label="7: 0.08581"];
1 -> 1 [label="Z: 0.1906"];
}
This produces:
which exhibits the same edge/label overlap problem in the simpler example above.
Other notes:
Answers from both ssteve and emden were very useful and have been upvoted. (thank you both!)
I am incorporating input from both and answering this question in its more complex version. I still do not feel like the solution is perfect, but it is the best I can generate so far. Future answers that improve on this (see below for what seems to be still lacking) and which address the larger graph version (see question) in a way that can be automated will be accepted in lieu of this answer.
First, the best solution so far in summary: turn labels in to xlabels for some of the edges (e.g. half of all bidirectional edges, chosen randomly) and randomly color edges and corresponding labels (via fontcolor
).
In specific, here is an instantiation of this solution, where edges are randomly red, green or black:
digraph {
size = "6,10.5";
ratio = "fill";
node [shape = circle];
node [fontsize = 24];
edge [fontsize = 24];
{graph [rank=same]; edge[color=invis];1;}
{graph [rank=same]; edge[color=invis];2 -> 0 -> 3 -> 4;}
0 -> 0 [label="6: 0.1764"];
0 -> 4 [xlabel="4: 0.1304" color=blue fontcolor=blue];
0 -> 3 [xlabel="5: 0.1551" color=green fontcolor=green];
0 -> 2 [label="7: 0.1489" color=red fontcolor=red];
0 -> 1 [label="Z: 0.3893"];
4 -> 0 [xlabel="6: 0.1237" color=green fontcolor=green];
4 -> 3 [xlabel="5: 0.05201 " color=green fontcolor=green];
4 -> 2 [xlabel="7: 0.15" color=blue fontcolor=blue];
4 -> 1 [label="Z: 0.4585" color=red fontcolor=red];
3 -> 0 [xlabel="6: 0.1658"];
3 -> 4 [xlabel="4: 0.13" color=red fontcolor=red];
3 -> 3 [label="5: 0.1038" color=blue fontcolor=blue];
3 -> 2 [xlabel="7: 0.1616"];
3 -> 1 [label="Z: 0.4388"];
2 -> 0 [label="6: 0.1661" color=blue fontcolor=blue];
2 -> 4 [xlabel="4: 0.1295" color=red fontcolor=red];
2 -> 3 [label="5: 0.2078" color=green fontcolor=green];
2 -> 2 [label="7: 0.1406"];
2 -> 1 [label="Z: 0.356 "];
1 -> 0 [label="6: 0.1103" color=red fontcolor=red];
1 -> 4 [label="4: 0.2591" color=blue fontcolor=blue];
1 -> 3 [label="5: 0.1382" color=green fontcolor=green];
1 -> 2 [label="7: 0.08581 "];
1 -> 1 [label="Z: 0.1906"];
}
This produces:
This is still not completely satisfactory because:
Other things I tried:
dir="both"
+ colorlist solution. Color edges randomly. And set labeldistance
randomly between 3 and 11 for head and tail labels to avoid label overlap at nodes. Result: this is harder to automate and still results in both edge label overlap and labels which are hard to trace back to the edges they correspond to. (see below)Here's an example of the last item in the "other things I tried" solutions list above.
size = "6,8.5";
ratio = "fill";
node [shape = circle];
node [fontsize = 24];
edge [fontsize = 24];
{graph [rank=same]; edge[color=invis];1;}
{graph [rank=same]; edge[color=invis];2 -> 0 -> 3 -> 4;}
0 -> 0 [label="6: 0.1764"];
0 -> 4 [dir="both", color="yellow:blue", labeldistance="5", headlabel=<<font color="yellow">4: 0.1304</font>>, taillabel=<<font color="blue">6: 0.1237</font>>];
0 -> 3 [dir="both", color="blue:black", labeldistance="8", headlabel=<<font color="blue">5: 0.1551</font>>, taillabel=<<font color="black">6: 0.1658</font>>];
0 -> 1 [label="Z: 0.3893"];
4 -> 1 [label="Z: 0.4585"];
3 -> 4 [dir="both", color="green:red", labeldistance="5", headlabel=<<font color="green">4: 0.13</font>>, taillabel=<<font color="red">5: 0.05201</font>>];
3 -> 3 [label="5: 0.1038"];
3 -> 1 [label="Z: 0.4388"];
2 -> 0 [dir="both", color="yellow:blue", labeldistance="11", headlabel=<<font color="yellow">6: 0.1661</font>>, taillabel=<<font color="blue">7: 0.1489</font>>];
2 -> 4 [dir="both", color="black:red", labeldistance="5", headlabel=<<font color="black">4: 0.1295</font>>, taillabel=<<font color="red">7: 0.15</font>>];
2 -> 3 [dir="both", color="blue:green", labeldistance="8", headlabel=<<font color="blue">5: 0.2078</font>>, taillabel=<<font color="green">7: 0.1616</font>>];
2 -> 2 [label="7: 0.1406"];
2 -> 1 [label="Z: 0.356 "];
1 -> 0 [label="6: 0.1103"];
1 -> 4 [label="4: 0.2591"];
1 -> 3 [label="5: 0.1382"];
1 -> 2 [label="7: 0.08581 "];
1 -> 1 [label="Z: 0.1906"];
}
This produces:
Other ideas / improvements solicited...