Bir dendritik akış ağında belirli bir erişimin akış yönündeki tüm yolları bulabilen bir kod yazdım.Python'da yol bulma verimliliği
4 -- 5 -- 8
/
2 --- 6 - 9 -- 10
/ \
1 -- 11
\
3 ----7
ebeveyn-çocuk çiftlerinin bir dizi olarak: Aşağıdakilerin ağı temsil eder, bir örnek olarak,
{(11, 9), (10, 9), (9, 6), (6, 2), (8, 5), (5, 4), (4, 2), (2, 1), (3, 1), (7, 3)}
bu, örneğin bir düğüm üst tüm yolları döndürür:
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)]]
Bu kod aşağıda yer almaktadır.
Soruma şudur: Bunu, herhangi bir erişimin milyonlarca yolu olabileceği çok büyük (örneğin, New England) bir bölgedeki her erişime uygulıyorum. Muhtemelen bu uzun bir operasyon olmaktan kaçınmanın bir yolu yoktur, fakat bu operasyonu gerçekleştirmek için pithonik bir yol var mıdır, öyle ki her yolla yepyeni yollar üretilmiyor mu? Örneğin
ben 2'de tüm yolların retracing olmadan (1, h) get_paths (s, 2) yukarı 2 ila tüm yollar bulunmuştur ve, daha sonra çalışabilir get_paths çalıştırmak olur?
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)
DÜZENLEME: Birkaç hafta önce bir ağda "TÜM" akıntıya karşı ulaşır bulma konusunda benzer bir soru sordu ve çok hızlı oldu mükemmel bir cevap aldı: Fark ettim
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(): Bu kodun bir kısmı, sıralı sırada düğümleri ekler, ancak yinelemeli bir işlev olduğundan, bunları tek bir listeye eklemek için iyi bir yol bulamıyorum. Belki de siparişi koruyan bu kodu değiştirmenin bir yolu vardır.
IMHO Doğru bir şekilde anladığımı düşünüyorsanız sorunun bir veritabanı veya yapı sorunu değil, bir "python-way" sorunu olduğunu düşünüyorum. Örneğin, ebeveyn-çocuk çiftlerine bazı verileri ekleyebilirsiniz. Oğullar ve 0 test edilmemiş erişim olarak temsil edilecekler, bu arada bu kadar çok yer varsa veriyi nerede saklamayı planlıyorsunuz? kolayca hafıza sorunları alabilirsiniz ... –