为什么 Floyd Warshall 算法的实现依赖于节点顺序?
Why is this implementation of Floyd Warshall algorithm dependent on node order?
这是我对 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}
如果我改变随机播放的种子,结果有时会改变。
为什么会这样?
编辑。
这是一个最小的工作示例:
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())
这是输出:
244
246
244
244
242
242
242
242
242
总长度应该是一样的,但随着种子的变化而变化。
你的最后一组循环没有考虑 k=0,它应该,否则你在搜索中忽略了形式 a->0->b 的路径。一般来说,使用 k 来索引节点和迭代的想法有点奇怪(并且使调试更难)。
您可以通过
轻松修复它
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())
这给出了
238
238
238
238
238
238
238
238
238
这是我对 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}
如果我改变随机播放的种子,结果有时会改变。
为什么会这样?
编辑。
这是一个最小的工作示例:
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())
这是输出:
244
246
244
244
242
242
242
242
242
总长度应该是一样的,但随着种子的变化而变化。
你的最后一组循环没有考虑 k=0,它应该,否则你在搜索中忽略了形式 a->0->b 的路径。一般来说,使用 k 来索引节点和迭代的想法有点奇怪(并且使调试更难)。
您可以通过
轻松修复它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())
这给出了
238
238
238
238
238
238
238
238
238