How to prevent Graphviz from moving nodes to accomodate an edge - graphviz

I'm trying to reproduce the following figure using Graphviz:
Here's what I came up with so far:
digraph
{
rankdir="LR";
splines=polyline;
b [shape=circle, label="", style=filled, color=gray, width=0.2, height=0.2];
c [shape=box, label="C(s)", style=filled, color=gray, xlabel=controller];
d [shape=box, label="P(s)", style=filled, color=gray, xlabel=plant];
a [shape=point, color=transparent, label="a"];
e [shape=point, color=transparent, label="e"];
f [shape=point, color=transparent, label="f"];
c -> d [label="u"]
b -> c [label="e"]
a -> b [label="r"]
d -> e [dir=none]
e -> f [label="y"]
e -> b
}
This gets me close but not quite there yet, as dot seems to move the nodes to accomodate the edge from e to b and not the other way round:
How do I get it so that the edge from e to b bends around the nodes rather than displacing them?

(lots of trial-and-error)
used html records to contrail external label positioning
constraint=false & dir=back for e->b edge
turned off edge clipping as needed to improve edges
digraph {
// lines were rearranged just to simplify my comprehension
rankdir="LR";
splines=polyline;
//splines=ortho; // might work, if edges use xlabels
a [shape=point, color=transparent, label="a"];
b [shape=circle, label="", style=filled, fillcolor=gray, width=0.2, height=0.2];
// c & d use html tables to better position exterior labels
c [shape=plaintext label=<<TABLE BORDER="0" >
<TR> <TD>controller</TD> </TR>
<TR> <TD border="1" port="p0" bgcolor="grey">C(s)</TD> </TR>
</TABLE>>];
d [shape=plaintext label=<<TABLE BORDER="0">
<TR> <TD>plant</TD> </TR>
<TR> <TD border="1" port="p0" bgcolor="grey">C(s)</TD> </TR>
</TABLE>>];
e [shape=point width=.01 label=""];
f [shape=point width=.00 label="" color=white];
a -> b [label="r"]
b -> c:p0 [label="e"]
c:p0:e -> d:p0:w [label="u"]
d:p0 -> e [dir=none headclip=false]
e -> f [label="y" tailclip=false headclip=false]
b -> e [dir=back constraint=false]
}
Giving:

Based on the above, wouldn't changing:
e -> b
into
e -> b [dir=none constraint=false]
i.e.
digraph
{
rankdir="LR";
splines=polyline;
b [shape=circle, label="", style=filled, color=gray, width=0.2, height=0.2];
c [shape=box, label="C(s)", style=filled, color=gray, xlabel=controller];
d [shape=box, label="P(s)", style=filled, color=gray, xlabel=plant];
a [shape=point, color=transparent, label="a"];
e [shape=point, color=transparent, label="e"];
f [shape=point, color=transparent, label="f"];
c -> d [label="u"]
b -> c [label="e"]
a -> b [label="r"]
d -> e [dir=none]
e -> f [label="y"]
e -> b [dir=none constraint=false]
}
as on: http://www.webgraphviz.com/
I get:
(Disadvantage we still have a small gap at the line labeled y).

Related

how to sort by levels in graphviz

I want to separate the rectangles like this
or (3 items per line)
You were quite close. Most of the changes are just for (my) clarity. rank=same and dir=back
// https://stackoverflow.com/questions/72449201/how-to-sort-by-levels-in-graphviz
digraph {
{rank=same; a -> b -> c}
{rank=same; edge [dir=back] f -> e -> d }
{rank=same; g -> h -> i}
{rank=same; edge [dir=back] l -> k -> j }
c -> d
f -> g
i->j
}
Giving:

How to make primary arrows straight with Graphviz when there are reverse links to the same nodes?

Given the following graph:
digraph g {
rankdir=LR;
node [shape=box];
A;
{ rank = same;
B; C; D; E;
};
A -> B [label="144"];
B -> A [label="261"; constraint=false];
B -> C [label="144"];
C -> B [label="261"; constraint=false];
C -> D [label="144"];
D -> C [label="261"; constraint=false];
D -> E [label="144"];
E -> D [label="261"; constraint=false];
B -> n1 [label="144"];
n1 -> B [label="261"; constraint=false];
n1 -> n2 [label="144"];
n2 -> n1 [label="261"; constraint=false];
C -> n3 [label="144"];
n3 -> C [label="261"; constraint=false];
n3 -> n4 [label="144"];
n4 -> n3 [label="261"; constraint=false];
D -> n5 [label="144"];
n5 -> D [label="261"; constraint=false];
n5 -> n6 [label="144"];
n6 -> n5 [label="261"; constraint=false];
E -> n7 [label="144"];
n7 -> E [label="261"; constraint=false];
n7 -> n8 [label="144"];
n8 -> n7 [label="261"; constraint=false];
};
The resulting output is:
This is almost what I want (in particular it took a lot of trouble to figure out how to make that straight line of letter nodes in the second rank), but my problem is with the way that the edge arrows are drawn in the vertical nodes.
What I want is for the "forward" arrow (the one going right/down in the graph, and the one without constraint=false) to be straight, and the "reverse" arrow (going left/up in the graph, with constraint=false) to be curved. And in both cases I want the labels to be out of the way of each other. (For the vertical arrows, this probably means pushing the label to the other side.)
I've tried playing with setting groups and weights but so far nothing has seemed to help swap the vertical arrows. And I haven't found anything that will move the label to the other side.
I also tried using the splines setting but it doesn't do anything.
Managing edge placement is very difficult.
Does this meet your requirements - it uses ports to tweak the edge placement.
digraph g {
rankdir=LR;
node [shape=box];
A;
{ rank = same;
B; C; D; E;
};
A -> B [label="144"];
B -> A [label="261"; constraint=false];
B -> C [label="144"];
C -> B:se [label="261"; constraint=false];
C -> D [label="144"];
D -> C:se [label="261"; constraint=false];
D -> E [label="144"];
E -> D:se [label="261"; constraint=false];
B -> n1 [label="144"];
n1 -> B [label="261"; constraint=false];
n1 -> n2 [label="144"];
n2 -> n1 [label="261"; constraint=false];
C -> n3 [label="144"];
n3 -> C [label="261"; constraint=false];
n3 -> n4 [label="144"];
n4 -> n3 [label="261"; constraint=false];
D -> n5 [label="144"];
n5 -> D [label="261"; constraint=false];
n5 -> n6 [label="144"];
n6 -> n5 [label="261"; constraint=false];
E -> n7 [label="144"];
n7 -> E [label="261"; constraint=false];
n7 -> n8 [label="144"];
n8 -> n7 [label="261"; constraint=false];
}

Graphviz Dot vertical alignment of nodes

I got this dot graph and want the nodes A and D, B and E and C and F to be aligned. Here is the related dot code:
digraph{
A
B
C
D
E
F
{rank = same; B; C}
{rank = same; E; F}
A -> B [label="2", weight=2]
A -> C [label="0", style=dashed, weight=2]
B -> C [label="0", style=dashed, weight=2]
B -> D [label="2", style=dashed, weight=2]
C -> D [label="0", weight=2]
D -> E [label="1", style=dashed, weight=2]
D -> F [label="0", weight=2]
E -> F [label="0", weight=2]
F -> A
}
As you can see I already tried to apply weights to the edges, but that didn't work out
It is possible to use the group attribute of the nodes to suggest aligning the edges between nodes of the same group in a straight line.
Declare the nodes with the group attribute:
A [group=g1]
{rank = same; B[group=g2]; C[group=g3]}
D [group=g1]
{rank = same; E[group=g2]; F[group=g3]}
Then make sure all of those nodes have an (invisible) edge between them:
edge[style=invis];
A -> D
B -> E
C -> F
Everything together:
digraph G {
A [group=g1]
{rank = same; B[group=g2]; C[group=g3]}
D [group=g1]
{rank = same; E[group=g2]; F[group=g3]}
A -> B [label="2", weight=2]
A -> C [label="0", style=dashed, weight=2]
B -> C [label="0", style=dashed, weight=2]
B -> D [label="2", style=dashed, weight=2]
C -> D [label="0", weight=2]
D -> E [label="1", style=dashed, weight=2]
D -> F [label="0", weight=2]
E -> F [label="0", weight=2]
F -> A
edge[style=invis];
A -> D
B -> E
C -> F
}

Topological sort, but with a certain kind of grouping

It seems this must be a common scheduling problem, but I don't see the solution or even what to call the problem. It's like a topological sort, but different....
Given some dependencies, say
A -> B -> D -- that is, A must come before B, which must come before D
A -> C -> D
there might be multiple solutions to a topological sort:
A, B, C, D
and A, C, B, D
are both solutions.
I need an algorithm that returns this:
(A) -> (B,C) -> (D)
That is, do A, then all of B and C, then you can do D. All the ambiguities or don't-cares are grouped.
I think algorithms such as those at Topological Sort with Grouping won't correctly handle cases like the following.
A -> B -> C -> D -> E
A - - - > M - - - > E
For this, the algorithm should return
(A) -> (B, C, D, M) -> (E)
This
A -> B -> D -> F
A -> C -> E -> F
should return
(A) -> (B, D, C, E) -> (F)
While this
A -> B -> D -> F
A -> C -> E -> F
C -> D
B -> E
should return
(A) -> (B, C) -> (D, E) -> (F)
And this
A -> B -> D -> F
A -> C -> E -> F
A -> L -> M -> F
C -> D
C -> M
B -> E
B -> M
L -> D
L -> E
should return
(A) -> (B, C, L) -> (D, E, M) -> (F)
Is there a name and a conventional solution to this problem? (And do the algorithms posted at Topological Sort with Grouping correctly handle this?)
Edit to answer requests for more examples:
A->B->C
A->C
should return
(A) -> (B) -> (C). That would be a straight topological sort.
And
A->B->D
A->C->D
A->D
should return
(A) -> (B, C) -> (D)
And
A->B->C
A->C
A->D
should return
(A) -> (B,C,D)
Let G be the transitive closure of the graph. Let G' be the undirected graph that results from removing the orientation from G and taking the complement. The connected components of the G' are the sets you are looking for.

Family tree layout with Dot/GraphViz

I am trying to draw a family tree with Dot and GraphViz.
This is what I currently have:
# just graph set-up
digraph simpsons {
ratio = "auto"
mincross = 2.0
# draw some nodes
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
# creating tiny nodes w/ no label, no color
"ParentsHomer" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsMarge" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsBart" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
# draw the edges
"Abraham" -> "ParentsHomer" [dir=none, weight=1] ;
"Mona" -> "ParentsHomer" [dir=none, weight=1] ;
"ParentsHomer" -> "Homer" [dir=none, weight=2] ;
"ParentsHomer" -> "Herb" [dir=none, weight=2] ;
"Clancy" -> "ParentsMarge" [dir=none, weight=1] ;
"Jackeline" -> "ParentsMarge" [dir=none, weight=1] ;
"ParentsMarge" -> "Marge" [dir=none, weight=2] ;
"ParentsMarge" -> "Patty" [dir=none, weight=2] ;
"ParentsMarge" -> "Selma" [dir=none, weight=2] ;
"Homer" -> "ParentsBart" [dir=none, weight=1] ;
"Marge" -> "ParentsBart" [dir=none, weight=1] ;
"ParentsBart" -> "Bart" [dir=none, weight=2] ;
"ParentsBart" -> "Lisa" [dir=none, weight=2] ;
"ParentsBart" -> "Maggie" [dir=none, weight=2] ;
"Selma" -> "Ling" [dir=none, weight=2] ;
}
If I run this through dot (dot simpsons.dot -Tsvg > simpsons.svg),
I get the following layout:
However, I'd like the edges to be more "family tree"-like: a T-junction between two married persons with the vertical line of the T again branching in an upside-down T-junction with small subdivisions for each of the children, like this mock-up, done in KolourPaint:
What is the dot syntax that I have to use to achieve this?
Try the following:
digraph simpsons {
subgraph Generation0 {
rank = same
Abraham [shape = box, color = blue]
Mona [shape = box, color = pink]
AbrahamAndMona [shape = point]
Abraham -> AbrahamAndMona [dir = none]
AbrahamAndMona -> Mona [dir = none]
Clancy [shape = box, color = blue]
Jackeline [shape = box, color = pink]
ClancyAndJackeline [shape = point]
Clancy -> ClancyAndJackeline [dir = none]
ClancyAndJackeline -> Jackeline [dir = none]
}
subgraph Generation0Sons {
rank = same
AbrahamAndMonaSons [shape = point]
HerbSon [shape = point]
HomerSon [shape = point]
HerbSon -> AbrahamAndMonaSons [dir = none]
HomerSon -> AbrahamAndMonaSons [dir = none]
MargeSon [shape = point]
PattySon [shape = point]
SelmaSon [shape = point]
MargeSon -> PattySon [dir = none]
PattySon -> SelmaSon [dir = none]
}
AbrahamAndMona -> AbrahamAndMonaSons [dir = none]
ClancyAndJackeline -> PattySon [dir = none]
subgraph Generation1 {
rank = same
Herb [shape = box, color = blue]
Homer [shape = box, color = blue]
Marge [shape = box, color = pink]
Patty [shape = box, color = pink]
Selma [shape = box, color = pink]
HomerAndMarge [shape = point]
Homer -> HomerAndMarge [dir = none]
Marge -> HomerAndMarge [dir = none]
}
HerbSon -> Herb [dir = none]
HomerSon -> Homer [dir = none]
MargeSon -> Marge [dir = none]
PattySon -> Patty [dir = none]
SelmaSon -> Selma [dir = none]
subgraph Generation1Sons {
rank = same
BartSon [shape = point]
LisaSon [shape = point]
MaggieSon [shape = point]
BartSon -> LisaSon [dir = none]
LisaSon -> MaggieSon [dir = none]
}
HomerAndMarge -> LisaSon [dir = none]
subgraph Generation2 {
rank = same
Bart [shape = box, color = blue]
Lisa [shape = box, color = pink]
Maggie [shape = box, color = pink]
Ling [shape = box, color = blue]
}
Selma -> Ling [dir = none]
BartSon -> Bart [dir = none]
LisaSon -> Lisa [dir = none]
MaggieSon -> Maggie [dir = none]
}
Produces:
I don’t think you can take an arbitrary family tree and auto-generate a dot file where it always looks good in GraphViz.
But I think you can always make it look good if you:
Use the rank=same other answers mentioned to get the 'T' connections
desired by the OP
Use the ordering trick Brian Blank did to prevent weird lines
Assume no second marriages and half-siblings
Draw only a
subset of the tree that obeys the following rules:
Let S be the “center” person
If S has siblings, make sure S is to right of all of them.
If S has a spouse and the spouse has siblings, make sure the spouse is to the left of all his/her siblings.
Don’t show nephews, nieces, aunts or uncles of S or S’s spouse
Don’t show spouses of siblings
Don’t show spouses of spouse’s siblings
Show children of S, but not their spouses or children
Show parents of S and parents of spouse
This will end up showing no more than 3 generations at once, with S in the middle generation.
In the picture below S=Homer (slightly modified from Brian Blank's version):
digraph G {
edge [dir=none];
node [shape=box];
graph [splines=ortho];
"Herb" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Homer" [shape=box, regular=0, color="blue", style="bold, filled" fillcolor="lightblue"] ;
"Marge" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Clancy" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Jackeline" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Abraham" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Mona" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Patty" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Selma" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Bart" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Lisa" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Maggie" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
a1 [shape=diamond,label="",height=0.25,width=0.25];
b1 [shape=circle,label="",height=0.01,width=0.01];
b2 [shape=circle,label="",height=0.01,width=0.01];
b3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Abraham -> a1 -> Mona};
{rank=same; b1 -> b2 -> b3};
{rank=same; Herb; Homer};
a1 -> b2
b1 -> Herb
b3 -> Homer
p1 [shape=diamond,label="",height=0.25,width=0.25];
q1 [shape=circle,label="",height=0.01,width=0.01];
q2 [shape=circle,label="",height=0.01,width=0.01];
q3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Homer -> p1 -> Marge};
{rank=same; q1 -> q2 -> q3};
{rank=same; Bart; Lisa; Maggie};
p1 -> q2;
q1 -> Bart;
q2 -> Lisa;
q3 -> Maggie;
x1 [shape=diamond,label="",height=0.25,width=0.25];
y1 [shape=circle,label="",height=0.01,width=0.01];
y2 [shape=circle,label="",height=0.01,width=0.01];
y3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Clancy -> x1 -> Jackeline};
{rank=same; y1 -> y2 -> y3};
{rank=same; Patty; Selma; Marge};
x1 -> y2;
y1 -> Marge;
y2 -> Patty;
y3 -> Selma;
}
This yields the following tree by GraphViz (with annotations I added with Power Point):
Gramps (www.gramps-project.org) generates dot files for family trees, with or without marriage nodes.
There is also a way to see this in the Gramps interface itself. http://gramps-project.org/wiki/index.php?title=Graph_View
So I would say, look at the output of your family tree as created by Gramps
Although you can't control node placement, I found you can help node placement by ordering the nodes in a different order. I re-ordered some of the nodes as shown below and got a graph that produced no cross-overs.
The following code:
digraph G {
edge [dir=none];
node [shape=box];
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
a1 [shape=circle,label="",height=0.01,width=0.01];
b1 [shape=circle,label="",height=0.01,width=0.01];
b2 [shape=circle,label="",height=0.01,width=0.01];
b3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Abraham -> a1 -> Mona};
{rank=same; b1 -> b2 -> b3};
{rank=same; Herb; Homer};
a1 -> b2
b1 -> Herb
b3 -> Homer
p1 [shape=circle,label="",height=0.01,width=0.01];
q1 [shape=circle,label="",height=0.01,width=0.01];
q2 [shape=circle,label="",height=0.01,width=0.01];
q3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Homer -> p1 -> Marge};
{rank=same; q1 -> q2 -> q3};
{rank=same; Bart; Lisa; Maggie};
p1 -> q2;
q1 -> Bart;
q2 -> Lisa;
q3 -> Maggie;
x1 [shape=circle,label="",height=0.01,width=0.01];
y1 [shape=circle,label="",height=0.01,width=0.01];
y2 [shape=circle,label="",height=0.01,width=0.01];
y3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Clancy -> x1 -> Jackeline};
{rank=same; y1 -> y2 -> y3};
{rank=same; Marge; Patty; Selma};
{rank=same; Bart; Ling}
x1 -> y2;
y1 -> Marge;
y2 -> Patty;
y3 -> Selma;
Selma -> Ling;
}
now produces this:
I don't fully understand why it's working, but here is the thought process into the changes that I made.
I placed Clancy/Jackeline before Abraham/Mona thinking that they were on the wrong side. This changed the picture, but still wasn't perfect.
I placed Homer/Marge first thinking that the software had to consider these pieces first and maybe place all other nodes relative to Homer/Marge. This further helped, but still wasn't perfect.
Herb was still mis-placed, so I put Herb first so that graphviz might consider placement of herb first.
It worked, but I still can't devise an algorithm that would ensure consistent trees with no overlapping edges. I feel that graphviz should do a better job without these hints. I don't know the algorithm used, but if they consider an objective function to minimize or eliminate overlapping edges, it should be possible to devise a better algorithm.
To do this in graphviz is fairly straightforward; there are a couple of syntax patterns you need:
(i) syntax to represent the line-to-line connection (the "T"-junction in your plots above); (ii) syntax to enforce the hierarchical structure (i.e., nodes of same generation on the same plane on the vertical axis). It's easier to show:
digraph G {
nodesep=0.6;
edge [arrowsize=0.3];
"g1" -> "g2" -> "g3" -> "g4"
{ rank = same;
"g1"; "King"; "ph1"; "Queen";
};
{ rank = same;
"g2"; "ph2"; "ph2L"; "ph2R"; "ph2LL"; "ph2RR"
};
{ rank = same;
"g3"; "ps1"; "ps2"; "pr1"; "pr2"
};
"King" -> "ph1" [arrowsize=0.0];
"ph1" -> "Queen" [arrowsize=0.0];
"ph1" -> "ph2" [arrowsize=0.0];
"ph2LL" -> "ph2L" [arrowsize=0.0];
"ph2L" -> "ph2" [arrowsize=0.0];
"ph2" -> "ph2R" [arrowsize=0.0];
"ph2R" -> "ph2RR" [arrowsize=0.0];
"ph2LL" -> "ps1" [arrowsize=0.0];
"ph2L"-> "pr1" [arrowsize=0.0];
"ph2R" -> "ps2" [arrowsize=0.0];
"ph2RR" -> "pr2" [arrowsize=0.0];
}
The code above will produce the graph below (i omitted the code i used to color the nodes). I left vislble the "guide" on the left (g1->g2....) just to show you how i enforced the positions among nodes of equal rank, you'll probably want to make it invisible in your own plots. Finally, the nodes with the labels beginning with 'ph' are the placeholder nodes for the "T-junctions."
I'm almost there, inspired by an old response on the graphviz-interest mailinglist and doug's answer.
The following code:
digraph G {
edge [dir=none];
node [shape=box];
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
a1 [shape=circle,label="",height=0.01,width=0.01];
b1 [shape=circle,label="",height=0.01,width=0.01];
b2 [shape=circle,label="",height=0.01,width=0.01];
b3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Abraham -> a1 -> Mona};
{rank=same; b1 -> b2 -> b3};
{rank=same; Herb; Homer};
a1 -> b2
b1 -> Herb
b3 -> Homer
p1 [shape=circle,label="",height=0.01,width=0.01];
q1 [shape=circle,label="",height=0.01,width=0.01];
q2 [shape=circle,label="",height=0.01,width=0.01];
q3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Homer -> p1 -> Marge};
{rank=same; q1 -> q2 -> q3};
{rank=same; Bart; Lisa; Maggie};
p1 -> q2;
q1 -> Bart;
q2 -> Lisa;
q3 -> Maggie;
x1 [shape=circle,label="",height=0.01,width=0.01];
y1 [shape=circle,label="",height=0.01,width=0.01];
y2 [shape=circle,label="",height=0.01,width=0.01];
y3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Clancy -> x1 -> Jackeline};
{rank=same; y1 -> y2 -> y3};
{rank=same; Marge; Patty; Selma};
{rank=same; Bart; Ling}
x1 -> y2;
y1 -> Marge;
y2 -> Patty;
y3 -> Selma;
Selma -> Ling;
}
now produces this:
So, looks good except for that strange edge around Homer.If I could find a way to move Abraham, Mona and Herb to the left hand side of the picture then I would have a perfectly aligned picture.
Any ideas on how to achieve that?

Resources