启发式搜索算法解析

在没有额外信息的情况下,探讨了各种盲目搜索算法,因为问题中只给出了约束条件。这些算法在达到目标状态之前会遍历许多不同的状态。这些搜索策略的缺点是时间复杂度非常差,因此使用这些策略解决现实世界问题是不合理的。

这个问题可以通过提供一些启发式信息来解决,即“通过暴露获得的经验”,从而引入了启发式搜索策略。这些算法承诺可以快速解决任何复杂问题,并且时间复杂度更低。

启发式搜索策略使用一些启发式函数来选择节点,以确保最有希望的路径到达目标。给搜索问题提供更多关于问题的信息的最流行方式是使用启发式函数。这是从特定节点n到目标状态的成本估计。任何问题特定的函数都是可以接受的(任意的和非负的)。如果n是目标节点,则H(n) = 0。

本文将介绍两种启发式搜索策略:最佳优先搜索算法和A*搜索算法。

最佳优先搜索算法

启发式广度优先搜索遵循贪婪的方法进行状态转换以达到目标。在这里,为每个节点维护一个评估函数(f(n)),它提供了成本估计。想法是每次都扩展具有最低f(n)的节点。这里的评估函数有一个启发式函数h(n)组件,即f(n) = h(n)。因此,看起来最接近目标的节点将被扩展。这个算法的实现是使用一个优先队列,按照每个节点的评估函数进行排序。伪代码如下:

function Best_First_Search(problem) { node = problem.initial_state; frontier = priority queue with node as the only element; explored = empty set; loop(until goal state is found) { if(frontier == empty) return failure; node = frontier.pop(); add node to explored_set; if(node == problem.goal_state) return path from Initial state up to the node; else generate successors of the node; if(successors not in frontier and not in explored_set) add successor to the priority queue; } }

最佳优先搜索算法的特性:

  • 完备性:不,有时会陷入循环。
  • 空间复杂度:O(b^m)。
  • 时间复杂度:O(b^m)(但一个好的启发式可以大幅改善)。
  • 最优性:不。

(b是分支因子,m是搜索空间的最大深度。)

A*搜索算法

A*搜索策略是最广泛使用的一种策略,因为它保证了最优解。这个想法是避免扩展已经昂贵的路径。与最佳优先搜索类似,它使用评估函数(f(n))来评估路径中的每个节点(状态)。

f(n) = g(n) + h(n),其中g(n)是从初始状态到当前节点的实际成本,h(n)是从当前节点到目标状态的估计成本。A*算法成功地找到了问题最短路径的解决方案,因此它是状态空间搜索中最广泛接受的解决方案。A*搜索的解的最优性取决于选择的启发式函数的可接受性。下面将详细介绍。

A*搜索策略的算法步骤:

  1. 初始化一个空集(explored)。初始化一个优先队列(frontier),按照节点的评估函数排序。将节点(初始状态)添加到队列中,其评估函数为f(start) = 0+h(start) ……(g(start)=0)。
  2. 循环直到找到目标 - 如果边界为空,则返回失败。否则,从边界中弹出评估函数最低的节点(best_node)。将best_node添加到explored集合中。检查best_node是否为目标状态;如果是,则返回解决方案。否则,生成其后继节点。
  3. 对于每个生成的后继节点,执行以下操作:
    1. 设置后继节点指向best_node。(这些后向链接有助于找到从第一个状态到最后目标状态的解决方案路径。)
    2. 计算后继节点的实际成本,即g(successor) = g(best_node) + 从best_node到后继节点的实际成本。
    3. 如果后继节点已经在边界中(即,已经存在到达该节点的路径),称之为old_node。
    4. 将old_node添加到best_node的后继节点列表中。现在,将比较通过其之前路径到达old_node的实际成本(g(n))和当前新路径(即,通过best_node)的实际成本。
    5. 如果旧路径更便宜,继续。否则,更新old_node的父节点链接指向best_node,并更新old_node的评估函数。
    6. 如果后继节点在explored中(即,已经访问过这个节点),称之为old_node。重复步骤3.4和3.5,看看是否得到新的、更好的路径。必须将改进传播到old_node的后继节点。
    7. 如果后继节点不在边界中且不在explored集合中,将其添加到边界中。将其放在best_node的后继节点列表中。计算其评估函数(f(successor) = g(successor) + h(successor))。

这个算法的时间复杂度是b^d。空间复杂度是b^d。(其中b是树的分支因子,d是解决方案节点的深度。)

解决方案的最优性取决于可接受的启发式。那么,什么是可接受的启发式呢?

如果对于每个节点,h(n)小于或等于g(n)(这里,g(n)是到达目标状态的实际成本),则启发式函数h(n)是可接受的。因此,一个可接受的启发式永远不会高估到达目标的成本。它总是对找到到达目标节点的最佳路径持乐观态度。如果h(n)对于A*算法是可接受的,得到问题的最优解。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485