811 Tietorakenteet (kevät 9) Harjoitus 11, ratkaisuja (Topi Musto) 1. Bellmanin-Fordin algoritmin alustusvaiheen jälkeen aloitussolmussa on arvo ja muissa solmuissa on arvo ääretön. Kunkin solmun arvo kuvaa tähän mennessä löydetyn lyhimmän reitin pituutta lähtösolmusta kyseiseen solmuun. Algoritmin suorituksen aikana toistetaan V kertaa kaikkien kaarien löysääminen (relaxation). Kaaren (u, v) löysäämisessä tarkistetaan pienenisikö solmun v arvo jos siihen tultaisiinkin solmusta u. Ne kaaret joiden löysäämisellä oli jotain vaikutusta on värjätty seuraavissa kuvissa punaisella. 8 8 9 1
9 Lopuksi täytyy käydä kaikki kaaret vielä kerran läpi. Mikäli verkossa olisi yhä jännitteitä, eli jonkin kaaren löysäämisellä olisi vieläkin jotain vaikutusta, niin verkossa olisi negatiivisen pituinen sykli. Tässä verkossa kaikki kaaret ovat lopussa löysättyjä, joten negatiivista sykliä ei esiinny. Lopullinen lyhin reitti alkusolmusta kohdesolmuun saadaan seuraamalla kohdesolmusta taaksepäin kaaria valiten aina se kaari, joka muokkasi läpikäynnin aikana viimeisenä kohdesolmun arvoa. Nämä kaaret on merkattu seuraavassa kuvassa punaisella.. Tarkastellaan verkkoa, jonka solmuina on lentokenttiä ja kaarina suorat lennot kultakin lentokentältä jollekin toiselle lentokentälle. Kunkin kaaren painona on todennäköisyys sille, että matkatavarat katoavat tällä lennolla. Merkataan P (x 1, x,..., x n ):llä todennäköisyyttä sille, että matkatavarat katoavat jollakin lennolla (x i, x i+1 ) kun lennetään lentoasemalta x 1 lentoasemalle x n lentoasemien x,..., x n 1 kautta. Todennäköisyydet P (x i, x j ), joissa on vain kaksi lentoasemaa i ja j, ovat siis annetut verkon kaarien painot.
Se, että matkatavarat katoavat jollain lennolla on vastatapahtuma sille, että matkatavarat eivät katoa millään lennolla, eli P (x 1, x,..., x n ) = 1 P (x 1, x ) P (x, x ) P (x n 1, x n ). Tämä saa pienimmän arvonsa kun tulo P (x 1, x ) P (x n 1, x n ) saa suurimman arvonsa. Logaritmin avulla tämä tulo saadaan muunnettua summaksi. Koska logaritmi on aidosti kasvava funktio, tämä tulo saa suurimman arvonsa kun ( ) log P (x 1, x ) P (x, x ) P (x n 1, x n ) = log P (x 1, x ) + log P (x, x ) + + log P (x n 1, x n ) saa suurimman arvonsa, joka edellyttää edelleen sitä, että log P (x 1, x ) log P (x, x ) log P (x n 1, x n ) saa pienimmän arvonsa. Siis korvaamalla verkon kunkin kaaren (i, j) painon painolla log(1 P (x i, x j )) (joka on aina positiivinen luku, koska 1 P (x i, x j ) on todennäköisyytenä aina korkeintaan 1) voidaan etsiä ne lentoreitit, joilla matkatavaroiden katoamisen todennäköisyys on pienin mahdollinen käyttämällä suoraan tavallista Dijkstran algoritmia. Vaihtoehtoinen tapa ratkaista tehtävä Matkatavarat ovat kadonneet lentokentälle x n tultaessa jos ja vain jos ne ovat kadonneet jo kentälle x n 1 tultaessa tai ne eivät olleet kadonneet kentälle x n 1 tultaessa mutta ne katosivat lennolla x n 1 :stä x n :ään. Siis P (x 1, x,..., x n ) = P (x 1, x,..., x n 1 ) + P (x 1, x,..., x n 1 )P (x n 1, x n ) = P (x 1, x,..., x n 1 ) + (1 P (x 1, x,..., x n 1 ))P (x n 1, x n ). Dijsktran algoritmia voidaan käyttää löytämään jostain lentokentästä lähtevät reitit matkatavaroita epätodennäköisimmin kadottavat reitit siten, että kuhunkin solmuun x n tallennetaan kullakin hetkellä sen reitin (x 1, x,..., x n ) todennäköisyys d[v] = P (x 1, x,..., x n 1, x n ), joka on tähän mennessä löydetyistä solmuun x n päättyvistä reiteistä paras, eli jolla matkatavaroiden hukkumistodennäköisyys on pienin. Tätä päivitetään löysentämisessä aiemman kaavan mukaan seuraavasti:
RELAX(u, v) 1 if d[v] > d[u] + (1 d[u])p (u, v) then d[v] d[u] + (1 d[u])p (u, v) p[v] u Algoritmi laskee selvästi lähtösolmusta s lähtevien polkujen matkatavaroiden hukkumistodennäköisyyksiä. Algoritmi löytää ne polut, joilla on pienimmät todennäköisyydet, koska Dijkstran algoritmissa kukin kaari (u, v) löysennetään vasta siinä vaiheessa kun tiedetään, että kaaren lähtösolmun arvo d[u] on sama kuin solmun arvo olisi optimaalisella reitillä, eli d[u] = δ(s, u). Algoritmi toimii siis samoin kuin tavallinen Dijkstran algoritmi verkossa, jonka kaarien painot ovat (1 δ(s, u))p (u, v). Löysennyksen jälkeen kaaren (u, v) kohdesolmun v arvoksi d[v] tulee siis δ(s, u) + (1 δ(s, u))p (u, v) mikäli tämä on pienempi kuin solmun v entinen arvo. Mahdollinen uusi arvo on optimaalisen reitin tavaroiden katoamistodennäköisyys jos solmuun v kuljetaan solmun u kautta.. Lyhimmät reitit shakkilaudalla löytyvät helposti leveyssuuntaisella haulla. Verkon solmuina ovat koordinaattiparit (x, y), missä x, y {1,,..., 8}. Koordinaatti x kertoo laudan sarakkeen ja koordinaatti y laudan rivin. Verkon kaarina ovat ne ratsun siirrot, jotka pysyvät laudan sisällä, eli esimerkiksi Adj[(1, 1)] = {(, ), (, )}.
RATSUNREITTI(G, start, destination) 1 for i 1 to 8 do for j 1 to 8 do colour[(i, j)] WHITE distance[(i, j)] parent[(i, j)] NIL colour[start] BLACK 7 distance[start] 8 Q tyhjä jono 9 ENQUEUE(Q, start) 1 while not EMPTY(Q) 11 do u DEQUEUE(Q) 1 if u = destination Mikäli kohdesolmu löytyy voidaan lopettaa. 1 then TULOSTAREITTI(start, destination) 1 return Muuten käydään läpi kaikki ratsun siirrot. 1 for delta {(1, ), (, 1), ( 1, ), (, 1), (, 1), (1, ), ( 1, ), (, 1)} 1 do v u + delta Tarkistetaan, että siirto pysyy laudalla. 17 if x[v] 1 and x[v] 8 and y[v] 1 and y[v] 8 18 then if colour[v] = WHITE 19 then colour[v] BLACK distance[v] distance[u] + 1 1 parent[v] u ENQUEUE(Q, v) Tänne ei pitäisi koskaan päätyä. ERROR "Reittiä ei löytynyt" Muodostettuja parent kenttiä seuraamalla löydetään lyhin reitti, jolla kohdesolmuun on päästy. Reitti täytyy kuitenkin ensin käydä kokonaan kerran läpi, jotta se saataisiin tulostettua oikeassa järjestyksessä. Helpoiten tämä onnistuu rekursiolla seuraavasti. Ongelma voitaisiin myös kiertää etsimällä lyhin reitti kohdesolmusta lähtösolmuun. TULOSTAREITTI(G, start, destination) 1 if destination start then TULOSTAREITTI(start, parent[destination]) PRINT(destination)