编程语言
首页 > 编程语言> > python-使用Dijkstra的算法时是否必须检查一次以上的访问节点?

python-使用Dijkstra的算法时是否必须检查一次以上的访问节点?

作者:互联网

我和我的同事正在讨论Dijkstra算法的实现.这是使用Python的实现:

def dijkstra(self, origin, destination):
        """Use Dijkstra's algorithm to find the cheapest path."""

        routes = Heap()
        for neighbor in self.neighbors(origin):
            price = self.get_price(origin, neighbor)
            routes.push(Route(price=price, path=[origin, neighbor]))

        visited = set()
        visited.add(origin)

        while routes:

            # Find the nearest yet-to-visit airport
            price, path = routes.pop()
            airport = path[-1]
            if airport in visited:
                continue

            # We have arrived! Wo-hoo!
            if airport is destination:
                return price, path

            # Tentative distances to all the unvisited neighbors
            for neighbor in self.neighbors(airport):
                if neighbor not in visited:
                    # Total spent so far plus the price of getting there
                    new_price = price + self.get_price(airport, neighbor)
                    new_path  = path  + [neighbor]
                    routes.push(Route(new_price, new_path))

            visited.add(airport)

        return float('infinity')

有争议的行是:

if neighbor not in visited:

我的观点是,此行必须替换为

if neighbor not in visited or new_price < cost_so_far[neighbor]

在我发现的所有算法实现中,您必须检查到达成本低于当前节点成本的节点时的情况.例如,此伪代码从Wikipedia开始的第17和18行:

1  function Dijkstra(Graph, source):
2      dist[source] ← 0                                    // Initialization
3
4      create vertex set Q
5
6      for each vertex v in Graph:           
7          if v ≠ source
8              dist[v] ← INFINITY                          // Unknown distance from source to v
9              prev[v] ← UNDEFINED                         // Predecessor of v
10
11         Q.add_with_priority(v, dist[v])
12
13
14     while Q is not empty:                              // The main loop
15         u ← Q.extract_min()                            // Remove and return best vertex
16         for each neighbor v of u:                       // only v that is still in Q
17             alt = dist[u] + length(u, v) 
18             if alt < dist[v]
19                 dist[v] ← alt
20                 prev[v] ← u
21                 Q.decrease_priority(v, alt)
22
23     return dist[], prev[]

问题是:我的同事的实施是否正确,还是应该修改代码以检查您是否到达某个价格低于当前价格的邻居?

注意:这是我同事的实施方案的source code.

解决方法:

所以,问题是代码中的行是否

if neighbor not in visited:

可以或必须替换为

if neighbor not in visited or new_price < cost_so_far[neighbor]:

答案是:可以,可以;可以.必须,不.
添加new_price< cost_so_far [neighbor]不会改变算法流程中的任何内容,每次未访问的邻居为false时为false. 原因是Dijkstra的算法如何工作.
本质上,它构建了最短路径的树.
每当添加一个要访问的机场时,都将其视为在树中:到此时,该算法已经找到到达该机场的最短路径.

假设在步骤x,我们向访问的机场添加了一个特定的机场A.
进一步假设在步骤y> x,到机场A的cost_so_far减少了.
怎么减少呢?
它将要求new_price = price self.get_price(机场,邻居)的价格小于步骤y的价格.
现在回想一下,路由是一个优先队列,因此它以非降序提供价格.
图的边缘也是非负的(否则,Dijkstra的算法确实会产生错误的结果,因此不适用).
因此,我们产生了一个矛盾:新的new_price至少是旧价格,但事实证明比旧价格要低.

造成混淆的原因可能是,实现的主循环一对一地考虑某些路由.
本质上,这些路线与图形的边缘相对应.
因此,可以有| E |路线,但只有| V |他们中的一个将被接受,如果访问过机场,则所有其他条件将失败:继续.
如果我们实现该算法,以便主循环的每次迭代恰好增加了一个要访问的机场(恰好是最短路径树的一个顶点),则整个问题可能会变得更加清晰.

标签:dijkstra,shortest-path,python,algorithm
来源: https://codeday.me/bug/20191119/2033884.html