给定一个图G、一个节点n和一个长度L,我想收集所有从n出发的长度为L的非循环路径。
您有任何关于如何解决这个问题的想法吗?
目前,我的图是一个networkx.Graph实例,但如果推荐使用igraph,我并不是很在意。
非常感谢!
给定一个图G、一个节点n和一个长度L,我想收集所有从n出发的长度为L的非循环路径。
您有任何关于如何解决这个问题的想法吗?
目前,我的图是一个networkx.Graph实例,但如果推荐使用igraph,我并不是很在意。
非常感谢!
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连续嵌套的所有单链路径后,只需对它们进行乘积运算即可得到整个路径。这些路径的数量就是从该节点开始所需深度的路径数。
这个解决方案在效率方面可能需要改进,但它似乎非常简短并利用了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
使用深度限制搜索(http://en.wikipedia.org/wiki/Depth-limited_search),在路径上保留已访问节点的集合以检测循环。例如,您可以从节点n构建一棵树,包括所有节点和长度为L,然后修剪该树。
我快速搜索了一下图形算法,但没有找到任何东西。有一个图形算法列表(http://en.wikipedia.org/wiki/Category:Graph_algorithms),可能会有你要找的内容。
在阅读了这里的答案后,我想出了另一种(相当天真)的实现方式:
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]