【问题标题】:How can I use the A star algorithm to find the first 100 shortest paths?如何使用 A 星算法找到前 100 条最短路径?
【发布时间】:2012-12-14 20:43:08
【问题描述】:

如何使用 A 星算法找到前 100 条最短路径?

【问题讨论】:

  • 您希望将这些路径用于什么目的?第 n 条最短路径通常是在某个点绕道的最短路径,对任何实际目的都没有用处。可能有一些合理的替代路径,但比困难的问题是如何判断路径对人类来说是否“合理”。
  • @Jan Hudec:在我的程序中,我将实现航班搜索系统。边的成本是飞行持续时间。我要找到定价的航班解决方案。但最快的路径可能不是便宜的路径。所以我要先找到 100 个最快的航班,然后再给路径定价相应地。
  • 100 次最快的航班会给你一堆垃圾,实际上可能不会给你任何便宜的路径,因为绝对没有办法知道便宜的路径有多远。相反,您要么希望基于部分排序(通过组合各种标准创建)找到所有最小路径,要么使用不同的目标函数多次运行算法。或者对深度和距离应用启发式限制并进行详尽的搜索;我怀疑它适用于航班,但不适用于公共汽车连接。
  • 无论如何,这是一个完全不同的问题,所以在您制定新问题后进行更详细的讨论 - “如何在具有多个标准(更便宜、更短、更快等)的时间表中搜索并找到所有其中任何一个中最小的路径”或“当需要许多替代结果时如何在飞行时间表中搜索”。或者两者兼而有之,如果你有兴趣的话。
  • 如果您正在为航班搜索系统实施此功能,您可能需要查看替代路线:algo2.iti.kit.edu/2073.phpalgo2.iti.kit.edu/english/1805.php

标签: algorithm graph-algorithm shortest-path a-star


【解决方案1】:

找到第 k 条最短路径的问题是 NP-Hard,因此任何对 A-Star 的修改都会满足您的要求 - 输入的大小将成指数增长。

证明:
(注意:我将在 simple 路径上显示)
假设你有一个多项式算法,它在多项式时间内运行并返回k的长度,最短路径让算法为A(G,k)

最大路径数是n!,通过在[1,n!] 范围内应用二分搜索来找到长度为n 的最短路径,您需要O(log(n!)) = O(nlogn) 调用A
如果您发现有一条长度为n 的路径 - 它是hamiltonian path
通过对图中的每个源和目标(其中O(n^2))重复该过程,假设存在A,您可以多项式求解Hamiltonian Path Problem
QED

由此我们可以得出结论,除非P=NP(大多数 CS 研究人员认为这不太可能),否则问题无法通过多项式解决。

另一种方法是使用Uniform Cost Search 的变体而不维护visited/closed 集。您也许也可以修改 A*,通过禁用封闭节点,并在遇到时产生/生成解决方案,而不是返回它们并完成,但我想不出一种方法来证明 A * 目前。

【讨论】:

  • 你能解释一下如何使用 A* 找到前 100 条最短路径吗?我实现了 A* 来找到最短路径。 A 使用了可接受的启发式算法。现在我想找到前 100 条最短路径。
  • 你能解释一下如何使用 A* 找到前 100 条最短路径吗?我实现了 A* 来找到最短路径。还使用了一个可接受的启发式方法。禁用关闭的节点列表将允许我们重用以前访问过的节点。但是现在我想找到前 100 条最短路径。请解释一下怎么做。
  • @user1815763,您需要将整个路径(source->v1->v2->..->vn)(当然还有它的分数)“推”到优先级队列中每一步都插入所有下一个可用路径,忽略您已经访问过或未访问过的顶点(访问所有顶点)。每当您从队列中弹出某个作为目的地的元素时 - 您找到了一条路径。我相信(尽管此时无法证明)你从队列中弹出一个目的地的第 k 次代表第 k 个最短路径。请注意,此解决方案是指数型的,因为您不会限制自己并且可以多次重新访问节点。
  • @KillianDS:不完全是,通过禁用封闭节点集并重新访问封闭节点,您可以使算法呈指数级 - 它可能导致在不证明 P=NP 的情况下解决问题(尽管我无法证明目前它会这样做,但我的直觉说它会这样做)。
【解决方案2】:

除了NP-hard 这个问题之外,如果不进行重大修改,使用A*dijkstra 是不可能做到这一点的。以下是一些主要原因:

首先,算法在每一步都只保留目前为止的最佳路径。考虑下图:

  A
 / \
S   C-E
 \ /
  B

假设距离d(S,A)=1, d(S,B)=2, d(A,C)=d(B,C)=d(C,E)=10

访问 C 时,您将通过A 选择路径,但您将无法在任何地方存储通过B 的路径。所以你必须保留这些信息。

但是,其次,您甚至没有考虑所有可能的路径,假设如下图:

S------A--E
 \    /
  B--C

假设距离d(S,A)=1, d(S,B)=2, d(B,C)=1, d(A,E)=3。您的访问订单将是{S,A,B,C,E}。所以在访问A 时,您甚至无法通过BC 节省绕道,因为您不知道。您必须为每个未访问的邻居添加类似“通过 C 的潜在路径”之类的内容。

第三,您必须合并循环和 cul-de-sacs's ,因为是的,其中包含循环的路径很可能最终成为您的 100 条最短路径之一。您当然可能希望限制这一点,但这是一种普遍的可能性。例如,考虑这样的图表:

S-A--D--E
  |  |
  B--C

很明显,您可以轻松地在此处开始循环,除非您禁止“返回”(例如,如果 A->D 已经在路径中,则禁止 D->A)。实际上,如果没有明显的图形循环,这甚至是一个问题,因为在一般情况下,您总是可以在两个邻居之间进行乒乓球(路径 A-B-A-B-A-...)。

现在我什至可能忘记了一些问题。

请注意,这些事情中的大多数也使得开发通用算法变得非常困难,当然最后一部分,因为使用循环很难限制可能路径的数量(“无限循环”)。

【讨论】:

    【解决方案3】:

    这不是一个 NP 硬算法,下面的链接是 Yen 算法,用于在多项式时间内计算图中的 K-最短路径。 Yen's algorithm link

    【讨论】:

    • Yen 的算法实际上在pseudopolynomial time 中运行,因为运行时间取决于 k 的数值。尽管对于任何固定的 k - 这里 k = 100 - 它确实会在多项式时间内运行。
    【解决方案4】:

    当目的地被第 k 次推入队列时,使用 a* 搜索。这将是第 k 条最短路径。

    【讨论】:

    • 不应该是第k次出队列,不被推送吗?
    • 我不认为这种说法是正确的。你能证明吗?
    • @Mehrdad 当目的地第一次进入队列时,该值应该是最短路径。对吗?
    • @amit a* 的正确性取决于启发式 h 函数。函数 h 必须是 admissible heuristic
    • @LazyChild:对于最短路径——确实如此。假设你有启发式h(v) = 0(这总是可以接受的,基本上意味着你的问题是不知情的。你能证明算法适用于第 k 条最短路径吗?(我对此表示怀疑,因为我只是展示了一般情况下的问题k是NP-Hard,必须有其他修改比如禁用closed set)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-12
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多