前言:针对单源最短路算法,目前最经典的思路即标号算法,以Dijkstra算法和Bellman-Ford算法为根本演进了各种优化技术和算法。针对复杂网络,传统的优化思路是在数据结构和双向搜索上做文章,或者针对不必要的循环进行排除。近年来,最短路算法大量应用于需要高及时性的领域,比如GIS领域,也大量应用于网络规模巨大的社会网络分析领域,这使得传统思路并不能很好地解决,于是把最短路算法思路本身抽象成两阶段算法,第一阶段为数据预处理,第二阶段为实时地搜索。这二者是互相矛盾的,如何找到平衡是各种算法技术所追求的。针对大规模网络,传统算法由于其复杂度与E或V必然有关系,甚至是线性关系这使得算法技术的直接应用无法满足要求,所以普遍会结合分层技术,通过分治与划分,把网络重新划分成多个子网或者多层网络来使传统算法技术也能很好的应用。其次,传统算法多是为单源多目的而设计,而且搜索范围很多时候过大导致性能下降,因此采用目标引导技术缩小搜索范围约束搜索方向,可以极高的提高算法性能。从这两个大思路上,有了一系列的优化技术。但值得注意的是,这些技术大多针对静态网络,少数技术对动态网络有较好的扩展,但完全针对动态网络的技术并不成熟,动态网络的路由还需要很多研究。
一. 符号约定:
a) E代表边或者边数,V代表顶点或者定点数,s标示出发点,t代表终点,R代表稀疏度,即E/V,w代表边的权重,d(i)代表节点i到出发点的距离标记,l(I,j)标示从i到j的距离,e(i,t)表示从节点i到t的估计值,E(s,t)表示从s到t的距离估计值
二. 基本加速技术
a) 优先队列系列
i. 通过堆结构加速:
K叉堆,性能O(ElgV)适用于稀疏度较小的图。实验结果表明,一般取2或4[ 1 ][ 2 ]
斐波拉切堆:其在堆插入上性能好过K叉堆,但其在取出最小值时的表现较差。其优势体现在如果R极高,则性能优势大。如果应用场合是交通图等R值不够高(不高于10)时,并不比K叉堆好。
ii. 通过桶结构加速[ 2 ]:
性能取决于最大边权值C,算法复杂度为:O(E+CV);桶算法本身可以继续优化,但优化的是桶的数据结构,流行的有这么几种,一是把连续桶空间平均划分之后减少桶数量的桶压缩算法和通过把大于某个长度的数据存在一个桶中,强行减少桶数量的桶截断算法。还有基于双桶结构的算法。这一类基于桶的算法由于优化点在选边这一环节上,故在稠密图上性能非常之好。
b) 双向搜索
i. 思路:传统的单向搜索技术会导致搜索范围过大,很多无效搜索,采用双向搜索可以限制搜索范围。
ii. 应用和缺点:双向搜索技术本身并不能带来很好的性能提升,但在配合其他技术使用时可以带来不错的性能提升,原因在于双向搜索对搜索范围的限制。同时双向搜索技术可以弱化终止规则,牺牲一定的准确性而带来性能提升
c) 预处理技术
i. 预处理技术本身是将搜索算法两阶段化和实时要求的产物,由于预处理必然带来空间的消耗,所以其本身并不单独使用而是作为一个辅助技术,配合目标引导技术或者分层搜索技术得到性能提升
三. 目标引导思想
a) 思路:传统算法多是为单源多目的而设计,而且搜索范围很多时候过大导致性能下降,因此采用目标引导技术缩小搜索范围约束搜索方向,可以极高的提高算法性能。目标引导策略大致分为四种:基于A*,基于剪枝,基于路标和基于潜在目标
b) 基于剪枝思想:
i. 思路:既然在搜索过程中,有很多节点不可能经过,那么在每一个搜索之前先判断一下接下来前往的区域有没有必要进行搜索即可。所以该思想指导下的技术核心在于如何判断某个区域是否有必要搜索以及如何划分区域。
ii. 核心原理:对于L(i) + e(i,t) <= E(s,t)的区域才有必要进行搜索,而e(i,t)越是小于真实值,E(s,t)越是大于真实值,该算法越能得到最优解,但性能会下降。反之性能会上升,但可能会牺牲准确性。该步骤只需在传统算法提取点进行搜索之前先判断一下即可。这种思想还有个可取之处。此类算法通常又一个估计值,当估计值永不高于实际值的时候(传统A*算法),算法一定能求到最优解。有趣的在于,估计值如果高于实际值,那么其速度大幅度提升,但不一定有最优解,这在堆精确度要求不高的情况下很有用,可以通过调整估计值和真实值的关系来调整策略,那么如何才能知道估计值与真实值的关系呢,这就是为什么此类算法都要搭配数据预处理的原因,数据预处理一部分让程序可以判断估计值和真实值的关系而又不必全部算出来,这就是此类算法在最短路算法的矛盾两阶段上找到的平衡。
iii. 具体实现策略:
先进先出算法,SPFA,固定序算法,拓扑序算法,划分算法:几个算法放在一起是因为其思路极为相似,且都是基于Bellman-Ford算法的改进。几种算法的改进思路都是一样的。Bellman-Ford算法慢就慢在两个地方,一是每个点可能多次入队,二是搜索的很多点是没有必要的,而关于这一点目前的解决思路有二:一是判断此点是否在有效搜索范围内,二是通过拓扑序的性质控制点搜索的顺序。从这两个地方入手,这四种算法的基本手段都是利用一个集合来存储下一个循环要循环的点,而是否进入这个集合的判断依据就是如果一次迭代过程中某个点没有被松弛,那么与其相关的边也不会再起效,下一轮迭代就没有必要从它开始去做搜索了。而这几种算法的不同之处在于集合的使用。其中SPFA,先进先出算法,拓扑序算法和固定序算法在初始化时将s放入集合中然后进入算法过程。而SPFA,先进先出算法,拓扑序算法和固定序算法的区别又在于从集合中取出点的顺序并不同,固定序算法是按照顶点序号取出,而拓扑序算法会先进行拓扑排序。而划分算法在初始化时将所有顶点放入集合中再开始算法过程。这几种算法没有明显优劣,针对不同的规模和不同的稀疏度有不同的表现。对比如下:相同网络规模,稀疏度越大,先进先出性能越好,但如果稀疏度相同,网络规模越大,固定序算法的性能越好,网络规模如果足够大,固定序会避免其在小规模的劣势,始终保持优势。而拓扑序算法也不见得比固定序算法效率更高。传统划分算法性能普遍占劣势,所以目前一般都是使用先进先出策略的划分算法。截止2012年,先进先出策略的划分算法加上门槛策略,是面对负权图最好的最短路算法。
PCD(Precomputing Cluster Distances)算法:此处的算法并非指PCD算法这一个算法,而是这一类算法思想,即数据预处理+分割思想在剪枝技术的应用。其中PCD算法将网络分割为若干簇,对任意簇之间的距离用两个簇之间的最短距离表征。该算法分为两阶段,第一阶段为预处理阶段,完成以下任务:一是对图进行分割,该算法的分割算法是K-cluster,实际实现是K’-cluster-oversampling算法。这里有个思路是很值得玩味的,就是设置一个虚拟节点,和其他节点的边权值为0,然后求一次最短路树。但我不认为这个算法的分割性能很好。预处理阶段做的第二件事是求不同簇的最短距离和相应的节点。第二阶段是实时搜索,剪枝依据是:
上界在搜索到一个cluster的边界点时更新,更新依据是:
,这个可以作为上界
与PCD算法思想类似的还有提出的算法,该算法分为两阶段和两种情况。第一阶段依然是预处理,即利用社团识别技术对网络进行分割降解。两种情况中第一种情况是初始点与目标点位于同一子网络内部的情形,采用对搜索区域重构的办法来计算最优路径(重构的搜索区域由该子网络内部的节点、边以及预处理阶段修正的边构成);第二种情况是初始点与目标点
位于不同子网络的情形,定义了子网络坐标并使用欧式距离来近似估计子网络间距离,通过选取距离较近的子网络对并将搜索范围限定在其内部加速算法。这种算法还可以一定程度上扩展到动态网络。之后再表
c) 基于A*算法:
i. 核心思想:这一类算法有两个重要的进步:一是并不像传统Dijkstra算法那样单一的使用边权值作为参考,而是采用已知距离g(x)加上估计距离h(x)来作为参考;二是在约束搜索范围时,并不简单地采用双向搜索,二是采用在单向搜索是,估计值是当前搜索节点到目的地的距离,这样的方法一是可以起到双向搜索所有的约束搜索范围的效果,二是不必承受双向搜索带来的存储消耗。如前文所述,当估计值永不高于实际值的时候(admissible),算法一定能求到最优解。有趣的在于,估计值如果高于实际值,那么其速度大幅度提升,但不一定有最优解。关于A*算法的改进很多:
ii. 实现策略与改进算法:
a) A*算法:A*算法的实施方法如上所言,在我看来,A*算法在最短路搜索技术上的突破在于结合了启发式技术和形式化的技术,即结合了图本身的信息做动态分析和数学的形式化分析,并使得最短路搜索从按照某种规则去寻找最短路成了按照某个方向去搜索。
b) Dijkstra式A*算法:通过Dijkstra算法的步骤实现A*算法。这种方法其实是利用了Pohl提出的势函数来实现的。以邻接矩阵为例,只需要将矩阵元素Dij改为Dij+Djt-Dit,实验证明,这里引入的Djt-Dit起到的效果就是h(x)的效果,即是约束搜索方向。从这里可以看出,A*算法的核心思想是尽量沿着欧式最短距离从出发点向目的点进行搜索。
c) ALT算法/ACT算法:即A*算法加地标加三角不等式技术的综合算法。ACT算法是ALT算法的一个改进,故放在一起讨论。ALT算法的手段是在数据预处理阶段选取少数几个地标,然后在搜索过程中,通过三角不等式得到势函数,然后用A*算法进行搜索。其地标选取采取的是maxcover,即最大覆盖。但maxcover的地标选取十分耗时,ACT做出改进,将地标选取改为中心点选取,此处采用贪心算法即可。然后通过中心点和三角不等式计算得到多个势函数,从而选出最大的势函数,然后在A*搜索过程中,利用REACH剪枝技术。
d) D*算法是改进的A*算法,很好的解决了动态寻路问题,其核心思想有两点:一是其预处理阶段计算的时目标节点到其前节点的距离,二是在检测到下一个节点阻出状况时,通过更新受影响节点的值,并搜寻哪一个邻居节点是当前最近的。这里的搜索方法是反复的调整节点是在降低距离还是增加距离的标记。D*算法的优化是focused D*
e)Lifelong Planning A* (LPA*)/ D*lite:其核心思想在于在发生拓扑发生变化时要充分利用已经有的计算结果。所以在拓扑变化之后,通过三角不等式找到那些变化了的边,然后将这些边的目的节点进行更新然后重新计算最短路树,只不过在这次计算时,使用A*优先搜索那些改变了的顶点,更新方式仍然是三角不等式。从这里可以看出,Bellman-Ford算法提出的松弛原理是在寻找最短路时效果相当好的依据。
f) Iterative deepening A* (IDA*):核心思路是A*加上迭代加深算法。迭代加深算法的思路就是在深度优先,每一个深度只搜索一次,搜索不到,就去下一个深度。与A*的结合在于去寻找那些最有可能的点。基本步骤设定一个深度极限Dmax,当前搜索的深度不能超过Dmax,如果超过,则更新一下Dmax重新搜索过。如果没有超过Dmax并且没有找到目标的话,就去下一个深度搜索。这个算法有这迭代加深算法避免广度优先算法无目标的缺点,也有A*算法的方向性,内存消耗也比A*小,缺点是每个点可能多次重复地被搜索。实际效果是在大规模图里面性能不错。
g) fringe search算法:其是一种介于IDA*和A*之间的算法。其出发点在于A*算法的搜索对内存消耗较高,而IDA*算法有两个重要缺陷:一是顶点会被重复搜索;二是每一次Dmax增加之后所有之前的计算并不能对之后的计算起作用。fringe search算法的基本思想是引入两个队列now和later用于存储搜索树的顶点,now用于当前这次循环,later用于下一次循环,其他部分与IDA*算法相似。
h) Simplified Memory Bounded A*(SMA* )这是对A*算法的一种内存优化算法。其与A*算法的不同在于其限定一个最大可用内存,如果可用内存在计算过程中消耗殆尽,将f值最大的点从内存中删去,但相关路径的长度会被记录,如果其他搜索出来的路径都不如这个数据,路径会被重构。
i) Any-angle path planning问题相关算法:这一类问题考虑的是传统算法都在考虑从一个点(区域)到另一个点(区域),但实际问题中会出现无法抽象出点的情况。我认为交通网和社交网都不符合这类问题范畴,不予讨论
d) 基于路标的算法:
i. 核心思想:基于路标的算法设计通过在每条边引入一个路标(signposts)作为指示牌,用来指引经由这条边的最短路径所能到达的节点的大致范围,从而减少无谓的搜索。
ii. 实现策略:目前基于路标的技术主要有三类:几何容器法,边标示法和潜在目标策略。
几何容器法:基本思想是对网络中每一条边预处理一个几何容器C(e),容器中容纳从节点i出发经由e的最短路径所能到达的所有节点
将保存每条边的这部分节点的问题转化为保存容器参量的问题。而在算法执行过程中,只需要松弛哪些对应容易包含目标点的边。这种思想由于对内存消耗过大,目前在大规模网络中少有应用。
边标示法:此类算法核心思想在于大规模网络既然难以直接寻路,那么就先找到其对应的区域,再在子网络去找。这和分层路由的思想极为相似。首先将网络分割成K个区域。然后针对每条边相对于所有区域记录是否可以到达该区域。在搜索时只考虑哪些对目标节点t所在区域可达的边。这种算法的性能注定是受K值的影响的。这里的边标示只需要在区域边界点执行单源最短路径计算即可。对于标记的改进主要有二,一是。。。。二是分层标记,我归类于分层技术。
潜在目标策略:通过选取s和t之间最优希望经过的那些节点作为潜在目标,将问题分治为多段路之间的最短路问题。
a) 将搜索范围限定在某些潜在子网络中,然后通过分别进行寻找子网边界点和子网内部搜索找到整个的最短路径。
b) 提出一种预处理中转节点的算法。这种算法应用于交通网,其核心思想在于,用户移动过程中,一定是尽可能地在高速公路上移动,而没有必要为了缩短距离而离开高速公路,该算法将高速公路作为重要节点,也就是所谓的中转节点,记录目标距离对应中转节点的距离,然后记录中转节点间的距离,将最短路搜索问题转化为类似RIP协议路有项更新的问题。
四. 分层技术
a) 核心思想:这种技术的核心思想在于,在一开始的时候,并没有必要考虑所有细节,先考虑关键点,然后再考虑关键点之间的细节,这样可以少考虑很多细节,而这些细节是没有必要知道的。作为类比,参考分层路由和OSPF协议,这三个应用场合都采用了这样的思考方式,即网络过于庞大复杂,而传统算法都是基于相对小的网络的,那么就要把网络变为传统算法效率很高的小网络。大网络问题到小网络问题的映射必然考虑把网络分割成很多子网,然后先将子网作为节点考虑最短路问题,再在子网内部考虑搜索最短路即可。
b) 实现策略:主要分两种策略,第一种是针对交通网的,利用交通网本身所具有的分层特性,利用干道和支路对网络进行分层。这种策略应用面相对较窄,而且对网络的识别和预处理复杂,甚至需要人工干预。第二种策略即人工对网络进行分割构造分层结构,通过人工分割使各子网规模大致均等,并尽量使得分割后的子网相互独立。接下来列举的并非实际论文的完整手段,二是这些手段中的分层策略,因为分层技术本身只是为了降解分割网络,然后应用其他技术。
i. 入口点策略:定义高级网络(主干道)的交 叉口为入口点,此类策略最初的手段是从s在低一级网络中找到最近入口点,然后在高一级网络中寻找最短路。此类手段在准确度上可能存在很大的偏差。改进策略分为两类,一类是s和t隶属的子网和高一级网络合并为一个网络,从而避免最近入口点并非最佳入口点的问题;第二类改进引入了前文剪枝策略中提到的虚拟链路技术,通过把s和t与本子网的入口点建立虚拟链路来将多层网络变为一层网络进行传统搜索。然后入口点策略本身的缺陷在于,很有可能最短路并不需要去到入口点,而是纯粹有非主干道组成。针对这个问题有一些改进措施,但并不能完美解决这个问题,因为有的时候对道路网而设计的,但注意到任何网络都可以利用道路网的等级特性来对网络加深认识,仿照道路网的等级特性,在搜索的过程中逐次增加层数。对每个点进行两阶段处理。第一阶段处理是求局部最短树,然后求到出发点到树最远端的高速路,然后再从最远点出发求下一阶段的最短路。整体看来,每一阶段都是局部的最短路,K次迭代求到的的局部最短路就是K-1次迭代得到的最短树的高级网络。从这个实现从距离上说,不经过入口点会更短,但其消耗也许会更大。入口点策略最初是针上已经可以看到,分层只是一种分解网络的手段,甚至只是一种思想,就是化全局为局部,只是这个局部如何实现分为在开始分割还是边搜索边分割。
ii. 分割分层策略:这种策略就是在预处理阶段将网络分割成多个独立的、规模相近的子网,子网间通过少量边相连。常用的分割技术有SPC、METIS、K-center-cluster以及社团识别技术等。基本思路都是在原网络的上求到子网边界点的路径,然后在然后在高层网络继续搜索。具体实施手段有。其中值得一说的是提出的最大穿越比策略,该策略综合了数据预处理,分层技术和剪枝技术,可以说是近年来的最短路算法的典型形式。具体策略如下:使用BTD算法分割图,该分割算法的基本思路是先将图分割成很多小的块,然后通过穿越比进行合并,约束图的规模,然后将子网抽象成点形成高层网络。使用HSP路由算法进行搜索,和前面在剪枝算法中提到的PCD算法的搜索算法是一致的,都依靠维持距离上界和距离下届来约束搜索范围。
五. 总结
首先考虑目前的最短路算法应用场合,如果是非实时要求应用场合,那么基于堆的Dijkstra算法和基于Bellman-Ford的划分算法还有A*算法都依然是行之有效的,因为对时间并没有太高要求。如果是实时场合,比如导航,比如社会网络匹配等,则需要考虑到网络的复杂性和计算的实时性。为满足这些要求,目前认为,算法应该是两阶段的,第一阶段,做数据预处理,为实时搜索提供线索;第二阶段才是实时都搜索。
由于网络的复杂性,降解分割是必要的,手段主要是两种,一种是利用交通网本身的分层特性或者仿照交通网的分层特性对网络进行自然划分,即入口策略中提到的算法,这种方法的效率很大程度上取决于局部最短路径树的构造,子网也不够理想;另一种是预处理分割方法,通常采用分割算法对图进行分割,目前主流的分割算法有SPC、METIS、K-center-cluster【12】、BTD算法以及社团识别技术,这种手段的缺陷在于,图分割算法多是应用于平面图的,但实际网络很大可能是三维的,所以如何分割仍待研究。其中BTD分割算法由于其分割目的是最短路径搜索,分割手段也是最短路径树,与其他纯粹的图分割算法不一样。
网络庞大的结构使得算法必须尽量避免去搜索那些不必要的路径区域,因此目标引导技术普遍应用于近年来的最短路算法。目标引导技术现在应用比较广的有这么几种:A*类利用估计函数引导,Pohl L提出的势函数用作计算估计函数效果最好;剪枝技术,主要有REACH剪枝,上下界剪枝,剪枝技术不但可以很好的约束方向,还可以精确控制搜索精度;路标技术,主要是几何容器法和边标示法,用空间换时间;基于潜在目标搜索,不一定是最优解,但速度快。
但目前的算法有一个普遍的缺陷,即很少有能针对动态网络作扩展的。网络权值是可能随时变的,基于静态搜索的动态网络扩展主要有这样两个思路:一是增量策略,即在网络变化时,测算出哪些地方变化了,受影响的有哪些区域,然后判断有没有必要重新计算图的信息;二是动态计算策略,即在最初行动时,并不知道最短路怎么走,不断计算前面该怎么走,这样可以一定程度上规避网络变化带来的影响。以目前的最短路技术而言,面对动态网络时,应该探索如何才能充分利用两方面信息:一是预处理阶段存储的网络信息;二是已经计算得到的最短路径信息。这里D*算法类提出了一种思想,但目前针对动态网络技术并不成熟,我认为这也是当前最短路算法时而使得实际移动时间高过预计的原因之一。
六. 参考文献
[1]基于四叉堆优先级队列及逆邻接表的改进型Dijkstra算法陆锋1999——Dijkstra改进
[2]复杂网络中最短路径算法的研究及应用罗飞2007——Dijkstra桶算法
[3]交通网络最短路径标号算法的实现与效率分析_陈洁2005
[4]对Dijkstra算法的优化策略研究_陈益富2006——Dijkstra改进
[5]改进的Dijkstra最短路径算法及其应用研究_王树西2012——Dijkstra改进
[6]关于最短路径的SPFA快速算法_段凡丁1994——SPFA
[7]距离寻优中Dijkstra算法的优化_鲍培明2001——Dijkstra改进
[8]网络最短路问题的改进算法_王晓东2002——Dijkstra桶算法
[9]固定序Bellman_Ford算法的一个改进_韩伟一2014——固定序算法,先进先出算法
[10]经典Bellman_Ford算法的改进及其实验评估_韩伟一2012——划分算法
[11]最短路径算法加速技术研究综述_宋青2012
[12]大规模图上的最短路径问题研究_张钟2014——ACL,ACT,路标算法
[13]适合复杂网络分析的最短路径近似算法_唐晋韬2011
[14]基于惩罚因子的多约束剪枝QoS路由算法_赵季红2015
[15]Bellman_Ford算法的改进研究_陈华容2006
[16]US7869946 2011
[17]Highway Hierarchies Hasten Exact shortest Path Queries_Sanders Schultes——任意网络构造成交通网(局部最小生成树)策略
[18]route planning in road networks_ Dominik Schultes——潜在目标策略
[19]Partitioning graphs to speed up point-to-point shortest path computations_ Qing Song, and Xiaofan Wang——BTD+HSP算法
[20]Bi-directional search[M], Pohl L, IBM TJ Watson Research Center, 1970——势函数
[21]Goal_directed_shortest_path_queries_using_Precomputed_Cluster_Distances——PCD算法
[22]The Focused D* Algorithm for Real-Time Replanning _ Anthony Stentz——Focused D*
[23]a tunable graph model for incorporating geographic spread in social graph models_ Rajesh Sharma and Anwitaman Datta
[24]a heuristic improvement of the bellman-ford algorithm_ ANDREW V. GOLDBERG——拓扑序算法
[25]topological routing in large-scale networks_ Jens Myrup Pedersen, Thomas Phillip Knudsen and Ole Brun Madsen——分层算法
[26]fast replaning for navigation in unknown terrain_ Sven Koenig——D* lite
[27]Optimal and Efficient Path Planning for Partially-Known Environments_ Anthony Stentz——Focused D*
[28]An efficient path computation model for hierarchically structured topographical road maps_ Sungwon Jung——分层技术(边界点连接高层网络)+A*
[29]Efficient routing on large road networks using hierarchical communities——双向搜索,分层技术(社团识别技术),降低精度搜索,扩展到动态网络
[30]A two-phase shortest path algorithm for networks with node coordinates——A*结合剪枝技术(三角不等式)
[31]Geometric containers for efficient shortest-path computation——几何容器法
[32]Level graphs and approximate shortest path algorithms——入口点分层算法