A*算法证明

原创 2015年11月19日 18:52:46


此文章目标人群为还未理解A*算法的或想更进一步了解它的人士。




术语定义。较枯燥,乃常规概念,可略过。

给定一个有向图,如果图中两个结点A、B存在边,则称结点A可达结点B。

如果图中任意一个结点A通过数个中间结点可达另外一个结点B,那么称A、B存在一条路径,定义该路径的长度为该路径经过的那些边的权值之和。

可以看出来,两个结点之间可能有不止一条路径,也可能没有路径。





给定有向图的两个结点求他们之间长度最短的路径,可以用到A*算法,算法在下面列出。

对图中某一结点N以及起始结点src、终止结点dst:
整个算法在执行过程中,会从src结点开始对图中的结点进行遍历(可能某些并不会被遍历到),算法在遍历到某个结点时,会记录下src到该结点经过的路径,该路径的长度就记为g(N)。在算法初始化时,很自然的,src结点的g值为0,其它的结点g值为∞,表示还未被遍历到。另外,某个结点可能被遍历多次,例如:

           A  

      ↗        ↘

src                               D → ….

      ↘      ↗

          B     

算法(可能)通过src->A->D这条路径遍历D之后,又折回去访问B,接着再访问D。
要谨记,结点的g值是动态生成的——在第一次遍历到它的时候生成(并且可能在以后遍历的时候更新,这是后话),不要被它吓到,如果你愿意,你可以就当它是从起始点到这一点的某条路径的长度。

h(N)表示结点N到目标点dst的“预估”长度。算法开始前,每个结点的h值都是预先确定好的。(怎么确定暂且不论)A*算法的一个思想是:路径是慢慢发现的,你发现了中途某个结点后,并不知道它离你的目标点准确有多远,只能知道个大概。不要急,这个东西在后面会慢慢解释。

g(N)和h(N)的和记为f(N)。f(n)表示了算法的遍历趋势,请铭记于心,g(N)代表这个节点离起始点的(本次遍历时经过)距离,h(N)代表这个节点离终点的(预估)距离。





有了上述概念,我们先来看看算法的形式化的步骤:
1. 建立两个容器,分别名为open和closed;
2. 将src结点添加到open中,置src结点的g值为0,置src结点的parent为null;
3. 只要open容器非空,执行以下步骤:
记open容器中f值最大的结点为cur,将cur移入closed中并将其从open中删除
如果cur就是dst结点,那么算法结束,;接下来,对cur结点的每一个相邻结点n:
如果n在close中
略过它,遍历下一个相邻结点
如果n在open中
如果cur的g值加上cur到n这条边的距离小于已存在的n的g值,那么更新已存在的n的g值为前者,更新其parent为cur;否则什么也不做。
否则
将它添加到open中去,其g值设为cur的g值加上cur到n这条边的距离,其parent设为cur



在解释算法之前,我们必须声明h的选取规则:

h*(N)表示结点N到dst的实际距离

为了使A*算法生效,我们必须令:

h(i) > h(j),如果存在一条i到j的边;递归推广一下,它的含义就是如果i能到j,那么我们给i的预估值一定要比j大

为了使A*算法找到的路径是最优路径,我们必须令:

h*(N)>=h(N);解释为我们给N的预估值一定不能超过它到dst的实际最短路径长度



接下来,我们来看看这个算法是如何奏效的。

刚开始,算法建立了两个容器,其中:

open代表已遍历的结点集合,并且它可能还可能会被遍历。

closed代表已遍历的结点集合,并且它不会再被遍历。

 我们在这里引入两个结论:

1. 当f值最小的那个结点从open加入close时,它确实不会再遍历了。

证明:由于我们每次循环都是挑选open中f值最小的结点,如果挑选出的这个结点cur会在遍历某个结点n后还被遍历,那么说明n能到cur(或者cur在n前面),那这就是说h(n)<h(cur);又因为f(cur)<f(n),那么肯定有g(cur)<g(h)。g(cur)<g(h)真的存在吗?这种情况只有没遍历n之前,已经通过其它路径遍历到了cur才出现,将n从open里拿出到close遍历其可达点时发现通过n到cur并不比之前的路径到n更快,但这说明n已经遍历过了,已经在close中而不在open中。因此,当结点从open拿出到close时,代表它不会再被遍历。

2. 对h*(n) > h(n)进行推导,可以得到:最短路径上任意点的f值都小于等于终点的f值

h(n) <= h*(n)                                       (前提)
h(n) <= h*(n) + h(dst)                          (因为h*(dst)为0,所以dst到dst的预估值h(dst)只能为0)
g(n) + h(n) <= g(n) + h*(n) + h(dst)     (不等式两边加g(n))
g(n) + h(n) <= g(dst) + h(dst)              (遍历时src到n经过的距离+n到dst的实际最短距离就是这条路径上src到dst的距离)
f(n) <= f(dst)                                          (f=g+h)

算法开始

从已经遍历的结点集合里弹出一个f最小的结点

观察这个结点的所有相邻结点,如果它的相邻结点已经在closed中,那么略过它,这是因为不允许环形图的出现;否则如果它的相邻结点不在open中,那么说明该结点还未被遍历过遍历过,那么把它加进open准备访问,它g值就是它的那个刚刚弹出的父前驱结点的g加上它俩的距离,这符合我们对g的定义;那么如果它在open的话,说明之前通过其它结点其它路径(这些结点已经“关”在closed里了)遍历到过,并且它的这个老g值就是那些路径里最短的一个,既然这样,那我们就拿当前这个路径的长度和之前那个最短的进行比较,看谁最短,就更新为g。

根据结论2,并且由于我们总是让f最小的结点进入close,那么如果存在最短路径,路径上的其它点肯定先于终点进入close;不过有可能直到终点进入了open(看好,不是close),最短路径上的点都还没进入open。比如以下情况:

 
 
   10     B    20
      ↗        ↘
A                  D
     ↘     C   ↗
   14           6
  
  
起点为A,终点为D,现用A*算法求最短路径

为了求出最短路径,令
h(A)=10(小于A到D实际最短距离)
h(B)=5(小于B到D实际最短距离)
h(C)=4(小于C到D最短距离)
h(D)=0


起始时:
open = {A(g=0 h=10)}
close = {}

1. open中A最小,加入A到close中,对A的后代B和C,把他们都加入到open中,于是
open = {B(g=10 h=5), C(g=14 h=4)}
close = {A}

2. open中B最小,加入B到close中,对于B的后代D,把它加入到open中,于是
open = {C(g=14 h=4), D(g=30 h=0)}
close = {A, B}

3. open中C最小,加入C到close中,对于B的后代D,它已经存在于open中,但是因为c->d的g值更小,于是更新D的g值为C的g值加C到D的边,于是
open = {D(g=20 h=0)}
close = {A B C}

4. 从open中取出D,算法结束


可以看到,虽然终点D在步骤2进入了open,但由于f值比它小的C一直存在——直到C进入close,它才得以进入close。

另外,就算终点提前进入了open,提前得到了g值,那条最短路径出open时也会把g值更新为最正确的。




于是,当终点进入close就宣告算法结束。



如果嫌推导不好记,我们可以这样理解上述说明的h的选取规则:

即使我们提前遍历到终点,我们也无法保证这就是最短的路径,详见上述终点提前遍历到的例子;而h(N)<h*(N)则通过f(N)<f(dst)保证了这一点——它保证,如果不是最短的路径,那么终点不会被错误弹出。

最短路径算法之AStar算法(一) AStar算法的证明

本文证明了A Star算法,并且给出了该算法的一个伪代码实现。
  • jiaoyong2011
  • jiaoyong2011
  • 2011年03月23日 10:17
  • 9292

最优性原理及其证明

最优性原理是指“多阶段决策过程的最优决策序列具有这样的性质:不论初始状态和初始决策如何,对于前面决策所造成的某一状态而言,其后各阶段的决策序列必须构成最优策略”这个最优性原理是动态规划的基础。 这个...
  • liguanxing
  • liguanxing
  • 2012年03月28日 10:28
  • 2239

哈夫曼树最优性的证明(思考良久)

哈夫曼树为什么就是最优树??怎么去证明!!?? 证明围绕着两个东西(一定要先看,而且要能够认同): 1. 现在还不知道树长什么模样,但不管怎样,可以确定:最小的两个权值是在整棵树的最下段的两片叶子...
  • qq_25847123
  • qq_25847123
  • 2015年10月09日 09:22
  • 3392

A星算法详解(个人认为最详细,最通俗易懂的一个版本)

A* 寻路算法 原文地址: http://www.gamedev.net/reference/articles/article2003.asp 概述 虽然掌握了 A* 算法的人认为它容易,但...
  • hitwhylz
  • hitwhylz
  • 2014年04月07日 10:29
  • 26194

堪称最好的A*算法

如此好贴,不能不转!原文地址:http://dev.gameres.com/Program/Abstract/Arithmetic/AmitAStar.mht本文版权归原作者、译者所有,我只是转贴;如...
  • b2b160
  • b2b160
  • 2009年04月08日 17:58
  • 88186

A*,那个传说中的算法

老王带你揭开传说中的面纱
  • zgwangbo
  • zgwangbo
  • 2016年07月31日 14:12
  • 18310

A*算法

Amit's A star Page中译文   译序 这篇文章很适合A*算法的初学者,可惜网上没找到翻译版的。本着好东西不敢独享的想法,也为了锻炼一下英文,本人译了这篇文章。 ...
  • coutamg
  • coutamg
  • 2016年12月29日 08:51
  • 3648

A* 算法详解

我们尝试解决的问题是把一个游戏对象(game object)从出发点移动到目的地。路径搜索(Pathfinding)的目标是找到一条好的路径——避免障碍物、敌人,并把代价(燃料,时间,距离,装备,金钱...
  • u013630349
  • u013630349
  • 2016年12月31日 10:37
  • 912

平行四边形优化

平行四边形优化(HDOJ3506) 2014-11-20 10:20 1034人阅读 评论(0) 收藏 举报  分类: 学习(3)  版权声明:本文为博主原...
  • silence401
  • silence401
  • 2017年03月09日 21:48
  • 270

A*算法图解

记得好象刚知道游戏开发这一行的时候老师就提到过A星算法,当时自己基础还不行,也就没有去看这方面的资料,前几天找了一些资料,研究了一天,觉的现在网上介绍A星算法的资料都讲的不够详细(因为我下的那个资料基...
  • guggy
  • guggy
  • 2017年02月20日 13:46
  • 1100
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:A*算法证明
举报原因:
原因补充:

(最多只允许输入30个字)