I'm trying to make an Entity-relationship diagram using the Graphviz DOT language. In my model I have a self-referencing relationship and here I would like the edges to be orthogonal, i.e. consist only of vertical and horizontal lines. Currently I have this diagram:
digraph G {
edge [arrowhead = none]
Entity [shape = box]
Relationship [shape = diamond]
Entity -> Relationship [headport = w, tailport = w]
Relationship -> Entity [headport = e, tailport = e]
}
I tried adding graph [splines = ortho] but then the diagram renders like this:
Any ideas? I'm using version 2.43.0 of DOT.
The ortho implementation is rather flawed, Here is a DIY version. It adds invisible point-shaped nodes to each side of the two ER nodes and then draws edges to connect everything to look "ortho".
digraph G {
splines=false
edge [arrowhead = none]
{ rank=same
Entity [shape = box]
node [shape=point label="" style=invis]
x1 [group=G1]
x2 [group=g2]
x1 -> Entity [tailclip=false]
Entity -> x2 [headclip=false]
}
{ rank=same
Relationship [shape = diamond]
node [shape=point label="" style=invis]
y1 [group=G1]
y2 [group=g2]
y1 -> Relationship [tailclip=false]
Relationship -> y2 [headclip=false]
}
x1 -> y1 [headclip=false tailclip=false]
x2 -> y2 [headclip=false tailclip=false]
}
Giving:
Related
For my flowchart, I have a vertical chart detailing the data flow. However on the downward arrows, I want to add side arrows to describe where the missing data is going. How do I do this? I can't see it in any of the documentation and examples because it tends to be about far more complex things, and I know this is a very basic task!
library(DiagrammeR)
grViz("digraph flowchart {
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle, fixedsize = false, width = 1]
1 [label = 'data (100%)']
2 [label = 'data (90.4%)']
3 [label = 'data \\ndata (83.3%)']
4 [label = 'data (66%)']
7 [label = 'data (100%)']
8 [label = 'data (74.4%)']
9 [label = 'data (69.6%)']
10 [label = 'data (55.4%)']
1 -> 2 -> 3 -> 4;
7 -> 8 -> 9 -> 10
} ")
This gives me two side by side panels, but I want arrows coming off the downward arrows where I can put the n for missing data.
The standard trick is to create invisible dummy nodes, then break up each edge into two parts: 1) source -> dummy, and 2) dummy -> target:
library(DiagrammeR)
grViz("digraph flowchart {
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle, fixedsize = false, width = 1]
1 [label = 'data (100%)']
2 [label = 'data (74.4%)']
3 [label = 'data (69.6%)']
4 [label = 'data (55.4%)']
m1 [label = 'missing (25.6%)']
m2 [label = 'missing (4.8%)']
node [shape=none, width=0, height=0, label='']
p1 -> 2; p2 -> 3 -> 4;
{rank=same; p1 -> m1}
{rank=same; p2 -> m2}
edge [dir=none]
1 -> p1; 2 -> p2;
}")
I shortened your example for demonstration purposes. In the above, p1 and p2 are invisible dummy nodes. There are three sets of edges:
Downward directed edges from dummy nodes to targets (e.g., p1 -> 2)
Horizontal directed edges from dummy nodes to "missing" nodes. Edge direction is imposed through rank=same.
Undirected edges from source to the dummy nodes
I am currently trying to create a flowchart using DiagrammeR
library(DiagrammeR)
grViz("
digraph g {
subgraph cluster_0 {
style=filled;
color=lightgrey;
label= To_Accrue
node [shape = rectangle, style = filled, fillcolor = Linen]
A
B
C
A->B->C
}
subgraph cluster_1 {
style=filled;
color=crimson;
label= Y
node [style=filled,color=blue, shape=folder]
1
2
3
1->2->3
}
}
")
Please refer to the link File to see what it currently generates (Tab-Sheet1). I was wondering if there is a way to achieve the desired output (Tab-Desired Output).
Thank you in advance.
The trick here is to use a blank node (called bnode here), groups (g1 in this example), and ranks (rank=same ...) to force the positioning and appearance you want. Nodes with the same group should appear in the same vertical plane, and nodes with the same rank will appear in the same horizontal plane.
library(DiagrammeR)
grViz("
digraph g {
subgraph cluster_0 {
style=filled;
color=lightgrey;
label= To_Accrue
node [shape = rectangle, style = filled, fillcolor = Linen]
bnode [style = invis, shape=point, width = 0, group=g1]
A [group=g1]
B
C [group=g1]
edge [arrowhead='none']
A->bnode
edge [arrowhead='normal']
B->bnode
bnode->C
{rank=same B bnode}
}
subgraph cluster_1 {
style=filled;
color=crimson;
label= Y
node [style=filled,color=blue, shape=folder]
1
2
3
1->2->3
}
}
")
I also edited the original code to generate the following to approach a rotational scenario.
enter image description here
library(DiagrammeR)
grViz("
digraph g {
subgraph cluster_0 {
style=filled;
color=lightgrey;
label= To_Accrue
node [shape = rectangle, style = filled, fillcolor = Linen]
a1 [style = invis, shape=point, width = 0, group=g1]
a2 [style = invis, shape=point, width = 0, group=g2]
a3 [style = invis, shape=point, width = 0, group=g3]
A [group=g1]
B
C [group=g1]
C [group=g2]
D
E [group=g2]
edge [arrowhead='none']
A->a1
C->a2
E->a3
edge [arrowhead='normal']
B->a1 {rank=same B a1}
a1->C
D->a2 {rank=same D a2}
a2->E
F->a3 {rank=same F a3}
a3->G
}
subgraph cluster_1 {
style=filled;
color=crimson;
label= Y
node [style=filled,color=blue, shape=folder]
1
2
3
1->2->3
}
}
")
In DFS you can count the elements by initializating two counters and incrementing them in the DFS-VISIT procedure(+1 node every time the procedure is called and +1 arc everytime that the adjacency list is explored). I was wondering How to obtain the same result in BFS.
This is the BFS pseudocode from Cormen's "Introduction to Algorithms", where G is the graph, s is the source node, d is the distance and π is the father node. How can i modify it to obtain the number of nodes and arcs in G?
BFS(G, s)
for each node u ∈ G.V - {s}
u.color = white
u.d = ∞
u.π = NIL
s.color = GRAY
s.d = 0
s.π = NIL
Q = Ø
ENQUEUE(Q, s)
while Q != Ø
u = DEQUEUE(Q)
for each v ∈ G.Adj[u]
if v.color == WHITE
v.color = GRAY
v.d = u.d + 1
v.π = u
ENQUEUE(Q, v)
u.color = BLACK
Well, both the adjacency list traversal and new vertex(node) discovery are done in the final while loop of your pseudocode. So, something like the modification given below could work.
numArcs = 0
numNodes = 0
while Q != Ø
u = DEQUEUE(Q)
numNodes += 1
for each v ∈ G.Adj[u]
numArcs += 1
if v.color == WHITE
v.color = GRAY
v.d = u.d + 1
v.π = u
ENQUEUE(Q, v)
u.color = BLACK
Note that if you want to count all the arcs, the incrementation of numArcs should be outside the scope of the if statement that follows it, as that if statement is only entered when the destination node is not previously enqueued.
Notice also that this algorithm gives only the number of arcs and nodes in the connected component including the starting node s. So, unless your BFS algorithm is modified to handle the case of the graph having multiple connected components, this algorithm will not find out all the nodes and arcs in a graph that is not connected.
I'd like to draw a network, as a fully connected directed graph, with arbitrary number of nodes and edges as shown in the pic.
What would be the easy way to draw this with GraphViz?
graphviz gallery has a very similar entry, with fancy graphic: it's as easy as replacing the names start, etc... with your own in the generating script. Feed it to dot program.
digraph G {bgcolor="red:cyan" gradientangle=0
subgraph cluster_0 {
style=filled;
color=lightgrey;
fillcolor="blue:yellow";
gradientangle=90;
node [fillcolor="yellow:green" style=filled gradientangle=270] a0;
node [fillcolor="green:red"] a1;
node [fillcolor="red:cyan"] a2;
node [fillcolor="cyan:blue"] a3;
a0 -> a1 -> a2 -> a3;
label = "process #1";
}
subgraph cluster_1 {
node [fillcolor="yellow:magenta"
style=filled gradientangle=270] b0;
node [fillcolor="magenta:cyan"] b1;
node [fillcolor="cyan:red"] b2;
node [fillcolor="red:blue"] b3;
b0 -> b1 -> b2 -> b3;
label = "process #2";
color=blue
fillcolor="blue:yellow";
style=filled;
gradientangle=90;
}
start -> a0;
start -> b0;
a1 -> b3;
b2 -> a3;
a3 -> a0;
a3 -> end;
b3 -> end;
start [shape=Mdiamond ,
fillcolor="yellow:brown",
gradientangle=90,
style=radial];
end [shape=Msquare,
fillcolor="orange:blue",
style=radial,
gradientangle=90];
}
I have to draw a small finite state machine that has some reflexive transitions (meaning the start and the end state of the transition are equal.
The problem is that rendering that in Graphviz has ugly results.
digraph finite_state_machine {
edge [fontsize=11];
S0 -> S0 [label = "td=1\n-/e2"];
S0 -> S1 [label = "td=3 \n-/e3" ];
S1 -> S0 [label = "td=3\n-/-\nt=0"];
S0 -> S2 [label = "P:i1/e4"];
S2 -> S0 [label = "td=0\n-/-" ];
S0 -> S0 [label = "i1/e1\ntd+=1"];
}
Is there a way to make this look a little better?
BTW: I tried head/tailport but they don't work on my version of Graphviz (1.13 on Mac OS X)
I am not limited to the dot engine, I only want a nice looking graph and don't care about the renderer/language.
Thanks a lot
So, if found a workaround, but not really an answer to my problem.
The trick is to have an invisible node that connections to the starting state. the starting state is then not the top of the hierarchy and one has a little bit more freedom in placing the nodes. Also then the head/tailport attributes work as they should.
The result is - if not a pretty as I would like it to be - ok to look at.
digraph finite_state_machine {
edge [fontsize=7];
fontsize = 11;
rankdir=LR;
{rank = same;null}
{rank = same; S0}
{rank = same; S1 S2}
nodesep = 1;
ranksep = 1;
null [shape = plaintext label=""];
null -> S0;
S0 -> S0 [label = "td=1\n-/e2", tailport = n, headport = n];
S0 -> S1 [label = "td=3 \n-/e3" ];
S1 -> S0 [label = "td=3\n-/-\nt=0"];
S0 -> S2 [label = "P:i1/e4"];
S2 -> S0 [label = "td=0\n-/-" ];
S0 -> S0 [label = "i1/e1\ntd+=1" headport = s tailport = s];
}
a rendering of the state machine http://img532.imageshack.us/img532/4083/previewd.png
While this works (for this particular example) I would still very much like some advice on dot/Graphviz or an alternative for rendering finite state machines in a pleasing way.