代码之家  ›  专栏  ›  技术社区  ›  NeoZoom.lua

我无法理解此优先级队列版本DFS?

  •  0
  • NeoZoom.lua  · 技术社区  · 5 年前

    下面是使用一个堆栈和一个大表来标记访问的节点的伪代码实现深度优先搜索(DFS):

    DFS(N0):
       StackInit(S)
       S.push((N0, null))
       if isGoal(N0) then do
          return true
       markVisited(N0)
       S.push((null, N0))
       while !isEmpty(S) then do
          (N, parent) := S.pop()
          R := next((N, parent))
          if isNull(R) then do
             continue             // So no new node add to this layer.
          S.push((R, parent))
          if marked(R) then do
             continue
          if isGoal(R) then do    // If it's goal don't have to explore it.
             return true
          markVisited(R)
          if depthMax((R, parent)) then do
             continue
          S.push((null, R))
       return false
    

    我想解决的问题是它的一个修改:它替代了堆栈 S 带优先级队列 PQ


    DFS2(N0, f, LIMIT):
       PriorityQueueInit(PQ)
       // A node (N, parent) stored in PQ represents a path from `N0` to `N`\
            passing the node `parent`; A node with smaller value on f() is \
            prioritized than those with larger value.
       PQ.push((N0, null))
       if isGoal(N0) then do
          return true
       markVisited(N0)
       PQ.push((null, N0))
       while !isEmpty(PQ) then do     // (1)
          (N, parent) := PQ.poll()
          R := next((N, parent))      // (2)
          if isNull(R) then do
             continue
          PQ.offer((R, parent))
          if marked(R) then do
             continue
          if isGoal(R) then do
             return true
          markVisited(R)
          if f((R, parent)) > LIMIT then do
             continue
          PQ.offer((null, R))
       return false
    
    • (1) :在*算法中,优先级队列用于存储尚未探索的节点,即开放列表。在我提供的第一个DFS伪代码中 S 资格预审 名单也很接近。那么,第二个伪代码如何用一个封闭列表模拟IDA*算法呢?
    • (2) :它从中获取当前最小的节点 资格预审 ,可能不是节点的同级 N ,即 从当前子树到另一子树包含 . 这条线的目的是什么?


    更新更多信息:我花了很多时间和精力在这个问题上,但似乎很难,因为以下几点:

    1. 教科书中出现的所有图形都是树状的,即每个节点只有一个父节点,以表示概念。这让我困惑:第二种算法只对树有效吗?

    2. 考虑到线路

      if f((R, parent)) > LIMIT then do ...
      

      如果第二个也适用于graph,而不仅仅是tree,那么可能会有很多家长去 R 我应该考虑所有的情况还是当前的情况? parent ?

    0 回复  |  直到 5 年前
        1
  •  2
  •   David Eisenstat    5 年前

    这里发生了很多事情。

    据我所知,这段代码总是返回到达队列顶部的第一个目标节点。在下面关于f和next的假设下,这个目标节点是f-最优的。但我不会把这个叫做艾达。

    首先,通常A*和IDA*会同时打开当前节点的所有邻居。这个代码…没有。它使用迭代器,但只有一个循环。第一次推送用于当前节点的下一个同级节点,第二次推送用于子节点。这很好,我想,除了兄弟姐妹应该以递增的f阶来枚举,这样有希望的兄弟姐妹就不会在没有希望的兄弟姐妹之后被隐藏。

    其次,与A*不同,IDA*没有一个封闭列表。从某种意义上说,艾达总是在寻找 ,因为如果它到达两个等价的节点,它仍然将它们视为不同的节点。A*确实有一个非常接近的列表,但它比这里的要复杂。A*处理循环的方式是,如果它发现到已经关闭的节点的更便宜的路径,那么它将重新打开该节点。这段代码没有,所以它只有在不需要重新打开节点时才是正确的。因此,这段代码需要f是所谓的一致启发式(在每一条路径上,f永远不会随着路径而下降),而a*只需要f是可容许的(f永远不会低估达到目标状态的成本)。

    推荐文章