启发式搜索1

回想起来我像第一次接触启发式搜索还是在本科大三的课程设计,但是当时还完全没有分类的概念。一直想总结一下启发式搜索的内容,现在能有时间做一些总结感觉真爽快。大笑

————————————————————————————————————————————————————————————————————————

启发式搜索(Informed Search / Heuristic Search)

一般的搜索策略都可以归纳成以下的算法过程

       - 初始化队列Q

       - 重复以下过程

                 - 取队列Q头的值,并测试其是否是我们的目标值,如果是结束搜索

                 - 拓展Q,例如产生候选节点并将其加入队列Q

因为在实际编程过程中,虽然实际模型常常是图Graph结构的,但是通常会使用队列Queue来保存搜索信息

不同的搜索算法根据添加新节点的顺序不同而区分,就是拓展步骤候选节点的选择顺序策略

从这种角度考虑时,深度优先搜索(DFS)和广度优先搜索(BFS)其实在处理新节点的方法上是一样的

区别仅仅在:

           - 深度优先搜索,在队列的加入新的候选节点

           - 广度优先搜索,在队列的加入新的候选节点

最佳优先搜索 Best First Search 使用评价函数 f(x) 来对上述的节点选择顺序进行排序

下面先定义两个函数

           - g(x) 为从根节点x节点的代价总和

           - h(x) 为从x节点目标节点的估计代价总和

这类应用算法有

代价一致搜索 (Uniform Cost Search)      f(x) = g(x)

贪心搜索 (Greedy Search)                       f(x) = h(x)

A星搜索 (A* Search)                                 f(x) = g(x)  + h(x)


关于模型的图

上面所讲的 g(x) h(x) 还是太过抽象,所以这里用一张经典的图进行说明,这是一张地图的抽象,假定目标节点为Bucharest

在上图中,h(x)指的是右边的各个节点(城市)到目标节点(Bucharest)的直线测量距离

可以想象,这个距离在实际中不可能等同于路程,除非你在驾驶一辆理想化的私人进行交通而且还无视航空法规。

但是,这个距离在大多情况下是能反映出一部分的实际距离的,因为无论怎样绕远路,直线距离100km和直线距离1km的两个地点在实际到达距离或时间(代价)上都是有区分度的。

这里又回到了数学建模问题,一个好的建模可以大大优化算法的执行质量。


贪心搜索是完全使用 h(x) 作为参考的,该算法会一直选择距离目标最近的点进行拓展。

由于每一步的拓展都是基于当前与节点相连接的节点进行选择的,所以贪心算法可能会出现环路状况,例如图中的 Iasi 和 Neamt 就会不断循环访问

而且贪心搜索无法保证结果的最优解,原因是我们用的数据是预测数据(直线距离)而不是真实数据,其具有一定概率上的相关性但不具备实际相关性。


代价一致搜索

用优先队列实现,关键点在于该算法不关心经过节点量,只关心该路径已走过路程和(代价和)。而且此算法就算到达目标点也不会停止,而是继续寻找是否有更佳路径,直至遍历完成

procedure UniformCostSearch(Graph, start, goal)
  node ← start
  cost ← 0
  frontier ← priority queue containing node only
  explored ← empty set
  prev[] ← empty set
  do
    if frontier is empty
      return failure
    node ← frontier.pop()
    if node is goal
      return solution
    explored.add(node)
    for each of node's neighbors n
      if n is not in explored
        if n is not in frontier
          frontier.add(n)
          prev[n] = node
        else if n is in frontier with higher cost
          replace existing node with n
          prev[n] = node
这里还有一个算法在我看来是和代价一致搜索是一样原理的,就是Dijkstra's algorithm。

这两个算法的区别在于UCS不需要像Dijkstra's那样一次吧所有节点的信息全部读入(初始化时所有节点的cost设置成无限大),而是在某节点有更新时才对其进行cost值初始化并加入优先队列。(黄色字部分为区别)

因为算法的限制,ucs不会出现环路情况,因为explored参数的存在

explored prev可以设置为每个节点的状态 ,也可以设成独立结构


A* Search

吸收了以上两个算法的优点

贪心的效率和ucs的精准

为什么A* Search能保证有最优解呢?

这是由于 h() 只要满足可允许(adimssible)条件:任何的h(x)都小于或等于h*(x)

h*(x) 是从节点x到目标的实际路径

那么从算法的角度看预测值的权永远小于或等于同等的实际距离的权

就是说预测对算法的影响不会大于实际值


Iterative Deepening A*

相对A*算法该算法使用了深度优先的搜索策略,并且在递归开始就设定了阈值,在算法搜索到一定深度后自动停止深度搜索

该算法无需进行访问判断和排序,相对占内存空间较小

 node              current node
 g                 the cost to reach current node
 f                 estimated cost of the cheapest path (root..node..goal)
 h(node)           estimated cost of the cheapest path (node..goal)
 cost(node, succ)  step cost function
 is_goal(node)     goal test
 successors(node)  node expanding function
 
 procedure ida_star(root)
   bound := h(root)
   loop
     t := search(root, 0, bound)
     if t = FOUND then return bound
     if t = ∞ then return NOT_FOUND
     bound := t
   end loop
 end procedure
 
 function search(node, g, bound)
   f := g + h(node)
   if f > bound then return f
   if is_goal(node) then return FOUND
   min := ∞
   for succ in successors(node) do //DFS
     t := search(succ, g + cost(node, succ), bound)
     if t = FOUND then return FOUND
     if t < min then min := t
   end for
   return min
 end function

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
盲目搜索启发式搜索是两种常见的搜索算法。盲目搜索是一种无信息搜索方法,它不利用任何关于问题结构的先验知识,而是通过遍历搜索空间的方式来找到解。常见的盲目搜索算法有深度优先搜索、广度优先搜索和迭代深化搜索。深度优先搜索按照深度优先的方式遍历搜索空间,但可能会陷入非目标状态的分支导致找不到解;广度优先搜索从起始状态开始,逐层扩展搜索,始终能够找到问题的解,但时间和空间消耗较大;迭代深化搜索是将深度优先和广度优先搜索结合起来,通过设置深度限制,在每一层的深度上进行深度优先搜索,当达到限制的深度时转到其他分支继续搜索,直到找到解为止。 启发式搜索是一种利用问题结构的启发信息来引导搜索的方法。启发式搜索算法根据某种评估函数对每个搜索节点进行评估,选择评估值最优的节点进行扩展。常见的启发式搜索算法有最佳优先搜索(Best-first search)和A*算法。最佳优先搜索每次扩展评估值最优的节点,但可能会受到启发函数的局限性,导致找不到最优解;A*算法综合考虑了节点的实际代价和启发函数的估计代价,通过评估函数f(n) = g(n) + h(n)选择评估值最优的节点进行扩展,其g(n)表示从起始节点到节点n的实际代价,h(n)表示从节点n到目标节点的启发式估计代价。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值