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:
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];
}
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
}
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.
Is it possible and practical for Mathematica to draw something like this (being created by Graphviz):
This is the best that I can get (but the shape and style are not satisfying):
Code:
GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D,
"went"}, {C -> C, "loop"}}, VertexLabeling -> True,
DirectedEdges -> True]
You can do something like this using VertexRenderingFunction.
GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}},
DirectedEdges -> True,
VertexRenderingFunction -> ({{White, Disk[#, 0.15]},
AbsoluteThickness[2], Circle[#, 0.15],
If[MatchQ[#2, A | B], Circle[#, 0.12], {}], Text[#2, #]} &)]
Method Updated February 2015
To preserve the ability to interactively rearrange the graph with the drawing tools (double click) one must keep the vertex graphics inside of GraphicsComplex, with indexes rather than coordinates. I believe one could do this from VertexRenderingFunction using an incrementing variable but it seems easier an possibly more robust to do it with post-processing. This works in versions 7 and 10 of Mathematica, presumably 8 and 9 as well:
GraphPlot[
{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}},
DirectedEdges -> True
] /.
Tooltip[Point[n_Integer], label_] :>
{{White, Disk[n, 0.15]},
Black, AbsoluteThickness[2], Circle[n, 0.15],
If[MatchQ[label, A | B], Circle[n, 0.12], {}], Text[label, n]}
There's no need for interactive placement to get your vertices at the desired location as mr.Wizard suggests in his answer. You can use VertexCoordinateRules for that:
GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}},
DirectedEdges -> True,
VertexRenderingFunction ->
({{White, Disk[#, 0.15]}, AbsoluteThickness[2], Circle[#, 0.15],
If[MatchQ[#2, A | B], Circle[#, 0.12], {}], Text[#2, #]} &),
VertexCoordinateRules ->
{A -> {0, 0}, C -> {0.75, 0},B -> {1.5, 0.25}, D -> {1.5, -0.25}}
]