Python 用Dijkstra求循环图的最短路径

Python 用Dijkstra求循环图的最短路径,python,python-3.x,graph-algorithm,dijkstra,Python,Python 3.x,Graph Algorithm,Dijkstra,我有一个循环有向图。下面是以python dict表示的图形 graph = { 'A': {'B': 5, 'D': 5, 'E': 7 }, 'B': {'C': 4}, 'C': {'D': 8, 'E': 2}, 'D': {'C': 8, 'E': 6}, 'E': {'B': 3} } 我写了一个简单的Dijkstra最短路径的实现。这似乎适用于给定的两点。下面是我

我有一个循环有向图。下面是以python dict表示的图形

graph = {
          'A': {'B': 5, 'D': 5, 'E': 7 },
          'B': {'C': 4},
          'C': {'D': 8, 'E': 2},
          'D': {'C': 8, 'E':  6},
          'E': {'B': 3}
        }
我写了一个简单的Dijkstra最短路径的实现。这似乎适用于给定的两点。下面是我的实现

def shortestpath(self, start, end, visited=[],distances={},predecessors={}):
        # initialize a big number
        maxint = 10000 

        if start==end:
            path=[]
            while end != None:
                path.append(end)
                end=predecessors.get(end, None)
            return distances[start], path[::-1]

        # detect if it's the first time through, set current distance to zero
        if not visited: distances[start]=0
        # process neighbors as per algorithm, keep track of predecessors
        for neighbor in self.graph[start]:
            if neighbor not in visited:
                neighbordist = distances.get(neighbor,maxint)
                tentativedist = distances[start] + self.graph[start][neighbor]
                if tentativedist < neighbordist:
                    distances[neighbor] = tentativedist
                    predecessors[neighbor]=start

        # neighbors processed, now mark the current node as visited
        visited.append(start)
        # finds the closest unvisited node to the start
        unvisiteds = dict((k, distances.get(k,maxint)) for k in self.graph if k not in visited)
        closestnode = min(unvisiteds, key=unvisiteds.get)
        # now we can take the closest node and recurse, making it current
        return self.shortestpath(closestnode,end,visited,distances,predecessors)
它将给我的路径和最短的重量

(9,['A','B','C']

在这种情况下。 但是,只要我
最短路径('B','B')
程序就会中断。
现在有一条从
B到B
的最短路径,因为它是一个循环图,路径是B-C-E-B。我只是不知道如何检查它,并相应地修改Dijktra的算法,让它检查像这样的循环情况。非常感谢您的任何建议。谢谢:)

严格来说,从
B
B
的最短距离是零,因为您已经在那里了。如果要查找循环距离,最简单的解决方案可能是添加一个新的虚拟节点
Bs
,该节点具有与
B
相同的出站边缘。然后你所要做的就是找到从
Bs
B
的最短路径。我认为还可以使用更通用的解决方案,例如,修改算法以不允许总距离为零。此外,您应该用一个集合替换
访问的
列表,以减少渐进运行时间,因为当访问的节点列表增加时,识别不在访问列表中的节点将花费太长时间(线性时间,这将使整个算法
>O(n^2)
。实现这一点的标准方法是检查开始节点是否为目标节点,即如果开始==end,则没有返回的路径。那么为什么要检查self==end?因为这是一个循环图。
shortestpath('A', 'C')