У меня есть лабиринт, подобный следующему:
||||||||||||||||||||||||||||||||||||
| 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 находит неоптимальный путь (стоимость: 74) всего за 160 расширений.
Я действительно пытаюсь понять, где я ошибаюсь. Я понимаю, что алгоритмы Greedy Best First могут вести себя так естественным образом, но разрыв в раскрытии узлов настолько велик, что я чувствую, что здесь что-то должно быть неправильным... любая помощь будет оценена по достоинству. Я рад добавить детали, если то, что я вставил выше, каким-то образом неясно.
CHECKED_NODES.append(nextNode.xy)
- это, похоже, сократило мое расширение вдвое для обоих алгоритмов. .. - person MrDuk   schedule 23.02.2015