Matemaattinen optimointi II Marko M. Mäkelä Turun yliopisto Matematiikan ja tilastotieteen laitos Kevät 21
Sisältö Esipuhe 1 1 Lyhimmät tiet ja diskreetti dynaaminen optimointi 2 1.1 Lyhimmän tien ongelmia............................ 2 1.2 Lyhimmät tiet dynaamisella optimoinnilla.................. 7 1. Lyhimmät tiet jostakin solmusta kaikkiin muihin............... 1 1.4 Lyhimmät tiet kaikkien solmuparien välillä.................. 12 1. Etäisyydet solmusta muihin ei-negatiivisten painojen tapauksessa..... 17 1.6 Lyhimmät tiet solmusta muihin syklittömässä verkossa........... 19 1.7 Projektin valvonta ja pisimmät tiet...................... 21 1.8 Diskreetti dynaaminen optimointi....................... 28 2 Virtaukset verkossa 42 2.1 Minimikustannusvirtausongelma........................ 42 2.2 Kulkusuunnat ketjuissa............................. 44 2. Perusalgoritmi minimikustannusvirtausongelman ratkaisemiseksi...... 49 2.4 Minimikustannusvirtausongelman ratkaisujen jaollisuus........... 1 2. Kuljetus- ja järjestelyongelmat......................... 2 2.6 Muita yhden tuotteen virtausongelmia.................... 7 2.7 Simplex-algoritmi verkoille........................... 61 2.8 Monen tuotteen virtaukset sekä lisääntyvät ja vähenevät virtaukset.... 6 Diskreetit optimointimallit 68.1 Kokkareiset lineaariset optimointitehtävät.................. 68.2 Selkäreppu- ja budjetointimallit........................ 7. Pakkaus-, peitto- ja ositusmallit........................ 7.4 Järjestely- ja paritusongelmat......................... 78. Kauppamatkustaja- ja reititysongelmat.................... 82.6 Sijoittelu ja verkon suunnittelu........................ 88.7 Töidenjärjestelyongelmat............................ 9.8 Paloittain lineaarinen approksimointi..................... 99 4 Diskreetit optimointimenetelmät 11 4.1 Täydellinen luettelointi............................. 1 4.2 Relaksaatiomenetelmä............................. 14 4. Tiukat relaksaatiot............................... 16 4.4 Branch and Bound............................... 11 4. Branch and bound -algoritmin tehostamistapoja............... 11 4.6 Parantava hakuheuristiikka........................... 121
4.7 Tabuhaku, simuloitu jäähdytys ja geneettiset algoritmit........... 1 4.8 Konstruktiiviset heuristiikat.......................... 18 Kirjallisuutta 148 2
Esipuhe Matemaattinen optimointi II on suoraa jatkoa kurssille Matemaattinen optimointi I, jossa käsiteltiin lähinnä jatkuvaa lineaarista optimointia. Tällä kurssilla keskitytään puolestaan diskreettiin lineaariseen optimointiin, jolla on vahvat yhteydet graafi- ja verkostoteoriaan. Luentomoniste perustuu emeritusprofessori Timo Leipälän vuonna 28 kirjoittamaan erinomaiseen monisteeseen [1]. Kyseisen monisteen pääasiallisena lähteenä on käytetty kirjan [2] lukuja 9 12. Erityiskiitos Outi Wilpulle tekstin huolellisesta ladonnasta ja kuvien tuottamisesta. Turussa keväällä 212 Marko M. Mäkelä 1
1 Lyhimmät tiet ja diskreetti dynaaminen optimointi 1.1 Lyhimmän tien ongelmia Esimerkki 1.1. Tarkastellaan Littlevillen keskustaa, jossa on yksi- ja kaksisuuntaisia katuja ja kunkin risteyksen välille on estimoitu sen ajamiseen kuluva aika sekunteina. Liikennesuunnittelussa voidaan selvittää kyselytutkimuksilla automatkojen aloittamis- ja lopettamiskohdat, mutta autoilija ei voi ilmoittaa valitsemaansa reittiä ennen kuin tietää minkälaisia tulevat liikennejärjestelyt (etuajo-oikeudet, yksisuuntaisuudet jne.) ovat. Liikennesuunnittelijoiden on kuitenkin arvioitava eri päätösvaihtoehtoja varten kullakin kadunpätkällä kulkevien autojen määrää. Yksi arviointitapa on olettaa, että kaikki autoilijat toimivat rationaalisesti ja valitsevat aina lyhimmän reitin. Silloin analyysissa täytyy määrätä lyhin tie jokaisesta reitin aloituskohdasta jokaiseen reitin lopetuskohtaan. 2 18 12 18 2 6 18 28 2 28 21 1 49 4 8 Kuva 1: Littlevillen keskusta Katuverkostoa ja monia muitakin asioita voidaan abstrahoida esittämällä se graafina (Q, E), missä Q = q 1, q 2,... on solmujen ja E = e 1, e 2,... niitä yhdistävien kaarten e k = (q i, q j ) joukko. Kaari voi olla suuntaamaton tai suunnattu. Jälkimmäisessä tapauksessa sitä pitkin voi liikkua vain suuntaan q i q j ja silloin puhutaan usein nuolista. Tällöin q i on nuolen alkusolmu (tail) ja q j loppusolmu (head). Katuverkostossa solmut esittävät risteyksiä, jotka on selvyyden vuoksi numeroitu. Yksisuuntaista katua esittää suunnattu nuoli ja kaksisuuntaista suuntaamaton kaari. Koska kaaren merkintä ei ole yksikäsitteinen, voidaan sopia, että järjestysnumeroltaan pienempi solmu on ensimmäisenä. Mikäli nuolilla/kaarilla (i, j) on reaalilukupainot c ij niin kuin kuvassa 2, voidaan formuloida ja ratkaista erilaisia kvantitatiivisia optimointiongelmia ja puhutaan graafin asemasta verkosta. Tässä paino voi esittää kustannusta, 2
matkaa, aikaa jne. Esitellään seuraavat verkkoihin liittyvät käsitteet: Verkko on suunnattu, jos kaikki sen kaaret ovat suunnattuja nuolia. Verkko on suuntaamaton, jos kaikki sen kaaret ovat suuntaamattomia. Polku tai tie solmujen i ja j välillä on katkeamaton kaari- tai nuolijono (i, k 1 ), (k 1, k 2 ),...,(k p 1, k p ), (k p, j), joka yhdistää verkon solmut i ja j. Tässä nuolet on kuljettava oikeassa järjestyksessä eikä missään solmussa käydä kahdesti. Verkko on yhtenäinen, jos jokaisen solmuparin välillä on polku. Polun pituus on polkuun kuuluvien nuolien (kaarien) painojen summa. Syklistä puhutaan, jos polun alku- ja loppupiste ovat samoja ja p 1. Sykli on negatiivinen, jos sen pituus on negatiivinen. Silmukka on nuoli (i, i) solmusta i itseensä. Puu on yhtenäinen suuntaamaton verkko, jossa ei ole syklejä. Verkkojen avulla voidaan havainnollisesti esittää monenlaisia tärkeitä käytännön ongelmia. Lisäksi verkko-ongelmiksi pystytään hyvin usein pukemaan myös tehtäviä, joiden verkkorakenne ei ole sillä tavalla ilmeinen kuin edellisessä esimerkissä. Oleellista on se, että yllä olevan määritelmän mukaiset abstraktit käsitteet pystytään muodostamaan. Lyhimmän tien ongelmassa etsitään pituudeltaan lyhintä polkua kahden annetun solmun välillä ts. yritetään minimoida polun kaarten/nuolten painojen summaa. 1 2 18 8 12 18 6 2 2 6 2 18 28 9 28 21 7 4 1 49 4 8 1 Kuva 2: Littlevillen keskustan katuverkosto
Kuvan 2 verkossa saadaan esimerkiksi polut 7 1 8 ja 4 1 8 solmujen ja 8 välille. Sen sijaan 7 6 8 ja 7 6 9 7 1 8 eivät ole polkuja. Koska painona on nyt ajoaika, yritetään lyhimmän tien ongelmassa määrätä nopein reitti solmusta i solmuun j. Edellä olevien reittien ajoajat ovat nyt + 49 + 28 = 17 ja 1 + 8 + 28 = 79 sekuntia. Esimerkkiongelmassa on sekä kaaria että nuolia, kaikki painot ovat ei-negatiivisia ja tavoitteena on ratkaista kaikkien solmuparien väliset lyhimmät reitit. Muitakin versioita lyhimmän tien ongelmasta tunnetaan ja niille on kehitelty erilaisia algoritmeja. Esimerkki 1.2. Ft. Worthissa sijaitseva kuljetusyritys jakelee tavaraa kuorma-autoissa kuvassa näkyviin kaupunkeihin. Kaupunkien etäisyydet on merkitty painoiksi. Jakelussa ei pysähdytä mihinkään välillä olevaan paikkaan vaan viedään koko lasti yhteen paikkaan. Kuljettajille maksetaan palkkaa lyhimmän etäisyyden mukaan, joten täytyy saada selville lyhimmät etäisyydet Ft. Worthista muihin kaupunkeihin. Muut lähtösolmut eivät nyt kiinnosta eikä tarvitse tietää optimaalisia reittejäkään, ainoastaan niiden pituudet ovat kiinnostavia. Verkko on nyt suuntaamaton. 1 Amarillo 122 9 Lubbock 2 Ft. Worth 167 18 Abilene 4 19 92 44 246 6 41 Austin 4 San Angelo 8 El Paso 21 79 Houston 199 7 San Antonio 21 1 Corpus Christi 1 9 Kuva : Kuljetusyrityksen jakelukaupungit Esimerkki 1.. Sirkuksen kesäkiertue on päättynyt Lincolniin ja sen olisi palattava talvilepoon Tallahasseen lähelle. Kuvan 4 verkkoon on merkitty paluureitin varrella mahdollisesti olevia kaupunkeja ja niiden väliset siirtymiskustannukset tuhansina dollareina. Kussakin kaupungissa on mahdollista järjestää esityksiä ja niistä saatavat arvioidut tuotot tuhansina dollareina on merkitty kaupunkia esittävän solmun kohdalle. Pyritään siihen, että matkakustannukset olisivat mahdollisimman pienet, jolloin esimerkki poikkeaa aikaisemmista siinä, että nyt jokaisella solmulla on lukuarvona siitä saatava tuotto. Tässä 4
Lincoln, 1 2.8.6 4.6 Wichita,2.1 4. Little Rock, Davenport 1,6 2 1.7 4 4. Springfield 1,. Chattanooga, 4.6 6 2.1.8 2.4 Jackson 1, 7 2.6 8 Montgomery 1, 4. 2.2 Tallahassee, 9 Kuva 4: Sirkuskiertueen reittimahdollisuudet tapauksessa saadaan suuntaamaton verkko, mutta jotta voidaan mallintaa solmuissa saatavat tuotot, täytyy aluksi muuntaa se suunnatuksi korvaamalla jokainen kaari kahdella suunnatulla nuolella. Koska kussakin solmussa voidaan käydä vain kerran, ei molempia 2.6.6 1.7 1.7 1 4.6 4.6 4.. 6 2.4 2.4 8 2.8 2.8.1.1 4. 4. 4.6 4.6.8.8 2.6 2.6 2.2 2.2 4. 4. 2.1 2.1 7 4. 4. 9 Kuva : Sirkusesimerkin suunnattu verkko solmujen i ja j välisiä nuolia voida reitissä käyttää. Nyt solmujen tuotot voidaan mallin-
taa jakamalla kukin solmu i kahdeksi solmuksi i 1 ja i 2. Solmuun i 1 pantaisiin tulemaan kaikki solmuun i tulevat nuolet ja solmusta i 2 lähtemään kaikki solmusta i lähtevät nuolet. Solmusta i 1 solmuun i 2 pantaisiin vielä kulkemaan nuoli, jonka painona olisi solmusta i saatavan tuoton vastaluku. Yksinkertaisempi tapa on kuitenkin vähentää kustakin solmusta i lähtevän nuolen painosta solmusta i saatava tuotto. 2.6 2..2.1 1 4.6.1 4 4. 2. 6.8.9 8.42.8 2..6 1.. 1.6 1.6 2.8.8 1.6 1.1 2.2.7 1. 1..9 1.1 7. 4. 9 Kuva 6: Sirkusesimerkin suunnattu verkko Vaikka tässä vähennetäänkin tuotto kaikista solmusta i lähtevistä nuolista, on huomattava, että kussakin polussa voi esiintyä korkeintaan yksi näistä. Verkko on nyt suunnattu ja myös negatiiviset painot ovat mahdollisia. Tavoitteena on määrätä lyhin reitti aloitussolmusta s solmuun k. Olkoon nyt tehtävänä määrätä lyhin tie solmusta s solmuun k suunnatussa verkossa. Otetaan käyttöön päätösmuuttuja { 1, jos optimireitti kulkee nuolta (i, j) pitkin x ij =, muuten. Ongelmasta saadaan binäärinen optimointitehtävä min s. t. i, j, (i,j) E i, (i,l) E c ij x ij x il j, (l,j) E x ij {, 1}, (i, j) E, 1, kun l = k x lj = 1, kun l = s, muulloin 6
mutta voidaan osoittaa, että sen kanssa identtisen ratkaisun tuottaa helpommin ratkaistava lineaarinen tehtävä min s. t. i, j, (i,j) E i, (i,l) E c ij x ij x il j, (l,j) E x ij, (i, j) E. 1, kun l = k x lj = 1, kun l = s, muulloin Tämä johtuu siitä, että kerroinmatriisi on nyt erikoista muotoa ja Simplex-algoritmissa jaetaan vain ykkösellä. Siksi ratkaisun täytyy olla kokonaisluku, ja ainoat mahdollisuudet ovat x ij = tai x ij = 1, joten erityistä kokonaislukuvaatimusta ei tarvita. Kun lasketaan kaikki varsinaiset rajoitukset yhteen, saadaan identiteetti =, joten ainakin yksi rajoituksista on muista riippuva ja voidaan poistaa. Voidaan osoittaa, että tasan yhden rajoituksen poistaminen riittää. Tehtävän duaali on max v k v s s. t. v j v i c ij, (i, j) E ja sitä käytetään ratkaisualgoritmeissa tehokkaasti hyväksi. Koska rajoituksista yksi oli muista riippuva, on myös yksi duaalimuuttujista muista riippuva ja usein valitaankin v s = ja ratkaistaan muut. Suure v i esittää silloin lyhimmän tien pituutta solmusta s solmuun i. 1.2 Lyhimmät tiet dynaamisella optimoinnilla Dynaaminen optimointi on menettely, jossa yksittäinen ongelma, kuten lyhin tie kiinnitetystä lähtösolmusta kiinnitettyyn tulosolmuun, ratkaistaan osana laajempaa ongelmaa, jossa selvitetään lyhimmät tiet lähtösolmusta kaikkiin solmuihin. Ratkaisu tapahtuu rakentamalla lyhintä tietä vaiheittain. Jos tarvitaan lyhimmät tiet kaikkiin solmuihin, käytetään seuraavia merkintöjä: v[k]: lyhimmän tien pituus lähtösolmusta solmuun k. Jos tällaista polkua ei ole olemassa, merkitään v[k] =, x ij [k] = { 1, jos optimireitti solmuun k kulkee nuolta (kaarta) (i, j) pitkin, muuten. Mikäli halutaankin lyhimmät tiet kaikista solmuista kaikkiin solmuihin, niin 7
v[k, l]: lyhimmän tien pituus solmusta k solmuun l. Jos tällaista polkua ei ole olemassa, merkitään v[k, l] =, x ij [k, l] = { 1, jos optimireitti solmusta k solmuun l kulkee nuolta (i, j) pitkin, muuten. Esimerkin 1.2 kuorma-auto-ongelmassa kulkee lyhin tie 8 7 1 Ft. Worthista Corpus Christiin Austinin ja San Antonion kautta. Jos nyt olisi lyhempi tie Ft. Worthista San Antonioon kuin äskeisen reitin käyttämä, niin jatkamalla siitä Corpus Christiin saataisiin optimaalista reittiä lyhyempi reitti. Optimireitin osat ovat siis varmasti optimaalisia, jos kaikki painot ovat ei-negatiivisia. Negatiiviset painot tuottavat vaikeuksia silloin, kun verkossa on sykli, jonka pituus on negatiivinen. v 1 v 2 2 1 2 1 2 4 12 v v 4 17 Kuva 7: Verkko, jossa negatiivinen sykli Esimerkki 1.4. Kuvan 7 verkossa lyhin tie solmusta 1 solmuun on 1 2. Kuitenkaan 1 2 ei ole optimireitti solmusta 1 solmuun 2 vaan se on 1 4 2. Kun tästä yritetään saada optimireittiä jatkamalla solmusta 2 solmuun, niin saadaan 1 4 2 ja tullaan solmuun toisen kerran eli saadaan sykli. Kun tästä reitistä jätetään pois sykli, jää jäljelle reitti 1, mutta sen pituus on 1 eikä se ole optimaalinen. Ongelmana on negatiivinen sykli 2 4 2, jonka pituus on + 12 2 = 1. Huomautus 1.. Mikäli verkossa on negatiivisia syklejä, lyhimmän tien määrääminen vaikeutuu oleellisesti. Oletetaan toistaiseksi ettei negatiivisia syklejä ole. Määritelmä 1.6. Dynaamisen optimoinnin optimaalisuusperiaate: jos lyhin tie s k kulkee solmun i kautta, niin se osa siitä, joka kulkee solmusta s solmuun i, on lyhin tie s i. Nyt saadaan rekursiiviset funktionaaliyhtälöt v[s] = v[k] = min i {v[i] + c ik (i, k) E}, k s, 8
joiden avulla lyhimmät reitit solmusta s solmuun k konstruoidaan optimaalisista reiteistä solmun k edeltäjäsolmuihin. Jos yhtään nuolta (i, k) E ei ole olemassa, sovitaan, että v[k] =. Kuorma-autoesimerkissä 1.2 lyhin reitti San Antonioon (solmu j = 7) on v[7] = min{v[6] + c 67, v[8] + c 87, v[9] + c 97, v[1] + c 1,7 } = min{v[6] + 21, v[8] + 79, v[9] + 199, v[1] + 1}. Lause 1.7. Kun verkossa ei ole negatiivisia syklejä, niin arvot v[k] ovat lyhimpien reittien pituuksia solmusta s solmuun k silloin ja vain silloin kun ne toteuttavat yllä olevat funktionaaliyhtälöt. Todistus. Ensin osoitetaan, että v[k] on jonkin reitin pituus. Nyt ja tässä v[k] = min{v[i] + c ik (i, k) E} = v[k p ] + c kp k i v[k p ] = min i {v[i] + c ikp (i, k p ) E} = v[k p 1 ] + c kp 1 k p. Sijoitetaan viimeksi saatu tulos edelliseen, josta seuraa Näin jatkaen lopulta v[k] = v[k p 1 ] + c kp 1 k p + c kp k. v[k] = v[s] + c sk1 + c k1 k 2 +... + c kp 1 k p + c kp k = c sk1 + c k1 k 2 +... + c kp 1 k p + c kp k, joten v[k] on polun s k 1 k 2... k p k pituus. Tarkastellaan sitten jotakin toista reittiä s l 1 l 2... l q k, jolloin funktionaaliyhtälöistä seuraa, että v[l 1 ] v[s] + c sl1. v[l 2 ] v[l 1 ] + c l1 l 2 Laskemalla nämä yhteen saadaan v[l q ] v[l q 1 ] + c lq 1 l q v[k] v[l q ] + c lqk. v[k] v[s] + c sl1 + c l1 l 2 +... + c lq 1 l q + c lqk = c sl1 + c l1 l 2 +... + c lq 1 l q + c lqk, joten tämän reitin pituus ei voi olla pienempi kuin v[k]. Mikäli halutaan lyhimmät tiet kustakin solmusta kuhunkin solmuun, muuttuvat funktionaaliyhtälöt muotoon v[k, k] =, k v[k, l] = min{c kl, {v[k, i] + v[i, l] i k, l}}, k l. 9
1. Lyhimmät tiet jostakin solmusta kaikkiin muihin Ratkaistaessa edellisen kohdan funktionaaliyhtälöitä tulee ongelmia silloin, kun verkossa on syklejä. Esimerkiksi jos siinä on sykli 1 2 1, niin saadaan laskukaavat v[1] = min{v[] + c 1,...} v[2] = min{v[1] + c 12,...} v[] = min{v[2] + c 2,...}, joista ei suoraan saada mitään irti. Bellman-Ford -algoritmilla voidaan kuitenkin määrätä lyhimmät tiet, jos negatiivisia syklejä ei ole. Siinä iteroidaan arvoja v[k] ja merkitään vaiheessa t saatua arvoa suureella v t [k]. Kun muutoksia ei tapahdu, saadaan optimaaliset arvot. Algoritmi 1.8. Bellman-Ford: lyhimmät tiet solmusta kaikkiin muihin Askel. Kun lähtösolmu on s, alustetaan etäisyydet. { v, kun k = s [k], muutoin. ja kierroslaskuri t 1. Askel 1. Kullekin solmulle k Q, k s lasketaan v t [k] min i {v t 1 [i] + c ik (i, k) E} = v t 1 [l] + c lk. Mikäli v t [k] < v t 1 [k], niin asetetaan d[k] l. Askel 2. Lopetetaan, jos v t [k] = v t 1 [k] jokaiselle solmulle k tai mikäli t on verkon solmujen lukumäärä. Edellisessä tapauksessa ilmoittavat arvot v t [k] optimaalisten reittien pituudet solmuihin k ja jälkimmäisessä tapauksessa on verkossa negatiivinen sykli. Askel. Päivitetään kierroslaskuria t t + 1 ja palataan askeleeseen 1. Algoritmin tuottama d[k] ilmoittaa solmua k edeltävän solmun lyhimmällä tiellä solmusta s solmuun k. Esimerkki 1.9. Kun sovelletaan Bellman-Ford -algoritmia sirkusesimerkkiin 1., saadaan lyhimpien teiden pituudet 1
t v t [1] v t [2] v t [] v t [4] v t [] v t [6] v t [7] v t [8] v t [9] 1.6 2.8 4.6 2.6 2.8.7 4.1 8.6.6 2.8.7 4.1.7.2 8. 4.6 2.8.7 4.1.7.2 4.8 6.7.6 2.8.7 4.1.7.2 4.8. 6.6 2.8.7 4.1.7.2 4.8. sekä solmujen optimaaliset edeltäjät t d[1] d[2] d[] d[4] d[] d[6] d[7] d[8] d[9] 1-1 1 1 - - - - - 2-1 1 2 4 - - - - 1 1 2 6-4 - 1 1 2 7 7-1 1 2 7 8 6-1 1 2 7 8 Kuvassa 8 on esitetty saadut optimireitit. 2.6.1 1 4 6 8 2.8 1.6 1.6.7 1..9 7 9 Kuva 8: Sirkusesimerkin optimireitit Jos se olisi ratkaistu luvussa 1.1 esitettynä lineaarisena optimointitehtävänä, olisi saatu optimireitti x 1 = x = x 7 = x 78 = x 89 = 1 sekä lisäksi degeneroituneet kantamuuttujat x 12 = x 24 = x 6 =. 11
Kun Bellman-Ford -algoritmista on suoritettu t vaihetta, saadaan lyhimpien teiden pituudet korrektisti niihin solmuihin, joihin pääsemiseksi tarvitaan korkeintaan t kaarta. Koska n solmuisessa verkossa olevassa polussa voi olla korkeintaan n 1 kaarta, voitaisiin lopettaa n 1 vaiheen jälkeen, jos negatiivisia syklejä ei ole. Mikäli verkossa on negatiivinen sykli, muuttuvat algoritmin antamat etäisyydet vielä vaiheessa n. Esimerkki 1.1. Sovellettaessa kuvan 7 negatiivisen syklin sisältäneeseen esimerkkiverkkoon Bellman-Ford -algoritmia, saadaan t v t [1] v t [2] v t [] v t [4] 1 2 1 2 2 22-17 4-8 17 t d[1] d[2] d[] d[4] 1-1 1-2 - 1 2-4 2 4-4 2 Algoritmi jää pyörimään negatiivisessa syklissä pienentäen siihen kuuluvien solmujen etäisyyksiä rajattomasti. Negatiivinen sykli saadaan konstruoitua vaiheessa n saaduista edeltäjäsolmuista, kun valitaan jokin siinä etäisyyttään muuttanut solmu ja selvitetään sen edeltäjä, edeltäjän edeltäjä jne. Esimerkissä solmujen 2 ja etäisyydet muuttuivat vaiheessa 4. Nyt d[2] = 4, d[4] = ja d[] = 2, joten negatiivinen sykli on 2 4 2. 1.4 Lyhimmät tiet kaikkien solmuparien välillä Kun halutaan esimerkin 1.1 tapaan lyhimmät tiet jokaisesta solmusta jokaiseen solmuun, voidaan käyttää Floyd-Warshall -algoritmia, jossa konstruoidaan optimireittejä kasvattaen välisolmujen määrää joka vaiheessa. Numeroidaan solmut perättäisillä kokonaisluvuilla alkaen numerosta 1 ja merkitään v t [k, l]: lyhimmän tien pituus solmusta k solmuun l, kun välisolmuina ovat solmut 1,..., t. d[k, l]: solmun l edeltäjäsolmu nykyisellä reitillä solmusta k solmuun l. Tällöin on luonteva valita v [k, l] = c kl. 12
Algoritmi 1.11. Floyd-Warshall: etäisyydet kaikkien solmuparien välillä Askel. Numeroidaan solmut ykkösestä alkaen ja asetetaan kaikille kaarille (k, l) E v [k, l] c kl d[k, l] k. Mikäli kaarta (k, l) ei ole verkossa v [k, l] {, jos k = l, muulloin. Asetetaan vielä kierroslukuindeksiksi t 1. Askel 1. Kaikille solmuille k, l t päivitetään v t [k, l] min{v t 1 [k, l], v t 1 [k, t] + v t 1 [t, l]}. Mikäli v t [k, l] < v t 1 [k, l], niin asetetaan d[k, l] d[t, l]. Askel 2. Lopetetaan, jos t on verkon solmujen määrä tai v t [k, k] < jossakin solmussa k. Edellisessä tapauksessa ilmoittavat viimeksi saadut suureet v t [k, l] lyhimmät etäisyydet ja jälkimmäisessä tapauksessa on verkossa solmun k kautta kulkeva negatiivinen sykli. Askel. Kasvatetaan kierroslaskuria t t + 1 ja palataan askeleeseen 1. Kun algoritmista on suoritettu t kierrosta, on saatu lyhimmät etäisyydet, joissa välisolmuina ovat solmut 1,..., t. Optimireitit saadaan taas takaperoisessa järjestyksessä käyttäen talletettuja edeltäjäsolmuja d[k, l]. Esimerkki 1.12. Sovellettaessa Floyd-Warshall algoritmia esimerkin 1.1 ratkaisuun saadaan alkuarvot solmujen 1
etäisyyksille v [k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1 12 k = 2 18 2 k = 1 k = 4 8 k = 2 18 k = 6 2 18 28 2 k = 7 28 21 49 k = 8 18 6 k = 9 2 21 6 4 k = 1 49 28 4 edeltäjille d[k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1-1 - - - - - - - - k = 2 - - 2 - - 2 - - - - k = - - - - - - - - k = 4 - - - - - - - - - 4 k = - - - - - - - - k = 6-6 - - 6-6 - 6 - k = 7 - - 7 - - 7 - - 7 7 k = 8 - - - - 8 - - - 8 - k = 9 - - - - - 9 9 9-9 k = 1 - - - - - - 1 1 1 - sekä vaiheen t = 1 jälkeen reittien pituudet v 1 [k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1 12 k = 2 18 2 k = 1 k = 4 8 k = 2 2 18 k = 6 2 18 28 2 k = 7 28 21 49 k = 8 18 6 k = 9 2 21 6 4 k = 1 49 28 4 14
ja viimeisen solmun edeltäjät d[k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1-1 - - - - - - - - k = 2 - - 2 - - 2 - - - - k = - - - - - - - - k = 4 - - - - - - - - - 4 k = 1 - - - - - - - k = 6-6 - - 6-6 - 6 - k = 7 - - 7 - - 7 - - 7 7 k = 8 - - - - 8 - - - 8 - k = 9 - - - - - 9 9 9-9 k = 1 - - - - - - 1 1 1 - Vaiheen t = 9 jälkeen ovat viimein etäisyydet v 9 [k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1 12 4 62 44 6 1 69 81 k = 2 7 18 1 2 48 9 7 69 k = 96 9 1 76 8 87 1 1 k = 4 8 k = 2 2 6 18 46 79 4 8 k = 6 8 2 6 18 28 61 2 6 k = 7 66 6 4 46 28 7 21 49 k = 8 8 68 81 18 6 7 6 76 k = 9 6 7 1 64 4 2 21 6 4 k = 1 66 78 79 92 46 64 49 28 4 ja edeltäjät d[k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1-1 2 6 2 9 6 4 k = 2-2 6 2 9 6 4 k = 6-6 7 9 7 4 k = 4 - - - - - - - - - 4 k = 1 2-6 9 6 9 k = 6 6 2 6-6 9 6 9 k = 7 6 7 6 7-9 7 7 k = 8 1 2 8 9-8 9 k = 9 6 7 6 9 9 9-9 k = 1 1 7 8 1 1 1-1
Viimeisessä vaiheessa t = 1 saadaan optimireitin pituudet v 1 [k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1 12 4 62 44 6 1 69 81 k = 2 7 18 1 2 48 9 7 69 k = 96 9 1 76 8 79 1 1 k = 4 14 116 117 84 12 87 66 78 8 k = 2 2 6 18 46 79 4 8 k = 6 8 2 6 18 28 61 2 6 k = 7 66 6 4 46 28 7 21 49 k = 8 8 68 81 18 6 7 6 76 k = 9 6 7 1 64 4 2 21 6 4 k = 1 66 78 79 92 46 64 49 28 4 ja optimaaliset edeltäjäsolmut d[k, l] l = 1 l = 2 l = l = 4 l = l = 6 l = 7 l = 8 l = 9 l = 1 k = 1-1 2 6 2 9 6 4 k = 2-2 6 2 9 6 4 k = 6-6 7 1 7 4 k = 4 1 7-8 1 1 1 4 k = 1 2-6 9 6 9 k = 6 6 2 6-6 9 6 9 k = 7 6 7 6 7-9 7 7 k = 8 1 2 8 9-8 9 k = 9 6 7 6 9 9 9-9 k = 1 1 7 8 1 1 1 - Solmujen ja 8 välisen optimireitin pituus on 79 ja se itse reitti on 4 1 8, sillä d[, 8] = 1, d[, 1] = 4, d[, 4] =. Esimerkki 1.1. Kun sovelletaan Floyd-Warshall algoritmia negatiivisen syklin sisältävään esimerkkiin 1.4, niin kahdessa ensimmäisessä vaiheessa t = ja t = 1 v t [k, l] l = 1 l = 2 l = l = 4 k = 1 2 1 k = 2 k = 12 k = 4-2 16
d[k, l] l = 1 l = 2 l = l = 4 k = 1-1 1 - k = 2 - - 2 - k = - - - k = 4-4 - - ja sen jälkeen saadaan v 2 [k, l] l = 1 l = 2 l = l = 4 k = 1 2 k = 2 k = 12 k = 4-2 -22 d[k, l] l = 1 l = 2 l = l = 4 k = 1-1 2 - k = 2 - - 2 - k = - - - k = 4-4 2 - sekä v [k, l] l = 1 l = 2 l = l = 4 k = 1 2 17 k = 2 1 k = 12 k = 4-2 -22-1 d[k, l] l = 1 l = 2 l = l = 4 k = 1-1 2 k = 2 - - 2 k = - - - k = 4-4 2 Nyt v [4, 4] min{, v 2 [4, ] + v 2 [, 4]} = min{, 22 + 12} = 1, joten verkossa on negatiivinen sykli. Se on 4 2 4, sillä d[4, 4] =, d[4, ] = 2, d[4, 2] = 4. 1. Etäisyydet solmusta muihin ei-negatiivisten painojen tapauksessa Kun oletetaan, että kaikki painot ovat ei-negatiivisia, voidaan tehostaa selvästi aikaisempia algoritmeja ja saadaan Dijkstran algoritmi 17
Algoritmi 1.14. Dijkstra: etäisyys solmusta muihin kun painot ei-negatiivisia Askel. Kun alkusolmuna on s, asetetaan { v[i], jos i = s, muulloin. Merkitään kaikkien solmujen etäisyydet väliaikaisiksi ja kiinnitetään seuraavaksi solmun p s etäisyys. Askel 1. Merkitään solmu p kiinnitetyksi ja jokaiselle siitä kiinnittämättömään solmuun i lähtevälle kaarelle (p, i) päivitetään etäisyydet v[i] min{v[i], v[p] + c pi }. Jos v[i] arvo muuttui, asetetaan d[i] p. Askel 2. Jos väliaikaisia solmuja ei enää ole, lopetetaan. Arvot v[i] ilmoittavat lyhimmät etäisyydet solmuun i. Askel. Kiinnitetään seuraavaksi solmu p, jonka väliaikainen etäisyys on pienin ts. v[p] = min{v[i] i väliaikainen} ja palataan askeleeseen 1. Dijkstran algoritmissa käsitellään kukin solmu vain kerran eikä kiinnitetyn solmun etäisyyttä alkusolmusta enää muuteta. Jokaisen iteraatiokierroksen jälkeen Dijkstran algoritmin tuottamat v[i] arvot ilmoittavat kiinnitettyjä solmuja käyttävien reittien lyhimmät etäisyydet solmuun i. Solmujen kiinnitysjärjestys on järkevä, sillä jos solmuun p johtaa useampia polkuja, täytyy pelkästään kiinnitetyistä solmuista koostuvan olla niistä lyhin. Muut polut sisältävät ensin solmusta s kiinnitettyjä solmuja ja ensimmäisenä kiinnittämättömänä solmuna i, josta kiinnittämättömiä solmuja solmuun p. Polun alkuosan pituudelle v[i] on solmun p valinnan nojalla voimassa v[i] v[p] ja nuolten pituuksien ei-negatiivisuudesta seuraa, että loppuosan pituus on ei-negatiivinen. Esimerkki 1.1. Kun ratkaistaan Dijkstran algoritmilla esimerkkiä 1.2, saadaan p v[1] v[2] v[] v[4] v[] v[6] v[7] v[8] v[9] v[1] - 9 18 19 246 9 47 62 18 272 19 246 8 9 47 62 18 272 274 19 246 9 9 47 62 18 272 274 19 246 461 6 9 47 62 18 272 274 19 246 461 7 9 47 62 18 272 274 19 246 427 2 9 47 62 18 272 274 19 246 427 1 9 47 62 18 272 274 19 246 427 1 9 47 62 18 272 274 19 246 427 4 9 47 62 18 272 274 19 246 427 18
ja p d[1] d[2] d[] d[4] d[] d[6] d[7] d[8] d[9] d[1] - - - - - - - - - 8-8 - 9-8 9 6-8 9 7-8 7 2-8 7 1-8 7 1-8 7 4-8 7 Viimeinen rivi etäisyystaulukosta esittää optimaalisia etäisyyksiä solmuihin ja reitit saadaan taas viimeisestä edeltäjärivistä. Esimerkiksi lyhimmän tien pituus solmusta s = solmuun i = 1 on 427 ja se on 8 7 1, sillä d[1] = 7, d[7] = 8, d[8] =. 1.6 Lyhimmät tiet solmusta muihin syklittömässä verkossa Jos oletetaan, ettei verkossa ole syklejä, voidaan edellen tehostaa lyhimpien teiden määräämistä. Suuntaamattomassa verkossa ei päästä syklittömyyteen, joten oletaan nyt, että verkko on suunnattu. Pienestä verkosta voidaan helposti tarkastaa milloin se on syklitön, mutta suunnattu verkko on yleisesti syklitön, mikäli sen solmut voidaan numeroida niin, että jokaiselle nuolelle (i, j) on voimassa i < j. Tällainen numerointi saadaan aikaan verkon solmujen syvyyshaulla, jossa numeroidaan vähenevään numerojärjestykseen yksi kerrallaan sellaisia solmuja, joista lähtevät nuolet johtavat jo käsiteltyihin solmuihin tai niitä ei ole ollenkaan. a b c d e Kuva 9: Esimerkin 1.16 verkko Esimerkki 1.16. Tarkastellaan kuvan 9 verkkoa, joka käsittää viisi solmua. Lähdetään nyt liikkeelle solmusta a. Sen seuraaja on solmu b, josta ei lähde yhtään solmua. Sen vuoksi solmu b voidaan numeroida solmuksi. Peruutetaan takaisin solmuun a, jolla 19
on toinen seuraaja d. Sen seuraajista solmu b on numeroitu joten mennään solmuun e, jonka ainoa seuraaja b on jo numeroitu. Solmu e numeroidaan solmuksi 4 ja peruutetaan solmuun d, jonka kaikki seuraajat on numeroitu. Sen järjestysnumeroksi asetetaan ja peruutetaan lähtösolmuun a sekä annetaan sille numero 2. Seuraavaksi täytyy valita jokin vielä numeroimaton solmu, josta menettelyä jatketaan. Ainoa mahdollisuus on nyt solmu c, jonka järjestysnumeroksi tulee 1. Kun syklejä ei nyt ole, voidaan solmujen etäisyydet määrätä järjestyksessä solmusta 1 alkaen ja ne saadaan kerralla kuntoon, koska solmuun funktionaaliyhtälön mukaisesti tulevat nuolet tulevat jo käsitellyistä solmuista. Algoritmi 1.17. Lyhimmät tiet syklittömässä verkossa Askel. Numeroidaan verkon solmut niin, että jokaiselle nuolelle (i, j) E on voimassa i < j. Asetetaan vielä v[s]. Askel 1. Lopetetaan, kun kaikki etäisyydet v[k] on määrätty. Muuten asetetaan indeksin p arvoksi pienin käsittelemättömän solmun numero. Askel 2. Jos solmuun p ei tule nuolia, asetetaan v[p]. Muuten lasketaan v[p] min{v[i] + c ip (i, p) E} = v[l] + c lp i ja asetetaan d[p] l. Palataan askeleeseen 1. 2 4 7 1 1 1 8 8 9 16 12 6 18 1 4 7 9 Kuva 1: Esimerkin 1.18 syklitön verkko Esimerkki 1.18. Sovelletaan algoritmia 1.17 kuvan 1 syklittömään verkkoon ja saadaan tulokseksi p 1 2 4 6 7 8 9 v[p] - 7 9 22 14 d[p] - 1 2-2 7 4 2
1.7 Projektin valvonta ja pisimmät tiet Suurten projektien kokonaishallinta on hankalaa, ja sitä varten ne kannattaa jakaa osaprojekteiksi eli töiksi, joista tiedetään niitä välittömästi edeltävät työt ja pystytään arvioimaan kestot. Ennen kuin työ voidaan aloittaa, täytyy kaikkien sen edeltäjätöiden olla valmiiksi suoritettuja. Ensisijainen kiinnostuksen kohde on koko projektin minimaalinen kesto sekä kunkin osatyön aikaisimmat ja myöhäisimmät mahdolliset aloitusajat, kun projekti toteutetaan mahdollisimman nopeasti. Samaten olisi kiinnostava saada informaatiota siitä, miten osaprojektien mahdolliset myöhästymiset vaikuttavat koko projektin kestoon. Oletetaan yksinkertaisuuden vuoksi, että projektin suoritus aloitetaan hetkellä t =. Esimerkki 1.19. Omakotitalon rakentamisessa ovat osatöitä seuraavan taulukon mukaiset työt. k työ kesto edeltäjät 1 perustukset 1-2 kunnallistekniikka - valutyöt 4 1,2 4 runkotyöt katto 7 4 6 sähkötyöt 1 4 7 lämmitys ja ilmastointi 1 2, 4 8 seinät 18 4, 6, 7 9 sisäpuolen viimeistely 2, 8 Näistä tiedoista täytyisi päätellä milloin aliurakoitsijoita ja mitäkin tavaraa kannattaa hankkia paikalle. Nyt ei ole valmiina mitään verkkoa, vaan sellainen täytyy muodostaa edeltäjätiedoista. Yksi tapa on esittää kutakin osatyötä suunnattuna nuolena, jonka paino on työn kesto. Solmut esittävät silloin töiden alkamis- ja loppumistapahtumia ja nuolien järjestyksellä voidaan hoitaa edeltäjärelaatiot kuntoon. Tässä tarvitaan kuitenkin usein aputöitä, joiden kestot ovat nollia. Yllä olevasta taulukosta huomataan, että työn 7 edeltäjänä työ 2 on turha, koska työn 7 edeltäjä on 4, työn 4 edeltäjä työ ja työn edeltäjä työ 2. Samoin on työn 8 edeltäjänä työ 4 turha. Kun nämä jätetään pois saadaan kuvan 11 syklitön projektiverkko, joka on muodostettu niin, ettei minkään solmuparin välillä ole rinnakkaisia nuolia. Aputyöt on merkitty katkoviivoin. 21
1 2 7 6 8 4 9 Kuva 11: Esimerkin 1.19 projektiverkko Paljon helpompaa on muodostaa verkko, jossa on alkusolmu, loppusolmu ja yksi solmu kullekin työlle. Jos työ i edeltää työtä j pistetään verkkoon kulkemaan suunnattu nuoli (i, j) ja asetetaan sen painoksi työn i kesto. Alkusolmusta s pistetään painoltaan nollan suuruinen nuoli jokaiseen solmuun, jolla ei ole edeltäjiä. Jos solmu i ei ole minkään työn edeltäjä, pistetään siitä nuoli loppusolmuun ja sen painoksi taas työn i paino. Tässä ei haittaa, vaikka edeltäjätöiden joukko ei olisikaan minimaalinen. Esimerkin 1.19 rakennusprojektista saadaan esimerkiksi kuvan 12 suunnatun verkon, joka taas on syklitön. Työn k aikaisin aloitushetki on nyt pisimmän tien pituus solmusta s solmuun k. Koko projektin kesto on pisimmän tien pituus alkusolmusta s loppusolmuun. Tätä polkua kutsutaan kriittiseksi poluksi, koska sillä olevien töiden viivästyminen viivästyttää koko projektia. 1 6 7 1 4 4 1 9 2 1 18 2 8 1 7 Kuva 12: Projektiverkko ilman rinnakkaisia nuolia Työt kannattaa numeroida ykkösestä lähtien niin, että edeltäjätyöllä on aina seuraajaa pienempi järjestysnumero. Oletetaan, että töitä on kaikkiaan n, jolloin verkon alkusolmu on ja loppusolmu n + 1. Kun merkitään solmua i vastaavan työn kestoa eli nuolen (i, j) painoa a i ja otetaan käyttöön päätösmuuttujat { 1, jos kriittinen polku kulkee nuolta (i, j) pitkin x ij =, muuten, 22
niin saadaan lineaarinen optimointitehtävä max a i x ij s. t. Sen duaalisessa tehtävässä (i,j) E x ik i j x ij, (i, j) E. min v n+1 v 1, kun k = n + 1 x kj = 1, kun k =, muulloin s. t. v j v i a i, (i, j) E voidaan taas valita yksi duaalimuuttuja mielivaltaisesti, jolloin kannattaa ottaa v =. Tällöin v i on pisin etäisyys alkusolmusta solmuun i. Saadaan algoritmi Algoritmi 1.2. Projektin töiden aikaisimmat aloitushetket Askel. Numeroidaan projektiverkon solmut kokonaisluvuin, 1,..., n + 1 niin, että verkon jokaiselle nuolelle (i, j) on i < j. Annetaan vielä aloitushetkelle arvo v[] ja p 1. Askel 1. Lopetetaan, kun p > n + 1. Askel 2. Määrätään työn p aikaisin aloitushetki v[p] max i p 1 {v[i] + a i (i, p) E} = v[l] + a l ja edeltäjä d[p] l. Kasvatetaan indeksiä p p + 1 ja palataan askeleeseen 1. Esimerkki 1.21. Rakennusesimerkissä 1.19 on 9 työtä ja niiden numerointi on jo valmiiksi kunnossa. Saadaan sillä v[] ja. p 1 2 4 6 7 8 9 1 v[p] 1 19 22 22 22 7 d[p] - 1 4 4 4 7 8 9 v[1] max{v[] + a } = + =, d[1] v[2] max{v[] + a } = + =, d[2] v[] max{v[1] + a 1, v[2] + a 2 } = max{ + 1, + } = 1, d[] 1 Siitä seuraa projektin kesto 7 sekä kriittinen polku 1 4 7 8 9 1, sillä d[1] = 9, d[9] = 8, d[8] = 7, d[7] = 4, d[4] =, d[] = 1, d[1] =. 2
Olkoon nyt projektin valmistumisella määräaika T, johon mennessä sen tulisi olla valmiina ja haluttaisiin tietää osaprojektin k viimeinen mahdollinen aloitusaika l[k], jotta tässä aikataulussa pysyttäisiin. Se saadaan laskemalla pisin tie solmusta k loppusolmuun n + 1 ja vähentämällä saatu arvo ajasta T eli l[n + 1] T l[k] min {l[j] a k (k, j) E}, k = n, n 1,...,. k+1 j n+1 Tässä täytyy määräajan olla vähintään projektin kesto eli T v[n + 1]. Jos määräaikaa T ei ole eksplisiittisesti annettu, käytetään sen arvona projektin kestoa v[n + 1]. Esimerkki 1.22. Jos esimerkissä 1.19 T = 8 ja solmun k seuraaja on r[k], niin ja taulukon muodossa. l[1] 8 l[9] min{8 2} = 6, r[9] 1 l[8] min{6 18} = 42, r[8] 9 k 1 9 8 7 6 4 2 1 l[k] 8 6 42 29 2 26 22 17 7 7 r[k] - 1 9 8 8 9 7 4 1 Erotusta s[k] = l[k] v[k], joka ilmoittaa työn k viimeisen ja aikaisimman aloitushetken erotuksen, kutsutaan pelivaraksi. Sen verran voidaan lykätä työn k aloitusta aikaisimmasta mahdollisesta ilman, että projekti myöhästyy määräajastaan T. Esimerkki 1.2. Rakennusesimerkissä 1.19 pelivarat ovat k 1 2 4 6 7 8 9 s[k] 7 17 7 7 1 1 7 7 7 Pelivarat voidaan myös laskea jokaiselle osatyölle, mutta niitä saadaan erilaisia riippuen siitä, kumpaa tapahtumishetkeä työn päätesolmuille käytetään. Määritellään osatyön i maksimaallinen pelivara s m [i] = min j {l[j] (i, j) E} v[i] a i turvallinen pelivara s t [i] = min j {l[j] (i, j) E} l[i] a i vapaa pelivara s f [i] = min j {v[j] (i, j) E} v[i] a i riippumaton pelivara s r [i] = max{, min j {v[j] (i, j) E} l[i] a i }. 24
Maksimaalinen pelivara saadaan, kun työ loppuu mahdollisimman myöhään ja alkaa mahdollisimman aikaisin. Riippumaton pelivara taas on aika, jonka osatyön suoritus voi viivästyä hidastamatta koko projektia, vaikka sen edeltäjät kestäisivät mahdollisimman kauan ja seuraajat alkaisivat mahdollisimman aikaisin. Aikataulun laatiminen ja resurssien tasaaminen. Nyt voidaan laatia aikataulu, jossa on kunkin työn ajoitus. Voidaan esimerkiksi pyrkiä ajoitukseen, jossa henkilöresurssien tarve pysyy mahdollisimman tasaisena koko ajan. 2 4 2 2 7 1 6 8 6 9 2 7 Kuva 1: Rakennusesimerkin suunnattu verkko Esimerkki 1.24. Kuvan 1 projektin töiden i kestot a i ja työvoimatarpeet h i ovat i 1 2 4 6 7 8 a i 2 7 2 6 h i 7 2 2 1 6 Projektin kriittinen polku on 1 8 9 ja kesto v[9] = 19. Oletetaan nyt, että T = 19 eli kriittisellä polulla olevilla töillä ei ole pelivaraa. Jos aloitetaan jokaisen työn suoritus mahdollisimman aikaisin, on aikavälillä [, ) käynnissä työ 1, välillä [, ) työt ja 2, välillä [, 6) työ, välillä [6, 8) työt, 4, 6, 7, välillä [8, 9) työt, 4, 6, välillä [9, 11) työt, 4 välillä [11, 1) työ sekä välillä [1, 19) työ 8. Resurssitarpeet ovat näinä aikoina, 1, 7, 1, 9, 7, 2 ja 6 henkeä. Resurssitarve 2 7 6 1 4 8 t Kuva 14: Resurssitarpeet, kun jokainen työ aloitetaan mahdollisimman aikaisin 2
Jos jokainen työ tehdään niin myöhään kuin mahdollista, on aikavälillä [, ) käynnissä työ 1, välillä [, 4) työ, välillä [4, 6) työt ja 2, välillä [6, 1) työ, välillä [1, 1) työt, 6, välillä [1, 14) työ 8, välillä [14, 17) työt 8, 4 sekä välillä [17, 19) työt 8, 4, 7. Resurssitarpeet ovat näinä aikoina, 7, 1, 2, 4, 6, 11 ja 12 henkeä. Resurssitarve 7 2 4 1 6 8 t Kuva 1: Resurssitarpeet, kun jokainen työ tehdään niin myöhään kuin mahdollista Jälkimmäinen on epätasaisempi, mutta edellistäkin voidaan parantaa siirtämällä työ 6 mahdollisimman myöhään ja työ 7 heti työn 4 jälkeen. Silloin saadaan suunnitelma, jossa tarvitaan koko ajan vähintään henkeä. Resurssitarve 2 6 alku 1 4 6 7 8 t Kuva 16: Resurssitarpeet, kun joka hetkellä tarvitaan vähintään henkeä Jos resursseja ei ole niin paljoa, että niitä riittäisi saadun ratkaisun toteuttamiseen, täytyy joidenkin töiden alkua viivyttää, vaikka tämä johtaisikin koko projektin viivästymiseen. Oletetaan, että töiden kestot ovat kokonaislukuja a i N. Silloin koko projektin kesto on korkeintaan n a i = T i=1 ja tarkastellaan resursseja erikseen kullakin aikavälillä [t 1, t), t = 1,..., T. Oletetaan, että resurssia k on välillä [t 1, t) käytettävissä määrä R kt ja että työn i tekemisessä sitä 26
tarvitaan koko ajan määrä b ik. Kun valitaan päätösmuuttujiksi { 1, kun työ i alkaa hetkellä t, t =, 1,..., T a i x it =, muuten, saadaan optimointitehtävä min s. t. T t= n i=1 T a j t= tx n+1,t b ik t 1 l=max{,t a i } tx jt T a i t= x il R kt, k = 1,..., K, t = 1,..., T tx it a i, T a i x it = 1, i =, 1,..., n + 1 t= (i, j) E x it {, 1}, i =, 1,..., n + 1, t =, 1,..., T 1 x it {, 1}, jos a i =, jossa on valitettavan paljon muuttujia ja rajoituksia ja jonka tarkka ratkaisu on siksi erittäin hankala. Voidaan kuitenkin saada likimääräisiä ratkaisuja seuraavasti. Aina kun jokin työ loppuu, vapautuu resursseja ja meille syntyy päätöksentekotilanne, jossa on valittava jokin tai joitakin töitä tilalle. Mahdollisista töistä, joiden kaikki edeltäjät on suoritettu, valitaan nyt suoritettava työ (i, j) jonkin yksinkertaisen kriteerin mukaan. Tällaisia ovat esimerkiksi valitaan kestoltaan lyhin työ valitaan resurssivaatimuksiltaan pienin työ valitaan työ, jonka myöhäisin aloitushetki on mahdollisimman pieni valitaan työ, jonka pelivara on pienin. Näistä kaksi ensimmäistä eivät vaadi minkäänlaisia etukäteislaskelmia työn kriittisestä polusta yms. mutta ne eivät yleensä tuota kovin hyvää tulosta. Kahden jälkimmäisen kriteerin vaatimat laskelmat voidaan tehdä ennalta tai dynaamisesti ennen jokaista päätöksentekotilannetta verkon suorittamattomalta osalta. Yleisesti pisimmän tien ongelma saadaan muunnetuksi lyhimmän tien ongelmasta muuttamalla minimointioperaatio maksimoinniksi. Ongelmia tuottavat negatiiviset syklit muuntuvat tällöin positiivisiksi sykleiksi ja tällaisia on kaikissa tämän luentomonisteen syklejä käsittävissä esimerkeissä. Onneksi projektiverkot ovat aina syklittömiä ja pisimmän tien määräämiset sujuvat ongelmitta. 27
1.8 Diskreetti dynaaminen optimointi Diskreetit dynaamiset optimointitehtävät voidaan käsittää yleistyksiksi lyhimmän tai pisimmän tien ongelmista ja ne voidaan usein saattaa siihen muotoon konstruoimalla sopiva suunnattu verkko. Dynaamisen optimoinnin perusidea on se, että ongelma jaetaan pienemmiksi osaongelmiksi (vaiheiksi), jotka voidaan ratkaista helpommin kuin alkuperäinen tehtävä. Saadaan siis jono toisistaan riippuvia osatehtävien ratkaisuja (päätöksiä), joista sitten muodostetaan alkuperäisen tehtävän ratkaisu. Laskutoimituksia syntyy paljon ja niiden suorittamiseen ja välitulosten tallentamiseen tarvitaan yleensä tietokonetta. Jo pienissäkin tehtävissä saattaa tarvittava muistitila paisua kovin suureksi, mikä on menetelmän ilmeinen heikkous. Dynaamisessa optimoinnissa ei ole mitään lineaarisen optimoinnin tapaista yleistä matemaattista formulointia. Se on sen sijaan yleisluontoinen lähestymistapa erilaisten tehtävien ratkaisemiseksi ja sen peruskäsitteet ilmenevät eri sovellutuksissa eri tavoin. Siksi dynaaminen optimointi esitetään seuraavassa pääasiassa esimerkkien avulla. Lyhimmän (ja pisimmän) tien määrääminen syklittömässä verkossa luvuissa 1.6 ja 1.7 on itse asiassa dynaamista optimointia. Tehtäville, joita voidaan ratkaista dynaamisella optimoinnilla, on yleensä ominaista seuraavat: 1. Tehtävä voidaan jakaa vaiheisiin, joista kuhunkin liittyy päätös. Lyhimmän tien ongelmassa vaiheena on tutkittava solmu, jonka kaikkien edeltäjien lähtösolmusta määrätyt lyhimmät tiet on jo selvitetty. 2. Jokaisessa vaiheessa on joukko tiloja. Tilojen on kussakin vaiheessa annettava riittävä informaatio päätöksen tekemiseen, eikä tiloista tarvitse tietää miten niihin on jouduttu. Lyhimmän tien ongelmassa mahdollisia tiloja ovat tutkittavaa solmua verkossa välittömästi edeltävät solmut. Nyt kiinnostuksen kohteena ei ole miten näihin solmuihin päästään optimaalisesti lähtösolmusta.. Kunkin vaiheen päätös kuvaa sitä, mihin seuraavan vaiheen tilaan joudutaan kustakin nykyisen vaiheen tilasta. Lyhimmän tien tapauksessa päätös ilmoittaa sen, mistä solmusta on optimaalista tulla tutkittavaan solmuun. 4. Kun nykyinen tila tunnetaan, eivät mitkään jäljellä olevat päätökset voi riippua aikaisemmista tiloista tai päätöksistä. Tämä on dynaamisen optimoinnin optimaalisuusperiaate. Lyhimmän tien ongelmassa se tarkoittaa sitä, että jos lyhin tie s t kulkee solmun i kautta, niin se osa siitä, joka kulkee kaupungista i t on samalla lyhin tie välillä i t.. Täytyy pystyä muodostamaan rekursiorelaatio, jolla kytketään perättäisten vaihei- 28
den kohdefunktiot toisiinsa. Lyhimmän tien ongelmassa tämä relaatio oli v[j] = min{c ij + v[i]}. i Käytännön ongelmissa esiintyy usein jonkin summan maksimointitehtäviä. Silloin pyritään muodostamaan vaiheessa n muotoa f n (x n ) = max y n {g n (x n, y n ) + f n 1 (h(x n, y n ))}, n = 1,..., N oleva dynaamisen optimoinnin rekursioyhtälö, jolla muodostetaan vaiheen n päätös. Tässä y n on päätösmuuttuja, x n tilamuuttuja ja f n (x n ) kohdefunktion arvo tilassa x n, kun vaiheeseen n asti on edetty optimaalisesti. Aaltosuluissa olevan summan ensimmäinen termi on vaiheen n ja jälkimmäinen termi vaiheiden 1,..., n 1 osuus kohdefunktiossa. Vaiheessa n tarvitaan aina edellisen vaiheen rekursiofunktio f n 1 ( ). Optimipäätökset y n määrätään päinvastaisessa järjestyksessä y N,..., y 1 ja niiden esille saamiseksi täytyy lisäksi tallettaa kaikkien vaiheiden päätösfunktiot y n( ), n = 1,..., N, jotka saadaan rekursioyhtälön ratkaisun yhteydessä. Jos vaiheet on muodostettu jakamalla suunnittelukausi osiin, niin voidaan edetä joko ajan mukaan, jolloin puhutaan etenevästä dynaamisesta optimoinnista tai sitä vastaan, jolloin on kyseessä takeneva dynaaminen optimointi. Jälkimmäinen on usein kätevämpi, koska dynaamisessa optimoinnissa meidän täytyy tietää viimeisen vaiheen N tilan x N arvo, joka tällöin on (toivottavasti) tunnettu lähtötilanne. Edellisen tilan x n 1, toimintapäätöksen y n ja nykyisen tilan x n välillä vallitsee relaatio (tilayhtälö) x n 1 = h(x n, y n ), joka täytyy aina pystyä eksplisiittisesti muodostamaan. Rekursiokaava voidaan tulkita seuraavasti: jos systeemin nykyinen tila tunnetaan, optimaaliset toimintapäätökset jäljellä olevissa vaiheissa eivät riipu nykyistä vaihetta aikaisemmista päätöksistä. Tieto siitä, missä tilassa systeemi tällä hetkellä on, sisältää kaiken sen tiedon systeemin aikaisemmasta käyttäytymisestä, joka tarvitaan optimipolitiikan määräämiseksi tästä eteenpäin. Tämä on dynaamisen optimoinnin optimaalisuusperiaate. Esimerkki 1.2. Tarkastellaan optimointitehtävää max s. t. N g i (y i ) i=1 N y i b i=1 y i, i = 1,..., N jossa on yksi rajoitus. Käsitellään ongelmaa yksi muuttuja kerrallaan ja niiden järjestys voi olla mielivaltainen. Yksinkertaisuuden vuoksi valitaan normaali numerojärjestys, joka samalla määrää vaihejaon. Vaiheessa i on siis käsitelty muuttujat y 1,..., y i 1. Päätösmuuttujaksi vaiheessa i valitaan y i ja tilamuuttujaksi x i resurssista b yhteensä tähän 29
mennessä käytetty määrä. Näillä valinnoilla on f i (x i ) = max {g 1(y 1 ) +... + g i (y i )}. y 1 +...+y i x i, y 1,...,y i Huomioimalla, että x i = x i 1 + y i, saadaan rekursioyhtälöksi 1-dimensioiset ongelmat f i (x i ) = max y i x i {g i (y i ) + f i 1 (x i y i )}, x i b, i = 1,..., N. Jotta tämä olisi mielekäs arvolla i = 1, sovitaan, että f ( ). Kohdefunktion optimiarvo on f N (b) ja itse optimipäätökset y i. ovat y N = y N(b) y N 1 = y N 1(b y N) y 1 = y 1(b y N... y 2). Dynaamisella optimoinnilla on nyt palautettu N-dimensioinen optimointitehtävä N yksidimensioisen optimointitehtävän jonoksi. Kukin funktio f i täytyy kyllä ratkaista koko välillä [, b], sillä nyt ei etukäteen tiedä kuinka paljon resurssista b kannattaa uhrata muuttujille y 1,..., y i. Seuraavassa oletaan yleensä, että sekä päätös että tilamuuttujat saavat arvoja diskreetistä joukosta, koska muuten joudutaan vaikeuksiin numeerisessa ratkaisussa. Esimerkki 1.26. Tarkastellaan diskreettiä investointiongelmaa, jossa yhtiöllä on käytettävissä C yksikköä rahaa olemassa olevien N tehtaansa laajentamiseen. Tehtaalla i on m i kappaletta vaihtoehtoisia laajennussuunnitelmia j, jotka vaativat c ij yksikköä pääomaa, ja joista saatava hyöty on r ij, i = 1,..., N, j = 1,..., m i. Oletetaan, että kunkin tehtaan suunnitelma 1 on sellainen, ettei laajenneta ollenkaan, jolloin c i1 = r i1 =. Tehtävänä on nyt määrätä rahoitettavat laajennukset niin, että saatava kokonaishyöty on mahdollisimman suuri, kun kunkin tehtaan laajennuksista toteutetaan korkeintaan yksi. Tehtävä voitaisiin ratkaista käymällä läpi kaikki erilaiset laajennuskombinaatiot, joita on m 1 m 2... m N kappaletta ja valitsemalla pääomarajoituksen toteuttavista kombinaatioista se, joka antaa suurimman kokonaishyödyn. Käsitellään tehtaat yksi kerrallaan ja tilamuuttujana x n olkoon vaiheessa n jakamatta oleva rahamäärä. Silloin saadaan rekursiivinen relaatio f n (x n ) = max j=1,...,m n, c nj x n {r nj + f n 1 (x n c nj )}, x n =, 1,..., C, n = 1,...N. Tässä on taas oletettu, että f ( ). Optimipäätökset talletetaan ja niistä saadaan. j N = j N(C) j N 1 = j N 1(C c Nj N ) j 1 = j 1(C c Nj N... c 2j 2 )
Sovelluksena tarkastellaan tilannetta, jossa N =, m 1 =, m 2 = 4, m = 2, C = 1 j c 1j r 1j c 2j r 2j c j r j 1 2 2 8 1 4 6 6 9 - - 4 - - 8 12 - - Vaiheessa 1 on mukana ainoastaan tehdas 1 ja joudutaan laskemaan funktiot f 1 (x 1 ) ja j1(x 1 ) arvoilla x 1 =, 1,..., 1. Laskelmat voidaan suorittaa taulukon muodossa, jolloin saadaan tulokseksi x 1 r 1j f 1 (x 1 ) j1(x 1 ) j = 1 j = 2 j = - - 1 1 - - 1 2-2 - 2 4 6 6 6 6 6 6 6 7 6 6 8 6 6 9 6 6 1 6 6 Vaiheessa 2 ovat mukana tehtaat 1 ja 2 ja tässä tarvitaan vaiheen 1 funktiota f 1 (x 1 ). Nyt on siis x 2 r 2j + f 1 (x 2 c 2j ) f 2 (x 2 ) j2(x 2 ) j = 1 j = 2 j = j = 4 + - - - 1 1 + - - - 1 2 + - - - 1 + - - - 1 4 +6 - - - 6 1 +6 8+ - - 8 2 6 +6 8+ 9+ - 9 7 +6 8+ 9+ - 1 2 8 +6 8+ 9+ 12+ 14 9 +6 8+6 9+ 12+ 14 2, 1 +6 8+6 9+6 12+ 17 4 1
Tässä on resurssilla 9 kaksi yhtä hyvää päätösvaihtoehtoa, jotka molemmat on otettu mukaan. Näin saadaan kaikki mahdolliset optimiratkaisut, mutta jos tyydytään yhteen, riittää tallettaa yksi päätös. Samoin kuin edellä saadaan edelleen vaiheen taulukko x r j + f 2 (x c j ) f (x ) j(x ) j = 1 j = 2 + - 1 1 + + 2 2 + + 1 + + 8 2 4 +6 + 8 2 +8 +6 9 2 6 +9 +8 11 2 7 +1 +9 1 1 8 +14 +1 16 2 9 +14 +14 17 2 1 +17 +14 17 1,2 Taulukon viimeiseltä riviltä saadaan kohdefunktion optimiarvoksi 17 ja vaiheen optimaaliseksi päätökseksi joko j = 1 tai j = 2. Jos valitaan suunnitelma j = 1, niin taulukoista 2 ja 1 seuraa, että j2 = 4 ja j1 = 2. Jos taas on j = 2, niin saadaan joko j2 = 2 ja j1 = tai j2 = ja j1 = 2. Tehtävällä on siis vaihtoehtoista optimiratkaisua. Niistä j1 = 2, j2 = ja j = 2 on siinä mielessa paras, että se kuluttaa vain 9 yksikköä rahaa. Se, että yhtä hyvä tulos voidaan saavuttaa tuhlaamatta koko käytettävissä olevaa rahamäärää näkyy taulukon toiseksi viimeiseltä riviltä. Varsinaisen tehtävän ratkaisemiseksi riittäisi laskea taulukosta vain viimeinen rivi, mutta muut rivit antavat hyödyllistä herkkyysanalyysin kaltaista tietoa siitä, miten ratkaisu muuttuu kun resursseja vähennetään. Kun lasketaan taulukko täydellisenä, saadaan siis ratkaistuksi tehtävä kaikille arvoille C =, 1,..., 1. Esimerkki 1.27. Tarkastellaan esimerkin 1.26 yleistyksenä resurssinjakamisongelmaa max s. t. N R i (y i ) i=1 N H i (y i ) M i=1 y i N, i = 1,..., N yhden rajoituksen tapauksessa. Tässä oletetaan, että jokainen H i (y i ) on ei-vähenevä funktio ja H i () =, i = 1,..., N. Kuten edellä, saadaan muotoa f i (x i ) = max y i N, H i (y i ) x i {R i (y i ) + f i 1 (x i H i (y i ))}, i = 1, 2,..., N 2
oleva rekursioyhtälö, jonka ratkaisu taas on yn = yn(m) yn 1 = yn 1(M H N (yn)). y1 = y1(m H N (yn)... H 2 (y2)). Esimerkki 1.28. (Dynaaminen varastomalli) Kauppias varastoi erästä tuotetta myyntiä varten, kun seuraavien N kauden kysynnät d i, i = 1,..., N oletetaan tunnetuiksi. Varastossa on pidettävä tuotteita niin paljon, että kysyntä jokaisena kautena voidaan täyttää. Kauppias voi tilata jokaisen kauden alussa varastoon lisää tuotteita ja oletetaan, että tilattavat määrät z i toimitetaan välittömästi tilauksen jälkeen. Jokaisesta tilauksesta aiheutuu kautena i tilausmäärästä riippumaton kiinteä kustannus K i ja lisäksi määrä z i maksaa hinnan c i (z i ). Siis määrän z i tilauksesta kautena i aiheutuu kokonaiskustannus {, jos z i = C i (z i ) = K i + c i (z i ), jos z i >. Varastointikustannukset kautena i ovat suoraan verrannolliset varaston kokoon kauden lopussa ja kustannus on h i rahaa tuoteyksikköä kohti. Olkoon x i varaston koko kauden i alussa. Silloin x i+1 = x i + z i d i, i = 1,..., N ja kauden i varastointikustannukset ovat h i x i+1. Tehtävänä on määrätä optimaaliset tilausmäärät z i, i = 1,..., N niin, että kokonaiskustannukset ovat mahdollisimman pienet. Oletetaan, että tunnetaan kauden 1 alussa varastossa oleva määrä x 1 ja viimeisen kauden lopussa varastossa tarvittava tavaramäärä x N+1. Dynaamista optimointia varten määritellään systeemin vaiheet, tilat ja päätökset. Nyt on mahdollista valita sekä etenevä, että takeneva dynaaminen optimointi, koska varastosta tunnetaan sekä alku- että lopputilanne. Valitaan etenevä dynaaminen optimointi, jolloin vaiheessa i ollaan käsitelty kaudet 1,..., i. Systeemin tila vaiheessa i olkoon varaston määrä x i+1 kauden i lopussa. Päätös vaiheessa i on luonnollisesti ostettava tavaramäärä z i. Muissa paitsi viimeisessä vaiheessa on voimassa epäyhtälö x i+1 d i+1 +... + d N + x N+1, i = 1,..., N 1. Yläraja on saatu siitä, että mitään ei tämän jälkeen tarvitse enää ostaa. Olkoon f i (x i+1 ) kausien 1,..., i pienin mahdollinen kokonaiskustannus, kun kauden i lopussa varaston määrä on x i+1. Kun tunnetaan vaiheen 1 tila x 2, täytyy kauden 1 tilauksen olla z 1 = x 2 + d 1 x 1 ja saadaan ilman optimointia kauden kustannuksiksi f 1 (x 2 ) = C 1 (x 2 + d 1 x 1 ) + h 1 x 2,