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