Python代码在逻辑上看起来是等效的,但一个出现了错误,另一个没有。

huangapple go评论69阅读模式
英文:

Python code seems logically equivalent but one is failing and the other is not

问题

以下是Bellman-Ford算法的实现,用于查找图中是否存在负循环。

def negative_cycle(n, graph):
    dist = [1001] * (n+1)          # 这段代码不会失败
    dist[1] = 0
    for i in range(n):
        for st, end, cost in graph:
            print(dist)
            if dist[end] > dist[st] + cost:
                dist[end] = dist[st] + cost
                if i == n - 1:
                    return 1
    return 0


if __name__ == '__main__':
    n_vertices, n_edges = map(int, input().split())
    edges = []
    for i in range(n_edges):
        a, b, w = map(int, input().split())
        edges.append((a, b, w)) 
    print(negative_cycle(n_vertices, edges))

请注意,代码中的一行被修改为使用固定的整数1001来初始化dist数组,而不是使用float('inf'),这样就不会导致失败。

英文:

The following is Bellman-Ford's algorithm implemented to find whether there is a negative cycle in the graph or not.
I do not have access to the test cases but there is some edge case that's causing the code to fail when the dist array is initialized with float('inf'). Why?

def negative_cycle(n, graph):
    # dist = [float('inf')] * (n+1)  (This code fails)
    dist = [1001] * (n+1)          # (this code doesn't)
    dist[1] = 0
    for i in range(n):
        for st, end, cost in graph:
            print(dist)
            if dist[end] > dist[st] + cost:
                dist[end] = dist[st] + cost
                if i == n - 1:
                    return 1
    return 0


if __name__ == '__main__':
    n_vertices, n_edges = map(int, input().split())
    edges = []
    for i in range(n_edges):
        a, b, w = map(int, input().split())
        edges.append((a, b, w)) 
    print(negative_cycle(n_vertices, edges))

答案1

得分: 1

在输入图具有以下特点时,将获得不同的输出:

  • 并非所有节点都可以从节点1到达
  • 存在不可从节点1到达的节点之间的负循环

在这种情况下,有缺陷的代码(带有 "inf")将报告没有负循环,而正确的代码将报告存在一个负循环。

以下是一个此类情况的示例输入/运行:

edges = [
    (1, 2, 0),
    (2, 1, 0),

    (3, 4, -1),
    (4, 3, 0),
    (4, 1, 0)
]
print(negative_cycle(4, edges))

每当访问具有负权重的边时,算法将比较 dist[4] > dist[3] - 1。在有缺陷的代码中,这个表达式是 float('inf') > float('inf') - 1,这是 False,而在正确的代码中,这个表达式是 1001 > 1001 - 1(第一次是这样,然后是 1000 > 1000 - 1,等等),因此 if 块会被重复执行,最终执行 return 1

备注

在正确的代码中,不需要以与其他节点不同的方式初始化 dist[1]。您可以将它们全部初始化为0。这个算法不需要有 "我以前从未来过这里" 的概念,而在其他算法中,这可能会使它有趣地初始化为 float('inf')

在这里唯一重要的是算法检测到一个或多个节点的距离持续减小,永远不会稳定到一个固定的值。对于这样的检测,起始算法的初始值无关紧要,只要它是有限值。

英文:

You'll get a different output when the input graph has these characteristics:

  • Not all nodes are reachable from node 1
  • There is a negative cycle between nodes that are not reachable from node 1

In this case the faulty code (with "inf") will report there is no negative cycle, while the correct code will report there is one.

Here is an example input/run of such a case:

edges = [
    (1, 2, 0),
    (2, 1, 0),

    (3, 4, -1),
    (4, 3, 0),
    (4, 1, 0)
]
print(negative_cycle(4, edges))

Each time the edge with the negative weight is visited, the algorithm will compare dist[4] > dist[3] - 1. In the faulty code this expression is float('inf') > float('inf') - 1 which is False, while in the correct code this expression is 1001 > 1001 - 1 (the first time, then 1000 > 1000 - 1, ...etc) and so the if block gets executed repeatedly, eventually executing return 1.

Remarks

In the correct code it is not necessary to initialise dist[1] in a different way than for the other nodes. You could initialise them all with 0. This algorithm doesn't need to have the notion of "I never was here before", which in other algorithms would make it interesting to initialise with float('inf').

Here the only thing that matters is that the algorithm detects that the distance of one or more nodes keeps reducing and never settles to a stable value. For such a detection it doesn't matter at which initial value you start the algorithm with, as long as it is a finite value.

huangapple
  • 本文由 发表于 2023年2月10日 14:21:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75407570.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定