有目的性地寻找最佳路径,首先定义一个损失函数,表示节点消耗:
$g$表示起点到当前节点的已知消耗
$h$表示对当前节点到终点消耗的猜测,估价函数有多种形式——启发式探索的核心
算法流程:
1 | 初始化openList |
算法性能在细节上的优化:http://theory.stanford.edu/~amitp/GameProgramming/
序言:路径搜索算法的前世今生
Dijkstra算法:从初始节点开始向外扩展,直到到达目标节点。算法保证能找到从初始点到目标点的最短路径。
最佳优先搜索BFS算法:算法能够评估任意节点到目标点的代价,并优先选择离目标最近的结点。启发式算法,比Dijkstra算法运行快得多,但是不能保证路径最短。
如下面这种情况:
因为BFS是基于贪心策略的,它只关注到尽可能向着目标点移动,而不考虑已花费的代价。Dijkstra算法则正相反,它会确保每一步都是最优的,但是为此要遍历周围全部的节点。
A*算法:将两种路径搜索算法的思想结合起来,考虑两个极端及其中间的情况:
如果$h(n)$是0,只有$g(n)$起作用,那么算法演变为Dijkstra算法。
如果$h(n)$能够始终满足“比当前节点移动到目标节点的实际代价小”,那么算法保证能够找到最短路径。($h(n)$越小,算法扩展的节点数就越多)
- 如果$h(n)$能够精确等于“当前节点移动到目标节点的实际代价”,那么算法将会仅仅扩展最优路径。而不扩展其他节点,算法运行非常快。
- 如果$h(n)$有时会“比当前节点移动到目标节点的实际代价大”,那么此时算法不能保证最短路径了。
- 如果$g(n)$比$h(n)$小的多,只有$h(n)$起作用,那么算法演变为BFS算法。
估价函数Heuristic function $h(a, b)$
估价函数的选择可以follow以下的instructions:
square grid that allows 4 directions:use Manhattan distance (L1)
square grid that allows 8 directions:use Diagonal distance (L∞)
当$D = D2 =1$时,$dis = dx + dy -min(dx, dy) = max(dx, dy)$,这个距离称为切比雪夫距离。
当$D = 1, D2 =\sqrt 2$时,这个距离称为octile distance。
square grid that allows any direcitons:use Euclidean distance (L2)
If A* is finding paths on the grid but you are allowing movement not on the grid, you may want to consider other representations of the map
欧几里得距离并不适用于栅格地图,因为这会导致代价函数g和估价函数的不匹配(代价函数并不是连续的)。
由于欧几里得距离引入了开根号计算,一些算法会直接用$dis = D(dxdx + dydy)$来代替,*不建议!,会引入尺度问题,$f = g + h$,其中代价函数会逐渐增长,估价函数则逐渐减小,平方会导致两个函数的变化速率不match,使得估价函数的权重过大,导致BFS。
code:
1 | public function manhattanHeuristic(a:Object, b:Object):Number { |
此时$h(a,b) = dis(a,b)+c-1 \leq h^{*}(a,b)$,此时能够找到最优解。