python中的等代价多路径Dijkstra算法

python中的等代价多路径Dijkstra算法,python,algorithm,dijkstra,Python,Algorithm,Dijkstra,使用此处提出的python配方: 及 并使用以下图表作为输入: graph_2 = { 'R1':{'R2':5,'R3':5}, 'R2':{'R1':5,'R4':5}, 'R3':{'R1':5,'R4':5}, 'R4':{'R2':5,'R3':5}, } 我正在尝试获取R1和R4之间的所有最短路径。然而,我只得到一条最短路径R1-R2-R4,而不是R1-R3-R4。我需要像OSPF那样模拟ECMP。我需要的是函数shortestPath返回所有最

使用此处提出的python配方:

并使用以下图表作为输入:

 graph_2  = {
    'R1':{'R2':5,'R3':5},
    'R2':{'R1':5,'R4':5},
    'R3':{'R1':5,'R4':5},
    'R4':{'R2':5,'R3':5},
}
我正在尝试获取R1和R4之间的所有最短路径。然而,我只得到一条最短路径R1-R2-R4,而不是R1-R3-R4。我需要像OSPF那样模拟ECMP。我需要的是函数shortestPath返回所有最短路径,即[[R1-R2-R4],[R1-R3-R4]],在顶部图_2等成本多路径的情况下返回,在单路径的情况下返回最短路径,例如:

  graph_3  = {
    'R1':{'R2':5,'R3':5},
    'R2':{'R1':5,'R4':5},
    'R3':{'R1':5,'R4':10},
    'R4':{'R2':5,'R3':5},
}
我对Dijkstra函数中的代码进行了如下修改:

from priodict import priorityDictionary

graph_2  = {

'R1':{'R2':5,'R3':5},
'R2':{'R1':5,'R4':5},
'R3':{'R1':5,'R4':5},
'R4':{'R2':5,'R3':5},
}



def Dijkstra(G,start,end=None):

    D = {}  # dictionary of final distances
    P = {}  # dictionary of predecessors
    Q = priorityDictionary()   # est.dist. of non-final vert.
    Q[start] = 0
    for v in Q:
        D[v] = Q[v]
        if v == end: break

        for w in G[v]:
            vwLength = D[v] + G[v][w]

            if w in D:
                if vwLength < D[w]:
                    raise ValueError, \
            elif w not in Q or vwLength < Q[w]:
                Q[w] = vwLength
                P[w] = [v]
            elif  w not in Q or vwLength == Q[w]: <---adding this part
                Q[w] = vwLength
                P[w] += [v]

    return (D,P)

def shortestPath(G,start,end):
    D,P = Dijkstra(G,start,end)
    print D,P
    Path = []
    while 1:
        Path.append(end)
        print end
        if end == start: break
        end = P[end]
    Path.reverse()
    return Path

print shortestPath(graph_2,'R1','R4')
我得到以下输出和错误:

{'R4': 10, 'R1': 0, 'R2': 5, 'R3': 5} {'R4': ['R2', 'R3'], 'R2': ['R1'], 'R3': ['R1']}

Traceback (most recent call last):
File "next-hop-resolver.py", line 194, in <module>
print shortestPath(graph_2,'R1','R4')
File "next-hop-resolver.py", line 172, in shortestPath
end = P[end]
TypeError: unhashable type: 'list'
我想使用图2得到的是:

[['R1',R2',R4',['R1',R3',R4']]

并使用图3:

[['R1','R2','R4']]

如果我按原样执行代码,即不进行任何代码修改,则无论我使用图2还是图3,我都会得到以下结果:

[['R1','R2','R4']]

i、 e始终是最短路径,即使有多条路径

我知道列表不可能是字典中的一个键,但老实说,我一直坚持这样做,所以任何帮助都是非常受欢迎的

感谢您提供可运行的代码。您还没有解释您的设计,但是功能上的问题已经足够清楚了:P负责沿着当前路径返回任何给定节点的前置节点。由于路径是严格线性的,因此只能有一个前置路径。最短路径中的while循环依赖于此

但是,您返回的p沿着当前路径列出了R4的两个前辈,并且您立即尝试同时使用这两个前辈为p编制索引。你不能那样做;您必须单独处理每条路径

解决方案

简单地修改代码就等于为自己做家庭作业;i、 不酷。既然您已经走到了这一步,我建议您在最短路径中修改循环,以通过多个路径工作。首先,依次处理每个返回值,一次一个:

while True:
    for node in end:
        # continue with single-path code
编码注释

是的,我将循环条件表单1更改为True。 您使用的食谱似乎是由从C或其他早期第三代语言翻译过来的人编写的,而没有学习当今的编码改进。单字母变量名、大写字母等是当今程序员的不合标准的习惯。我自己也不得不重新学习一些


要了解您可以朝什么方向努力,请参见。

最后,我想我得到了我想要的:

这是最后的代码

from priodict import priorityDictionary
from collections import defaultdict
from collections import OrderedDict
import sys
graph_2  = {

'R1':{'R2':5,'R3':5},
'R2':{'R1':5,'R4':5},
'R3':{'R1':5,'R4':5},
'R4':{'R2':5,'R3':5,'R5':5},
'R5':{'R4':5}

}

graph_3 = {

'192.168.255.1':{'192.168.255.2':10,'192.168.255.3':10},
'192.168.255.2':{'192.168.255.1':10,'192.168.255.3':50},
'192.168.255.3':{'192.168.255.1':20,'192.168.255.2':50},
'192.168.255.4':{'192.168.255.3':20},
'192.168.255.3':{'192.168.255.4':20}
}

graph_4 = {
'R1':{'R2':5},
'R2':{'R1':5},
'R2':{'R3':5},
'R3':{'R2':5},
'R3':{'R4':5},
'R4':{'R3':5}
}

graph_5 = {

'A':{'B':5,'C':10,'E':2},
'B':{'A':5,'C':5},
'C':{'B':5,'A':10,'E':8,'D':4},
'D':{'C':4,'E':5},
'E':{'A':2,'D':5,'C':8}

}

def Dijkstra(g,start,end=None):

    d = {}  # dictionary of final distances
    p = {}  # dictionary of predecessors
    q = priorityDictionary()   # est.dist. of non-final vert.
    q[start] = 0
    for v in q:
        d[v] = q[v]
        if v == end: break      
        for w in g[v]:
            vwLength = d[v] + g[v][w]
            if w in d:
                if vwLength < d[w]:
                    raise ValueError
            elif w not in q or vwLength < q[w]:
                q[w] = vwLength
                p[w] = [v]
            elif  w not in q or vwLength == q[w]:
                q[w] = vwLength
                p[w] += [v] 
    return (d,p)        

def shortestPath(g,start,end):

    d,p = Dijkstra(g,start,end)
    path = [[end]]
    while True:
        if len(p[end]) > 1:
            path.append(p[end])
            for node in p[end]:
                if node != start:
                    if ''.join(p[end]) == start: break
                    end = node
        path.append(p[end])
        if ''.join(p[end]) == start: break
        for node in p[end]:
            if node == start: break
            end = node  
    return path[::-1]


print shortestPath(graph_2,'R1','R5')
print shortestPath(graph_3,'192.168.255.1','192.168.255.2')
print shortestPath(graph_4,'R1','R4')
print shortestPath(graph_5,'A','C')

欢迎来到StackOverflow。请阅读并遵循帮助文档中的发布指南。适用于这里。在您发布MCVE代码并准确描述问题之前,我们无法有效地帮助您。您的代码存在缩进问题、一些语法错误,并且至少缺少一个外部变量。这使我们无法准确地再现问题。我修改了代码,添加了缺少的部分,并试图改进对问题的解释。谢谢你的提示@Prune
[['R1'], ['R2', 'R3'], ['R4'], ['R5']]
[['192.168.255.1'], ['192.168.255.2']]
[['R1'], ['R2'], ['R3'], ['R4']]
[['A'], ['A', 'E', 'B'], ['C']]