日元的K最短路径给出错误的结果(Python)

时间:2019-11-26 17:15:28

标签: algorithm graph networkx python-3.7

我正在尝试基于https://en.wikipedia.org/wiki/Yen%27s_algorithm中的伪代码来实现日元的K最短路径算法。这是代码。

import numpy as np
import networkx as nx

edge_list = [[0, 1], [0, 2], [0, 7], [1, 2], [1, 9], [2, 5], [2, 7], [2, 9], [3, 4], [3, 5], [3, 6], [3, 8], [4, 5], [4, 6], [4, 7], [4, 8], [5, 6], [5, 7], [5, 8], [6, 8], [7, 8]]
graph = nx.Graph()
graph.add_edges_from(edge_list)
nx.draw(graph, with_labels = True)
source_node = 8
destination_node = 9

def yen_ksp(graph, source, sink, K):
    A, B = [], []
    A.append(nx.shortest_path(graph, source=source, target=sink))
    for k in range(1, 1+K):
        for i in range(len(A[k - 1]) - 1):
            spurNode = A[k-1][i]
            rootPath = A[k-1][0:i+1]
            removed_edges, removed_nodes = [], []
            for p in A:
                if rootPath == p[0:i+1] and p[i:i+2] not in removed_edges:
                    removed_edges.append(p[i:i+2])

            for edge in removed_edges:
                graph.remove_edge(edge[0], edge[1])
            try:
                spurPath = nx.shortest_path(graph, source=spurNode, target=sink)
            except:
                for edge in removed_edges:
                    graph.add_edge(edge[0], edge[1])
                continue

            totalPath = rootPath + spurPath[1:]
            B.append(totalPath)
            for edge in removed_edges:
                graph.add_edge(edge[0], edge[1])

        if B == []:
# This handles the case of there being no spur paths, or no spur paths left.
# This could happen if the spur paths have already been exhausted (added to A), 
# or there are no spur paths at all - such as when both the source and sink vertices 
# lie along a "dead end".
           break
        B.sort()
        A.append(B[-1])
        B.pop(-1)
    return A

print(yen_ksp(graph.copy(), source_node, destination_node, 10))

这应该是根据上面的代码生成的无向,无权图。

undirected, unweighted graph

这是代码的输出。

[[8, 5, 2, 9],
 [8, 7, 2, 9],
 [8, 7, 2, 1, 9],
 [8, 7, 2, 1, 2, 9],
 [8, 7, 2, 1, 2, 1, 9],
 [8, 7, 2, 1, 2, 1, 2, 9],
 [8, 7, 2, 1, 2, 1, 2, 1, 9],
 [8, 7, 2, 1, 2, 1, 2, 1, 2, 9],
 [8, 7, 2, 1, 2, 1, 2, 1, 2, 1, 9],
 [8, 7, 2, 1, 2, 1, 2, 1, 2, 1, 2, 9],
 [8, 7, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 9]]

很明显,算法缺少了较短的路径。并且,结果包含具有循环的路径。我只想要那些没有的人。

另外,在其他情况下,结果顺序错误,一些较长的路径出现在其他较短的路径之前。在KSP问题中,结果的顺序显然很重要,因为如果我停在k点左右,我想确保没有我错过的更短路径。

我愿意接受其他算法,这些算法可以正确有效地解决KSP问题,并且在无向非加权图上没有循环。

请帮助。

1 个答案:

答案 0 :(得分:2)

Networkx提供了从最短的shortest_simple_paths开始生成从源到目标的图形中所有简单路径的列表的功能。正如您可以在文档中阅读的那样,此过程完全基于Yen的算法。

使用非常简单:

paths = list(nx.shortest_simple_paths(graph, source_node, target_node))

如果仅需要前K条最短路径,则可以使用islice

from itertools import islice
paths = list(islice(nx.shortest_simple_paths(graph, source_node, target_node), K))

示例:

from itertools import islice

K = 10
source_node = 8
target_node = 9

graph = nx.Graph()
edge_list = [[0, 1], [0, 2], [0, 7], [1, 2], [1, 9], [2, 5], [2, 7],
             [2, 9], [3, 4], [3, 5], [3, 6], [3, 8], [4, 5], [4, 6],
             [4, 7], [4, 8], [5, 6], [5, 7], [5, 8], [6, 8], [7, 8]]
graph.add_edges_from(edge_list)

for path in islice(nx.shortest_simple_paths(graph, source_node, target_node), K):
    print(path)

输出:

[8, 5, 2, 9]
[8, 7, 2, 9]
[8, 5, 7, 2, 9]
[8, 5, 2, 1, 9]
[8, 3, 5, 2, 9]
[8, 7, 0, 1, 9]
[8, 7, 2, 1, 9]
[8, 4, 5, 2, 9]
[8, 7, 5, 2, 9]
[8, 7, 0, 2, 9]

如果您想了解shortest_simple_path的实现方式,则可以查看其source code:它写得很好并且很容易理解!