-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathtarjan.py
113 lines (90 loc) · 3.09 KB
/
tarjan.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
## Tarjan's strongly connected components algorithm
# References:
# https://epubs.siam.org/doi/abs/10.1137/0201010
# https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
from snap import PNGraph, PNEANet, TFIn, TNEANet, TIntStrH, DrawGViz, gvlNeato
import os
import graph_tools
# prepares data structures and runs the core algorithm
def tarjan(trust_graph, thresh):
global node_count
global component_count
global index
global lowlink
global stack
global component
global threshold
component = {} # maps nodes to components
index = {} # maps nodes to the index given during Tarjan execution
lowlink = {} # maps nodes to the lowest-indexed node reachable from it
stack = []
node_count = 0 # number of nodes visited
component_count = 0 # number of components found
threshold = thresh # sensitivity of the algorithm
# Set data structures
# Before running the algorithm, each node has -1 as index, lowlink and component
for node in trust_graph.Nodes():
n_id = node.GetId()
component[n_id] = -1
index[n_id] = -1
lowlink[n_id] = -1
# Visit each unvisited node
for node in trust_graph.Nodes():
n_id = node.GetId()
if index[n_id] == -1:
visit(n_id, trust_graph)
return (component, component_count)
def visit(u, trust_graph):
global node_count
global component_count
global index
global lowlink
global stack
global component
global threshold
index[u] = node_count
lowlink[u] = node_count
node_count = node_count + 1
stack.append(u)
U = trust_graph.GetNI(u)
# Visit all nodes v which are neighbors of u
for v in U.GetOutEdges():
eid_u = trust_graph.GetEId(u, v)
trust_u = trust_graph.GetFltAttrDatE(eid_u, "Trust")
# Sensitivity threshold of the algorithm.
# A number closer to 1 makes it more restrictive.
if trust_u < threshold:
continue
# If v is unvisited, visit it.
if index[v] == -1:
visit(v, trust_graph)
lowlink[u] = min(lowlink[u], lowlink[v])
elif v in stack:
lowlink[u] = min(lowlink[u], index[v])
# If u is the lowest node reachable from itself, form a component.
if lowlink[u] == index[u]:
while True:
w = stack.pop()
component[w] = component_count
if (w == u):
break
component_count += 1
if __name__ == '__main__':
# Sample graph for testing.
G = PNEANet.New()
# for i in range(0,7):
# G.AddNode(i)
edges = [(0,1), (1,0), (1,2), (1,5), (2,3), (3,4), (4,2), (5,0), (5,6)]
for edge in edges:
u = edge[0]
v = edge[1]
if not G.IsNode(u):
G.AddNode(u)
if not G.IsNode(v):
G.AddNode(v)
if not G.IsEdge(u, v):
eid = G.AddEdge(u,v)
G.AddFltAttrDatE(eid, 1, "Trust")
(ids, n_component) = tarjan(G, 0.5)
print n_component, "components found"
print ids