最短路径算法简介
据所知最短路经算法现在的应用有计算机网络路由算法,机器人探路,交通路线导航,人工智能,游戏设计等。据说,美国火星探测器核心的寻路算法就是采用的D*(D Star)算法。
最短路经计算分静态最短路计算和动态最短路计算。
静态路径最短路径算法
是外界环境不变,计算最短路径。主要有Dijkstra算法,A*(A Star)算法。
动态路径最短路径算法
是外界环境不断发生变化,在不能预测的情况下计算最短路,如游戏中敌人或障碍物不断移动的情况下。典型的有D*算法。
真实路网计算K条路径示例:
节点5696到节点3006,三条最快速路,可以看出路径基本上走环线或主干路。黑线为第一条,兰线为第二条,红线为第三条。约束条件系数为1.2。共享部分路段。 显示计算部分完全由Drew自己开发的程序完成。
Dijkstra
算法求最短路径:
Dijkstra
算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
Dijkstra
算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
Dijkstra
一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表方式。
A*
(A Star)算法:启发式(
heuristic
)算法
A*
(A-Star)算法是一种静态路网中求解最短路最有效的方法。
公式表示为: f(n)=g(n)+h(n),
其中f(n) 是节点n从初始点到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n)是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。
如果 估价值>实际值, 搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
估价值与实际值越接近,估价函数取得就越好。
例如对于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价值,即f=g(n)+sqrt((dx-nx)*(dx-nx)+(dy-ny)*(dy-ny));这样估价函数f在g值一定的情况下,会或多或少的受估价值h的制约,节点距目标点近,h值小,f值相对就小,能保证最短路的搜索向终点的方向进行。明显优于Dijstra算法的毫无无方向的向四周搜索。
上图是和上面Dijkstra算法使用同一个路网,相同的起点终点,用A*算法的情况,计算的点数从起始点逐渐向目标点方向扩展,计算的节点数量明显比Dijkstra少得多,效率很高,且能得到最优解。
A*
算法和Dijistra算法的区别在于有无估价值,Dijistra算法相当于A*算法中估价值为0的情况。
推荐文章链接:
Amit
斯坦福大学一个博士的游戏网站,上面有关于A*算法介绍和不少有价值的链接 http://theory.stanford.edu/~amitp/GameProgramming/
Sunway
写的两篇很好的介绍启发式和A*算法的中文文章并有A*源码下载:
初识A*算法 http://creativesoft.home.shangdu.net/AStart1.htm
深入A*算法 http://creativesoft.home.shangdu.net/AStart2.htm
需要注意的是Sunway上面文章“深入A*算法”中引用了一个A*的游戏程序进行讲解,并有这个源码的下载,不过它有一个不小的Bug, 就是新的子节点放入OPEN表中进行了排序,而当子节点在Open表和Closed表中时,重新计算估价值后,没有重新的对Open表中的节点排序,这个问题会导致计算有时得不到最优解,另外在路网权重悬殊很大时,搜索范围不但超过Dijkstra,甚至搜索全部路网, 使效率大大降低。
Drew
对这个问题进行了如下修正,当子节点在Open表和Closed表中时,重新计算估价值后,删除OPEN表中的老的节点,将有新估价值的节点插入OPEN表中,重新排序,经测试效果良好,修改的代码如下,红色部分为Drew添加的代码.添加进程序的相应部分即可。
另一种A*(A Star)算法:
这种算法可以不直接用估价值,直接用Dijkstra算法程序实现A*算法,Drew对它进行了测试,达到和A*完全一样的计算效果,且非常简单。
以邻接矩阵为例,更改原来邻接矩阵i行j列元素Dij为 Dij+Djq-Diq; 起始点到目标点的方向i->j, 终点q. Dij为(i到j路段的权重或距离)
其中:Djq,Diq的作用相当于估价值 Djq=(j到q的直线距离);Diq=(i到q的直线距离)
原理:i 到q方向符合Dij+Djq > Diq ,取Dij+Djq-Diq 小,如果是相反方向Dij+Djq-Diq会很大。因此达到向目标方向寻路的作用。
动态路网,最短路径算法 D*
A*
在静态路网中非常有效,但不适于在动态路网,环境如权重等不断变化的动态环境下。 D*是动态A*(D-Star,Dynamic A Star) 卡内及梅隆机器人中心的Stentz在1994和1995年两篇文章提出,主要用于机器人探路。是火星探测器采用的寻路算法。
主要方法
1.
先用
Dijstra
算法从目标节点
G
向起始节点搜索。储存路网中目标点到各个节点的最短路和该位置到目标点的实际值
h,k
(
k
为所有变化
h
之中最小的值
,
当前为
k=h
。每个节点包含上一节点到目标点的最短路信息
1(2),2(5),5(4)
,
4
(
7
)。则
1
到
4
的最短路为
1-2-5
-4
。
原
OPEN
和
CLOSE
中节点信息保存。
2.
机器人沿最短路开始移动,在移动的下一节点没有变化时,无需计算,利用上一步
Dijstra
计算出的最短路信息从出发点向后追述即可,当在
Y
点探测到下一节点
X
状态发生改变,如堵塞。机器人首先调整自己在当前位置
Y
到目标点
G
的实际值
h(Y)
,
h(Y)=X
到
Y
的新权值
c(X,Y)+X
的原实际值
h(X).X
为下一节点
(
到目标点方向
Y->X->G
),
Y
是当前点。
k
值取
h
值变化前后的最小。
3.
用
A*
或其它算法计算,这里假设用
A*
算法
,
遍历
Y
的子节点,点放入
CLOSE,
调整
Y
的子节点
a
的
h
值,
h(a)=h(Y)+Y
到子节点
a
的权重
C(Y,a),
比较
a
点是否存在于
OPEN
和
CLOSE
中,方法如下: