哪些算法可以计算地图上从A点到B点的方向?


542

地图提供商(例如Google或Yahoo! Maps)如何建议方向?

我的意思是,他们可能具有某种形式的现实世界数据,当然包括距离,还可能包括诸如行车速度,人行道的存在,火车时刻表等。但是,假设数据采用的是更简单的格式,例如一个非常大的有向图边缘权重反映距离。我希望能够快速计算从一个任意点到另一点的方向。有时这些点会很靠近(在一个城市内),而有时它们会很远(越野)。

像Dijkstra的算法这样的图算法将无法工作,因为图非常大。幸运的是,像A *这样的启发式算法可能会起作用。但是,我们的数据非常结构化,也许某种分层方法可能有效?(例如,存储相距很远的某些“关键”点之间的预先计算的方向以及一些本地方向。然后,两个遥远点的方向将涉及到关键点的本地方向,到另一个关键点的全局方向,然后是本地再次指示。)

实际上实际使用哪些算法?

PS。这个问题是由在在线制图方向上找到古怪之处引起的。与三角形不等式相反,有时Google Maps认为XZ比使用XYZ中的中间点花费的时间更长,而且更远。但是也许他们的步行方向也针对另一个参数进行了优化?

PPS。这是对三角形不等式的另一种违反,对我而言,这暗示了他们使用某种分层方法:XZXYZ。前者似乎使用了著名的塞巴斯托波尔大道,尽管有点偏离。

编辑:这些示例似乎都不工作了,但在原始帖子发布时都可以。


3
顺便说一句,A *算法“是Dijkstra算法的一种概括,它缩小了必须探索的子图的大小,如果有其他可用信息可以提供到目标“距离”的下限”
米奇·麦特

关于A *:是的,的确如此。幸运的是,在我们的情况下,例如可以通过使用直线距离来获得此“附加信息”。当我在上面说“ Dijkstra”时,是指香草Dijkstra。
A. Rex

步行路线?邓诺(Dunno)在其他任何地方,但在此附近(英国汉普郡),大G没有行人数据-它沿着行人专用区等附近的道路指引我的路线。唯一有益的是更改路线所需时间的估计值:)
jTresidder

我并不特别在意方向是开车还是步行。我只想知道它们是如何工作的!之所以有步行链接,是因为我正在计算一种在巴黎周围漫步并参观所有66个华莱士喷泉的方法。(这些地图的端点应该是华莱士喷泉。)
A. Rex

对这个问题的赏识是鼓励鼓励更多更好的答案,特别是那些在主要提供者之一工作的人的答案。关于数据结构,算法,预计算的数量等的注释均应得到赞赏。
A. Rex

Answers:


526

以在地图公司工作了18个月的人的身份发言,其中包括在路由算法方面的工作...是的,Dijkstra确实可以工作,但有一些修改:

  • 您不必从源头到目标都进行一次Dijkstra的工作,而要从两端开始,并扩展双方直到中间相遇。这消除了大约一半的工作(2 * pi *(r / 2)^ 2 vs pi * r ^ 2)。
  • 为了避免探索源与目的地之间每个城市的后巷,您可以使用几层地图数据:仅包含高速公路的“高速公路”层,仅包含次要街道的“辅助”层,依此类推。然后,您仅浏览更详细层的较小部分,并根据需要进行扩展。显然,此描述省略了很多细节,但是您可以理解。

沿着这些路线进行修改,您甚至可以在非常合理的时间范围内进行越野布线。


29
在现实世界中从事此工作的人真棒!您是否知道可以进行多少次预计算,如另一条评论中有关Google的文章中所述?
A. Rex

10
我们没有对这种性质进行任何预处理,但是看起来确实是一个有趣的优化。
尼克·约翰逊,

29
“这只能保证提供解决方案,不一定是最有效的解决方案”。只要允许使用启发式算法,A *算法就会产生成本最低的路径。可以接受意味着成本永远不会被高估,但可能会被低估(但是估算不佳会使算法变慢)。使用来自预处理的数据可能有助于做出更好的可接受启发式,从而使A *工作更快。
a1kmm

6
实际上,进一步考虑,您是完全正确的。您可以通过简单地将目标节点和目标之间的大圆距离添加到要评估的边的成本中,来增强现有算法以利用此算法。我实际上不确定我们的算法是否能做到这一点-但这是一个非常明智的优化。
尼克·约翰逊,

11
在最坏的情况下(表示所有路径都相等的启发式方法),A *等于Djikstra的值。
Tordek 2010年

111

近年来,这个问题一直是研究的活跃领域。主要思想是对图形进行一次预处理,以加快所有后续查询的速度。利用这些附加信息,可以非常快速地计算行程。尽管如此,Dijkstra的算法仍是所有优化的基础。

Arachnid描述了基于分层信息的双向搜索和边缘修剪的用法。这些加速技术效果很好,但是最新的算法在所有方面都优于这些技术。使用当前的算法,在大陆公路网络上,最短路径的计算时间可少于一毫秒。Dijkstra的未修改算法的快速实现需要大约10秒

工程快速路线规划算法》一书概述了该领域的研究进展。有关更多信息,请参见该文件的参考。

已知最快的算法不会在数据中使用有关道路等级状态的信息,即,如果是高速公路或本地道路。取而代之的是,它们在预处理步骤中计算自己的层次结构,并对其进行优化以加快路线规划。然后可以使用这种预计算来简化搜索:在Dijkstra算法中,无需考虑远离起点和目的地的慢行道路。好处是非常好的性能和结果的正确性保证。

第一个优化的路线规划算法仅处理静态道路网络,这意味着图中的边具有固定的成本值。实际上,情况并非如此,因为我们要考虑动态信息,例如交通拥堵或与车辆相关的限制条件。最新的算法也可以解决此类问题,但仍有许多问题需要解决,并且研究正在进行中。

如果您需要最短的路径距离来为TSP计算解决方案,那么您可能会对包含源与目标之间的所有距离的矩阵感兴趣。为此,您可以考虑使用高速公路层次结构计算多对多最短路径。请注意,在过去的两年中,这已经通过更新的方法得到了改善。


1
确实有启发性。您提到的是哪种较新的方法?
Tomas Pajonk

1
特别是收缩层次结构。您可以在这里找到更多有关它的信息:algo2.iti.kit.edu/routeplanning.php。还有一个Google技术方面的话题:youtube.com/watch?v=-0ErpE8tQbw
SebastianK,2010年

19

仅仅解决三角不等式违规问题,希望他们正在优化的额外因素是常识。您不一定需要最短或最快的路线,因为它可能导致混乱 破坏。如果您希望自己的路线偏爱卡车友好的主要路线,并且可以应付所有跟随卫星导航的驾驶员,那么您可以迅速放弃三角形不等式[1]。

如果Y是介于X和Z之间的狭窄居民区,那么您可能只想在用户明确要求XYZ时通过Y使用快捷方式。如果他们要求使用XZ,那么即使走得更远并且花费更长的时间,他们也应该坚持主要道路。这类似于Braess的悖论 -如果每个人都试图走最短,最快的路线,那么造成的拥堵就意味着它不再是任何人的最快路线。从这里开始,我们从图论到博弈论。

[1]实际上,当您允许单向道路并且失去对称性要求时,任何希望产生的距离将是数学意义上的距离函数的希望都会消失。失去三角形不等式也只是在伤口上撒盐。



9

我以前从未在Google或Microsoft或Yahoo Maps上工作过,所以无法告诉您它们是如何工作的。

但是,我为一家能源公司设计了一个定制的供应链优化系统,其中包括针对其卡车队的调度和路线选择应用程序。但是,我们的路线选择标准要比针对业务的标准要高得多,而不是针对建筑或交通缓慢或关闭车道的地方。

我们采用了一种称为ACO(蚁群优化)的技术来调度和路由卡车。此技术是一种AI技术,已应用于旅行商问题以解决路线问题。ACO的窍门是根据路由的已知事实建立错误计算,以便图形求解模型知道何时退出(何时错误足够小)。

您可以通过Google ACO或TSP来查找有关此技术的更多信息。但是,我没有为此使用任何开源AI工具,因此无法提出一个建议(尽管我听说SWARM非常全面)。


4
路由!= tsp。在茶匙中,您知道所有距离并优化止损顺序-这不是点对点算法。
Karussell 2012年

8

像Dijkstra的算法这样的图算法将无法工作,因为图非常大。

这个论点不一定成立,因为Dijkstra通常不会看完整的图,而只是看一个很小的子集(图的互连越好,这个子集就越小)。

对于行为良好的图,Dijkstra实际上可能表现不错。另一方面,通过仔细的参数化,A *的性能将始终相同或更好。您是否已经尝试过如何处理数据?

话虽如此,我也非常有兴趣听到其他人的经历。当然,诸如Google Map搜索之类的突出示例尤其有趣。我可以想像像定向最近邻居启发式的东西。


2
假设您尝试查找从点A到B的方向,其最佳距离为d。Dijkstra的算法至少将检查距A最多d处的所有点。如果A是旧金山,B是波士顿,则意味着它检查了美国大部分地区。N'est-ce pas?
A. Rex

2
是的。我想说的是,可以代替使用A *,并且它总是找到最佳解决方案(即使它使用了启发式方法)!
康拉德·鲁道夫

当然是。写完原始帖子后,我想到了我使用的“启发式”一词。这里有点不准确,因为它确实找到了最佳解决方案。
A. Rex 2009年

2
那么,问题是,A * 使用启发式(而不是一个),以确定下一个步骤。这个决定确实可能不是最佳的。但这只会影响运行时,而不会影响结果,因为它只能确定比猜测的Dijstra好多少。
康拉德·鲁道夫

8

就静态道路网络的查询时间而言,当前的最新技术是Abraham等人提出的Hub标签算法。http://link.springer.com/chapter/10.1007/978-3-642-20662-7_20。最近通过Microsoft技术报告http://research.microsoft.com/pubs/207102/MSR-TR-2014-4.pdf出版了对该领域的详尽透彻的调查报告。

简短的版本是...

集线器标记算法可为静态道路网络提供最快的查询,但需要大量的内存才能运行(18 GiB)。

传输节点路由稍微慢一些,尽管它只需要大约2 GiB的内存,并且预处理时间更快。

压缩层次结构在快速预处理时间,低空间要求(0.4 GiB)和快速查询时间之间提供了很好的折衷方案。

没有人能完全控制算法...

彼得·桑德斯(Peter Sanders)的这次Google技术讲座可能会引起人们的兴趣

https://www.youtube.com/watch?v=-0ErpE8tQbw

还有Andrew Goldberg的演讲

https://www.youtube.com/watch?v=WPrkc78XLhw

可以从KIT的Peter Sanders研究小组网站上获得收缩层次结构的开源实现。http://algo2.iti.kit.edu/english/routeplanning.php

也是Microsoft撰写的有关CRP算法在该处的用法的易于访问的博客文章。http: //blogs.bing.com/maps/2012/01/05/bing-maps-new-routing-engine/


7

我很惊讶没有看到这里提到的Floyd Warshall算法。该算法的工作与Dijkstra的非常相似。它还有一个非常不错的功能,那就是只要您希望继续允许更多中间顶点,就可以进行计算。因此,它自然会很快找到使用州际公路或高速公路的路线。


6

实际上,我已经做了很多次,尝试了几种不同的方法。根据地图的大小(地理位置),您可能需要考虑使用Haversine函数作为启发式方法。

我做出的最好的解决方案是将A *与直线距离作为启发函数。但是随后您需要为地图上的每个点(相交或顶点)提供某种坐标。您还可以为试探函数尝试不同的权重,即

f(n) = k*h(n) + g(n)

其中k是大于0的常数。


4

大概类似于主要位置和分层地图之间的预先计算路线的答案,但我的理解是,在游戏中,为了加快A *速度,您需要使用一张非常粗略的地图进行宏导航,并使用一张细粒度的地图导航到宏方向的边界。因此,您有2条较小的路径可以计算,因此您的搜索空间比简单地到达目的地的单个路径要小得多。而且,如果您需要做很多事情,那么您将需要对大量数据进行预先计算,因此至少一部分搜索是对预先计算的数据的搜索,而不是路径的搜索。


3

这纯粹是推测,但我想他们可能会使用覆盖有向图的影响图数据结构来缩小搜索范围。当所需行程较长时,这将允许搜索算法将路径引导至主要路线。

鉴于这是一个Google应用程序,因此可以合理地假设很多魔术是通过广泛的缓存完成的。:)如果缓存最常见的5%的Google Map路线请求中的大部分(20%或50%?)的请求可以通过简单的查询来回答,我不会感到惊讶。


您对“影响图数据结构”有很好的参考吗?谢谢!
A. Rex

3

我对此有更多的想法:

1)请记住,地图代表的是物理组织。存储每个交叉点的纬度/经度。您无需进行过多检查即可超出目标方向。仅当发现自己被阻止时,您才需要超越此范围。如果存储高级连接的叠加,则可以进一步限制它-通常,您永远不会以与最终目的地背道而驰的方式跨越其中之一。

2)将世界划分为由有限连通性定义的整个区域,并定义区域之间的所有连通性点。查找源和目标所在的区域,从您的位置到每个连接点的起点和终点区域路线,连接点之间的简单映射之间的区域。(我怀疑其中很多已经预先计算了。)

请注意,区域可以小于都市区域。任何具有地形特征的城市(例如河流)都将是多个区域。


3

我对使用的启发式方法感到非常好奇,前一段时间,我们从圣罗莎附近的同一出发地到约塞米蒂国家公园的两个不同的露营地都有路线。尽管这两个路线汇合了最后100英里(沿着CA-120),但最终却又分开了几英里,因此这些不同的目的地产生了截然不同的路线(通过I-580或CA-12)。这是相当可重复的。两条路线之间相距50英里(约100英里),但距离/时间却彼此相距不远。

las,我无法重现这一点-算法必须已更改。但这让我对算法感到好奇。我可以推测的是,从远处看,有一些定向修剪恰好对目的地之间的微小角度差异非常敏感,或者通过选择最终目的地而选择了不同的预计算段。


3

谈到基于OpenStreetMap的快速开源路线规划器GraphHopper,我已经阅读了一些文献并实现了一些方法。最简单的解决方案是Dijkstra,一个简单的改进是双向Dijkstra,它仅探索大约一半的节点。使用双向Dijkstra,通过整个德国的路线已花费1秒(对于汽车模式),在C中大概只有0.5秒左右;)

我在这里使用双向Dijkstra创建了真实路径搜索的动画gif 。还有更多的想法可以使Dijkstra更快,就像做A *,这是“面向目标的Dijkstra”一样。我也为此创建了gif动画

但是如何(更快)做到呢?

问题在于,对于路径搜索,必须探索位置之间的所有节点,这确实很昂贵,因为在德国已经有数百万个了。但是Dijkstra等人的另一个痛苦点是,这种搜索使用了大量的RAM。

有启发式解决方案,也有一些精确的解决方案可以在层次结构中组织图(道路网络),既有优点也有缺点,主要解决了速度和RAM问题。我已经在这个答案中列出了其中一些。

对于GraphHopper,我决定使用收缩层次结构,因为它相对“易于实施”并且不需要花费很多时间来准备图形。它仍然可以带来非常快的响应时间,就像您可以在我们的在线实例GraphHopper Maps上进行测试一样。例如,从南非到中国东部,导致23000公里的距离和近14天的汽车行驶时间,并且在服务器上仅花费了约0.1s。


使用地标进行双向Dijkstra进行目标定向搜索比单独使用双向Dijkstra效率更高。请参阅www14.informatik.tu-muenchen.de/lehre/2010SS/sarntal/…。 但是,本文不够详细,无法计算潜在函数,这有些棘手,或者选择了界标。
Paul Chernoch

2

我从事路由工作已经有几年了,由于客户的需求,最近的活动激增了,我发现A *足够快。确实没有必要寻找优化或更复杂的算法。在巨大的图形上路由不是问题。

但是速度取决于整个路由网络,这是指内存中分别表示路由段和路口的弧和节点的有向图。主要时间开销是创建此网络所需的时间。基于运行Windows并在整个西班牙范围内路由的普通笔记本电脑的一些粗略数据:创建网络所需的时间:10-15秒;计算路线所需的时间:太短而无法测量。

另一个重要的事情是能够根据需要重新使用网络进行尽可能多的路由计算。如果您的算法以某种方式标记了节点以记录最佳路径(到当前节点的总成本,以及到达该节点的最佳弧度)(如在A *中所必须的),则您必须重置或清除此旧信息。与其遍历数十万个节点,不如使用世代号系统。在每个节点上标记其数据的生成编号;计算新路线时增加世代数;具有较早代号的任何节点都是陈旧的,其信息可以忽略。


1

我看到了OP中的地图的最新动态:

查看指定了中间点的路线:由于该道路不直,因此该路线稍微向后走。

如果他们的算法不会回溯,它将看不到更短的路线。


有趣的主意。我在PPS中向OP添加了另一个违规行为。请看一看,看看是否可以在其中看到解释。
A. Rex

WAY缩小至A点-最多点击一次 注意三点路线如何向西,向南,向东行驶。我认为我们正在寻找一种不希望回溯的算法,除非有必要经过一个瓶颈。
罗伦·佩希特尔

在我的PPS示例中,将起始地址更改为“巴黎75019法兰德大街10号”。这消除了您正在谈论的小问题,但问题仍然存在。我认为主要的问题是,它真的想留在主要的大道上
A. Rex

1
我想我是在这种情况下找到的:开车来做这些和时间安排是否合理。它可能会认为这条大路走得更快,而步行路线并没有阻止它。
罗伦·佩希特尔

1
PS:按照这个标准,最初的问题也很有意义,可能不是造成它的回溯。
罗伦·佩希特尔

0

全对最短路径算法将计算图中所有顶点之间的最短路径。这将允许对路径进行预先计算,而不是每次有人要查找源与目标之间的最短路径时都需要计算路径。Floyd-Warshall算法是全对最短路径算法。


-4

地图永远不会考虑整个地图。我的猜测是:1.根据您的位置,它们会加载一个位置以及该位置上的地标。2.搜索目的地时,即当它们加载地图的另一部分并在两个位置之外绘制一个图,然后应用最短路径算法。

另外,有一种重要的技术是动态编程,我怀疑它可以用于计算最短路径。您也可以参考。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.