Python网格世界不正确的深度优先搜索算法实现

问题描述

我正在尝试编写一个深度优先搜索算法,该算法将找到一个路径形式,其中代理(黑色立方体)到右侧路径底部的出口。但是我编写的算法作为找到的路径的一部分循环回到自身。我如何实现不这样做的 DFS 算法?

对我做错了什么有任何想法吗?

非常感谢任何帮助。

谢谢 世界是什么样子:

The world/maze.

深度优先搜索路径规划的结果:

Output/result of path planning

我的代理类代码

class Agent(turtle.Turtle):
    def __init__(self,location,endPoint,world): 
        turtle.Turtle.__init__(self)
        self.shape("square")
        self.color("black")
        self.penup()
        self.speed(0)
    
        # Variables
        self._bump = 0
        self._location = location
        self._endPoint = endPoint
        self._world = world
        self._map = dict()
    
    def dfs_paths(self,start,goal,path=None):
        if path is None:
            path = [start]
        if start == goal:
            yield path
        for next in self._map[tuple(start)] - set(path):
            yield from dfs_paths(next,path + [next])
    
    def _planPath(self,node,visited=None):
        if visited is None:
            visited = [node]
        self._map[tuple(node)] = self._world.testDirections(node)
        if node not in visited:
            visited.append(tuple((node)))
            print("Visited = " + str(visited))
            for neighbour in self._map[tuple((node))]:
                print("Neighbour = " + str(neighbour))
                if neighbour == self._endPoint:
                    visited.append(neighbour)
                    print("Here 1...")
                    return [node,neighbour]
                else:     
                    path = self._planPath(neighbour,visited)
                    if path:
                        print("Here 2...")
                        return [node] + path

解决方法

您正在根据 visited 信息构建路径。但这并不代表路径。它只代表您访问过的节点,其中包括您已经回溯的不成功路径。

当您找到目标节点时,您应该创建一个仅包含结束节点的(部分)路径,并将其返回给调用者。调用者可以从递归调用的返回值中检测到目标已找到,然后可以将自己的节点添加到该部分路径中,并将其返回给自己的调用者。

这样回溯阶段(成功后)将用于构建路径。

所以,为了让你开始,替换这个:

self._planPath(neighbour,visited)

与:

path = self._planPath(neighbour,visited)
if path:  # success!
    return [node] + path

或者做一个更有效的append,但是你必须在最后改变路径。

并替换这个:

self._world.showPath(visited)

与:

return [node,neighbor]

self._planPath 的主要调用者可能会这样做:

path = self._planPath(startnode,[])
if path:
    self._world.showPath(path)

请注意,对于 visited,您实际上应该使用 set,而不是列表。