How can I draw diagonal lines between two nodes in Graphviz (Dot Language).
I want to draw the following shape.
I tried:
graph G {
V[pos="0,0"];
N[pos="40,40!"];
V -- N [label="NSUBJ"]
}
But it draws orthogonal lines. besides I want to draw multiple subgraphs with an order number as above!
It's possible to use pos attribute, but in that case you'd have to use neato and set pos for every node:
graph G {
V [pos = "0,100"]
N [pos = "50,0"]
S [pos = "200,100"]
VPC [pos = "150,0"]
NPC [pos = "250,0"]
V -- N [label="NSUBJ"]
S -- VPC
S -- NPC
}
Then use the following:
neato -n -Tpng -o test.png test.gv
The output is the following:
Also it's possible to make lines diagonal if use invisible nodes:
graph G {
node [shape=plaintext]
labelloc="b"
pencolor=transparent
subgraph cluster_1 {
label="(1)"
S_1 [label="S"]
VPC_1 [label="VPC"]
NPC_1 [label="NPC"]
V_1 [label="V"]
invis_1 [style=invis]
N_1 [label="N"]
V_1 -- invis_1 [style=invis]
V_1 -- N_1 [label="NSUBJ"]
S_1 -- VPC_1
S_1 -- NPC_1
}
subgraph cluster_2 {
label="(2)"
VPC_2 [label="VPC"]
V_2_2 [label="V"]
NPC_2 [label="NPC"]
V_2 [label="V"]
invis_2 [style=invis]
N_2 [label="N"]
V_2 -- invis_2 [style=invis]
V_2 -- N_2 [label="COPCOMP"]
VPC_2 -- V_2_2
VPC_2 -- NPC_2
}
}
Running this sequence of commands produces the following output:
ccomps -Cx test.gv | dot | gvpack -array_1 | neato -n2 -Tpng > test.png
Related
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:
I am trying to plot a regular graph with grViz in R like the below:
using the following code:
grViz("
graph {
# a graph statement
graph [layout = circo]
# a node statement
node [shape = circle,
style = filled,
color = grey,
fillcolor = orange];
nodesep=4
A; B; C; D; E; F; G; H;
# an edge statement
edge [color = grey]
A -- B
B -- C
C -- D
D -- E
E -- F
F -- G
G -- H
H -- A
A -- D
H -- E
B -- G
C -- F
}")
However, I cannot place the nodes in sequential order despite trying the different options for rankdir:
First the notation:
Let d[v] is a distance between root of the BFS tree and vertex v
This book states the following lemma:
During BFS the queue Q contains the vertices: v_1, v_2, ..., v_r, where
v_1 is the head of Q
v_r is the tail of Q
Then:
d[v_r] <= d[v_1] + 1
d[v_i] <= d[v_(i + 1)] for i = 1, 2, ..., r - 1
I do not understand first statement. In words it says: the last vertex v_r that BFS added to the queue has shorter distance to the root than the first vertex v_1 that we added to the queue. Visually:
root
/ \
v_1 v_2
/
v_3
/
v_r
How it can be possible?
You're misreading the statement.
d[v_r] <= d[v_1] + 1
means that the depth of v_r can be no greater than one more than the depth of v_1. v_r can be on the same level of the BFS tree or on the level below, but never farther than that. Relabeling your tree slightly,
root
/ \
v_a v_b
/
v_c
/
v_x
v_x can never be in the queue at the same time as v_a or v_b, but v_c can.
The only way d[v_r] could be less than d[v_1] is if you enqueued a previously-visited vertex.
How can I calculate neighborhood overlap between two nodes (i,j) in a weighted graph?
"...we define the neighborhood overlap of an edge connecting A and B to be the ratio: (number of nodes who are neighbors of both A and B)/ (number of nodes who are neighbors of at least one of A or B) where in the denominator we don’t count A or B themselves (even though A is a neighbor of B and B is a neighbor of A)."
https://www.cs.cornell.edu/home/kleinber/networks-book/networks-book-ch03.pdf
networkx has a built-in function to find the common neighbors of two nodes in a graph: common_neighbors. Now we only need to find the number of nodes that are neighbors to either A or B. Note that
| N(u) ⋃ N(v) | = |N(u)| + |N(v)| - | N(u) ⋂ N(v)|
where N(u) is the set of neighbors of u. Since we don't count A or B in the denominator, we need to subtract 2 from | N(u) ⋃ N(v) |.
def neighborhood_overlap(g, u, v):
n_common_nbrs = len(set(nx.common_neighbors(g, u, v)))
n_join_nbrs = g.degree(u) + g.degree(v) - n_common_nbrs - 2
return n_common_nbrs / n_join_nbrs
However, you still need to decide what happens if the denominator is 0, i.e., when the nodes A and B form a connected component of the graph.
I know the tag of the question is networkx, but since this is the first thing that pop ups on Google, on igraph the function would be
neighborhood_overlap <- function(g, node1, node2)
{
nh1 = neighborhood(graph=g, order=1, nodes=node1)[[1]]
nh2 = neighborhood(graph=g, order=1, nodes=node2)[[1]]
common = intersect(nh1, nh2)
commonl = length(common)
# | N(u) ⋃ N(v) | = |N(u)| + |N(v)| - | N(u) ⋂ N(v)|
union = degree(net_vc, v=node1) + degree(net_vc, v=node2) - commonl - 2
return(commonl/union)
}
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.