如何在迭代深化/深度限制搜索中存储访问状态?

时间:2012-09-26 09:45:48

标签: algorithm artificial-intelligence depth-first-search iterative-deepening

更新:搜索第一个解决方案。

对于正常的深度优先搜索,它很简单,只需使用哈希集

    bool DFS (currentState) =
    {
          if (myHashSet.Contains(currentState))
          {
               return;
          }
          else
          {
                myHashSet.Add(currentState);
          }
          if (IsSolution(currentState) return true;         
          else
          {
              for (var nextState in GetNextStates(currentState))
                   if (DFS(nextState)) return true;
          }
          return false;
     }

然而,当它变得深度受限时,我不能简单地这样做

    bool DFS (currentState, maxDepth) =
    {
          if (maxDepth = 0) return false;
          if (myHashSet.Contains(currentState))
          {
               return;
          }
          else
          {
                myHashSet.Add(currentState);
          }
          if (IsSolution(currentState) return true;         
          else
          {
              for (var nextState in GetNextStates(currentState))
                   if (DFS(nextState, maxDepth - 1)) return true;
          }
          return false;
     }

因为在maxdepth

之前它不会进行完整的搜索(在某种意义上总是能够找到解决方案)

我该如何解决?它会给算法增加更多的空间复杂度吗?

或者它根本不需要记忆状态。

更新

例如,决策树如下:

   A - B - C - D - E - A
                   |
                   F - G (Goal)

从状态A开始,G是目标状态。显然,在深度3下有一个解决方案。

然而,在深度4下使用我的实现,如果搜索的方向恰好是

A(0) -> B(1) -> C(2) -> D(3) -> E(4) -> F(5)超出深度,然后它会回溯到A,但访问E,它会忽略检查方向A - E - F - G

3 个答案:

答案 0 :(得分:2)

我和你的问题一样,这是我的帖子Iterative deepening in common lisp

基本上使用哈希表来解决这个问题,你不能只检查一个节点是否被访问过,你还必须考虑它之前访问过的深度。如果您要检查的节点包含以前未见过的状态,或之前已经看过的状态但是在更高的深度,那么您仍然应该考虑它,因为它可能导致更浅的解决方案,这是迭代加深应该do,它返回BFS返回的相同解决方案,这将是最浅的。因此,在哈希表中,您可以将状态作为键,将深度作为值。在找到较浅的节点之后,您将需要不断更新哈希表中的深度值。

循环检查的另一种解决方案是回溯从当前节点到根的路径,如果您要检查的节点已经出现在路径上,那么它将导致循环。这种方法更通用,可以与任何搜索策略一起使用。它比哈希表方法慢,具有O(d)时间复杂度,其中d是深度,但内存复杂度将大大降低。

答案 1 :(得分:1)

在IDFS的每个步骤中,您实际上都在搜索最短的路径,您不能简单地使用 hashSet 。只有当您搜索长度无限制的路径时,HashSet才有帮助。

在这种情况下,您应该使用 hashMap 来存储最小步骤以达到状态,并仅在无法更新地图值时修剪分支。时间复杂度可能会相应变化。

但实际上,当空间有限时,使用IDFS代替BFS。作为散列,状态可能占用的空间几乎与BFS一样多,通常您无法将所有状态存储在IDFS中。

wiki中的IDFS也没有哈希值。 http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search

所以让我们放弃空间的哈希和交易时间!

<强>更新

将状态存储在当前dfs堆栈中是值得的,然后搜索路径不会导致无关紧要的循环。实现此功能的psudocode将是:

bool DFS (currentState, maxDepth) =
{
      if (maxDepth = 0) return false;
      if (myHashSet.Contains(currentState))
      {
           return;
      }
      else
      {
            myHashSet.Add(currentState);
      }
      if (IsSolution(currentState) return true;         
      else
      {
          for (var nextState in GetNextStates(currentState))
               if (DFS(nextState, maxDepth - 1)) return true;
      }
      myHashSet.Remove(currentState); //the state is pop out from the stack
      return false;
 }

答案 2 :(得分:0)

您展示的解决方案非常精细,适用于DFSID(深度优先搜索,迭代加深)。在增加深度之前,不要忘记清除myHashSet