在*搜索中重新访问访问的节点

2024-09-30 18:22:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试应用一个*搜索定向越野,以获得最佳路线。输入是两个文件-一个是解释地形的图像文件,一个是定义高程的文本文件。我根据预先设定的值计算地形难度,以定义穿越地形的速度。我还定义了基于坡度的海拔难度(向下的坡度可以加快速度,反之亦然)。在

地形和高程数据存储在矩阵(列表列表)中。因此,输入是与地图上的点相同的索引。提供两个输入-例如:

start = [230,327]
end = [241,347]

问题是我的代码一直在重新访问已访问队列中已存在的节点。节点定义如下:

^{pr2}$

我还使用了一个子节点类来定义函数,时间被定义为自我的时间+毕达哥拉斯斜边到目标的距离:

class SubNode(Node):
    def __init__(self, value, parent, start=[], goal=[]):
        super(SubNode, self).__init__(value, parent, start, goal)
        self.timeToGoal = self.GetTime()

    def GetTime(self):
        if self.value == self.goal:
            return 0
        [currentX, currentY] = self.value
        [targetX, targetY] = self.goal
        parentTime = 0
        if self.parent:
            parentTime = self.timeTravelled
        heuristicTime = 99999.99
        # Pythagorean Hypotenuse - Straight-line Distance
        distance = math.sqrt(((int(currentX) - int(targetX)) ** 2) + (int(currentY)- int(targetY)) ** 2)
        speed = 1.38 * calculateTerrainDifficulty(terrainMap[currentX][currentY])
        if speed != 0:
            heuristicTime = distance / speed
        heuristicTime=heuristicTime+parentTime
        return heuristicTime


    def CreateChildren(self):
        if not self.children:
            dirs = [-1, 0, 1]
            [xVal, yVal] = self.value
            for xDir in dirs:
                newXVal = xVal + xDir
                if newXVal < 0 or newXVal > 394: continue
                for yDir in dirs:
                    newYVal = yVal + yDir
                    if ((xVal == newXVal) and (yVal == newYVal)) or (newYVal < 0 or newYVal > 499) or (
                        calculateTerrainDifficulty(terrainMap[newXVal][newYVal]) == 0):
                        continue
                    child = SubNode([newXVal, newYVal], self)
                    self.children.append(child)

A*search类的定义如下。您可以看到,我将条件放在那里,以确保节点不会被重新访问,并且当我在其中输入打印时,我可以看到该条件多次满足。在

class AStarSearch:
    def __init__(self, start, goal):
        self.path = []
        self.visitedQueue = []
        self.priorityQueue = PriorityQueue()
        self.start = start
        self.goal = goal

    def Search(self):
        startNode = SubNode(self.start, 0, self.start, self.goal)
        count = 0
        self.priorityQueue.put((0, count, startNode))
        while (not self.path and self.priorityQueue.qsize()):
            closestChild = self.priorityQueue.get()[2]e
            closestChild.CreateChildren()
            self.visitedQueue.append(closestChild.value)
            for child in closestChild.children:
                if child.value not in self.visitedQueue:
                    count += 1
                    if not child.timeToGoal:
                        self.path = child.path
                        break
                    self.priorityQueue.put((child.timeToGoal, child.value, child))
        if not self.path:
            print("Not possible to reach goal")
        return self.path

由于某些原因,我的程序不断地重新访问一些节点(正如我在打印访问的队列时从输出中看到的那样)。我怎样才能避免这种情况?在

[230、327]、[231、327]、[231、326]、[229、326]、[231、325]、[231、328]、[229、328]、[[229、328]、,[强[强[[231、327][231、327],[第[229、327]的,[229、327],[229,327],[229,325[[[231,327],[231,329][230,323],[231,329,329,329,329][231,327],[229,327],[229,327][229,327][2299,329,327][[[231323],[229330],[229331]]

我面临的另一个问题是:

TypeError: unorderable types: SubNode() < SubNode()

有没有一种方法可以在不改变python优先级队列使用的情况下克服这个问题?在


Tags: pathselfchildif节点定义valuedef
1条回答
网友
1楼 · 发布于 2024-09-30 18:22:22

您需要在closestChild而不是其子级上添加测试:

closestChild = self.priorityQueue.get()[2]e
if closesChild.value not in self.visitedQueue:
    closestChild.CreateChildren()
    self.visitedQueue.append(closestChild.value)

否则,可以说您访问n1,然后访问n2,两者都链接到节点n3n3priorityqueue中添加了两次,因此弹出了两次,然后添加了两次到visitedQueue。在

条件if child.value not in self.visitedQueue:有助于加快速度(通过保持较小的优先级队列),但不是必需的(因为priorityQueue中不必要的对象在解卷时将被丢弃)。在

关于您得到的错误:PriorityQueue不支持自定义排序,这是您的优先级队列所需要的,因此您必须自定义一个。有一个example here。显然,_get_priority函数需要返回timeTravelled,而不是{}

编辑3:我们(tobias_k和我)首先说,您需要为SubNode实现__eq__函数,这样python就知道它们中的两个是相等的,但实际上情况并非如此,因为您只将值存储在自访问队列. 在

相关问题 更多 >