簡體   English   中英

使用python從節點n開始的所有長度為L的路徑

[英]All paths of length L from node n using python

給定一個圖G,一個節點n和一個長度L,我想收集所有從n出發的長度L的(非循環)路徑。

您對如何解決這個問題有任何想法嗎?

現在,我的圖形是一個networkx.Graph實例,但是我並不在乎是否建議使用igraph。

非常感謝!

解決(並完全解決)此問題的一種非常簡單的方法是使用圖的鄰接矩陣A。 A ^ L的(i,j)個元素是長度為L的節點ij之間的路徑數。 因此,如果將所有j求和並保持i固定為n ,則所有路徑都從長度為L的節點n發出。

不幸的是,這也將計算循環路徑。 可以從元素A^L(n,n) ,因此只需減去它們即可。

因此,您的最終答案是: Σj{A^L(n,j)} - A^L(n,n)

溫馨提示:假設您正在從節點1尋找長度為5的路徑,該計算還將計算內部1-2-3-2-4 (如1-2-3-2-4的路徑,長度取決於您的方式為5或4選擇看它,所以要小心。

我只想介紹Lance Helsten的出色答案:

深度限制搜索將搜索特定深度(稱為長度L)內的特定節點,並在找到它時停止搜索。 如果您在他的答案中查看Wiki鏈接中的偽代碼,您將會理解:

DLS(node, goal, depth) {
  if ( depth >= 0 ) {
    if ( node == goal )
      return node

    for each child in expand(node)
      DLS(child, goal, depth-1)
  }
}

但是,對於您而言,從節點尋找長度為L的所有路徑時,您將不會在任何地方停下來。 因此,偽代碼必須修改為:

DLS(node, depth) {
    for each child in expand(node) {
      record paths as [node, child]
      DLS(child, depth-1)
    }
}

在記錄了DLS的連續嵌套中的所有單鏈接路徑之后,只需對它們進行乘積即可獲取完整路徑。 這些數量為您提供了從節點開始的所需深度的路徑數量。

使用深度限制搜索( http://en.wikipedia.org/wiki/Depth-limited_search ),在其中保留一組訪問節點,以在路徑上檢測循環。 例如,您可以從節點n構造具有所有節點且長度為L的樹,然后修剪該樹。

我快速搜索了圖算法以執行此操作,但未找到任何內容。 有一系列圖形算法( http://en.wikipedia.org/wiki/Category:Graph_algorithms )可能具有您想要的功能。

此解決方案的效率可能有所提高,但是看起來很短,並且使用networkx功能:

G = nx.complete_graph(4)
n =  0
L = 3
result = []
for paths in (nx.all_simple_paths(G, n, target, L) for target in G.nodes_iter()):
    print(paths)
    result+=paths

這是我在閱讀了這里的答案后想到的另一個(相當幼稚的)實現:

def findAllPaths(node, childrenFn, depth, _depth=0, _parents={}):
    if _depth == depth - 1:
        # path found with desired length, create path and stop traversing
        path = []
        parent = node
        for i in xrange(depth):
            path.insert(0, parent)
            if not parent in _parents:
                continue
            parent = _parents[parent]
            if parent in path:
                return # this path is cyclic, forget
        yield path
        return

    for nb in childrenFn(node):
        _parents[nb] = node # keep track of where we came from
        for p in findAllPaths(nb, childrenFn, depth, _depth + 1, _parents):
            yield p


graph = {
    0: [1, 2],
    1: [4, 5],
    2: [3, 10],
    3: [8, 9],
    4: [6],
    5: [6],
    6: [7],
    7: [],
    8: [],
    9: [],
    10: [2] # cycle
}

for p in findAllPaths(0, lambda n: graph[n], depth=4):
    print(p)

# [0, 1, 4, 6]
# [0, 1, 5, 6]
# [0, 2, 3, 8]
# [0, 2, 3, 9]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM