【问题标题】:Why is my Depth First Search Implementation Broken为什么我的深度优先搜索实施失败了
【发布时间】:2012-10-16 14:15:56
【问题描述】:

我一直在尝试不同的方式来实现深度优先搜索。我找到了一些工作方法,但它们涉及一些相当繁琐的字典工作。我使用列表开发了一个新想法,但是此实现返回的操作与所需的结果不匹配。我会尽量清楚地注释代码:

start = problem.getStartState()            ## returns an (x, y) tuple
children = problem.getSuccessors(start)    ##returns the children of a parent node in ((start                  
                                           state), action, cost) format. 
stack = Stack()                            ##creates a Stack (LIFO) data structure
visited = []                               ##list of visited nodes
visited.append(start)
for child in children:
    stack.push((child, [], [], 0))         ##push children to fringe in the format of (child,
    while stack:                           ##path taken, actions taken, cost) 
        parent = stack.pop()
        node = parent[0]
        if parent[0] in visited: continue
        visited.append(parent[0])
        path = parent[1] + [node[0]]           ##assigns previous path/actions/cost to new 
        actions = parent[2] + [node[1]]        ##node, creating a cumulative, ordered list of
        print actions                          ##the path/actions and a cumulative cost
        cost = parent[3] + node[2]
        if problem.isGoalState(node[0]):
            print parent[2]
            return parent[2]                    ## returns list of actions 
        children = problem.getSuccessors(node[0])
        if children != []:
            for child in children:
                stack.push((child, path, actions, cost))   ##assigns cumulative lists to child

有人看到我的问题在这个实现中可能出在哪里吗?顺便说一句,我知道 DFS 在大多数情况下是一种低效的算法。但是一旦我正确地实现了这个实现,它应该能够通过简单地更改存储父节点子节点的数据结构来跨越其他搜索算法。

【问题讨论】:

  • 你能举一个预期输出与你的输出的例子吗?
  • 您有一种代码味道,在迭代其子节点时,您将“开始”节点与其他节点区别对待。我打赌这个错误与此有关。
  • 嗯,这是非常具体的问题,如果没有大量规范,可能不会有太多意义。基本上,我期待一份行动清单,这些行动将引导我走上通往目标的正确道路。问题到达目标目的地(否则它不会返回任何内容),但动作列表不知何故让我回溯已经覆盖的地面(尽管我访问过的列表)并停在死胡同。
  • 你能添加一些调试符号吗?例如在此处提供的图表上:code.activestate.com/recipes/576723-dfs-and-bfs-graph-traversal?

标签: python algorithm depth-first-search


【解决方案1】:

CS188 朋友 :D 在这里阅读您的代码真的很难...所有这些索引 %) 使用更多的变量,它会更清楚。 我的解决方案:

def depthFirstSearch(problem):
    fringe = util.Stack()
    expanded = set()
    fringe.push((problem.getStartState(),[],0))
    
    while not fringe.isEmpty():
        curState, curMoves, curCost = fringe.pop()
        
        if(curState in expanded):
            continue
        
        expanded.add(curState)
        
        if problem.isGoalState(curState):
            return curMoves
        
        for state, direction, cost in problem.getSuccessors(curState):
            fringe.push((state, curMoves+[direction], curCost))
    return []

我希望我不需要评论它。这很容易阅读:) 祝你有美好的一天;)

【讨论】:

  • 虽然有效(原则上没有测试),但它没有回答问题:Anyone see where my problems might lie in this implementation?
  • 请注意,在 Python 中放置不必要的分号通常被认为是不好的风格。
  • 是的,对不起,我以前大部分的编码时间都在使用 C/C++/C# :) 阿米特,你的代码有很多错误。我认为找到它们需要一个多小时:) 至少你的第一个 for 循环违反了访问节点的顺序。您可以使用 Eclipse + PyDev 来调试您的代码。
  • @parkee:这不是 my 代码,我只是一个评论者。它仍然没有回答问题。
  • @user1427661:检查集合中的成员是 O(1),而检查列表中的成员是 O(n)。
【解决方案2】:

你似乎有名字冲突。请注意:

children = problem.getSuccessors(start)    ##returns the children of a parent node in ((start                  
... 
for child in children:
    ...
    while stack:
        ...
        children = problem.getSuccessors(node[0])
        ...

在第一次迭代之后,您的原始子代会丢失,因为它被内部循环中的子代覆盖。

一般来说,DFS最好使用recursive function实现,大致如下(未测试):

def dfs(problem, state, visited):
    visited.append(state)

    # have we reached the goal?
    if problem.isGoalState(state):
        return [state]

    for child in problem.getSuccessors(state):
        # if child is already visited, don't bother with it
        if child in visited: continue

        # otherwise, visit the child
        ret = dfs(problem, child, visited)

        if ret is not None:
            # goal state has been reached, accumulate the states
            ret.append(state)
            return ret

    return None # failed to find solution here
    # note that Python return None by default when reaching the end of a function

【讨论】:

  • +1:既指出了问题,又提供了更优雅的选择。
  • 好答案。不过,函数调用相对较高的开销可能是一个问题吗?或者,对于大型数据结构,递归限制呢?仅仅是这些通常可以忽略不计且不太可能分别达到吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-02
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多