地图提供商(例如Google或Yahoo! Maps)如何提供方向?
我的意思是,他们可能有某种形式的真实数据,当然包括距离,但也可能包括行驶速度,人行道的存在,火车时刻表等等。但是假设数据格式较简单,比如说非常简单。具有反映距离的边权重的大有向图。我希望能够快速计算从任意点到另一个点的方向。有时候这些点会在一起(在一个城市内),而有时它们会相隔很远(越野)。
Dijkstra算法之类的图算法不起作用,因为图形很大。幸运的是,像A *这样的启发式算法可能会起作用。但是,我们的数据非常有条理,也许某种分层方法可能有用吗? (例如,存储远离某些“关键”点之间的预先计算方向,以及一些局部方向。然后,两个远点的方向将涉及到关键点的本地方向,到另一个关键点的全局方向,然后是本地方向再次指示。)
实际使用了哪些算法?
PS。这个问题的动机是通过在线地图方向找到怪癖。与三角不等式相反,有时谷歌地图认为X-Z需要更长时间,并且比使用X-Y-Z中的中间点更远。但也许他们的行走方向也会优化另一个参数?
PPS。这是对三角不等式的另一个违反,它暗示(对我而言)他们使用某种分层方法:X-Z与X-Y-Z。前者似乎使用着名的Boulevard de Sebastopol,尽管它稍微偏僻。
修改:这些示例似乎都不再起作用,但两者都是在原始帖子发布时。
答案 0 :(得分:510)
作为在地图公司工作了18个月的人,其中包括处理路由算法...是的,Dijkstra's确实有效,只需进行一些修改:
通过这些方面的修改,您甚至可以在非常合理的时间范围内进行跨国路由。
答案 1 :(得分:107)
这个问题在过去几年一直是一个活跃的研究领域。主要想法是在图表上预处理 一次,加速所有后续查询。通过这些附加信息,可以非常快速地计算行程。仍然, Dijkstra的算法是所有优化的基础。
Arachnid 描述了基于分层信息的双向搜索和边缘修剪的用法。这些加速技术运行良好,但最新的算法无论如何都优于这些技术。使用当前算法,可以在大陆公路网上以比 1毫秒相当短的时间计算最短路径。快速实现Dijkstra的未修改算法需要 10秒。
文章Engineering Fast Route Planning Algorithms概述了该领域的研究进展。有关详细信息,请参阅该论文的参考文献。
最快的已知算法不使用关于数据中道路的分层状态的信息,即,如果它是高速公路或本地道路。相反,他们在预处理步骤中计算自己的层次结构,该层次结构经过优化以加速路径规划。然后可以使用该预计算来修剪搜索:在Dijkstra算法期间,不需要考虑远离起点和目的地的慢速道路。效果非常好性能,正确性保证结果。
第一个优化路径规划算法仅处理静态道路网络,这意味着图中的边缘具有固定的成本值。这在实践中并非如此,因为我们想要考虑交通拥堵或车辆相关限制的动态信息。最新算法也可以解决这些问题,但仍有问题需要解决,研究正在进行中。
如果您需要最短路径距离来计算 TSP 的解决方案,那么您可能对包含源和目标之间所有距离的矩阵感兴趣。为此,您可以考虑Computing Many-to-Many Shortest Paths Using Highway Hierarchies。请注意,在过去的两年中,这种方法得到了改进。
答案 2 :(得分:18)
只是解决三角不等式违规问题,希望他们优化的额外因素是常识。您不一定需要最短或最快的路线,因为它可能会导致chaos and destruction。如果您希望您的路线更喜欢卡车友好的主要路线,并且能够应对每个坐骑导航跟随的司机,那么您很快就会丢弃三角形不等式[1]。
如果Y是X和Z之间的狭窄住宅街道,如果用户明确要求X-Y-Z,您可能只想通过Y使用快捷方式。如果他们要求X-Z,他们应该坚持主要道路,即使它更进一步,需要更长的时间。它类似于Braess's paradox - 如果每个人都试图采用最短,最快的路线,那么产生的拥堵意味着它不再是任何人的最快路线。从这里我们偏离了图论到博弈论。
[1]事实上,当你允许单向道路并失去对称性要求时,任何希望所产生的距离将成为数学意义上的距离函数。失去三角不等也只是在伤口擦盐。
答案 3 :(得分:14)
这是世界上最快的路由算法,比较并证明了正确性:
http://algo2.iti.uka.de/schultes/hwy/schultes_diss.pdf
这是关于这个主题的谷歌技术讲座:
http://www.youtube.com/watch?v=-0ErpE8tQbw
以下是schultes讨论的高速公路 - 层次结构算法的实现(目前仅在柏林,我正在编写接口,并且正在开发移动版本):
答案 4 :(得分:9)
之前我没有在谷歌,微软或雅虎地图上工作过,所以我不能告诉你它们是如何工作的。
然而,我确实为一家能源公司设计了一个定制供应链优化系统,其中包括为其车队提供的调度和路由应用程序。但是,我们的路线标准远比建筑或交通减速或车道关闭更具商业性。
我们采用了一种名为ACO(蚁群优化)的技术来安排和路由卡车。这种技术是一种AI技术,应用于旅行商问题以解决路由问题。 ACO的技巧是根据路由的已知事实构建错误计算,以便图解决模型知道何时退出(何时错误足够小)。
您可以使用Google ACO或TSP查找有关此技术的更多信息。我没有使用任何开源AI工具,所以不能建议一个(虽然我听说SWARM非常全面)。
答案 5 :(得分:8)
像Dijkstra算法这样的图算法不起作用,因为图形很大。
这个论点并不一定适用,因为Dijkstra通常不会查看完整的图,而只是一个非常小的子集(图表越好互连,这个子集越小)。
对于表现良好的图表,Dijkstra实际上可能表现得相当不错。另一方面,通过仔细的参数化,A *总能表现得更好或更好。您是否已经尝试过如何对数据执行操作?那就是说,我也很想知道其他人的经历。当然,谷歌地图搜索等突出的例子特别有趣。我可以想象像定向最近邻居启发式的东西。
答案 6 :(得分: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。
简短版本是......
Hub标记算法为静态道路网络提供最快的查询,但需要运行大量的ram(18 GiB)。
Transit节点路由稍慢,但它只需要大约2 GiB的内存并且预处理时间更短。
收缩层次结构在快速预处理时间,低空间要求(0.4 GiB)和快速查询时间之间提供了良好的折衷。
没有一种算法完全支配......
Peter Sanders的Google技术演讲可能会引起人们的兴趣
https://www.youtube.com/watch?v=-0ErpE8tQbw
安德鲁·戈德堡的这次演讲
https://www.youtube.com/watch?v=WPrkc78XLhw
KIT的Peter Sanders研究组网站提供了收缩层次结构的开源实现。 http://algo2.iti.kit.edu/english/routeplanning.php
这是一篇易于访问的博客文章,由微软撰写有关使用CRP算法的文章... http://blogs.bing.com/maps/2012/01/05/bing-maps-new-routing-engine/
答案 7 :(得分:7)
我有点不高兴看不到这里提到的Floyd Warshall's algorithm。这个算法与Dijkstra非常相似。它还有一个非常好的功能,它允许您计算,只要您想继续允许更多的中间顶点。所以它会很快找到使用州际公路或高速公路的路线。
答案 8 :(得分:6)
我已经做了很多次,实际上,尝试了几种不同的方法。根据地图的大小(地理位置),您可能需要考虑使用hasrsine函数作为启发式。
我所做的最佳解决方案是使用直线距离A *作为启发式函数。但是,你需要为地图上的每个点(交叉点或顶点)设置某种坐标。您还可以尝试不同的启发函数权重,即
f(n) = k*h(n) + g(n)
其中k是某个大于0的常数。
答案 9 :(得分:4)
可能类似于主要位置和分层地图之间的预先计算路线的答案,但我的理解是,在游戏中,为了加快A *,你有一张非常粗略的地图用于宏观导航,并且精细 - 用于导航到宏观方向边界的粒度图。因此,您有2个小路径可供计算,因此您的搜索空间远比简单地执行到目的地的单个路径要小得多。如果您经常这样做,那么您需要预先计算大量的数据,因此至少部分搜索是搜索预先计算的数据,而不是搜索路径。
答案 10 :(得分:3)
这是我的纯粹推测,但我认为他们可能会使用覆盖定向地图的影响地图数据结构来缩小搜索范围。这将允许搜索算法在期望的旅行很长时将路径引导到主要路线。
鉴于这是一个谷歌应用程序,假设通过广泛的缓存完成了很多魔术也是合理的。 :)如果缓存前5%最常见的谷歌地图路线请求允许通过简单的查找来回答大块(20%?50%?)的请求,我不会感到惊讶。
答案 11 :(得分:3)
我对此有了更多的想法:
1)请记住,地图代表一个物理组织。存储每个交叉路口的纬度/经度。您不需要检查远远超出目标方向的点。只有当你发现自己被阻止时,你才需要超越这个范围。如果你存储一个优质连接的叠加层,你可以限制它 - 你通常不会以远离最终目的地的方式穿过其中一个。
2)将世界划分为由有限连接定义的一大堆区域,定义区域之间的所有连接点。查找源和目标所在的区域,从您的位置到每个连接点的起始和结束区域路径,以及简单地在连接点之间映射的区域。 (我怀疑很多后者已经预先计算好了。)
请注意,区域可能小于都市区域。任何具有地形特征的城市(例如河流)将是多个区域。
答案 12 :(得分:3)
我对使用的启发式方法非常好奇,不久前我们从圣罗莎附近的同一起始位置到约塞米蒂国家公园的两个不同的露营地。这些不同的目的地产生了完全不同的路线(通过I-580或CA-12),尽管两条路线在最后100英里(沿着CA-120)汇合,然后在最后几英里再次发散。这是非常可重复的。这两条路线相距50英里,行程约100英里,但距离/时间非常接近,正如您所期望的那样。
唉我无法重现 - 算法必须改变。但它让我对这个算法感到好奇。我可以推测的是,有一些定向修剪恰好对从远处看到的目的地之间的微小角度差异非常敏感,或者通过选择最终目的地选择了不同的预先计算的分段。
答案 13 :(得分:3)
说到GraphHopper, 一个基于OpenStreetMap的快速开源路由规划器,我已经阅读了一些文献并实现了一些方法。最简单的解决方案是Dijkstra,简单的改进是双向Dijkstra,它大致只探索了一半的节点。通过双向Dijkstra,通过整个德国的路线已经需要1秒(对于汽车模式),在C中它可能只有0.5秒左右;)
我用双向Dijkstra here创建了一个真实路径搜索的GIF动画。还有更多的想法make Dijkstra faster喜欢做A *,这是一个“目标导向的Dijkstra”。我也为它创建了一个gif-animation。
但是如何(更多)更快地完成它?
问题在于,对于路径搜索,必须探索这些位置之间的所有节点,这实际上是非常昂贵的,因为德国已有数百万个节点。但Dijkstra等另一个痛点就是这种搜索使用了大量的RAM。
有启发式解决方案,但也有确切的解决方案,在层次结构层中组织图形(道路网络),既有优点和缺点,主要解决速度和RAM问题。我在this answer中列出了其中一些内容。
对于GraphHopper,我决定使用Contraction Hierarchies,因为它相对“容易”实现,并且不需要花费很长时间来准备图表。它仍会导致非常快的响应时间,就像您可以在我们的在线实例GraphHopper Maps进行测试一样。例如。 from south Africa to east China导致23000公里的距离和近14天的驾驶时间,并且在服务器上只需0.1秒。
答案 14 :(得分:2)
我已经在路由工作了几年,最近我的客户需求引发了一系列活动,我发现A *很快就够了;实际上没有必要寻找优化或更复杂的算法。在巨大的图表上进行路由不是问题。
但速度取决于拥有整个路由网络,我指的是分别在内存中表示路径段和连接点的弧和节点的有向图。主要的时间开销是创建此网络所需的时间。基于普通笔记本电脑运行Windows的一些粗略数字,以及整个西班牙的路由:创建网络的时间:10-15秒;计算路线所花费的时间:太短而无法衡量。
另一个重要的事情是能够重新使用网络进行任意数量的路由计算。如果您的算法以某种方式标记节点以记录最佳路径(当前节点的总成本,以及最佳弧度) - 就像它必须在A *中一样 - 您必须重置或清除这些旧信息。与使用数十万个节点不同,使用世代号系统更容易。用每个节点的数据世代号标记每个节点;计算新路线时增加世代号;具有较旧代号的任何节点都是陈旧的,其信息可以忽略。
答案 15 :(得分:1)
我看到OP中的地图有什么用:
查看指定中间点的路线:由于道路不直,路线略微向后移动。
如果他们的算法不会回溯,则不会看到较短的路线。
答案 16 :(得分:0)
全对最短路径算法将计算图中所有顶点之间的最短路径。这将允许预先计算路径,而不是每当有人想要找到源和目的地之间的最短路径时需要计算路径。 Floyd-Warshall算法是一对全对最短路径算法。
答案 17 :(得分:-4)
地图永远不会考虑整个地图。 我的猜测是: - 根据你所在的位置,他们在那个地方装载一个地方和地标。 2.当您搜索目的地时,那就是当他们加载地图的其他部分并从两个地方创建一个图表然后应用最短路径算法。
此外,还有一项重要的技术动态编程我怀疑它用于计算最短路径。你也可以参考它。