Optimaalisen polun haku graafista A* -algoritmilla

Samankaltaiset tiedostot
Algoritmit 1. Luento 9 Ti Timo Männikkö

A ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä.

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Algoritmit 1. Luento 8 Ke Timo Männikkö

PARITUS KAKSIJAKOISESSA

Ohjelmoinnin perusteet Y Python

10. Painotetut graafit

Ohjelmoinnin perusteet Y Python

5. Rajoitelaskenta (Constraint Satisfaction)

A TIETORAKENTEET JA ALGORITMIT

Ohjelmoinnin perusteet Y Python

Algoritmit 1. Luento 14 Ke Timo Männikkö

Ohjelmoinnin perusteet Y Python

Graafit ja verkot. Joukko solmuja ja joukko järjestämättömiä solmupareja. eli haaroja. Joukko solmuja ja joukko järjestettyjä solmupareja eli kaaria

T : Max-flow / min-cut -ongelmat

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssien laaja oppimäärä

A TIETORAKENTEET JA ALGORITMIT

A TIETORAKENTEET JA ALGORITMIT

AJAX-konsepti AJAX. Asynkronisuus. Nykyisten web-ohjelmien ongelmia. Asynchronous JavaScript And XML

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Ohjelmoinnin peruskurssien laaja oppimäärä

6.4. Järjestyssuhteet

T Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 7 (opetusmoniste, kappaleet )

Kognitiivinen mallintaminen 1

13 Lyhimmät painotetut polut

Ohjelmoinnin perusteet Y Python

Luento 3: Tietorakenteiden esittäminen

Luku 7. Verkkoalgoritmit. 7.1 Määritelmiä

58131 Tietorakenteet (kevät 2009) Harjoitus 11, ratkaisuja (Topi Musto)

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

.. X JOHDATUS TEKOÄLYYN TEEMU ROOS

Sokkelon sisältö säilötään linkitetyille listalle ja tekstitiedostoon. Työ tehdään itsenäisesti yhden hengen ryhmissä. Ideoita voi vaihtaa koodia ei.

TIE Tietorakenteet ja algoritmit 261

Johdatus graafiteoriaan

Ohjelmoinnin perusteet Y Python

Määrittelydokumentti

Tämän lisäksi listataan ranskalaisin viivoin järjestelmän tarjoama toiminnallisuus:

Se mistä tilasta aloitetaan, merkitään tyhjästä tulevalla nuolella. Yllä olevassa esimerkissä aloitustila on A.

Ohjelmoinnin perusteet Y Python

1.1 Pino (stack) Koodiluonnos. Graafinen esitys ...

10. Painotetut graafit

2. Seuraavassa kuvassa on verkon solmujen topologinen järjestys: x t v q z u s y w r. Kuva 1: Tehtävän 2 solmut järjestettynä topologisesti.

Ohjelmoinnin perusteet Y Python

4 Heuristinen haku. Eero Hyvönen Helsingin yliopisto

Algoritmit 1. Luento 1 Ti Timo Männikkö

Ohjelmoinnin perusteet Y Python

Tietorakenteet ja algoritmit

58131 Tietorakenteet ja algoritmit (kevät 2014) Uusinta- ja erilliskoe, , vastauksia

Ohjelmoinnin perusteet Y Python

JOHDATUS TEKOÄLYYN TEEMU ROOS

Esimerkkejä polynomisista ja ei-polynomisista ongelmista

Ohjelmoinnin perusteet Y Python

1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

Ohjelmoinnin peruskurssi Y1

TIETORAKENTEET JA ALGORITMIT

Hintatiedotus ja tietojen välitys. Loppuraportti

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Lyhin kahden solmun välinen polku

Kysymyksiä koko kurssista?

Ohjelmoinnin perusteet Y Python

15. Ohjelmoinnin tekniikkaa 15.1

Ohjelmoinnin perusteet Y Python

Projektityö: Mobiiliajopäiväkirja. Mikko Suomalainen

Tietotekniikan valintakoe

15. Ohjelmoinnin tekniikkaa 15.1

Ohjelmoinnin perusteet Y Python

JOHDATUS TEKOÄLYYN TEEMU ROOS

Hakemistojen sisällöt säilötään linkitetyille listalle.

HTML5 video, audio, canvas. Mirja Jaakkola

TIE = JOTU. VH5 - MagicDraw

Hohde Consulting 2004

Department of Mathematics, Hypermedia Laboratory Tampere University of Technology. Roolit Verkostoissa: HITS. Idea.

Ryhmäläisten nimet:

Joonas Haapala Ohjaaja: DI Heikki Puustinen Valvoja: Prof. Kai Virtanen

Algoritmit 1. Luento 12 Ti Timo Männikkö

811312A Tietorakenteet ja algoritmit V Verkkojen algoritmeja Osa 2 : Kruskalin ja Dijkstran algoritmit

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Eloisuusanalyysi. TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 16. marraskuuta 2009 TIETOTEKNIIKAN LAITOS. Eloisuusanalyysi.

Ohjelmoinnin jatkokurssi, kurssikoe

Kognitiivinen mallintaminen I

TKT20001 Tietorakenteet ja algoritmit Erilliskoe , malliratkaisut (Jyrki Kivinen)

Apuja ohjelmointiin» Yleisiä virheitä

Algoritmit 1. Luento 10 Ke Timo Männikkö

Ohjelmointikielet ja -paradigmat 5op. Markus Norrena

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin perusteet Y Python

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

VAATIMUSMÄÄRITTELY. PROJEKTITYÖ Tik Wclique

Ohjelmoinnin perusteet Y Python

Luku 8. Aluekyselyt. 8.1 Summataulukko

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

JOHDATUS TEKOÄLYYN TEEMU ROOS

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

(p j b (i, j) + p i b (j, i)) (p j b (i, j) + p i (1 b (i, j)) p i. tähän. Palaamme sanakirjaongelmaan vielä tasoitetun analyysin yhteydessä.

Harjoitustyö: virtuaalikone

Transkriptio:

Miika Nurminen Optimaalisen polun haku graafista A* -algoritmilla TIE340 (Tekoäly) -kurssin harjoitustyöraportti 3.3.2003 Jyväskylän yliopisto Tietotekniikan laitos

Tietoja raportista Tekijä: Miika Nurminen (minurmin@cc.jyu.fi) Työn nimi: Optimaalisen polun haku graafista A* -algoritmilla Title in English: Searching optimal path in graph using A* -algorithm Työ: TIE340 (Tekoäly) -kurssin harjoitustyöraportti. Sivumäärä: 13 Tiivistelmä: Raportissa kuvataan A*-algoritmiin perustuvaa ratkaisua optimaalisen polun löytämiseen suunnatussa ja kaarilta painotetussa graafissa. Lisäksi kuvataan Python-kielellä toteutettua graafista sovellusta, jota käytetään algoritmin toiminnan seuraamiseen ja verkkomallin määrittelyyn. Sovellus on saatavilla tekijän kotisivujen alta: <URL: http://users.jyu.fi/~minurmin/opiskelu/ai/> A*-algoritmi, GXL, heuristinen haku, Python, tekoäly, verk- Avainsanat: koteoria. Keywords: A*-algorithm, Artificial intelligence, graph theory, GXL, heuristic search, Python. I

Sisältö 1 Tehtävän kuvaus 1 2 Ratkaisumenetelmä 2 3 PathFinder-sovellus 3 3.1 Järjestelmän rakenne ja rajapinnat............... 3 3.2 Käyttöliittymä ja olemassaolevan koodin käyttö....... 4 Lähteet 6 Liitteet 7 A Hakuesimerkki 7 B A*-toteutuksen ohjelmalistaus 8 C GXL-esimerkki 10 II

1 Tehtävän kuvaus Lyhimmän polun hakeminen graafista on merkittävä ongelma monilla tekoälyn sovellusalueilla. Ongelmaan on olemassa tarkkoja ratkaisuja, mutta suurilla graafeilla tarkan ratkaisun laskeminen voi olla hidasta. Esimerkiksi Floydin algoritmin kompleksisuus on O(n 3 ). Harjoitustyön tarkoituksena on lyhimmän polun hakeminen suunnatussa ja kaarilta painotetussa graafissa kahden annetun solmun väliltä. Lisäksi oletetaan, että jokaisesta solmusta tiedetään sijainti, jonka perusteella lasketaan kaarille painot. Solmujen sijaintia käytetään myös heuristisen kustannusfunktion laskemiseen. Tehtävän havainnollistamiseksi varsinaisen ratkaisualgoritmin lisäksi toteutettiin yksinkertainen sovellus, jolla käyttäjä voi luoda tai muuttaa verkon rakennetta graafisesti ja seurata polun hakemisen etenemistä. Lisäksi pyrittiin huomioimaan liitännät muihin graafeja käsitteleviin sovelluksiin. Algoritmia testattiin Jyväskylän keskustan katuja likimääräisesti mallintavalla suppeahkolla graafilla, jossa solmut vastaavat tienristeyksiä ja kaaret katuja. Yksisuuntaiset kadut otetaan huomioon kaarien suuntauksella ja solmujen suhteelliset paikat vastaavat sijaintia kartalla. Solmut on esitetty kaksiulotteisessa euklidisessa avaruudessa, mutta algoritmi on sovellettavissa myös yleisempään tilanteeseen. 1

2 Ratkaisumenetelmä Lyhimmän polun laskemiseen käytetään heuristista hakua A*-algoritmilla. Paikkainformaation ansiosta haku on selvästi tarkkaa ratkaisua nopeampi ja voidaan osoittaa, että A*-algoritmi saavuttaa tarkkojen algoritmien tapaan parhaan hakutuloksen. [2, 3] Heuristiikkana käytettiin solmujen paikoista laskettua euklidista etäisyyttä käsiteltävästä solmusta loppusolmuun. Toteutuksessa käytetty algoritmi on seuraava (ks. liite B): 1. Alustus 2. Iterointi 1 Määrittele alku- ja loppusolmut (startnode), (endnode) sekä listat open ja closed. 2 Aseta alkusolmun kuljetuksi matkaksi (minbegincost) 0. 3 Lisää open-listaan alkusolmu. 1 Jos open-lista on tyhjä, mene pääkohtaan 3. 2 Poimi open-listan ensimmäinen alkio arvioitavaksi. 3 Lisää alkio closed-listaan hakustrategian mukaiselle paikalle. 4 Jos alkio on loppusolmu, mene pääkohtaan 3. 5 Tutkitaan alkion naapurisolmut. Jos jokin naapurisolmu on jo open tai closed-listassa ja niiden kuljettu matka on suurempi kuin tämänhetkinen, korjaa open ja closed -listojen solmujen kuljetut matkat rekursiivisesti. 6 Aseta lopuille alkioille kuljettu matka ja lisää ne open-listaan hakustrategian mukaiselle paikalle. 7 Palaa kohtaan 1. 3. Optimaalisen polun palautus 1 Alusta lista optimaalisista poluista ja valitse loppusolmu. 2 Lisää valittu solmu listan alkuun. 3 Jos valittu solmu on alkusolmu, lopeta ja palauta lista. 4 Käy läpi solmut, joista on kaari valittuun solmuun. 5 Valitse uudeksi solmu, jonka kuljettu matka on pienin. Jos solmua ei ole, lopeta ja palauta tyhjä lista. 6 Palaa kohtaan 2. 2

3 PathFinder-sovellus Sovelluksen toteutuskieleksi valittiin Python 2.2. Syinä tähän ovat Pythonin käyttöjärjestelmäriippumattomuus, oliopohjaisuus ja tehokkaat listojen ja assosiaatiotaulujen käsittelytoiminnot [4]. Sovelluksen tavoitteeksi asetettiin yleiskäyttöisyys, laajennettavuus ja mahdollisuus toimia muiden graafiohjelmien kanssa. Tavoitteet huomioitiin järjestelmän rakenteessa (verkkomallin esitys ja käyttöliittymä on erotettu toisistaan) sekä tallennusformaatin (GXL) ja käyttöliittymäkirjaston (wxpython) valinnoissa. Toteutuksessa keskityttiin lähinnä A*-algoritmin toteutukseen ja graafien esittämiseen. Käyttöliittymä tehtiin wxpython-käyttöliittymäkirjaston mukana tulleen pysketch-esimerkkiohjelman päälle. Muokattu sovellus on saatavilla tekijän kotisivujen alta: <URL: http://users.jyu.fi/~minurmin/opiskelu/ai/> 3.1 Järjestelmän rakenne ja rajapinnat Kuvassa 1 on esitetty järjestelmän rakenne UML-luokkakaaviona. Verkkomalli Graph +importgxl() +exportgxl() Käyttöliittymä DrawingFrame Edge +name +length +connectnodes() Node +name +position +connectto() DrawingObject PathFinder +beginpathsearch() +searchiteration() +endpathsearch() Kuva 1: Järjestelmän luokkakaavio. 3

Luokat Graph, Node ja Edge kuvaavat verkon rakenteen. Graph toimii säiliöluokkana solmuille, Node sisältää assosiaatiotaulun solmuun lähtevistä ja tulevista kaarista. Solmujen heuristiset kustannukset lasketaan position-attribuutin avulla. Varsinainen optimaalisen polun haku on kapseloitu PathFinder-luokkaan, jonka keskeisimmät metodit on listattu liitteessä B. Graph-luokka sisältää metodit verkon tietojen tuomiseen ja viemiseen GXL-muodossa. GXL (Graph exchange Language) on XML-pohjainen tallennusformaatti, joka on suunniteltu verkkomuotoisen tiedon välittämiseen sovellusten välillä [1]. Formaatti on suunnitelmtu mahdollisimman yleiskäyttöiseksi ja sen avulla voi kuvata tavallisten graafien lisäksi hypergraafeja ja sisäkkäisiä graafeja. Lisäksi solmuihin voi liittää mielivaltaisia attribuutteja, tämän sovelluksen tapauksessa nimi- ja paikkatiedot. Esimerkki GXL-tiedoston rakenteesta on liitteessä C. GXL-tietojen lukemiseen käytettiin Python-kielen MiniDOM -XML-jäsennintä. Luokat DrawingFrame- ja DrawingObject kuuluvat verkkomallista riippumattomaan käyttöliittymään. Algoritmin toimintaa voi tarvittaessa testata suoraan tekstitilassa PathFinder-luokkaa käyttämällä. Kuvassa olevien luokkien lisäksi sovellukseen kuuluu muutamia apuluokkia ja - funktioita, kuten XML-tiedon kirjoittaja ja vektorilaskennan perusfunktiot. 3.2 Käyttöliittymä ja olemassaolevan koodin käyttö wxpython on käyttöjärjestelmäriippumaton kirjasto graafisten sovellusten kirjoittamiseen. Se on Python-kielinen rajapinta C++ -kieliseen wxwindows -käyttöliittymäkirjastoon. [5] Sovelluksen käyttöliittymä perustuu wxpython-levityspaketin mukana tulleeseen, Erik Wekstran kirjoittamaan pysketch-piirto-ohjelmaan. Tekijä on ilmoittanut sovelluksen olevan vapaa ja sallii muutosten tekemisen. Alkuperäinen Sketch-ohjelma mahdollisti viivojen, suorakulmioiden, ellipsien ja tekstien vapaan sijoittelun työtilaan. Lisäksi ohjelma latasi ja tallensi tietoja omassa formaatissaan. Graafeihin liittyviä apuvälineitä ohjelmassa ei kuitenkaan ollut eikä esim. tukea kiinnittää viivoja objekteihin. Sketch-sovellusta muokattiin niin, että käyttäjän tekemät ellipsit edustavat verkon solmuja ja viivat kaaria. Käyttäjän editoidessa työtilaa verkkomalli muuttuu vastaavasti. Solmujen paikat päätellään työtilan koordinaateista lineaarisella muunnoksella ja niiden siirto onnistuu. Myös GXLtietojen lataus ja tallennus lisättiin ohjelmaan. 4

Kuvassa 2 on esitetty muokatun sovelluksen käyttöliittymä optimaalisen polun haun jälkeen. Kuva 2: Sovelluksen käyttöliittymä. Optimaalisen polun etsintää varten sovellukseen lisättiin mahdollisuus valita polun alku- ja loppusolmut (StartNode- ja EndNode-painikkeet työkalupalkissa) sekä A*-algoritmin ajaminen ja näyttäminen askel kerrallaan. Kuvassa algoritmia on ajettu Jyväskylän keskustan pelkistetyssä mallissa Kalevankatu/Kauppakatu -risteyksestä Vasankatu/Vapaudenkatu - risteykseen. Tummansiniset solmut kuvaavat optimaalista reittiä, turkoosit solmut ovat muut reitin etsimisessä tutkitut solmut. Liitteessä A on kuvattu PathFinder-luokat tulostamat viestit haun edetessä. 5

Lähteet [1] GXL-kuvauskielen kotisivu <URL: http://www.gupro.de/gxl/>. [2] Pasi Koikkalainen, Tekoäly (luentomoniste), Jyväskylän yliopisto, 2001. [3] Nils Nilsson, Artificial Intelligence: A New Synthesis, Morgan Kaufmann Publishers, 1998. [4] Python-ohjelmointikielen kotisivu <URL: http://www.python.org/>. [5] wxpython-käyttöliittymäkirjaston kotisivu <URL: http://wxpython.org/>. 6

Liitteet A Hakuesimerkki Searching: Node 13 (6.63,1.08) Searching: Node 20 (6.79,1.91) Searching: Node 19 (5.60,1.89) Searching: Node 18 (4.57,1.91) Searching: Node 6 (6.47,0.05) Now fixing cost values... Searching: Node 5 (5.49,0.09) Searching: Node 4 (4.30,0.06) Searching: Node 26 (5.79,2.92) Now fixing cost values... Searching: Node 12 (5.50,1.05) Now fixing cost values... Searching: Node 3 (3.06,0.00) Searching: Node 11 (4.41,1.06) Now fixing cost values... Searching: Node 25 (4.67,2.99) Searching: Node 24 (3.62,2.90) Searching: Node 23 (2.63,2.92) Searching: Node 2 (2.04,0.00) Searching: Node 10 (3.20,1.00) Now fixing cost values... Searching: Node 22 (1.44,3.00) Searching: Node 17 (3.39,1.96) Searching: Node 1 (1.02,0.00) Searching: Node 9 (2.28,1.00) Searching: Node 8 (1.16,1.00) Searching: Node 15 (1.30,2.00) Searching: Node 21 (0.42,3.00) Searching: Node 14 (0.28,2.00) Optimal path: Node 13 (6.63,1.08) -> Node 6 (6.47,0.05) -> Node 12 (5.50,1.05) -> Node 11 (4.41,1.06) -> Node 10 (3.20,1.00) -> Node 9 (2.28,1.00) -> Node 16 (2.46,1.91) -> Node 15 (1.30,2.00) -> Node 14 (0.28,2.00) 7

B A*-toteutuksen ohjelmalistaus """A* -based optimal pathfinder class - Miika Nurminen, 21.02.2003""" def init (self,nodelist,startnode,endnode): """Constructor for PathFinder-class""" self.nodelist = nodelist self.startnode=startnode self.endnode=endnode self.countheuristiccost() for x in self.nodelist: x.minbegincost=-1 #-1 stands that node in not searched yet self.searchstate=0 def countheuristiccost(self): for x in self.nodelist: x.length = vectormath.distance( x.position,self.endnode.position) def newnodecost(self,oldnode, newnode): return oldnode.minbegincost+vectormath.distance( oldnode.position,newnode.position) def recursivebegincostfix(self,totallist,src,target): "Fixes heuristic minimal costs. doesn t sort lists" print "Now fixing cost values..." target.minbegincost = self.newnodecost(src,target) for x in target.edgemap.keys(): try: totallist.index(x) if x.minbegincost > self.newnodecost(target,x): recursivebegincostfix(totallist,target,x) except: continue def getoptimalpathlist(self,node,list): """Recursive function returning optimal path based on begincost. Takes endnode and an empty list as argument""" list.insert(0,node) if node==self.startnode: return list nodes = filter(lambda x:x.minbegincost>=0,node.edgemapin.keys()) if len(nodes)==0: return [] #no solution 8

newnode = nodes[0] for x in nodes: if x.minbegincost< newnode.minbegincost: newnode = x return self.getoptimalpathlist(newnode,list) def beginpathsearch(self): """Initialization step for A*-algorithm""" self.startnode.minbegincost=0 self.open = SortedNodeList() self.closed = SortedNodeList() self.open.addnodewithsortedcost(self.startnode) self.traversed = [] self.searchstate = 1 def searchiteration(self): """Iteration step for A*-algorithm""" assert self.searchstate==1 if len(self.open.nodelist)==0: self.searchstate=2 return 1 n = self.open.nodelist.pop(0) #next node to evaluate print "Searching: "+str(n) i = self.closed.addnodewithsortedcost(n) self.traversed.append(n) if n==self.endnode: self.searchstate=2 return 1 newnodes = [] totallist = self.open.nodelist + self.closed.nodelist for x in n.edgemap.keys(): # fixing existing path values if x.minbegincost==-1: newnodes.append(x) if x.minbegincost > self.newnodecost(n,x): self.recursivebegincostfix(totallist,n,x) for x in newnodes: x.minbegincost = self.newnodecost(n,x) self.open.addnodesortedcost(x) def endpathsearch(self): """Returns optimal path if available""" assert self.searchstate==2 return self.getoptimalpathlist(self.endnode,[]) #solution 9

C GXL-esimerkki <?xml version="1.0" encoding="iso-8859-1"?> <gxl> <graph edgeids="false" id="jkl" edgemode="directed"> <node id="11"> <attr name="label"> <string>11</string> </attr> <attr name="x1"> <string>4.3</string> </attr> <attr name="x2"> <string>1.06</string> </attr> </node> <edge to="12" isdirected="true" from="11"> </edge> <edge to="10" isdirected="true" from="11"> </edge> <node id="10"> <attr name="label"> <string>10</string> </attr> <attr name="x1"> <string>3.1</string> </attr> <attr name="x2"> <string>1.0</string> </attr> </node> <!--... --> </graph> </gxl> 10