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

问题描述 投票:5回答:3

我有一个如下的迷宫:

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

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

  • 通往+的路径成本最低(1跳=成本+ 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个节点。

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

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

python artificial-intelligence path-finding a-star heuristics
3个回答
4
投票

A *为问题提供了最佳答案,贪心最好的第一次搜索提供了任何解决方案。

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

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

例如,你可以试试这个:

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

2
投票

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


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
© www.soinside.com 2019 - 2024. All rights reserved.