我正在开发一个寻路程序。据说理论上A *比Dijkstra好。事实上,后者是前者的特例。然而,当在现实世界中进行测试时,我开始怀疑A *真的更好吗?
我使用了来自 9th DIMACS Implementation Challenge - Shortest Paths 的纽约市数据,其中给出了每个节点的纬度和经度。
当应用A *时,我需要使用Haversine Formula计算两点之间的球面距离,其中涉及sin,cos,arcsin,平方根。所有这些都非常耗时。
结果是,
使用Dijkstra:39.953毫秒,扩展了256540个节点。
使用A *,108.475 ms,扩展了255135个节点。
注意到在A *中,我们扩展了1405个节点。但是,计算启发式的时间远远超过保存的时间。
根据我的理解,原因在于,在一个非常大的实图中,启发式的权重将非常小,并且可以忽略它的效果,而计算时间占主导地位。
答案 0 :(得分:33)
我认为你或多或少错过了A *的观点。它旨在成为一种非常高效的算法,部分是通过有意识地做更多的工作,但是使用廉价的启发式方法,并且当你使用极其准确的预测启发式加载它时,你会有点撕裂它。
对于A *中的节点选择,您应该使用距离的近似值。简单地使用(latdiff ^ 2)+(lngdiff ^ 2)作为近似距离应该使您的算法比Dijkstra更高效,并且在任何现实世界场景中都不会给出更糟糕的结果。实际上,如果您使用Haversine正确计算选定的节点上的行进距离,结果应该完全相同。只需使用便宜的算法来选择潜在的下一次遍历。
答案 1 :(得分:11)
A*
简化为Dijkstra。 Dijkstra有三种可能的改进方式:
A*
应该使用一种启发式方法,它不会高估与目标的距离,作为其成本函数的一部分。对于后者,你应该尝试在现有的研究基础上,例如: Abraham等人“公路维度,最短路径和可证明的高效算法”
答案 2 :(得分:9)
与宇宙中的一切一样,需要权衡利弊。您可以将dijkstra的算法用于精确计算启发式算法,但这样做会失败的目的不是吗?
A *是一个很好的算法,因为它让你倾向于有一个基因想法首先扩展哪个方向的目标。也就是说,你应该保持启发式尽可能简单,因为你需要的只是一个大方向。
事实上,不基于实际数据的更精确的几何计算并不一定能为您提供更好的方向。只要它们不是基于数据,所有这些启发式方法都只为您提供了一个方向,它们都是正确的(正确)。
答案 3 :(得分:4)
一般来说A *比Dijkstra更高效,但它确实取决于你在A *中使用的启发式功能。你会想要一个乐观的h(n)并找到最低成本路径,h(n)应该小于真实成本。如果h(n)> = cost,那么你最终会遇到类似于你所描述的情况。
你能发布你的启发式功能吗?
答案 4 :(得分:3)
还要记住,这些算法的性能很大程度上取决于图的性质,这与启发式的准确性密切相关。
如果你比较Dijkstra和A *在迷宫中导航时每个段落对应一个图形边缘,那么性能可能差别很小。另一方面,如果图形在“远离”节点之间具有许多边缘,则差异可能非常大。想象一下机器人(或AI控制的计算机游戏角色)在几乎没有障碍的情况下在几乎开阔的地形中航行。
我的观点是,尽管您使用的纽约数据集绝对是“真实世界”图形的一个很好的例子,但它并不能代表所有真实世界的寻路问题。