A-star
A*算法
更新后继
open-set是当前已经发现的、还没有搜索的点,即从起点有一条有限长的路径到这些点,
close-set是已经搜索更新后继完毕的点。
更新后继时:
- 后继不在任意一个set中,说明这个点第一次被发现,加入open-set即可。
- 后继在open-set中,说明发现了一个从起点出发到这个点的新的道路,需要与历史记录相比选更短的。
- 后继在close-set中,与上一种情况类似。注意此时若新发现的道路更短,意味着之前的搜索是不准确的,需要将其加入open-set再次搜索。
正确性
A*算法的关键是估计函数h,h值的估计要放宽条件,从而从n点到终点的估计代价要小于实际代价。
考虑终点
先考虑已经找到从起点开始的最短路径的那些点,从起点经过这些点到达终点的路径长度一定大于这些点的f值(A*算法的条件),因而大于当前已经找到的最短路径。
在考虑那些尚未找到最短路径的点,向上追溯祖先会找到一个已经确定最短路径的点,由上一条得知这也不会是起点到终点的最短路径。
一些结论
- 在算法过程中,任意一个节点的f值会不严格地递减。
- OPEN表上任一具有f(n) < f*(s)的节点定会被A*扩展。只要某一时刻的f值小于f*(s)都成立。换言之,整个过程中不被扩展的节点,其f值一定恒大于等于f*(s)
- A*扩展的任一节点,定有f(n) ≤ f*(s)。整个过程中,open表里的最小f值会上下波动,但是一定小于等于f*(s)(除了最后一步)。
- 当h(n)恒等于0时,h为单调的。
- 对两种不同的h估计方法,如果
(目标节点除外),则A1扩展的节点数 A2扩展的节点数,即A2的效果更好。
对5的证明
注意评判标准是扩展的节点数,不是扩展节点的次数。
只需证明被A2扩展的点一定被A1扩展即可,使用反证法:
假设某一个点
由条件123,可以大略画出A1过程中f值的变化: 则在A1过程中,
如果条件是
考虑f值等于f*(s)的点,其在A1不一定被扩展,但在A2中,可能被扩展,因为黑线不一定上移。
策略优化
单调性
多次对同一个点搜索会降低效率,问题在于第一次找到某个点的路径不一定是最短路径。考虑改进h(n)。
对h(n)增加条件:若
增加条件后,若
假如
单调性无法满足时
思考的出发点来源于结论34。对于那些f(n) ≤ f*(s)的点。将其放入一个集合名为NEST中,则它们一定被扩展,那么在扩展这些集合时可以将h定为0,这样满足单调性,提高效率。但是问题是不能知道f*(s)的值,所以用当前扩展的点中最大的点的f值估计。
优化后算法(抄PPT):
-A-algorithm(s) //s为初始节点
Modified=(s), CLOSED=(), f(s)=g(s)+h(s), fm=0;
OPENwhile OPEN不空 do:
begin={ni|f(ni)<fm,ni∈OPEN}
NESTif NEST ≠ ( )
=NEST中g最小的节点
nelse
=FIRST(OPEN), fm=f(n);
nif GOAL(n)
return n;
(n, OPEN), ADD(n, CLOSED);
REMOVE(n) →{mi},
EXPAND(n, mi)=g(n, mi)+h(mi);
计算f(mj, OPEN), 标记mj到n的指针;
ADDif f(n, mk)<f(mk)
(mk)=f(n, mk), 标记mk到n的指针;
fif f(n, ml)<f(ml,)
(ml)=f(n, ml),标记ml到n的指针,
f(ml, OPEN);
ADD
OPEN中的节点按f值从小到大排序;while
end return FAIL;