简体   繁体   English

为什么 Floyd Warshall 算法的这种实现依赖于节点顺序?

[英]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.

相关问题 Floyd Warshall 在 Python 中的实现 - Floyd Warshall implementation in Python Floyd Warshall 算法未按预期工作 - Floyd Warshall algorithm not working as intended 使用 numba 在 GPU 上的 Floyd-Warshall 算法 - Floyd-Warshall algorithm on GPU using numba Networkx Floyd Warshall 算法给出错误的距离 - Networkx Floyd Warshall algorithm giving wrong distance Floyd-Warshall算法:获得最短路径 - Floyd-Warshall algorithm: get the shortest paths Warshall 算法与 python 中的 Floyd 算法有何不同? - How is the Warshall algorithm different from Floyd algorithm in python? 网络x图和floyd warshall - network x graph and floyd warshall 有没有一种方法可以使用 Floyd-Warshall 算法给出最短路径,其中存在负权重循环而不允许重叠边缘? - Is there a way that gives shortest path using Floyd-Warshall's algorithm where negative weight cycle exists whereas overlapped edges are not allowed? 我正在尝试实现 Floyd_Warshall 算法。 但是,我收到错误消息“float object 不支持项目分配” - I am trying to implementi the Floyd_Warshall algorithm. However, I have been getting the error message 'float object does not support item assignment' 如何在此关键路径算法中记录路径(Python - Floyd Warshall) - How to record the path in this critical path algo (Python - Floyd Warshall)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM