在 networkx 图中查找给定长度的所有 paths/walks
Finding all paths/walks of given length in a networkx graph
我正在使用 networkx 并尝试在图中找到所有长度为 3 的路径,特别是具有三个边的路径。我试图在 networkx 文档中找到有关算法的一些信息,但我只能在图中找到最短路径的算法。如果最短路径是 14 -> 15 -> 16,我能否找到通过特定节点的路径长度,例如通过节点 14 -> 11 -> 12 -> 16 的路径?这是一个示例图的图像:
最简单的版本(下面是我认为更快的另一个版本):
def findPaths(G,u,n):
if n==0:
return [[u]]
paths = [[u]+path for neighbor in G.neighbors(u) for path in findPaths(G,neighbor,n-1) if u not in path]
return paths
这需要一个网络 G
和一个节点 u
以及一个长度 n
。它递归地找到所有长度为 n-1 的路径,从不包括 u
的 u
的邻居开始。然后它将 u
粘在每个这样的路径的前面,并 returns 这些路径的列表。
注意,每个路径都是一个有序列表。它们都从指定的节点开始。所以对于你想要的,只需围绕这个循环:
allpaths = []
for node in G:
allpaths.extend(findPaths(G,node,3))
请注意,这将有任何 a-b-c-d
路径以及反向 d-c-b-a
路径。
如果您发现 "list comprehension" 难以解释,这里有一个等效的选项:
def findPathsNoLC(G,u,n):
if n==0:
return [[u]]
paths = []
for neighbor in G.neighbors(u):
for path in findPathsNoLC(G,neighbor,n-1):
if u not in path:
paths.append([u]+path)
return paths
为了优化这一点,尤其是在有很多循环的情况下,可能值得发送一组不允许的节点。在每个嵌套调用中,它会知道不包括递归中更高层的任何节点。这将代替 if u not in path
检查。代码会有点难以理解,但会 运行 更快。
def findPaths2(G,u,n,excludeSet = None):
if excludeSet == None:
excludeSet = set([u])
else:
excludeSet.add(u)
if n==0:
return [[u]]
paths = [[u]+path for neighbor in G.neighbors(u) if neighbor not in excludeSet for path in findPaths2(G,neighbor,n-1,excludeSet)]
excludeSet.remove(u)
return paths
请注意,我必须在递归调用之前将u
添加到excludeSet
,然后在返回之前将其删除。
我正在使用 networkx 并尝试在图中找到所有长度为 3 的路径,特别是具有三个边的路径。我试图在 networkx 文档中找到有关算法的一些信息,但我只能在图中找到最短路径的算法。如果最短路径是 14 -> 15 -> 16,我能否找到通过特定节点的路径长度,例如通过节点 14 -> 11 -> 12 -> 16 的路径?这是一个示例图的图像:
最简单的版本(下面是我认为更快的另一个版本):
def findPaths(G,u,n):
if n==0:
return [[u]]
paths = [[u]+path for neighbor in G.neighbors(u) for path in findPaths(G,neighbor,n-1) if u not in path]
return paths
这需要一个网络 G
和一个节点 u
以及一个长度 n
。它递归地找到所有长度为 n-1 的路径,从不包括 u
的 u
的邻居开始。然后它将 u
粘在每个这样的路径的前面,并 returns 这些路径的列表。
注意,每个路径都是一个有序列表。它们都从指定的节点开始。所以对于你想要的,只需围绕这个循环:
allpaths = []
for node in G:
allpaths.extend(findPaths(G,node,3))
请注意,这将有任何 a-b-c-d
路径以及反向 d-c-b-a
路径。
如果您发现 "list comprehension" 难以解释,这里有一个等效的选项:
def findPathsNoLC(G,u,n):
if n==0:
return [[u]]
paths = []
for neighbor in G.neighbors(u):
for path in findPathsNoLC(G,neighbor,n-1):
if u not in path:
paths.append([u]+path)
return paths
为了优化这一点,尤其是在有很多循环的情况下,可能值得发送一组不允许的节点。在每个嵌套调用中,它会知道不包括递归中更高层的任何节点。这将代替 if u not in path
检查。代码会有点难以理解,但会 运行 更快。
def findPaths2(G,u,n,excludeSet = None):
if excludeSet == None:
excludeSet = set([u])
else:
excludeSet.add(u)
if n==0:
return [[u]]
paths = [[u]+path for neighbor in G.neighbors(u) if neighbor not in excludeSet for path in findPaths2(G,neighbor,n-1,excludeSet)]
excludeSet.remove(u)
return paths
请注意,我必须在递归调用之前将u
添加到excludeSet
,然后在返回之前将其删除。