巨型图上的Dijkstra算法


15

我对Dijkstra非常熟悉,并且对算法有一个特定的问题。如果我有一个巨大的图,例如35亿个节点(所有OpenStreetMap数据),那么我显然将无法在内存中使用该图,因此该图存储在数据库的磁盘上。

有一些库可用于计算此类图上的最短路径。他们如何做到这一点?更具体地说,他们如何加载图的必需部分以运行Dijkstra的算法?

根据我的统计数据,获取访问的每个顶点的邻接表将需要每10,000个节点大约1,500个数据库查询,因此显然不是他们如何做到的。那太慢了。

他们是如何做到的呢?我正在尝试自己实施。


2
您确定他们使用Dijkstra吗?还有许多其他最短路径算法可能更适合您描述的情况。
David Richerby '16

1
你看过代码了吗?我们怎么知道 “数据库查询”-希望您不使用DBMS来存储图形吗?
拉斐尔

@DavidRicherby是的,我确定,请查看此链接
dimitris93

2
“研究纯C代码将是一个非常繁琐的过程。” 但这是了解代码功能的唯一方法。因此,您只是在要求我们为您完成繁琐的任务,这并不是您所要解决的最大问题……
David Richerby 2016年

1
@Shiro您明确地问:“他们是怎么做到的?” 如果这不是您真正要问的问题,则需要重新措辞。
拉斐尔

Answers:


6

有一些库可用于计算此类图上的最短路径。他们如何做到这一点?更具体地说,他们如何加载图的必需部分以运行Dijkstra的算法?

您可以使用DB,从光盘读取的自定义文件格式和内存设置。

但是根据我的经验,与基于“简单”链接列表格式编写自己的文件格式相比,使用数据库的速度大约慢5到10倍,并且占用大量内存。

好消息是有几种使用OSM的软件框架是开源的,因此您可以直接查看代码,例如参见此处。在GraphHopper开源路由引擎中,从内存映射设置(基于磁盘)切换到内存中设置非常容易-两者都使用相同的格式。“ mmap”设置甚至允许在受内存限制的移动设备上使用,如果您在服务器上有必要的RAM,则后者的执行速度要快得多。例如,对于一张全球图(> 100mio节点),您需要大约8-10gb的RAM,如果想进一步加速一切,例如收缩层次结构,则需要更多的RAM-对于您想要的每辆车,大约需要5-8gb。

格式非常简单,基本上只存储您需要的数据,并通过一些技巧使其紧凑。在此处了解更多信息。免责声明:我是GraphHopper的作者。

关于其他答案:

Dijkstras算法在适用时被认为不是针对此问题的最佳算法

“正常”的Dijkstra可以执行非常合理的操作(对于3mio节点示例这样的全国性查询,其结果为<1s),并且在“理论意义上” 是最佳的,但需要进行一些调整才能在生产场景中快速实现。诸如收缩等级法之类的技术使用了它的双向修改,并且表现出色。

道路网络是分层且平坦的。

道路网络是仅适用于汽车的分层系统,并非平坦的(桥梁,隧道等)


我还有一个问题。如何NodeID从中找到最近的节点latitude/longitude?这是计算最短路径A-> B所必需的。而且我们还需要记住,A和B可能不作为节点存在,因为并非每平方米都包含一个节点。因此,我们需要找到A和B的2个最接近的NodeID。–
dimitris93

这是在LocationIndexTree中完成的,LocationIndexTree是一种四叉树,可有效地在一个单元中存储NodeID,例如,对于GraphHopper,其半径约为500m。如果什么也没找到,它会将半径扩大到一定程度。从理论上讲,这听起来很简单,但是却非常复杂,因为您可能需要跨越该区域的边缘,因此在创建和查询区域时还需要提高效率。
Karussell

搜索最近的邻居时,KD树不是更有效吗?为什么选择QuadTrees而非KD-Trees?我现在正在为我的路由引擎实现KD-Trees。我开始实现QuadTree,但由于发现KD-Tree是同一件事,但是却更容易编写代码,并且更快地查询最近的邻居而停止了。我错了吗 ?
dimitris93 '16

当使用四叉树时,无需显式存储边界框即可为它提供存储优势,这对我的用例而言更为关键(我也发现四叉树更容易;)。查询速度不是问题。实际上,有人研究过这种尝试,它的性能优于其他任何实现,包括。KD树,但我认为一切都取决于特定的实现...
Karussell

如果您查看斯坦福大学这份pdf文件的第9页,则在KD-Trees中搜索最近的邻居根本不需要您知道边界框。另一件事是,因为我们事先知道所有点,所以我们可以创建一个logn高度的平衡树。您是否仍然坚信四叉树比kd树有任何优势?
dimitris93

2

您无需将所有相邻的边放在优先级队列中。对Dijkstra的算法“说谎”,并仅将入射到顶点(例如w)的最短顶点v从栈中拉出。然后,当v被拉出队列时,您说“哎呀”,我犯了一个错误,并且也应该给您这个顶点,它是第二个最接近顶点w的顶点。可以很容易地看出,通过这种方式,您将获得正确的解决方案,并且队列大小仅减少到一个入射顶点,而不是多个顶点。但是,您需要跟踪事件,以便始终在需要时给出下一个最接近的顶点。评论中的一项声称道路网络是平面的,这是不正确的。实际上,一项研究表明它们是高度非平面的。想想所有通过桥梁穿过城市的高速公路会导致许多非平面性。


0

尽管可以将更有效的变体视为“相似”,但Dijkstras算法虽然适用,但对于该问题并不是最佳选择。有各种简化。道路网络是等级的平面的。这是基本方法。该区域通常称为“道路网络中的路线规划”。

  • 可以从邻接表数据中“编译”图形结构。这是您引用的库SpatiaLite中的方法。这些图形结构以压缩的二进制格式存储,其中图形位置由二进制编码的整数等表示,因此图形表示和操作所占用的空间比存储所有道路名称等要少得多。看来SpatiaLite算法不是“在线”的,并且完全在内存中运行。

  • 有并行/分布式算法。参见例如可扩展GPU图遍历 / Merrill,Garland,Grimshaw。

  • 该问题使用客户端-服务器术语,即“查询”。从客户端-服务器的角度来看,这些算法不能通过“查询”数据库来运行。诸如SQL之类的高级查询语言是数据库的接口,可用于传输请求以计算最小路由,但算法内部不使用。通常,该算法在“数据库内部”运行,即完全在“服务器端”运行。因此,在小型数据库中,但在中大型数据库中,在数据库查询中编写最短路径算法是可行的。

  • 还有另一种方法可以接受较小百分比的估算。基本思想是保持节点之间的距离索引。参见例如大图中最短路径的快速准确估计 / Gubichev,Bedathur,Seufert,Weikum

  • (235p!)博士论文特别适用。道路网络 /舒尔特山脉中的路线规划

  • 一些算法使用了许多这样的想法,而另一些则经过高度调整和专有,并在竞争性商业机密上得到验证。例如谷歌的。在这个问题上可能会有一些误导性的媒体。例如,使Google地图成为可能的简单,优雅的算法声称/暗示Google使用Dijkstras算法而没有引用。


1
Google Maps当然已经升级到比Dijskstra更好的东西。每个中途有能力的开发人员都将A *用作路线图,但是在我之前的工作中,我们发现Google的引擎可以在不到100毫秒的时间内通过航路点重新规划2500公里的路线。对于A *来说,这太快了,因此他们可能使用了诸如ArcFlags之类的东西。
MSalters '16

Karussell的答案挑战了这一开篇句子“ Dijkstras算法,而适用性被认为不是针对该问题的最佳选择”,这没想到会引起争议。Schultes论文(早期)中的断言得到了非常有力的支持,这也是对该地区的非常全面/最新的调查,还解释了“分层和平面”的“近似”。不幸的是,在关于游标搜索的开放文献中似乎没有迹象表明实际的谷歌算法。
vzn

-2

在如此大的数据集上,要获得如此快速的结果,我发现最好使用具有路径压缩的联合查找数据结构。但是,如果您只想使用Djikstra的算法并对其进行优化,则取决于图形中每个节点具有的信息。您很可能不需要全部进行1,500个查询。

例如,考虑以下示例。可以说,我正在尝试查找任意两个演员之间的分离度(培根数),并且想找到加权最小的路径(使用最新电影的路径)。现在,假设我有一个名为的函数shortestPath(actor A, actor B);。请考虑以下情形。

如果演员A从1970年开始表演,演员B从2000年开始表演,那么鉴于该信息,找到从演员B的第一部电影开始到演员A的路径是更合乎逻辑的。反对迭代演员A所扮演的每部电影。

因此,主要要点是Djikstra算法的优化实际上取决于您的数据集。您需要为您的数据集提供更多信息,以帮助我们优化算法。

编辑:假设您正在尝试查找同一国家/地区中两个城市之间的最短路径,并且如果该国家/地区的长度大于国家/地区的范围,例如阿根廷,那么您可以根据国家/地区的经度和纬度进行查询边界。然后,您可以开始垂直移动(使用经度)而不是水平移动。Ofc,将需要进行异常处理,但是您已经了解了一般思路。


1
您如何在Dijkstra中使用Union-Find?
拉斐尔

数据是空间数据,纬度和经度。我以为很清楚。
dimitris93
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.