Verkot Verkko on (äärellinen) matemaattinen malli, joka koostuu pisteistä ja pisteitä toisiinsa yhdistävistä viivoista. Jokainen viiva yhdistää kaksi pistettä, jotka ovat viivan päätepisteitä. Esimerkiksi sovelluksessa pisteet voivat olla kaupunkeja ja viivat - suorat yhteydet, eli tiet joita pitkiin kaupungista pääsee toiseen suoraan (ei muiden verkon kaupunkien kautta). Tässä kuva tyypillisestä verkosta. Käytämme sitä esimerkkinä usein jatkossa. v 1 B v 6 D E v 7 A v 8 v 9 v 5 v 2 F C v 3 v 4 G Viiva voi olla kaksisuuntainen, jolloin se voidaan kulkea molempiin suuntiin tai yhdensuuntainen, jolloin sitä voi kulkea vain yhteen suuntaan. Jälkimmäisessä tapauksessa viivalla on alkupiste ja loppupiste ja kuvissa se merkitään nuolena. Myös kaksisuuntaisen viivan tapauksessa puhumme alku-ja loppupisteestä, jolloin jompikumpi päätepiste voidaan sanoa alkupisteeksi (toinen on silloin loppupiste), riippuen siitä, mihin suuntaan halutaan kulkea. Esimerkiksi yllä olevassa kuvassa v 2 ja v 9 ovat yhdensuuntaisia, muut viivat kaksisuuntaisia. Hyväksymme myös silmukoita, eli viivoja, jotka yhdistävät piste itseensä (kuvassa v 7 ) ja monikertaisia viivoja eli erilaisia viivoja samojen pisteiden välillä - kuvassa viivoilla v 3 ja v 4 samat päätepisteet, mutta ne ajatellaan erilaisiksi viivoiksi. Painotettu verkko, on sellainen verkko, jossa jokaiseen viivaan on liitetty 1
joku lukuarvo, joka sanotaan viivan painoksi (weight). Esimerkiksi jos verkon pisteet edustavat kaupunkeja ja viivat- teitä, viivan paino voi olla kaupunkien välinen etäisyys eli tien pituus. Painotettu verkko näyttää seuraavanlaiselta - 1 B 2 D E 2 A 4 5 4,3 F 9 C 3 2 G Jos verkosta otetaan kaksi pistettä, niiden välillä ei välttämättä ole viivoja, mutta voi olla, että toisesta pääsee toiseen muutamaa viivaa pitkin. Tällaista kulkua sanotaan reitiksi tai poluksi. Formaalisti siis reitti pisteestä a pisteseen b on ketju viivoja w 0,w 1,...,w n, missä vivan w 0 alkupiste on a, w n loppupiste on b ja jokaisen seuraavan viivan v i alkupiste on edellisen viivan v i 1 loppupiste. Tällöin a on reitin alkupiste ja b reitin loppupiste. Jos verkko on painotettu, reitillä on pituus - se on summa siihen sisältyvien viivojen painoista. Esimerkiksi yllätarkastellussa verkossa (v 1,v 6 ) onpolkua:stä D:hen. Tietysti niiden välillä on olemassa myös lyhyempi polku, jossa on vain yksi viiva v 8. Mutta jos sama verkko tarkastellaan painotettuna verkkona kuten yllä, niin ensimmäisen reitin paino on 1+2 = 3, kun taas toisen reitin paino on 5. Jos nämä painot edustavat joitakin kustannuksia, ensimmäinen onkin edullisempi. Verkko, jossa jokaisesta pisteestä päästään jokaiseen toiseen pisteeseen polkua pitkin, sanomme yhtenäiseksi. 2
Optimisaatio verkossa. Verkkoihin liittyy luonnollisella tavalla monta tärkeätä optimointi-ongelmaa. Tarkastelemme niistä kaksi - minimaalisen virittävän puun ongelma ja lyhyemmän reitin ongelma. Minimaalisen virittävän puun ongelma Sykli verkossa on sellainen reitti, joka yhdistää pisteen itseensä eli jonka alku-jaloppupisteetovatsamapiste.esimerkiksi verkossaylläviivatv 1,v 6,v 8 muodostavat syklin, joka yhdistää A:n itseensä. Myös (v 3,v 4 ) on sykli. Puu on sellainen yhtenäinen verkko, jossa ei ole sykliä. Puussa ei ole turhia viivoja, vaan jokaisesta pisteestä päästään toiseen vain yhtä reittiä pitkin. Puu yhtenäisessä verkossa G on sellainen kokoelma sen pisteitä ja viivoja (aliverkko) joka on itse verkkona puu. Virittävä puu verkossa, on puu verkossa, joka sisältää kaikki sen pisteet. Virittävä puu on siis ikäänkuin minimaalinen tapa valita annetussa verkossa yhteyksiä (viivoja), niin että kaikki pisteet ovat yhteydessä, mutta viivoja on mahdollisimman vähän. Jos verkko on painotettu, haluamme löytää siinä minimaalinen virittävä puu, eli sellainen verkon alipuu, jolla on pienin mahdollinen paino (sen viivojen yhteenlaskettu paino). Minimaalisen virittävän puun löytäminen. Minimaalinen virittävä puu rakennetaan vaiheittain tietyn algoritmin mukaan, lisämällä siihen yksi uusi piste ja yksi viiva kerrallaan. Algoritmin jokaisessa vaiheessa verkon pisteet ovat jaettu kahteen luokkaan - luokka A, jossa on ne pisteet, jotka ovat jo lisätty puuhun ja luokka B, jossa on ne pisteet, jotka eivät ole vielä puussa. Algoritmin alussa A koostuu vain yhdestä pisteestä, jonka saa valittaa mielivaltaisesti. 3
Algoritmin jokainen välivaihe on samanlainen- tarkastellaan kaikki viivat, joiden toinen päätepiste on A:ssä ja toinen B:ssä. Valitaan niistä viivoista sen, jolla on pienin paino ja lisätään se, sekä sen toinen päätepiste puuhun. Tällöin joukko A kasvaa ja joukko B pienenee. Jos viivoja jolla on pienin paino on enemmän kuin yksi, niistä valitaan kuitenkin vain yksi. Sen saa ottaa mielivaltaisesti. Algoritmi päättyy kun kaikki verkon pisteet kuuluvat puuhun. Esimerkki: Tarkastellaan seuraavaa verkkoa: b 1 4 6 3 e a 7 9 5 d 5 c 8 Aloitetaan minimaalisen puun konstruktio esim. pisteestä a (alkupisteen valinnalla ei ole merkitystä). Tarkastellaan kaikki a:sta lähtevät viivat (paitsi silmukat, joita ei nyt verkossa olekaan joka tapauksessa). Niistä painoltaan pienin on viiva ab, jonka paino 1. Lisätään siis tämä viiva ja sen loppupiste b puuhun. Seuraavaksi tarkastellaan viivoja, joiden toinen päätepiste on a tai b, mutta toinen ei ole. Nyt näistä pienin on be, sen paino on 3. Lisätään siis puuhun piste e ja viiva be. Jatketaan samalla tavalla. Seuraavassa vaiheessa pienin viiva on bd (paino 4), sitten seuraavassa vaiheessa df (paino 3). Nyt jäljellä on vain piste c. Kaikista viivoista, jotka johtavat pisteeseen c kaksi painoltaan pienintä ovat ac tai dc, molempien paino on 5. Näistä valitaan jompikumpi (mutta ei molempia, tällöin ei tule puuta!!!). 10 3 f 4
Saadaan siis kaksi mahdollista ratkaisua. Näin ollen minimaalinen puu ei ole välttämättä yksikäsitteinen, mutta kaikilla mahdollisilla vastauksilla on sama pituus. Tässä tapauksessa minimaalisen puun pituus 1+3+4+3+5 = 16. Sama lopputulos saadaan kun lähdetään liikkeelle mistä tahansa muusta pisteestä. Lyhyemmän reitin ongelma Olkoot a ja b jonkun painotetun verkon pisteitä. Halutaan löytää pituudeltaan mahdollisimman pieni reitti niiden välisssä. Tarkastelemme niin sanottua Dijekstran algoritmia, jonka avulla lyhyemmän reitin ongelma voidaan ratkaista. Algoritmi on monimutkaisempi kuin virittävän puu algoritmi. Edelleenkin jokaisessa algoritmin vaiheessa verkon pisteet jakautuvat kahteen luokkaan. Luokassa A ovat niin sanotut pysyvät pisteet, eli sellaiset pisteet joille on jo löydetty pienin reitti, joka yhdistää niitä pisteseen a. Jokaiselle pysyvälle pisteelle x on lisäksi annettu niin sanottu leima, joka on muodoltaan pari (t, y). Tämän parin ensimmäinen osa t on luku, joka kertoo, kuinka pitkä pituudeltaan on lyhin mahdollinen reitti pisteestä a tähän pisteeseen x. Toinen osa y on taas pisteen x edeltäjä tällaisessa reitissä. Leiman toisen osan avulla voidaan siis jäljittää myöhemmin lyhin reitti piste kerrallaan. Pysyvien pisteiden leimat eivät enää koskaan muutu vaikka algoritmi jatkuisi vielä. Algoritmi pysähtyy silloin, kun pisteestä b tulee pysyvä. Tällöin voidaan leimojen avulla jäljittää haluttu lyhin reitti. Miten se tapahtuu käytännössä selviää esimerkkeistä alla. Toisessa luokassa B on verkon kaikki muu, ei-pysyvät (tässä vaiheessa) pisteet, joihin asti, emme vielä löytäneet lyhintä reittiä pisteestä a. Joillakin ei-pysyvillä pisteillä on myös leimoja, jotka ovat muotoa (t, x), mutta ei välttämättä kaikilla. Lisöksi nämä leimat saattavat muuttua niiden kohdalla algoritmin edetessä, kun taas pysyvien pisteiden leimat eivät koskaan enää päivitty. 5
Leimoissa varastetaan samaa informaatiota kuin pysyvien pisteiden leimoissa, paitsi, että nyt kyse on mahdollisesta eli ainoastaan tähän mennessä löydetystä lyhimmästä reitistä. Jos löydetään lyhyempi, leima siis päivitetään. Algoritmin jokainen välivaihe näyttää seuraavalta. Tarkastellaan taas kaikki viivat, joiden alkapiste on A:ssä (pysyvien pisteiden luokassa) ja loppupiste on B:ssä. Olkoon v sellainen viiva, olkoon c sen alkupiste A:ssä ja d sen loppupiste B:ssä. Olkoon p(v) viivan v paino ja (t,y) pisteen c:n leima. Huomaa, että t on tällöin sellaisen reitin paino, joka yhdistää pisteitä a ja d, lisäksi lyhyemmän sellaisen. Jos tähän reittiin lisätään perään viiva v, saadaan eräs reitti pisteestä a pisteseen d. Jos pisteellä d ei vielä ole leimaa, asetetaan sen leimaksi (t + p(v),a). Ajatus tämän takana on seuraava - jos lyhin reitti pisteestä a pisteseen c on jo konstruoitu, niin eräs reitti pisteseen d saadaan, kun jatketaan edellinen reitti viivalla v. Tämä on ainakin jokin reitti a:stä d:hen, ja koska d:llä ei ole leimoja vielä, tämä reitti on ainakin toistaiseksi paras kandidaatti pienempään reittiin. Jos taas pisteellä d on jo leima (t,z), tämä tarkoittaa, että aikaisemmin löydettiin jo jokin mahdollisesti lyhin reitti a:stä d:hen, ja sen pituus on t. Toisaalta nyt meillä on myös uusi reitti pisteestä a pisteseen d pisteen c kautta ja sen paino on t+p(v). Verrataan tämä uusi reitti aikaisemman löydettyyn eli katsotaan onko t + p(v) mahdollisesti pienempi kuin t. Jos on, vanha reitti ei ollutkaan lyhin mahdollinen, joten muutetaan (eli päivitetään) d:n leima muotoon (t+p(v),a). Jos taas uusi reitti ei ollut pidempi kuin vanha eli t t+p(v), ei muuteta mitään. Näin siis tehdään jokaisen sopivan viivan kohdalla. Sopiva tässä yhteydessä siis tarkoittaa sellaista viiva jonka alkupiste on pysyvien joukossa ja loppupiste ei ole. Kierroksen lopussa tarkastellaan kaikki B:n pisteet, joilla on leima, ja valitaan niistä se piste, jolla on pienin leiman ensimmäinen osa (reitin pituus). Tämä piste siirretään leimaineen pysyvien joukkoon ja seuraava kierros alkaa. Jos pisteitä joilla on sama pienin leiman ensimmäinen osa on enemmän 6
kuin yksi, siirretään niistä joku yksi pysyvien joukkoon, ei ole väliä mikä. Algoritmi jatketaan kunnes b on siirtynyt pysyvien joukkoon. Esimerkki: Tarkastellaan vaihtelun vuoksi seuraavaa järjestettyä verkkoa, jossa siis kaikki viivat yhdensuuntaisia eli nuoleja. 100 b 20 15 10 d 50 a c 30 60 Halutaan löytää lyhyin reitti pisteiden a ja b välillä. e Alussa piste a on ainoa pysyvä piste ja se saa leiman (0,a) (ei tarvita mitään viivoja, että pääse a:stä a:han). Tarkastellaan kaikki viivat, jotka lähtevät a:stä. Niitä on- viiva ab, jonka paino 100 ja viiva ac, jonka paino 30. Koska pisteillä b ja c ei ole vielä leimoja, b saa leiman (100,a) ja c saa leiman (30, a). Leimoista kannattaa pitää erikseen kirjaa, esim. taulukkomuodossa. Nyt joukossa B sijaitsevat kaikki pisteet paitsi a ja niistä leimoja ovat saaneet b ja c. Pienin leima on c:llä (30), joten c siirretään pysyvien joukkoon. Algoritmin ensimmäinen kierros päättynyt. Kierros 2: Nyt pysyvien pisteiden joukossa on pisteet a ja c. Nyt pitäisi tarkastella kaikki nuolet, jotka alkavat a:ssä tai c:ssä ja päättyvät muihin pisteisiin. Mutta nuoli ab on jo tarkasteltu ensimmäisen kierroksen aikana, joten siitä ei tarvitse enää välitä. Sama havainto pätee itse asiassa jokaisen kierroksen kohdalla - riittää tarkastella vain niitä viivoja, jotka alkavat uudessa pisteessä, joka lisättiin siis edellisen kierroksen lopussa. Viiva cd tuo pisteelle d leiman (30+10 = 40,c) ja viiva ce - leiman (90,c) pisteelle e. Näistä pienin on pisteellä d, joten se siirtyy pysyvien pisteiden joukkoon. Kierros 3: Pysyvien pisteiden joukossa pisteet a, c, d. Tarkastellaan taas viivat, jotka alkavat tuoreessa pysyvässä pisteessä d ja loppuvat ei-pysyvään 7
pisteeseen. Tällaisia on kaksi - viiva de ja viiva db. Näistä de määrää reitin a c d e, jonka pituus on 30+10+50 = 90. Tämä ei ole parempi kuin d leiman (90, c) ensimmäinen osa, joten sitä leimaa ei tarvitse päivitä. Sen sijaan jos tarkastellaan viivaa db, jonka pituus 15, niin koska 40+15 = 55 < 100, tästä saadaan parempi tulos kuin aikaisempi b:n leima (100, 1). Muutetaan b:n leima siis leimaksi (55, d). Nyt ei-pysyvistä pisteistä b:llä on leima (55, d) ja e:llä leima (90, c). Näistä 55 on pienin, joten b:stä tulee pysyvä piste. Koska olemme etsineet lyhintä reittiä a:stä b:hen, voimme lopettaa. Pienin reitti on siis pituudeltaan 55. Sen viivoja voidaan jäljittää nyt menemällä leimoja pitkin taaksepäin. b:n leima on (55,d), joten sen edeltäjä on d. d:n leima puolestaan (40,c), joten sen edeltäjä c ja niin edelleen. Haluttu polku on siis a c d b. Alla kuva samasta verkosta, jossa lisätty informaatiota kaikista leimoista, jotka algoritmin suorituksen aikana tulivat esille (55, d) 100 (100, a) b 20 15 d (40, c) 50 (0, a) a 30 c (30, a) 60 e (90, c) Huomaa, että lyhimmän reitin jokainen osa on myös lyhin mahdollinen. Näin ollen samalla olemme laskeneet, että lyhin reitti a:stä c:hen on a c ja lyhin reitti a:stä d:hen on a c d. Näitä ei tarvitse siis laskea samalla algoritmilla uudestaan. Lyhimmän reitin ongelma lineaarisena optimointiongelmana Lyhimmän reitti ongelma voidaan muotoilla myös lineaarisena optimointiongelmana. Sen jälkeen se voidaan ratkaista esimerkiksi Solverilla. 8
Malli konstruoidaan seuraavalla tavalla. Muuttujat vastaavat verkon viivoja - yksi muuttuja per viiva. Yleensä muuttujat merkitään x ij, missä ij on se viiva, joka alkaa pisteessä i ja loppuu pisteeseen j. Objektifunktio saadaan kertomalla viiva ij vastaava muuttuja viivan painolla ja laskemalla kaikki nämä yhteen. Tämä funktio edustaa polun pituutta, joten se pitää minimoida. Esimerkiksi edellisessä esimerkissä ongelmassa olisi 7 muuttujaa - x ab,x ac, x cd, x db, x bc, x de ja x ce. Ajatus on siinä, että ratkaisussa muuttujan x ij arvosta nähdään onko vastaava viiva ij parhaassa reitissä vai eikö seuraavasti - jos vastaavan muuttujan arvo 0, viiva ei ole reitissä mukana, jos se on taas > 0, viiva on mukana. Yleensä jälkimmäisessä tapauksessa arvo on 1, mutta jos ratkaisu ei yksikäsitteinen (vähintään kaksi erilaista lyhintä reittiä), näin ei välttämättä ole. Reunaehtoja saadaan seuraavan periaatteen mukaisesti - jokaisessa verkon pisteessä sisään menevien nuolten summan pitää olla sama kuin ulospäin menevien. Lisäksi verkkoon lisätään yksi pisteeseen a menevä nuoli (ilman alkupistettä), jonka arvo 1, samoin yksi viiva joka lähtee b:stä. Eli edellisessä esimerkissä näin: 1 15 b d 100 20 50 a c e 1 30 60 Huomaa, nämä arvot 1 EIVÄT ole painoja, vaan vakioita, joita kohdellaan samalla tavalla kuin muuttujia. Nyt jokaista verkon pistettä vastaa yhtälö, jossa vasemmalla puolella - kaikki viivat (tai siis niitä vastaavat muuttujat tai vakiot) jotka tulevat pisteeseen sisään ja oikealla puolella - kaikki jotka menevät ulos. Siis: Piste a - 1 = x ab +x ac, Piste b - x ab +x db = x bc +1, Piste c - x ac +x bc = x cd +x ce, Piste d - x cd = x db +x de, Piste e - x ce +x de = 0. Nämä siis ovat vastaavan lineaarisen ongelman reunaehdot. 9
Jos ne kirjoittaa kuten on tapana sillä tavalla, että vasemmalla puolella on muuttujat ja oikealla vakiot, saadaan ehdot muotoon Piste a - x ab +x ac = 1, Piste b - x bc x ab x db = 1, Piste c - x ac +x bc x cd +x ce = 0, Piste d - x cd x db x de = 0, Piste e - x ce +x de = 0. Huomataan, että jos näiden kertoimia kootaan taulukoksi, jossa sarakkeet vastaavat muuttujia eli viivoja ja rivit pisteitä, se näyttää seuraavanlaiselta - Tyhjät kohdat vastaavat nollia. x ab x ac x bc x cd x ce x db x de a 1 1 1 b 1 1 1 1. c 1 1 1 1 0 d 1 1 1 0 e 1 1 0 Tällainen taulukko konstruoidaan seuraavalla yksinkertaisella tavalla - jokaisessa sarakkeessa laitetaan 1 saraketta vastaavan viivan alkupisteen kohdalle ja 1 loppupisteen kohdalle. Loput alkiot nollia. Viimeinen sarake vastaa ehtojen oikeanpuoleisia vakioita- niistä etsityn reitin alkupisteettä vastaa 1, loppupistettä 1 ja loput nollia. Minimoittava objekti funktio on 100x 12 +30x 13 +20x 23 +10x 34 +60x 35 +15x 42 +50x 45. Katso myös sama esimerkki Excel-tiedostona ratkaistuna Solverin avulla. 10