[Unidad] Algoritmo de búsqueda de caminos: amplitud primero, Dijkstra, heurístico, una estrella

Lo siguiente es una comprensión y un resumen simple que obtuve al leer este enlace (la escritura es realmente buena y el autor también proporciona algunas operaciones visuales para facilitar la comprensión de las similitudes y diferencias de varios algoritmos, lo cual es muy recomendable). Si hay desviaciones o errores, corríjame en el área de comentarios.


 

1.Búsqueda de amplitud primero (algoritmo de amplitud primero)

a. Expanda hacia afuera sin restricciones, recorra y guarde los nodos de origen de todos los nodos y guárdelos en el diccionario came_from:

frontier = Queue()
frontier.put(start )
came_from = dict() # path A->B is stored as came_from[B] == A
came_from[start] = None

while not frontier.empty():
   current = frontier.get()
   for next in graph.neighbors(current):
      if next not in came_from:
         frontier.put(next)
         came_from[next] = current

b. Comenzando desde el punto objetivo, busque el punto inicial en la dirección inversa en came_from. Si no se encuentra el punto inicial, el bucle se repite hasta encontrar el punto inicial. Luego, el punto objetivo se agrega a la ruta de búsqueda de ruta. y el camino se invierte:

current = goal
path = []

while current != start:
   path.append(current)
   current = came_from[current]

path.append(start) # optional
path.reverse() # optional

Optimizar. Agregue una condición de juicio al buscar came_from en el a. anterior. Si se encuentra el nodo de destino, salte del bucle:

frontier = Queue()
frontier.put(start )
came_from = dict()
came_from[start] = None

while not frontier.empty():
   current = frontier.get()
   if current == goal:
      break           
   for next in graph.neighbors(current):
      if next not in came_from:
         frontier.put(next)
         came_from[next] = current

2.Algoritmo de Dijkstra ( algoritmo de Dijkstra )

En algunos casos, el consumo (tiempo, física, etc.) de cada paso es diferente, por lo que es necesario agregar un nuevo parámetro cost_so_far para registrar el costo total consumido desde la posición inicial hasta la posición actual. Por lo tanto, al agregar el nodo came_from, primero considere comparar el costo, encuentre el nodo con el menor consumo y agréguelo a came_from.

frontier = PriorityQueue() #Queue(队列)->PriorityQueue(优先队列)
frontier.put(start, 0)
came_from = dict()
cost_so_far = dict()
came_from[start] = None
cost_so_far[start] = 0

while not frontier.empty():
   current = frontier.get()

   if current == goal:
      break
   
   for next in graph.neighbors(current):
      new_cost = cost_so_far[current] + graph.cost(current, next)
      if next not in cost_so_far or new_cost < cost_so_far[next]:
         cost_so_far[next] = new_cost
         priority = new_cost
         frontier.put(next, priority)
         came_from[next] = current

Nota: PriorityQueue debe devolver primero el valor más pequeño de la cola (si es un valor numérico en Python, se organizará de mayor a menor de forma predeterminada y es necesario personalizar otros tipos).

Dado que el coste mínimo no es necesariamente el camino más corto, se utiliza la siguiente búsqueda heurística.

3.Búsqueda heurística (búsqueda heurística)

En la mayoría de los casos, no necesitamos buscar una ruta en ninguna dirección, solo necesitamos buscar una ruta en la dirección del punto objetivo. Por lo tanto, en Greedy Best First Search, no consideramos el costo como una cola prioritaria, sino que siempre agregamos la distancia entre el siguiente nodo y el punto final a la cola, luego encontramos la distancia más corta, sacamos este nodo y luego comenzamos desde este nodo para encontrar el siguiente nodo A, haciendo un bucle hasta encontrar el final.

frontier = PriorityQueue()
frontier.put(start, 0)
came_from = dict()
came_from[start] = None

while not frontier.empty():
   current = frontier.get()

   if current == goal:
      break
   
   for next in graph.neighbors(current):
      if next not in came_from:
         priority = heuristic(goal, next)
         frontier.put(next, priority)
         came_from[next] = current

Ventajas: Si el terreno es sencillo, la búsqueda de caminos será rápida. 

Desventajas: Si el terreno es complejo, como se muestra en la figura...

El algoritmo fue directamente al punto objetivo, pero descubrió que el camino estaba bloqueado, luego buscó hacia atrás y dio un gran giro, como resultado, el camino encontrado no era el más corto. 

Solución: algoritmo de estrella A.

4.El algoritmo A* (algoritmo en estrella)

El algoritmo de Dijkstra puede encontrar el camino más corto, pero es una pérdida de tiempo; Greedy Best First Search es relativamente rápido, pero no puede encontrar el camino más corto.

El algoritmo A-star no solo utiliza el algoritmo de Dijkstra para obtener el consumo de distancia real desde el punto de partida hasta la posición actual, sino que también utiliza la distancia estimada desde la distancia actual hasta el punto final como juicio y suma el valor obtenido sumando los dos resultados a la cola de prioridad y obtiene El valor más pequeño es el siguiente punto objetivo en movimiento.

frontier = PriorityQueue()
frontier.put(start, 0)
came_from = dict()
cost_so_far = dict()
came_from[start] = None
cost_so_far[start] = 0

while not frontier.empty():
   current = frontier.get()

   if current == goal:
      break
   
   for next in graph.neighbors(current):
      new_cost = cost_so_far[current] + graph.cost(current, next)
      if next not in cost_so_far or new_cost < cost_so_far[next]:
         cost_so_far[next] = new_cost
         priority = new_cost + heuristic(goal, next)
         frontier.put(next, priority)
         came_from[next] = current

como escoger

1. Si tu juego requiere una búsqueda de ruta exhaustiva, dale prioridad al uso de Breadth First Search o el algoritmo de Dijkstra. Si su costo en cada paso es el mismo, use Breadth First Search; de lo contrario, elija el algoritmo de Dijkstra.

2. Si solo necesita encontrar la ruta desde el punto de partida hasta el punto de destino, utilice primero el algoritmo de estrella A.

Ejemplos de la implementación del algoritmo anterior en Python, C++ y C#


Esta es una demostración implementada por mí mismo, usando Unity + C #, el efecto es el siguiente:

Enlaces de recursos

Supongo que te gusta

Origin blog.csdn.net/qq302756113/article/details/124858376
Recomendado
Clasificación