了解单个目标迷宫的A *启发式算法

时间:2015-02-23 03:48:01

标签: python artificial-intelligence path-finding a-star heuristics

我有一个如下的迷宫:

||||||||||||||||||||||||||||||||||||
|                                 P|
| ||||||||||||||||||||||| |||||||| |
| ||   |   |      |||||||   ||     |
| || | | | | |||| ||||||||| || |||||
| || | | | |             || ||     |
| || | | | | | ||||  |||    |||||| |
| |  | | |   |    || ||||||||      |
| || | | |||||||| ||        || |||||
| || |   ||       ||||||||| ||     |
|    |||||| |||||||      || |||||| |
||||||      |       |||| || |      |
|      |||||| ||||| |    || || |||||
| ||||||      |       ||||| ||     |
|        |||||| ||||||||||| ||  || |
||||||||||                  |||||| |
|+         ||||||||||||||||        |
||||||||||||||||||||||||||||||||||||

目标是P找到+,其子目标为

  • +的路径成本最低(1 hop = cost + 1)
  • 搜索的单元格数(扩展的节点)最小化

我试图理解为什么我的A *启发式游戏的表现比我对Greedy Best First的执行情况要糟糕得多。以下是每个代码的两位代码:

#Greedy Best First -- Manhattan Distance
self.heuristic = abs(goalNodeXY[1] - self.xy[1]) + abs(goalNodeXY[0] - self.xy[0])

#A* -- Manhattan Distance + Path Cost from 'startNode' to 'currentNode'
return abs(goalNodeXY[1] - self.xy[1]) + abs(goalNodeXY[0] - self.xy[0]) + self.costFromStart

在这两种算法中,我使用heapq,根据启发式值进行优先排序。主搜索循环对于两者都是相同的:

theFrontier = []
heapq.heappush(theFrontier, (stateNode.heuristic, stateNode)) #populate frontier with 'start copy' as only available Node

#while !goal and frontier !empty
while not GOAL_STATE and theFrontier:
    stateNode = heapq.heappop(theFrontier)[1] #heappop returns tuple of (weighted-idx, data)
    CHECKED_NODES.append(stateNode.xy)
    while stateNode.moves and not GOAL_STATE:
        EXPANDED_NODES += 1
        moveDirection = heapq.heappop(stateNode.moves)[1]

        nextNode = Node()
        nextNode.setParent(stateNode)
        #this makes a call to setHeuristic
        nextNode.setLocation((stateNode.xy[0] + moveDirection[0], stateNode.xy[1] + moveDirection[1]))
        if nextNode.xy not in CHECKED_NODES and not isInFrontier(nextNode):
            if nextNode.checkGoal(): break
            nextNode.populateMoves()
            heapq.heappush(theFrontier, (nextNode.heuristic,nextNode))

所以现在我们来讨论这个问题。虽然A *找到了最佳路径,但这样做非常昂贵。为了找到cost:68的最佳路径,它会扩展(导航和搜索)452个节点。 a_star

虽然Greedy Best实现我只在160次扩展中找到了次优路径(成本:74)。

greedy_best_first

我真的想知道我在哪里出错了。我意识到Greedy Best First算法可以自然地表现得这样,但是节点扩展中的差距太大我觉得 在这里出错了......任何帮助都会受到赞赏。如果我上面粘贴的内容在某种程度上不清楚,我很乐意添加详细信息。

3 个答案:

答案 0 :(得分:4)

A *提供了问题的最佳答案,贪婪的最佳搜索提供了任何解决方案。

预计A *必须做更多工作。

如果您想要A *的变体不再是最佳但是更快地返回解决方案,您可以查看加权A *。它只包括对启发式加权(权重> 1)。在实践中,它会为您带来巨大的性能提升

例如,您可以试试这个:

return 2*(abs(goalNodeXY[1] - self.xy[1]) + abs(goalNodeXY[0] - self.xy[0])) + self.costFromStart

答案 1 :(得分:2)

A *搜索尝试找到问题的最佳解决方案,而贪婪的最佳 - 首先只是试图找到任何解决方案。 A *有一个非常艰巨的任务,它必须投入大量的工作来探索可能是最好的每一条路径,而贪婪的最佳优先算法直接​​用于看起来最接近目标的选项

答案 2 :(得分:1)

由于这还没有得到解决,即使OP询问的错误可以用Fezvez's answer来解决,我觉得我需要问这个问题并且可能回答什么是错误以及为什么Fezvez的答案可以解决它:你用A *算法检查了所有节点的启发式值并注意到奇怪的东西吗?他们都不平等吗?因为尽管您的启发式算法对于最佳优先算法是正确的,但它并不直接适合您的A *算法。我在java中创建了一个类似的项目,我遇到了这个问题,这就是我在这里问的原因。例如,假设您有这些兴趣点:

  • 开始(P) - (0,0)
  • 结束(+) - (20,20)
  • P1 - (2,2) - > (你的启发式)+(路径成本)=((20-2)+(20-2))+((2-0)+(2-0))= 40
  • P2 - (4,3) - > (你的启发式)+(路径成本)=((20-4)+(20-3))+((4-0)+(3-0))= 40

而且,如果我没有弄错的话,对于迷宫中的所有要点都是如此。现在,考虑到 A *算法通常像具有启发式(和路径成本)的广度优先算法一样实现,因为你的启发式总是给你相同的总数(F = h + g)它实际上是一个广度优先的算法,它也为你提供了最好的解决方案,但实际上总是比A *通常要慢。现在正如Fezvez所说的那样,给你的启发式赋予权重可能只是混合了两个世界中的最佳(最好的第一和广度优先),并且看起来像上面给出的点:

  • 开始(P) - (0,0)
  • 结束(+) - (20,20)
  • P1 - (2,2) - > 2 *(你的启发式)+(路径成本)= 2 *((20-2)+(20-2))+((2-0)+(2-0))= 76
  • P2 - (4,3) - > 2 *(你的启发式)+(路径成本)= 2 *((20-4)+(20-3))+((4-0)+(3-0))= 73