#python #algorithm #a-star
#python #алгоритм #a-star
Вопрос:
Это моя реализация A * на Python
class Node:
def __init__(self, (x, y), g, h, parent):
self.x = x
self.y = y
self.g = g
self.h = h
self.f = g h
self.parent = parent
def __eq__(self, other):
if other != None:
return self.x == other.x and self.y == other.y
return False
def __lt__(self, other):
if other != None:
return self.f < other.f
return False
def __str__(self):
return "(" str(self.x) "," str(self.y) ") " str(self.f)
def mean(lst):
print sum(lst)/len(lst)
def find_path(start_node, end_node, map, no_diag=True):
open_list = [start_node]
closed_list = []
solution = []
while len(open_list) > 0:
open_list.sort()
current_node = open_list.pop(0)
if current_node == end_node:
while current_node != None:
solution.append(current_node)
current_node = current_node.parent
break
for x,y in [(0,-1), (1,0), (0,1), (-1,0)]:
touching_node = Node((current_node.x x, current_node.y y), 10, (abs(end_node.x-current_node.x) abs(end_node.y-current_node.y))*10, current_node)
tile_in_range = touching_node.x >= 0 and touching_node.y >= 0 and touching_node.x < len(map[0]) and touching_node.y < len(map)
if not tile_in_range or touching_node == current_node.parent or map[touching_node.y][touching_node.x] == 1:
continue
if touching_node in open_list:
n = open_list[open_list.index(touching_node)]
if n > touching_node:
open_list.remove(n)
else:
continue
if touching_node in closed_list:
n = closed_list[closed_list.index(touching_node)]
if n > touching_node:
closed_list.remove(n)
open_list.add(touching_node)
closed_list.append(current_node)
return solution
map = [[1,1,0,1,0,0],
[0,0,0,0,1,0],
[0,0,1,0,0,0],
[0,0,0,1,0,0],
[0,1,0,1,1,1],
[0,1,0,0,0,0]]
map2 = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,2,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]
def test(map, start, end):
for r in map:
print r
res = find_path(Node(start,1000,1000,None), Node(end,1000,1000,None), map)
for n in res:
print n
test(map, (0,5), (5,0))
test(map2, (3,8), (2,11))
С первой картой путь найден сразу. На втором, однако, даже через полчаса путь не найден. Я пытался использовать более быстрый список, но это не имело никакого значения. Может кто-нибудь, пожалуйста, указать, в чем проблема?
Комментарии:
1. что такое sortedlist? это не стандартный тип.
2. Сброс кода здесь и обращение за помощью — не лучший способ задать вопрос. Вы убедились, что ваш код не переходит в бесконечный цикл? Вы профилировали свой код?
3. @misha sortedlist взят из модуля под названием blist . Я думал, что использование простого старого list.sort() было причиной замедления — это не так.
Ответ №1:
Проблема с вашей реализацией заключается не в производительности, а скорее в том, что она на самом деле неверна — она никогда не заканчивается для второй карты!
В части, где узел удаляется из закрытого набора, отсутствует else: continue
— если узел уже является частью любого набора — его нельзя добавлять в открытый набор!