`

[转]A*算法中启发函数的使用(1)

阅读更多
链接:http://godorz.info/2009/11/heuristics-1/


A*算法使用启发函数h(n)来获得对于从任意结点n走到目标结点的最小代价的估计,因此选用一个好的启发函数是非常重要的.

A*算法中启发函数的使用
启发函数可以用来控制A*算法的行为.

在极端情况下,如果h(n)=0,那么只有g(n)实际上是有用的,这时A*算法也就是迪杰斯特拉算法,它能保证一定可以找到一条最优路径.
如果h(n)总是小于(或者等于)从结点n走到目标结点的步数,那么A*算法是一定可以找到最优路径的.h(n)越小,A*扩展的结点越多,导致A*算法越慢.
如果h(n)恰好等于从结点n走到目标结点的步数,A*算法扩展的所有结点都在最优路径上,它不会扩展任何其他无关结点,此时A*算法的速度是非常快的.尽管你无法总是做到这一点,但在某些特定情况下你确实做到.知道A*算法可以在某些时候运行的很好是一件很值得高兴的事.
如果h(n)所给出的信息有时大于从结点n走到目标结点的步数,那么A*算法将无法确保能够找到最优路径,但它会运行得更快.
在另一种极端的情况下,如果h(n)非常接近于g(n),那么只有h(n)将起作用,此时A*算法实际上变成宽度优先搜索.

注意:

从纯粹的技术上说,如果启发函数是对实际耗散值的过低估计的话,A*算法应该叫做简单的A算法.然而,由于在实现上 ,两种算法并无不同的地方,而且在游戏开发社区中,A*算法和A算法并不会被区分开来,所以,接下来我仍然称之为A*算法.
经过上述的讨论后,我们会发现我们面临一个很有趣的问题:我们能通过A*算法得到什么呢?正确的答案是,我们可以很快地得到最优路径.如果h(n)值太低了,那么我们一定能够得到最优路径,但这是以牺牲了算法速度为d代价的.如果h(n)值太高了的话,那么A*算法速度会变快,但是我们无法确保所得到的路径一定是最优的.

在游戏中,A*的这种特性是非常有用的.举个例子,某些时候,你宁愿更快得找出”较优”路径而不是慢悠悠地等着”最优的”路径.为了在h(n)和g(n)中找到平衡,你可以修改其中一个的具体实现.

速度还是准确度?
正如我们提过的,A*算法的表现取决于它的启发函数和耗散函数,这一点在游戏中是很有价值的.权衡速度和准确度的,可以让你的游戏运行得更快.对于大多数游戏而言,你没有必要一定要找出两点间的最优路径.你需要的仅仅是足够接近的答案.你需要什么应视游戏进度和电脑多快决定.

假设你的游戏地图中有两种地形:平原和山地,而且在平原上的单位距离移动代价是1,在山地上的单位距离移动代价是3.(A*算法的目标是找出地图上两点间的最优路径),那么A*算法每在山地上搜索1个单位距离,它在平原上将搜索3个单位距离.这是因为也许存在一条最优路径,它一碰到山地就绕行,即该路径仅仅经过平原地形.通过将两点间的估计距离(即启发信息)设定为1.5,A*算法的速度就可以得到提升了.这时A*算法将比较的是3和1.5,而不是导致它变慢的比较3和1,在山地地形上它的效率将不像后者那么不尽如人意,因此它不会花费太多的时间.或者,你可以通过将A*算法在山地上搜索单位距离的代价降低来提高它的效率–比如说设定为2而不是3,这时A*算法每在山地上搜索1个单位距离,它在平原上将仅仅搜索2个单位距离.两种方法都无法找到最优路径,但能够更快地找到较优路径.

在速度和准确度上的选择并不一定是一成不变的.你可以动态地权衡,这决定于CPU的速度,找出路径的时间对游戏的影响,地图上的结点数目,结点的重要程度,路径群组的大小,游戏的难度级别,或者其他的一些因素.一种动态权衡的方法是,假定最优路径通过单位方格的代价为1,修正的耗散函数如下:

g'(n) = 1 + alpha * (g(n) - 1)
如果alpha=0,那么这个修正的将永远是1.这时,单位距离的代价是被忽略的,A*算法仅是运行在简单的可达方格/不可达方格的程度.如果alpha=1,此时修正的耗散方程将还是原来的耗散方程,这时A*算法效率将带来更好的效率.你可以将alpha设定为[0,1]之间的任意值.

同时,你应该考虑使启发函数返回的是期望最小代价,而不是绝对最小代价.比如说,如果你的地图大部分是单位距离移动代价为2的草地,小部分是单位距离移动代价为1的小路,那么也许你会考虑整副地图启发信息都为2,意味着地图上没有小路.

在速度和准确度上的选择并不一定是全局的.你可以根据某些地图上准确度的重要性来灵活选择.举个例子,假如我们在某些点能够结束路径的重新计算或者改变路径方向,那么选择接近于当前所在结点的路径可能是更为重要的,这样的话,为什么我们还要费事纠结于千里之外的其他路径呢?再举意个例子,在地图上的安全区域,找到最优路径是比较重要的,但是在偷偷的经过敌对势力占领的村子时,快速地得到一条安全的较优路径的要求来得将更为迫切.

比例
A*算法计算f(n)=g(n)+h(n).因此,g(n)和h(n)必须拥有协调的比例.如果g(n)以小时计算,而h(n)以米计算,那么A*算法将会认为g(n)或者h(n)过大,这样的话,要么你无法得到最优路径,或者A*算法将比它原本可以的速度要慢.

精确的启发
如果你的启发函数给出的两个结点间的估计距离恰好等于最优路径上该两点间的距离,那么,正如你将在下一节的图表中看到的,A*算法扩展极少结点.发生在A*算法内部的是,在每一结点,它都会计算f(n)=g(n)+h(n),当h(n)整好等于g(n)时,在遍历最优路径上的结点时,每一结点上的f(n)值恒定不变.所有不在最优路径上的结点的f值都会比最优路径上的结点的f值要高.因为A*算法在考虑完所有拥有较低的f值的结点之前,它并不会考虑f值更高的结点,因此它永远不会偏离最优路径.

已计算过的准确启发信息

一种构造精确启发函数的方法是,预计算最优路径上任意两个结点之间的距离.对于大多数游戏地图而言,这是行不通的.然而,找到近似于精确启发函数的方法是存在的.

考虑所有可能的粗糙结点,它不是最优路径上的结点.预计算任意两个粗糙结点的最短路径.
预计算任意两个拐点(Arthur1989注:请一定猛击链接查看waypoint的定义,才疏学浅的我只能如此翻译了.)之间的最短路径.这是前面粗糙栅格法的一种泛化.
然后,把从任意结点到拐点(Arthur1989注:天阿,为什么又是它,我快自杀了)的估计函数h’加入启发函数h中.最终的启发函数是这样子的:

h(n) = h'(n, w1) + distance(w1, w2), h'(w2, goal)
或者,你可以这样考虑更优的,但是花费计算量更大的启发函数:评价所有临近于起始结点n的结点w1,和所有临近于目标结点的结点w2.

线性精确启发函数

特定情况下,你可以无须通过任何的预计算就得到精确的启发函数.如果你有一个没有任何障碍物的地图,或者地图上没有代价较大的地形,那么从起始结点到目标结点的最优路径就是连接该两点的直线.

如果你正在用着一个简单的启发函数(它并不清楚地图上会有障碍物),那么它将匹配线性精确启发函数,如果不是这样的话,或者在g和h的比例上出现了问题,或者你选择的启发函数类型有些缺陷.
分享到:
评论

相关推荐

    A*算法A星算法

    3. **启发式函数**:A*算法的效率在很大程度上取决于启发式函数的选择。在代码或文档中,可能会讨论如何定义和实现启发式函数,例如使用曼哈顿距离或欧几里得距离,以及它们在不同情况下的优缺点。 4. **路径优化**...

    八数码问题A*算法代码

    在`solvePuzzleAStarSearch.cpp`和`solvePuzzleAStarSearch.h`这两个文件中,很可能包含了A*算法的实现细节,如状态表示、启发式函数定义、节点拓展规则以及优先队列的数据结构等。这些代码将演示如何使用C++来处理...

    A*算法Matlab 代码

    A* 算法是一种在图形搜索中广泛使用的启发式搜索策略,它的主要目标是找到从起点到终点的最短路径。在这个特定的上下文中,我们讨论的是在Matlab环境中实现A*算法来解决路径规划问题。A*算法结合了Dijkstra算法的最...

    用A*算法解决TSP问题

    描述中提到"用python语言实现",意味着我们将使用Python编程语言来编写A*算法的代码,并且该实现已经在一个包含400个节点的数据集上进行了测试。这暗示了我们将涉及到数据结构、图的表示以及Python的编程技巧。 **A...

    A*算法的讲解PPT(A算法)

    A*算法是一种在图形搜索问题中寻找最优路径的启发式搜索算法,由Peter Hart、Nils Nilsson和Bertram Raphael在1968年提出。它的主要目标是在有限的计算时间内找到从起点到终点的最短路径,特别适用于静态路网中的...

    基于A*算法的最优路径规划系统

    【A*算法详解】 A*算法是人工智能领域中用于寻找最短路径的一种高效搜索策略,尤其在路径规划问题中有着广泛的应用。...在实际应用中,A*算法需要根据具体的环境和问题特点,设计适当的启发式函数,以达到最优性能。

    A*算法求解N码难题+Word分析说明

    在提供的文档"rr.doc.doc"和"A算法"中,可能会详细解释A*算法的原理,包括如何构建搜索树、如何计算启发式函数、如何维护开放列表和关闭列表等。同时,可能会通过实例演示如何应用A*算法来解决具体的N码难题,展示...

    A*算法Java/C++实现

    同时,优化A*算法的方法包括使用二进制堆优化开放列表、动态调整启发式函数精度、以及使用启发式函数缓存以减少重复计算。 总的来说,理解和实现A*算法需要对图论、数据结构和搜索算法有深入的理解。在Java和C++中...

    A*算法在ROS上的简单移植

    A*算法的核心思想是在搜索过程中结合了启发式信息,即一个从当前节点到目标节点的估计代价,通常用一个启发式函数(如曼哈顿距离或欧几里得距离)来表示。这个算法使用了一个开放节点集和关闭节点集,通过评估每个...

    A*算法学习(python代码实现)

    A*算法的核心在于引入了启发式函数,使得搜索更加高效,能够在大量可能的路径中找到最优解。 在Python中实现A*算法,首先需要理解其基本步骤: 1. **初始化**:创建一个空的开放列表和关闭列表。开放列表用于存放待...

    移动机器人路径规划 几种A*算法改进matlab实现

    2. **动态调整启发式**:根据搜索过程中的信息更新启发式函数,如使用A-D*算法,当路径发生变化时,能够快速重新规划。 3. **记忆化搜索**:利用已搜索节点的信息,避免重复计算,提高效率。 4. **开放列表排序...

    基于matlab的双向A*算法

    2. **启发式函数**:定义用于估计从当前节点到目标节点代价的函数,如曼哈顿距离或欧几里得距离。 3. **双向搜索**:分别从起点和终点开始,使用优先队列(如二叉堆)存储待处理节点,并按照f值进行排序。 4. **节点...

    A*算法实现旅行商tsp java

    A*算法是一种在图形搜索中广泛应用的启发式搜索策略,其目标是找到从起点到终点的最短路径。在这个特定的场景中,A*算法被用于解决旅行商问题(Traveling Salesman Problem, TSP)。TSP是一个经典的组合优化问题,...

    A星算法 c语言实现 a*算法

    A星(A*)算法是一种在图形搜索中广泛使用的路径规划算法,它的主要目标是找到从起点到终点的最短路径。A*算法结合了Dijkstra算法的全局最优性和最佳优先搜索的效率,通过引入启发式函数来指导搜索,使得算法能够更...

    A*算法详细介绍

    A*算法的启发函数是f(n)=g(n)+h(n),其中g(n)表示从起始搜索点到当前点的代价,h(n)表示当前结点到目标结点的估值。h(n)的设计是A*算法的关键,h(n)的设计好坏直接影响着A*算法的效率。 A*算法的优点是可以快速地...

    A*算法C#实现

    3. **F、G、H函数**:A*算法的核心在于F、G、H三个函数。G值表示从起始节点到当前节点的实际代价;H值是启发式函数,它估计从当前节点到目标节点的预计代价;F值是G值与H值之和,用于决定节点的选择顺序。 4. **...

    A*算法求解迷宫寻路问题(启发式算法)

    入口坐标和出口坐标分别为(startx,starty)和(endx,eny),每一个坐标点有两种可能:0或1,其中0表示该位置允许通过,1表示该位置不允许通过。以寻路问题为例实现A*算法的求解程序,设计两种不同的估价函数。

    A*走路 自动寻路A*算法 易语言源码优化版

    3. **启发式函数**:`h(n)`的计算是A*算法的关键,它需要提供一个估计目标距离的近似值。常见的启发式函数有曼哈顿距离、欧几里得距离、切比雪夫距离等。优化版可能对启发式函数进行了调整,使其更准确或计算更快。 ...

    A*算法解决十五数码问题(Python程序、报告)

    2. **启发式函数**:设计h(n)函数,例如曼哈顿距离或欧几里得距离,以估算从当前节点到目标状态的距离。 3. **开放列表和关闭列表**:开放列表存储待处理的节点,按f(n)值排序;关闭列表存储已处理过的节点,避免...

    C#实现的A*算法代码

    A*(A-star)算法是一种在图形搜索中用于找到从起始节点到目标节点最短路径的启发式搜索算法。它的核心思想是结合了Dijkstra算法的最优性和BFS(广度优先搜索)的效率,通过引入启发式函数来估计从当前节点到目标...

Global site tag (gtag.js) - Google Analytics