Graphviz Dot vertical alignment of nodes - graphviz

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
}

Related

How to prevent Graphviz from moving nodes to accomodate an edge

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).

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];
}

Generating First Set from the grammar

Algorithm for Finding first set:
Given a grammar with the rules A1 → w1, ..., An → wn, we can compute the Fi(wi) and Fi(Ai) for every rule as follows:
initialize every Fi(Ai) with the empty set
set Fi(wi) to Fi(wi) for every rule Ai → wi, where Fi is defined as follows:
Fi(a w' ) = { a } for every terminal a
Fi(A w' ) = Fi(A) for every nonterminal A with ε not in Fi(A)
Fi(A w' ) = Fi(A) \ { ε } ∪ Fi(w' ) for every nonterminal A with ε in Fi(A)
Fi(ε) = { ε }
add Fi(wi) to Fi(Ai) for every rule Ai → wi
do steps 2 and 3 until all Fi sets stay the same.
Grammar:
A -> B C c
A -> g D B
B -> EPSILON | b C D E
C -> D a B | c a
D -> EPSILON | d D
E -> g A f | c
This website generates the first set as follows:
Non-Terminal Symbol First Set
A g, ε, b, a, c, d
B ε, b
C a, c, ε, d
D ε, d
E g, c
But the algorithm says Fi(A w' ) = Fi(A) for every nonterminal A with ε not in Fi(A) so the First(A) according to this algorithm should not contain ε. First(A) = {g, b, a, c, d}.
Q: First(A) for the above grammar is = First(B) - ε U First(C) U {g} ?
This video also follows the above algorithm and do not choose ε.
First(B) = {ε, b}
First(D) = {ε, d}
First(E) = {g, c}
First(C) = {c, d, a}
First(A) = {b, g, c, d, a}
Example:
X -> Y a | b
Y -> c | ε
First(X) = {c, a, b}
First(Y) = {c, ε}
First(X) doesn't have ε because if you replace Y by ε, then First(Y a) is equal to First(ε a) = {a}
First set implementation on my github.
Edit: Updated link
https://github.com/amirbawab/EasyCC-CPP/blob/master/src/syntax/grammar/Grammar.cpp#L229
Computing the first and follow sets are both available on the new link above.

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.

Resources