Алгоритм A(произносится как «A-star») — широко используемый алгоритм поиска в информатике и искусственном интеллекте. Это алгоритм информированного поиска, который эффективно находит кратчайший путь между двумя узлами графа. Алгоритм Aсочетает в себе элементы алгоритма Дейкстры и жадного поиска по принципу «наилучшее качество».
Вот шаги алгоритма A*:
- Инициализируйте два набора: открытый и закрытый. Открытый набор содержит узлы, подлежащие оценке, а закрытый набор содержит узлы, которые уже были оценены.
- Назначьте ориентировочную стоимость каждому узлу. Стоимость представляет собой сумму двух частей: стоимость достижения текущего узла из начального узла (известная как g(n)) и расчетная стоимость достижения целевого узла из текущего узла (известная как h(n)). Ориентировочная стоимость обычно рассчитывается с помощью эвристической функции.
- Добавьте начальный узел в открытый набор.
- Продолжайте цикл, пока открытое множество не станет пустым:
- Выбрать узел с наименьшей стоимостью (f(n) = g(n) + h(n)) из открытого множества. Этот узел является текущим.
- Переместить текущий узел из открытого набора в закрытый набор.
- Сгенерировать соседние узлы текущего узла.
- Для каждого соседнего узла:
- Если он уже есть в закрытом наборе, пропустите его.
- Если его нет в открытом наборе, добавьте его в открытый набор и рассчитайте его стоимость.
- Если он уже есть в открытом наборе, сравните новую стоимость с ранее назначенной стоимостью. Если новая стоимость ниже, обновите стоимость и обновите родительский узел.
- Остановить цикл, если целевой узел добавлен в закрытый набор.
Условия оптимальности.
Алгоритм A* является одновременно полным и оптимальным при определенных условиях:
- Эвристическая функция (h(n)) никогда не должна переоценивать стоимость достижения целевого узла из текущего узла. Если h(n) допустимо, то есть никогда не завышает фактическую стоимость, то A* гарантированно найдет кратчайший путь.
- Искомый граф должен быть конечным и иметь неотрицательные веса ребер.
- Aдолжен исследовать узлы в определенном порядке. Если эвристическая функция непротиворечива (или удовлетворяет неравенству треугольника), Aтакже гарантированно будет оптимальным.
Вот пример реализации алгоритма A* в Python:
from queue import PriorityQueue
def astar(graph, start, goal, heuristic):
open_set = PriorityQueue()
open_set.put((0, start))
came_from = {}
g_score = {start: 0}
f_score = {start: heuristic(start, goal)}
while not open_set.empty():
_, current = open_set.get()
if current == goal:
return reconstruct_path(came_from, current)
for neighbor in graph[current]:
tentative_g_score = g_score[current] + graph[current][neighbor]
if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score[neighbor] = g_score[neighbor] + heuristic(neighbor, goal)
open_set.put((f_score[neighbor], neighbor))
return None
def reconstruct_path(came_from, current):
path = [current]
while current in came_from:
current = came_from[current]
path.append(current)
path.reverse()
return path
# Example usage
graph = {
'A': {'B': 5, 'C': 3},
'B': {'D': 2},
'C': {'D': 4, 'E': 6},
'D': {'E': 1},
'E': {}
}
heuristic = {
'A': 10,
'B': 6,
'C': 8,
'D': 4,
'E': 0
}
start = 'A'
goal = 'E'
path = astar(graph, start, goal, heuristic)
print(path) # Output: ['A', 'C', 'D', 'E']
В этом примере демонстрируется алгоритм A*, находящий кратчайший путь от узла «A» к узлу «E» в графе. Эвристическая функция предоставляется отдельно и оценивает стоимость от каждого узла до целевого узла.