我有一个如下的迷宫:
||||||||||||||||||||||||||||||||||||
| 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个节点。
虽然Greedy Best实现我只在160次扩展中找到了次优路径(成本:74)。
我真的想知道我在哪里出错了。我意识到Greedy Best First算法可以自然地表现得这样,但是节点扩展中的差距太大我觉得 在这里出错了......任何帮助都会受到赞赏。如果我上面粘贴的内容在某种程度上不清楚,我很乐意添加详细信息。
答案 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中创建了一个类似的项目,我遇到了这个问题,这就是我在这里问的原因。例如,假设您有这些兴趣点:
而且,如果我没有弄错的话,对于迷宫中的所有要点都是如此。现在,考虑到 A *算法通常像具有启发式(和路径成本)的广度优先算法一样实现,因为你的启发式总是给你相同的总数(F = h + g)它实际上是一个广度优先的算法,它也为你提供了最好的解决方案,但实际上总是比A *通常要慢。现在正如Fezvez所说的那样,给你的启发式赋予权重可能只是混合了两个世界中的最佳(最好的第一和广度优先),并且看起来像上面给出的点: