一、问题求解器
- 约束条件
- 额外信息
二、以寻找最短路径为例
- 状态:原图中的节点(即城市)可以看成状态
- 动作:当前城市到达下一城市的过程
- 状态转移:当前状态经过某一动作后到达另一状态的过程
- 路径:一组状态转移的序列,例如(A,B,C)就是由A到达C的一种路径
- 目标测试:判断当前状态是否为所需要求解的目标状态,比如是否要求解A到C,若不是,则上面那个路径错误
启发式搜索(有信息搜索)
启发式搜索需要利用与所需求解问题的有关信息,具体的后面会详细解释。以下为该方式的三个关键要素:
- 辅助信息:所需要求解问题之外且与求解过程相关的信息
- 评价函数f(n):从当前节点n出发,根据评价函数来选取下一个节点
- 启发函数g(n):计算当前节点n到目标节点之间路径的最小值,将两点间的直线距离作为启发函数
三、贪婪最佳搜索算法:评价函数f(n)=启发函数h(n)
问题如下:请计算出Arad到达Bucharest的最短路径
关注图中给出的辅助信息,即每个城市到达Bucharest的直线距离
接下来我们逐步分析过程(见图中右侧树形图)
a. 初始状态
b. 扩展了起始城市Arad后,与三个城市Sibiu、Timisoara和Zerind相连,这里解释一下三个数字的253、329以及374的含义,因为贪婪最佳搜索算法认为评价函数f(n)=启发函数h(n),评价函数是寻找下一个节点的,启发函数是辅助信息带来的,所以这里的只需要根据辅助信息来进行评价。所以可以知道三个数字的253、329以及374的含义实际上是Sibiu、Timisoara和Zerind三个城市到达目标城市Bucharest的直线距离。经过评价后知道此时最优解为Sibiu。
c. 后续分析其实和上述步骤一致,找到Sibiu相连的城市,继续根据辅助信息进行评价。
后续过程省略......
思考该方法会存在什么问题呢?
答:会存在死循环的问题,参考图中这一部分,如果以Iasi到Fagaras为求解问题,那么Iasi到Neamt,然后会再到Iasi,再到Neamt,进而形成死循环。
A*算法:评价函数f(n)=g(n)+h(n)
接下来分析:
a. 初始状态
b. 与Arad相连的同样还是三个城市Sibiu、Timisoara和Zerind,以Sibiu为例分析,Sibiu的393=140+253,这里的140其实是g(Sibiu),也就是Arad到达Sibiu的距离,253是h(Sibiu),也就是Sibiu后续到达目标城市Bucharest的直线距离。这种方法很好的考虑到了未来的情况,不仅仅贪心现在,优化了贪心算法的短视(只顾现在,而不考虑未来,所以贪心算法往往不是最优解)的缺陷。所以在该步骤最终Sibiu获胜。
c. Sibiu相连的城市同样是三个,以与Sibiu相连的Arad为例,可能会有人奇怪这里的第一个数字为什么是280而不是140,这里需要回到g(n)的定义上,g(n)的定义是起点开始到当前节点的最短路径,我们的起点是Arad,先到达Sibiu,然后再由Sibiu到达Arad,实际上是140*2=280,后面的366就很好理解了,是Arad到达Bucharest的直线距离,其他几个也可以同样的方式分析。
后续过程省略......
补充说明一点: g(n)是从起始节点到节点n的实际代价开销,且f(n)=g(n)+h(n),因此f(n)不会高估经过节点n路径的实际开销。 其实也好理解,因为g(n)相当于截止目前所走的距离,h(n)是未来会走的距离,所以不会对实际结果进行过分偏离的高估。结合过去和未来,所以A*算法的结果才是真正的最短路径。