A* (A-tähti)-hakualgoritmi: nopea reitinetsintä ja polunhaku

A*-hakualgoritmi: nopea ja tehokas reitinetsintä kartoilla — heuristiikka yhdistää tarkkuuden ja nopeuden, ideaalinen polunhakuun, peleihin ja robotiikan reitinsuunnitteluun.

Tekijä: Leandro Alegsa

A* on joukko vaiheita (algoritmi), joiden avulla tietokoneet voivat selvittää, miten päästä nopeasti jonnekin kahden paikan välillä. Jos sinulla on luettelo paikoista ja tiedot siitä, kuinka vaikeaa tai kallista on liikkua suoraan yhdestä paikasta toiseen, A*:n avulla voit tehokkaasti löytää lyhyimmän tai edullisimman reitin. Se on läheistä sukua Dijkstran algoritmille, mutta A* käyttää arvioita (heuristiikkaa) ohjatakseen hakua kohti maalia, joten se tekee vähemmän turhia tarkistuksia kuin pelkkä Dijkstra. A* on hyvä valinta, kun haluat etsiä reitin yhdestä pisteestä toiseen. Jos sen sijaan haluat löytää kaikkien parien pisimmät tai lyhimmät reitit samasta kartasta kerralla, kannattaa harkita esimerkiksi Floyd–Warshallin algoritmia. A* ei myöskään sovellu ratkaisemaan ongelmia, joissa pitää käydä useassa paikassa yhdessä matkassa (travelling salesman -ongelma).

Miten A* toimii

A* pitää yllä kahta joukkoa: open-joukkoa (solmut, joita aiotaan vielä tutkia) ja closed-joukkoa (solmut, jotka on jo tutkittu). Jokaiselle solmulle n algoritmi laskee arvion kustannuksesta päästä lähtökohdasta kyseiseen solmuun (g(n)) ja arvio kustannuksesta solmusta maaliin (h(n), heuristiikka). Solmun kokonaisarvio on f(n) = g(n) + h(n). A* valitsee aina sen open-joukon solmun, jolla on pienin f-arvo, laajentaa sitä ja päivittää naapureita.

Keskeiset käsitteet

  • g(n) = todellinen kustannus lähtöpisteestä solmuun n.
  • h(n) = heuristiikka: arvio jäljellä olevasta kustannuksesta solmusta n maaliin.
  • f(n) = g(n) + h(n) = arvioitu kokonaiskustannus reitistä lähtöpisteestä maaliin, joka kulkee solmun n kautta.
  • Admissible (hyväksyttävä) heuristiikka = heuristiikka, joka ei yliarvioi todellista jäljellä olevaa kustannusta. Jos h(n) ei koskaan yliarvioi, A* on optimaalinen (löytää lyhimmän reitin).
  • Consistent / monotone heuristiikka = heuristiikka, jonka täytyy täyttää h(n) ≤ cost(n, m) + h(m) kaikille kaarille n→m. Konsistentti heuristiikka takaa, että f-arvot eivät pienene polkua pitkin, mikä yksinkertaistaa toteutusta.

Pseudokoodi (lyhyt kuvaus)

Yksinkertaistettuna A* toimii näin:

  • Aseta lähtösolmu open-joukkoon, g(alku)=0, f(alku)=h(alku).
  • Kun open ei ole tyhjä: valitse openista solmu n, jolla on pienin f(n).
  • Jos n on maali → rakenna polku takaisin lähtöön ja palauta se.
  • Siirrä n closed-joukkoon ja käsittele kaikki naapurit m:
  • - laske mahdollinen uusi g-arvo: g_new = g(n) + cost(n,m).
  • - jos m on closed ja g_new ≥ g(m) → ohita; muuten päivitä g(m), f(m) ja edeltäjä ja lisää m openiin.
  • - jos m ei ole openissa → lisää se openiin.

Heuristiikoita (esimerkkejä)

  • Manhattan-etäisyys (ruudukko, liikkuminen neljään suuntaan): |dx| + |dy|.
  • Euclidean-etäisyys (vapaa taso): suora-etäisyys pisteiden välillä.
  • Chebyshev-etäisyys (ruudukossa, jossa sallitaan diagonaaliliikkuminen kustannuksella 1): max(|dx|, |dy|).

Valitse heuristiikka, joka on realistinen ja mieluiten admissible tai konsistentti, jotta saat optimaalisuuden ja tehokkuuden.

Suorituskyky ja rajoitukset

  • Optimaalisuus: Jos heuristiikka on admissible, A* löytää lyhyimmän reitin.
  • Täydellisyys: A* on yleensä täydellinen (löytää ratkaisun jos sellainen on olemassa), kun heuristiikka on järkevä ja hakutila on äärellinen.
  • Aikavaativuus: Pahimmassa tapauksessa A* voi vaatia eksponentiaalisesti aikaa (riippuu heuristiikan laadusta). Hyvä heuristiikka pienentää tutkittavien solmujen määrää merkittävästi.
  • Tila: A* pitää usein suurta open-joukkoa muistissa, joten muistinkulutus voi rajoittaa käytännön sovelluksia suurissa kartoissa.

Käytännön vinkkejä

  • Käytä mahdollisimman informatiivista, mutta admissible-heuristiikkaa. Mitä lähempänä todellista jäljellä olevaa kustannusta h(n) on, sitä tehokkaampi haku on.
  • Jos muisti on ongelma, harkitse IDA*-tyyppisiä iteratiivisia menetelmiä tai muistikompromisseja (esim. weighted A* tai muistirajoitteiset variantit).
  • Pelien reitinhakuissa usein käytetään yksinkertaisia heuristiikkoja (Manhattan / Euclidean) sekä hakun rajaamista (timeout, maksimi solmujen määrä) käytännön suorituskyvyn takia.
  • Jos teet monta hakua samasta verkosta, ennakkolaskenta (esim. etäisyyden tallentaminen tai reititystaulut) voi olla tehokkaampaa kuin toistuva A*.

Sovelluksia

A* on laajasti käytössä: pelikehityksessä hahmojen reitinhakua varten, robotiikassa polun suunnittelussa, karttapalveluissa ja erilaisissa optimointiongelmissa, joissa etsitään lyhintä reittiä kahden pisteen välillä. Kun tarvitset kaikki parien etäisyydet tai erityisiä käyntirajoitteita (esim. travelling salesman -tyyppiset ongelmat), on syytä valita muita menetelmiä tai laajennuksia.

Yhteenvetona: A* on tehokas ja joustava algoritmi yksittäisten reitinetsintätehtävien ratkaisuun, kun valitset sopivan heuristiikan ja pidät mielessä muisti- ja suorituskykyrajoitukset.

Vaiheet

A* tarvitsee ensin luettelon kaikista paikoista, joihin voit mennä, ja sitten luettelon siitä, kuinka pitkä matka kunkin paikan välillä on. Sen jälkeen se kertoo, mikä on nopein tapa päästä paikasta A paikkaan Z.

Esimerkkinä sanotaan, että A on yhdistetty paikkoihin B ja C, ja B ja C ovat molemmat yhdistettyinä paikkoihin D ja E. D ja E ovat molemmat yhdistettyinä paikkoihin Z. A:sta Z:hen voi mennä neljällä eri tavalla: A-B-D-Z, A-C-D-Z, A-B-E-Z tai A-C-E-Z. Tietokone, joka käyttää A*:ta, tarkastelee ensin, kuinka vaikeaa on päästä A:sta B:hen ja A:sta C:hen. Tämä on näiden paikkojen "kustannus". Paikan kustannukset tarkoittavat sitä, kuinka vaikeaa on päästä paikasta A kyseiseen paikkaan. Kun tietokone on kirjannut ylös molemmat kustannukset, se tarkastelee, kuinka vaikeaa on päästä B:stä D:hen, ja lisää tämän B:n kustannuksiin. Se kirjoittaa tämän ylös D:n kustannuksiksi. Sitten tietokone tarkastelee, kuinka vaikeaa on päästä C:stä D:hen, ja lisää tämän C:n kustannuksiin. Tämä on eri kustannus D:lle, ja jos se on pienempi kuin jo olemassa oleva kustannus, se korvaa vanhan. Tietokone haluaa tietää vain parhaan reitin, joten se ei ota huomioon reittiä, jonka kustannukset ovat korkeammat. Se muistaa vain jommankumman vaihtoehdoista A-B-D ja A-C-D, sen mukaan, kumpi on nopeampi.

Tietokone jatkaa matkaa ja etsii nopeimman tavan päästä kohteeseen E. Lopuksi se menee D:stä Z:hen ja löytää kustannukset, ja E:stä Z:hen ja löytää kustannukset. Se saa lopullisen kustannuksen Z:lle, ja tämä on pienin mahdollinen kustannus. Nyt tietokone tietää, mikä tie on nopein, ja sillä on vastaus. Tietokone voi tehdä samanlaisen sarjan vaiheita, mutta paljon, paljon useammassa paikassa. Joka kerta se tarkastelee paikkaa, joka on lähimpänä A:ta, ja laskee yhteen kyseisen paikan naapurien kustannukset.

Edellä mainittua vaihesarjaa kutsutaan Dijkstran algoritmiksi. Dijkstran algoritmi voi olla hidas, koska se tarkastelee monia paikkoja, jotka saattavat kulkea väärään suuntaan kohteesta Z. Jos kysyisit tietokoneelta, miten päästä yhdestä kaupungista läheiseen kaupunkiin, Dijkstran algoritmi saattaisi päätyä etsimään toiseen osavaltioon.

A* korjaa tämän ongelman. A*:n avulla voit kertoa tietokoneelle arvion siitä, kuinka pitkä matka on kustakin paikasta loppuun. Tietokone voi käyttää arvausta kertoakseen, kuinka pitkä matka tietystä paikasta on suunnilleen matkaan Z. Sen sijaan, että se valitsisi vain A:ta lähimmän paikan, se tarkastelee sitä, jonka kokonaismatka on todennäköisesti pienin. Se löytää tämän kokonaismäärän lisäämällä kustannukset jäljellä olevaan odotettuun etäisyyteen. Näin se voi katsoa vain suuntaan, jossa asiat todennäköisesti paranevat. Ei haittaa, jos arvaus ei ole täydellinen, mutta yksinkertainenkin huono arvaus voi saada ohjelman etenemään paljon nopeammin. Jos yrität löytää reitin kahden paikan välillä reaalimaailmassa, hyvä arvaus on vain niiden välinen etäisyys suorassa linjassa. Todellinen polku teiden yli on pidempi, mutta näin ohjelma voi arvata sen, eikä se mene väärään suuntaan.

Matematiikan tai tietojenkäsittelytieteen kirjallisuudessa tämä arvaus on usein paikan funktio, ja sitä kutsutaan heuristiikaksi. Kukin paikka on piste, ja jokainen kahden paikan välinen polku on reuna. Nämä ovat sanoja graafiteoriasta.



Etsiä
AlegsaOnline.com - 2020 / 2025 - License CC3