我写了一些代码,在树状流网络中找到给定范围上游的所有路径。例如,如果我表示以下网络:4 -- 5 -- 8
/
2 --- 6 - 9 -- 10
/ \
1 -- 11
\
3 ----7
作为一组父子对:
^{pr2}$
它将返回节点上游的所有路径,例如:get_paths(h, 1) # edited, had 11 instead of 1 in before
[[Reach(2), Reach(6), Reach(9), Reach(11)], [Reach(2), Reach(6), Reach(9), Reach(10)], [Reach(2), Reach(4), Reach(5), Reach(8)], [Reach(3), Reach(7)]]
代码包含在下面。在
我的问题是:我把这个应用到一个非常大的地区(例如新英格兰)的每一个河段,任何一个河段都可能有数百万条路径。可能没有办法避免这是一个非常长的操作,但是有没有一种Python式的方法来执行这个操作,这样每次运行都不会生成新的路径?在
例如,如果我运行get_paths(h,2)并且找到了从2开始的所有上游路径,那么以后是否可以运行get_paths(h,1),而不重新追踪2中的所有路径?在import collections
# Object representing a stream reach. Used to construct a hierarchy for accumulation function
class Reach(object):
def __init__(self):
self.name = None
self.ds = None
self.us = set()
def __repr__(self):
return "Reach({})".format(self.name)
def build_hierarchy(flows):
hierarchy = collections.defaultdict(lambda: Reach())
for reach_id, parent in flows:
if reach_id:
hierarchy[reach_id].name = reach_id
hierarchy[parent].name = parent
hierarchy[reach_id].ds = hierarchy[parent]
hierarchy[parent].us.add(hierarchy[reach_id])
return hierarchy
def get_paths(h, start_node):
def go_up(n):
if not h[n].us:
paths.append(current_path[:])
for us in h[n].us:
current_path.append(us)
go_up(us.name)
if current_path:
current_path.pop()
paths = []
current_path = []
go_up(start_node)
return paths
test_tree = {(11, 9), (10, 9), (9, 6), (6, 2), (8, 5), (5, 4), (4, 2), (2, 1), (3, 1), (7, 3)}
h = build_hierarchy(test_tree)
p = get_paths(h, 1)
编辑:
几周前,我问了一个类似的问题,关于在一个网络中寻找“所有”上游河段,得到了一个非常快的极好答案:class Node(object):
def __init__(self):
self.name = None
self.parent = None
self.children = set()
self._upstream = set()
def __repr__(self):
return "Node({})".format(self.name)
@property
def upstream(self):
if self._upstream:
return self._upstream
else:
for child in self.children:
self._upstream.add(child)
self._upstream |= child.upstream
return self._upstream
import collections
edges = {(11, 9), (10, 9), (9, 6), (6, 2), (8, 5), (5, 4), (4, 2), (2, 1), (3, 1), (7, 3)}
nodes = collections.defaultdict(lambda: Node())
for node, parent in edges:
nodes[node].name = node
nodes[parent].name = parent
nodes[node].parent = nodes[parent]
nodes[parent].children.add(nodes[node])
我注意到这段代码的def upstream():部分按顺序添加上游节点,但由于它是一个迭代函数,所以我找不到一个好的方法将它们追加到单个列表中。也许有一种方法可以修改此代码以保持顺序。在