Przejdź do treści

A* (A-star) — heurystyczny algorytm znajdowania najkrótszej ścieżki

A*: heurystyczny algorytm znajdowania najkrótszej ścieżki — szybkie, efektywne wyszukiwanie tras między punktami z inteligentnym przybliżeniem kosztów.

A* to zestaw kroków (algorytm), które komputery mogą wykorzystać do określenia, jak szybko dostać się gdzieś pomiędzy dwoma miejscami. Jeśli masz listę lokalizacji i wiesz, jak trudno jest dostać się z jednej prosto do drugiej, użycie A* może szybko wskazać najszybszą drogę. Jest to algorytm podobny do algorytmu Dijkstry, ale zgaduje tak, że nie spędza tak dużo czasu próbując powolnych dróg. Jest to dobra seria kroków, jeśli chcesz tylko ścieżkę między dwoma miejscami. Jeśli zamierzasz poprosić o wiele ścieżek z tej samej mapy, to istnieją szybsze sposoby, które znajdują wszystkie odpowiedzi naraz, takie jak algorytm Floyda-Warshalla. A* nie zadziała, jeśli chcesz odwiedzić kilka miejsc podczas jednej podróży (Travelling salesman problem).

Co to jest A* — krótki opis

A* to algorytm wyszukiwania najkrótszej (najtańszej) ścieżki w grafie, który łączy podejście przeszukiwania najlepiej-rosnącego (best-first search) z informacją heurystyczną. Dla każdego węzła oblicza się wartość:

  • g(n) — koszt najtańszej znalezionej dotąd ścieżki od węzła startowego do węzła n,
  • h(n) — heurystyczne oszacowanie kosztu najtańszej ścieżki z węzła n do celu,
  • f(n) = g(n) + h(n) — szacowany całkowity koszt przejścia przez n do celu.

Algorytm wybiera do rozwinięcia węzeł o najmniejszym f(n), co sprawia, że kieruje się jednocześnie znanym kosztem i przewidywanym kosztem do celu.

Własności heurystyki

  • Admissible (dopuszczalna) — heurystyka nie przeszacowuje rzeczywistego kosztu do celu: dla wszystkich n h(n) ≤ rzeczywisty koszt do celu. Gwarantuje to optymalność A* (znajdzie najtańszą ścieżkę).
  • Consistent/Monotoniczna (spójna) — dla każdej krawędzi (n→m) zachodzi h(n) ≤ koszt(n,m) + h(m). Spójność upraszcza implementację (nie trzeba ponownie rozważać węzłów w otwartym zbiorze) i również zapewnia optymalność.

Przykłady heurystyk dla siatek 2D: Manhattan (odległość L1) nadaje się gdy ruch jest tylko w czterech kierunkach, Euclidean (odległość w linii prostej) gdy ruch jest dowolny kierunkowo. Jeżeli ustawimy h(n)=0, A* zachowuje się jak algorytm Dijkstry.

Właściwości algorytmu

  • Kompletność — A* jest kompletny, jeśli graf ma skończoną liczbę węzłów lub heurystyka nie prowadzi do nieskończonego eksplorowania stanów.
  • Optymalność — jeśli heurystyka jest dopuszczalna (i często spójna), A* znajdzie optymalną ścieżkę.
  • Złożoność czasowa i pamięciowa — w najgorszym przypadku (słaba lub zerowa heurystyka) złożoność może rosnąć wykładniczo w rozmiarze przestrzeni stanu. A* zwykle wymaga dużej pamięci, ponieważ przechowuje otwarty i zamknięty zbiór węzłów.

Jak zaimplementować A* — podstawowe kroki

  • Utwórz zbiór otwarty (open set) i dodaj węzeł startowy z g(start)=0 i f=start+h(start).
  • Utwórz zbiór zamknięty (closed set) na węzły już odwiedzone.
  • Póki open set nie jest pusty:
    • Wyjmij węzeł n o najmniejszym f(n).
    • Jeśli n jest celem — zakończ i odtwórz ścieżkę korzystając z wskaźników do rodzica.
    • Dla każdego sąsiada m węzła n policz proponowany koszt g_temp = g(n) + koszt(n,m). Jeśli m nie jest w open lub g_temp < g(m), zaktualizuj g(m), ustaw rodzica m na n i ustaw f(m) = g(m) + h(m). Jeśli m nie jest w open — dodaj go.
    • Przenieś n do closed set.

W praktycznej implementacji open set przechowuje się w kolejce priorytetowej (min-heap) indeksowanej po f(n), a closed set jako hash/zestaw do szybkiego sprawdzania odwiedzin. Przydatne jest też przechowywanie mapy rodziców dla odtwarzania zakończonej ścieżki.

Praktyczne uwagi i optymalizacje

  • Wybór heurystyki — im dokładniejsza, ale dopuszczalna heurystyka, tym mniej węzłów zostanie zbadanych. Zbyt optymistyczne (niska) h zwiększy koszt wyszukiwania; zbyt pesymistyczna (przeszacowana) może utracić optymalność.
  • Tie-breaking — przy równych f można preferować większe g (bliżej startu) lub mniejsze h; wpływa to na kształt ścieżki i szybkość znalezienia rozwiązania.
  • Memory-bounded A* — wersje takie jak IDA* (iterative deepening A*) używają mniej pamięci kosztem dodatkowych przejść, co jest przydatne przy ograniczeniach pamięciowych.
  • Weighted A* — mnożnik przy heurystyce (f = g + w*h, w>1) przyspiesza wyszukiwanie kosztem utraty gwarancji optymalności; stosowane, gdy potrzebne jest szybkie rozwiązanie przy akceptowalnej jakości.
  • Bidirectional A* — jednoczesne przeszukiwanie od startu i od celu może znacząco skrócić przestrzeń przeszukiwania, ale wymaga odpowiedniego dopasowania heurystyk.

Zastosowania

  • Planowanie ścieżek w grach komputerowych i symulacjach (ruch jednostek po siatce).
  • Nawigacja robotów i pojazdów autonomicznych (planowanie trasy z uwzględnieniem przeszkód i kosztów).
  • Rozwiązywanie problemów kombinatorycznych modelowanych jako grafy (np. puzzle przesuwne), o ile cel jest pojedynczy.
  • Systemy trasowe i logistyka, kiedy poszukujemy pojedynczej optymalnej trasy między dwoma punktami.

Ograniczenia

  • A* nie jest efektywny, gdy trzeba równocześnie znaleźć optymalne trasy dla wielu par punktów — wtedy lepsze mogą być algorytmy wielopunktowe jak Floyd-Warshall lub precomputing struktur (np. contraction hierarchies dla map drogowych).
  • Przy problemach typu Travelling Salesman Problem (wielu celów wymagających odwiedzin) A* w prostej postaci nie jest odpowiedni — wymagane są modyfikacje lub inne algorytmy heurystyczne/metryczne.
  • Złożoność pamięciowa może być krytyczna — A* przechowuje dużą część grafu w pamięci, co dla wielkich przestrzeni stanów bywa niepraktyczne.

Podsumowując, A* to uniwersalny i mocny algorytm do znajdowania najkrótszych ścieżek pomiędzy dwoma punktami, o ile dobierzemy odpowiednią heurystykę i uwzględnimy ograniczenia pamięciowe. W praktyce jest to jedna z najczęściej stosowanych metod w grach, robotyce i systemach nawigacyjnych.

Kroki

A* najpierw potrzebuje listy wszystkich miejsc, do których można się udać, a następnie listy odległości między nimi. Następnie wskaże Ci najszybszy sposób dotarcia z miejsca A do miejsca Z.

Dla przykładu, powiemy, że A jest połączone z miejscami B i C, a B i C są połączone z D i E. D i E są połączone z Z. Istnieją 4 możliwe sposoby przejścia z A do Z. Można przejść A-B-D-Z, A-C-D-Z, A-B-E-Z lub A-C-E-Z. Komputer używający A* najpierw sprawdza, jak trudno jest dostać się z A do B i z A do C. Jest to "koszt" tych miejsc. Koszt danego miejsca oznacza, jak trudno jest dostać się z punktu A do tego miejsca. Po zapisaniu obu kosztów komputer sprawdza, jak trudno jest dostać się z B do D, i dodaje to do kosztu B. Zapisuje to jako koszt D. Zapisuje to jako koszt D. Następnie komputer sprawdza, jak trudno jest dostać się z C do D, i dodaje to do kosztu C. Jest to inny koszt dla D. Jest to inny koszt dla D i jeśli jest on niższy niż ten, który już ma, to zastąpi go starym. Komputer chce znać tylko najlepszą ścieżkę, więc ignoruje ścieżkę o wyższym koszcie. Zapamiętuje tylko jedną z A-B-D i A-C-D, w zależności od tego, która jest szybsza.

Komputer idzie dalej i znajduje najszybszy sposób dotarcia do E. W końcu przechodzi z D do Z i znajduje koszt, oraz z E do Z i znajduje koszt. Dostaje ostateczny koszt dla Z, i to jest najmniejszy koszt, jaki może uzyskać. Teraz komputer wie, która droga jest najszybsza, i ma odpowiedź. Komputer może wykonać podobną serię kroków, ale z o wiele większą liczbą miejsc. Za każdym razem będzie patrzył na miejsce, które jest najbliżej A, i będzie sumował koszty dla sąsiadów tego miejsca.

Ludzie nazywają powyższą serię kroków algorytmem Dijkstry. Algorytm Dijkstry może być powolny, ponieważ będzie sprawdzał wiele miejsc, które mogą być w złym kierunku od Z. Jeśli zapytasz komputer, jak dostać się z jednego miasta do innego, algorytm Dijkstry może skończyć się szukaniem w innym stanie.

A* rozwiązuje ten problem. A* pozwala podać komputerowi przypuszczenie, jak daleko będzie z każdego miejsca do końca. Komputer może użyć tego przypuszczenia, aby określić w przybliżeniu, jak daleko trzeba będzie dojść z danego miejsca do Z. Zamiast wybierać miejsce najbliższe A, aby je sprawdzić, komputer sprawdzi to, które prawdopodobnie będzie miało najniższą sumę. Znajduje tę sumę przez dodanie kosztu do oczekiwanej odległości w lewo. W ten sposób można patrzeć tylko w kierunku, w którym prawdopodobnie będzie lepiej. Nie ma problemu, jeśli zgadywanie nie jest idealne, ale nawet proste złe zgadywanie może sprawić, że program będzie działał o wiele szybciej. Jeśli próbujesz znaleźć ścieżkę między dwoma miejscami w prawdziwym świecie, dobrym przypuszczeniem jest po prostu odległość między nimi w linii prostej. Prawdziwa ścieżka po drogach będzie dłuższa, ale dzięki temu program może ją odgadnąć i nie pójdzie w złym kierunku.

W literaturze matematycznej lub informatycznej, to przypuszczenie jest często funkcją miejsca i jest nazywane heurystyką. Każde miejsce jest wierzchołkiem, a każda ścieżka między dwoma miejscami jest krawędzią. Są to słowa z teorii grafów.

Autor

AlegsaOnline.com A* (A-star) — heurystyczny algorytm znajdowania najkrótszej ścieżki

URL: https://pl.alegsaonline.com/art/2

Udostępnij