secuencial ordenamiento método listas ejemplos codigo búsqueda busqueda binaria algoritmos algoritmo python algorithm performance a-star

ordenamiento - Python: agiliza un algoritmo de búsqueda de estrellas



ejemplos de busqueda secuencial (3)

Como se sugirió anteriormente, convierta closedSet en un conjunto.

Intenté codificar openList como heap de import heapq montón:

import heapq def aStar(self, graph, current, end): closedList = set() path = [] def retracePath(c): path.insert(0,c) if c.parent == None: return retracePath(c.parent) openList = [(-1, current)] heapq.heapify(openList) while openList: score, current = openList.heappop() if current == end: return retracePath(current) closedList.add(current) for tile in graph[current]: if tile not in closedList: tile.H = (abs(end.x-tile.x)+abs(end.y-tile.y))*10 if tile not in openList: openList.heappush((tile.H, tile)) tile.parent = current return path

Sin embargo, aún necesita buscar if tile not in openList , así que haría esto:

def aStar(self, graph, current, end): openList = set() closedList = set() def retracePath(c): def parentgen(c): while c: yield c c = c.parent result = [element for element in parentgen(c)] result.reverse() return result openList.add(current) while openList: current = sorted(openList, key=lambda inst:inst.H)[0] if current == end: return retracePath(current) openList.remove(current) closedList.add(current) for tile in graph[current]: if tile not in closedList: tile.H = (abs(end.x-tile.x)+abs(end.y-tile.y))*10 openList.add(tile) tile.parent = current return []

He codificado mi primer algoritmo ligeramente complejo, una implementación del algoritmo A Star Pathfinding . Seguí algunos consejos de Python.org sobre la implementación de gráficos para que un diccionario contenga todos los nodos a los que está vinculado cada nodo. Ahora, dado que esto es todo por un juego, cada nodo es realmente solo un mosaico en una grilla de nodos, por lo tanto, cómo estoy resolviendo la heurística y mi referencia ocasional a ellos.

Gracias a timeit, sé que puedo ejecutar esta función con éxito un poco más de cien veces por segundo. Es comprensible que esto me sienta un poco incómodo, sin otros elementos de juego, como los gráficos o el cálculo de la lógica del juego. Así que me encantaría ver si alguno de ustedes puede acelerar mi algoritmo, no estoy completamente familiarizado con Cython o su parentesco, no puedo codificar una línea de C.

Sin más divagaciones, esta es mi función A Star.

def aStar(self, graph, current, end): openList = [] closedList = [] path = [] def retracePath(c): path.insert(0,c) if c.parent == None: return retracePath(c.parent) openList.append(current) while len(openList) is not 0: current = min(openList, key=lambda inst:inst.H) if current == end: return retracePath(current) openList.remove(current) closedList.append(current) for tile in graph[current]: if tile not in closedList: tile.H = (abs(end.x-tile.x)+abs(end.y-tile.y))*10 if tile not in openList: openList.append(tile) tile.parent = current return path


Una optimización fácil es usar conjuntos en lugar de listas para los conjuntos abierto y cerrado.

openSet = set() closedSet = set()

Esto hará que todas las in y not in pruebas O (1) en lugar de O ( n ).


Usaría los juegos como se dijo, pero también usaría un montón para encontrar el elemento mínimo (el que será el siguiente). Esto requeriría mantener tanto un openSet como un openHeap, pero la memoria no debería ser realmente un problema. Además, establece insertar en O (1) y montones en O (log N) para que sean rápidos. El único problema es que el módulo heapq no está hecho para usar claves con él. Personalmente, simplemente lo modificaría para usar las teclas. No debería ser muy difícil. Alternativamente, puede usar tuplas de (mosaico.H, mosaico) en el montón.

Además, seguiría la idea de aaronasterling de usar iteración en lugar de recursión, pero también agregaría elementos al final de la path y la path inversa al final. La razón es que insertar un artículo en el lugar 0 en una lista es muy lento, (O (N) creo), mientras que al agregarlo está O (1) si recuerdo correctamente. El código final para esa parte sería:

def retracePath(c): path = [c] while c.parent is not None: c = c.parent path.append(c) path.reverse() return path

Pongo la ruta de retorno al final porque parece que debería hacerlo desde tu código.

Aquí está el código final que usa conjuntos, montones y lo que no:

import heapq def aStar(graph, current, end): openSet = set() openHeap = [] closedSet = set() def retracePath(c): path = [c] while c.parent is not None: c = c.parent path.append(c) path.reverse() return path openSet.add(current) openHeap.append((0, current)) while openSet: current = heapq.heappop(openHeap)[1] if current == end: return retracePath(current) openSet.remove(current) closedSet.add(current) for tile in graph[current]: if tile not in closedSet: tile.H = (abs(end.x - tile.x)+abs(end.y-tile.y))*10 if tile not in openSet: openSet.add(tile) heapq.heappush(openHeap, (tile.H, tile)) tile.parent = current return []