我正在使用networkx并尝试在图中找到长度为3的所有步行,特别是具有三条边的路径。我试图在networkx文档中找到有关算法的一些信息,但我只能找到图中最短路径的算法。我是否可以通过特定节点找到路径的长度,例如通过节点14->的路径。 11 - > 12 - >如果最短路径为14,则为16。 15 - > 16?以下是示例http://i62.tinypic.com/2ekj602.jpg
的图表图像答案 0 :(得分:7)
最简单的版本(我认为另一个版本更快):
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
粘贴在每个这样的路径的前面,并返回这些路径的列表。
注意,每个路径都是一个有序列表。它们都从指定的节点开始。所以对于你想要的东西,只需绕一个循环:
allpaths = []
for node in G:
allpaths.extend(findPaths(G,node,3))
请注意,这将包含任何a-b-c-d
路径以及反向d-c-b-a
路径。
如果您发现“列表理解”是一个需要解释的挑战,那么这是一个等价的选项:
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
,然后在返回之前将其删除。