[英]Why is this implementation of Floyd Warshall algorithm dependent on node order?
This is my implementation of the Floyd Warshall algorithm:这是我对 Floyd Warshall 算法的实现:
def algorithm(self, graph):
nodes = graph.keys()
shuffle(nodes, lambda : 0.5)
int_nodes = range(len(nodes))
arcs = set((a,b) for a in nodes for b in graph[a])
distances = {}
for i in int_nodes:
distances[(i, i, 0)] = 0
for i in int_nodes:
for j in int_nodes:
distances[(i, j, 0)] = 1 if (nodes[i], nodes[j]) in arcs else float("inf")
for k in range(1, len(nodes)):
for i in int_nodes:
for j in int_nodes:
distances[(i, j, k)] = min(distances[(i, j, k-1)], distances[(i, k, k-1)] + distances[(k, j, k-1)])
return {(nodes[i], nodes[j]): distances[(i, j, len(nodes)-1)] for i in int_nodes for j in int_nodes}
If I change the seed of the shuffle, the results sometimes change.如果我改变 shuffle 的种子,结果有时会改变。
Why does it happen?为什么会发生?
edit.编辑。
Here a minimal working example:这是一个最小的工作示例:
from random import shuffle
def algorithm(graph, n):
nodes = graph.keys()
shuffle(nodes, lambda : n)
int_nodes = range(len(nodes))
arcs = set((a,b) for a in nodes for b in graph[a])
distances = {}
for i in int_nodes:
distances[(i, i, 0)] = 0
for i in int_nodes:
for j in int_nodes:
distances[(i, j, 0)] = 1 if (nodes[i], nodes[j]) in arcs else float("inf")
for k in range(1, len(nodes)):
for i in int_nodes:
for j in int_nodes:
distances[(i, j, k)] = min(distances[(i, j, k-1)], distances[(i, k, k-1)] + distances[(k, j, k-1)])
return {(nodes[i], nodes[j]): distances[(i, j, len(nodes)-1)] for i in int_nodes for j in int_nodes}
if __name__ == "__main__":
graph = {'Z': ['B', 'H', 'G', 'O', 'I'], 'F': ['C', 'G', 'D', 'O'], 'L': ['M', 'C', 'D', 'E', 'H'], 'C': ['F', 'G', 'B', 'L', 'M', 'I'], 'B': ['C', 'Z', 'I', 'O', 'H', 'G'], 'D': ['F', 'L', 'G', 'M', 'E'], 'E': ['L', 'D', 'G', 'M'], 'H': ['B', 'L', 'Z', 'I', 'O'], 'G': ['C', 'F', 'D', 'E', 'Z', 'B'], 'O': ['B', 'H', 'F', 'I', 'Z'], 'M': ['L', 'D', 'E', 'C'], 'I': ['B', 'H', 'O', 'Z', 'C']}
for i in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]:
dis1 = algorithm(graph,i )
print sum(dis1.values())
And this is the output:这是输出:
244
246
244
244
242
242
242
242
242
The total leght should be the same, but it changes as the seed changes.总长度应该相同,但随着种子的变化而变化。
Your final set of loops is not considering k=0, and it should, otherwise you omit paths of form a->0->b in your search.您的最后一组循环不考虑 k=0,它应该考虑,否则您会在搜索中省略 a->0->b 形式的路径。 In general the idea of using k to index both nodes and iteration is a bit odd (and makes debugging harder).一般来说,使用 k 来索引节点和迭代的想法有点奇怪(并且使调试更加困难)。
You could easily fix it by你可以很容易地修复它
from random import shuffle
def algorithm(graph, n):
nodes = graph.keys()
shuffle(nodes, lambda : n)
int_nodes = range(len(nodes))
arcs = set((a,b) for a in nodes for b in graph[a])
distances = {}
for i in int_nodes:
distances[(i, i, -1)] = 0
for i in int_nodes:
for j in int_nodes:
distances[(i, j, -1)] = 1 if (nodes[i], nodes[j]) in arcs else float("inf")
for k in int_nodes:
for i in int_nodes:
for j in int_nodes:
distances[(i, j, k)] = min(distances[(i, j, k-1)], distances[(i, k, k-1)] + distances[(k, j, k-1)])
return {(nodes[i], nodes[j]): distances[(i, j, len(nodes)-1)] for i in int_nodes for j in int_nodes}
if __name__ == "__main__":
graph = {'Z': ['B', 'H', 'G', 'O', 'I'], 'F': ['C', 'G', 'D', 'O'], 'L': ['M', 'C', 'D', 'E', 'H'], 'C': ['F', 'G', 'B', 'L', 'M', 'I'], 'B': ['C', 'Z', 'I', 'O', 'H', 'G'], 'D': ['F', 'L', 'G', 'M', 'E'], 'E': ['L', 'D', 'G', 'M'], 'H': ['B', 'L', 'Z', 'I', 'O'], 'G': ['C', 'F', 'D', 'E', 'Z', 'B'], 'O': ['B', 'H', 'F', 'I', 'Z'], 'M': ['L', 'D', 'E', 'C'], 'I': ['B', 'H', 'O', 'Z', 'C']}
for i in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]:
dis1 = algorithm(graph,i )
print sum(dis1.values())
which gives这使
238
238
238
238
238
238
238
238
238
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.