Initial fork commit
This commit is contained in:
0
scripts/geodata/graph/__init__.py
Normal file
0
scripts/geodata/graph/__init__.py
Normal file
41
scripts/geodata/graph/scc.py
Normal file
41
scripts/geodata/graph/scc.py
Normal file
@@ -0,0 +1,41 @@
|
||||
VISIT, VISIT_EDGE, POST_VISIT = range(3)
|
||||
|
||||
|
||||
def strongly_connected_components(graph):
|
||||
'''
|
||||
Find strongly connected components in a graph using iterative
|
||||
depth-first search.
|
||||
|
||||
Based on:
|
||||
http://code.activestate.com/recipes/578507-strongly-connected-components-of-a-directed-graph/
|
||||
'''
|
||||
identified = set()
|
||||
stack = []
|
||||
index = {}
|
||||
boundaries = []
|
||||
|
||||
for v in graph:
|
||||
if v not in index:
|
||||
todo = [(VISIT, v)]
|
||||
while todo:
|
||||
op, v = todo.pop()
|
||||
if op == VISIT:
|
||||
index[v] = len(stack)
|
||||
stack.append(v)
|
||||
boundaries.append(index[v])
|
||||
todo.append((POST_VISIT, v))
|
||||
todo.extend([(VISIT_EDGE, w) for w in graph[v]])
|
||||
elif op == VISIT_EDGE:
|
||||
if v not in index:
|
||||
todo.append((VISIT, v))
|
||||
elif v not in identified:
|
||||
while index[v] < boundaries[-1]:
|
||||
boundaries.pop()
|
||||
else:
|
||||
# op == POST_VISIT
|
||||
if boundaries[-1] == index[v]:
|
||||
boundaries.pop()
|
||||
scc = stack[index[v]:]
|
||||
del stack[index[v]:]
|
||||
identified.update(scc)
|
||||
yield scc
|
||||
32
scripts/geodata/graph/topsort.py
Normal file
32
scripts/geodata/graph/topsort.py
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
def topsort(graph):
|
||||
'''
|
||||
Topological sort for a dependency graph, e.g.
|
||||
|
||||
Usage:
|
||||
|
||||
>>> graph = {
|
||||
'a': ['b'],
|
||||
'b': ['d'],
|
||||
'c': ['d', 'a'],
|
||||
'd': [],
|
||||
}
|
||||
>>> topsort(graph)
|
||||
|
||||
Returns: ['d', 'b', 'a', 'c']
|
||||
|
||||
'''
|
||||
todos = set(graph.keys())
|
||||
seen = set()
|
||||
result = []
|
||||
while todos:
|
||||
for key in todos:
|
||||
deps = graph[key]
|
||||
if len([d for d in deps if d in seen]) == len(deps):
|
||||
break
|
||||
else:
|
||||
raise Exception('Cycle: {}'.format(todos))
|
||||
todos.remove(key)
|
||||
result.append(key)
|
||||
seen.add(key)
|
||||
return result
|
||||
Reference in New Issue
Block a user