1 / 17

Algoritmit ja laskennan vaativuus

Algoritmit ja laskennan vaativuus. Tietotekniikan perusteet 10.11.1998 Pekka Orponen. Algoritmit ja ohjelmat. Algoritmi: täsmällinen kuvaus jonkin (laskenta)tehtävän suoritustavasta. Ohjelma: Algoritmin esitys jollakin tietokoneella suoritettavissa olevalla ohjelmointikielellä.

elden
Download Presentation

Algoritmit ja laskennan vaativuus

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Algoritmit ja laskennan vaativuus Tietotekniikan perusteet 10.11.1998 Pekka Orponen

  2. Algoritmit ja ohjelmat • Algoritmi: täsmällinen kuvaus jonkin (laskenta)tehtävän suoritustavasta. • Ohjelma: Algoritmin esitys jollakin tietokoneella suoritettavissa olevalla ohjelmointikielellä. • Esim. Valintalajittelualgoritmi lukujoukon järjestämiseksi suuruusjärjestykseen: Olkoot lajiteltavat luvut talletettu taulukon A alkioiksi A[1] ... A[n]. 1. Aseta i ¬ 1. 2. Etsi taulukon alkioista A[i] ... A[n] pienin. Olkoon tämän indeksi imin. 3. Vaihda alkiot A[i] ja A[imin] keskenään. 4. Aseta i ¬ i+1; jos i < n, palaa riville 2. 5. Kun i = n, taulukon alkiot ovat suuruusjärjestyksessä. • Algoritmin esitys C-ohjelmointikielellä: int A[nmax+1]; void selectsort(int n) { int i, j, amin, imin, atmp; for (i = 1; i < n; i++) { amin = A[i]; imin = i; for (j = i+1; j <= n; j++) if (A[j] < amin) { amin = A[j]; imin = j;} A[imin] = A[i]; A[i] = amin; } }

  3. Valintalajitteluohjelma #include <stdio.h> #include <stdlib.h> #include <time.h> #define nmax 1000000 int A[nmax+1]; void selectsort(int n) {...} main() { int n, i; float t0, t1; printf("Number of items = "); while (scanf("%i", &n)) { if (n > nmax) {printf("Number too large. Try again: "); continue;} printf("Generating %d random numbers in the range 0..%d.\n", n, RAND_MAX); for (i = 1; i <= n; i++) A[i] = rand(); printf("Beginning selection sort of %d items\n", n); t0 = ((float) clock())/((float) CLOCKS_PER_SEC); selectsort(n); t1 = ((float) clock())/((float) CLOCKS_PER_SEC); printf("Done. Time = %.2f seconds.\n", t1-t0); printf("Number of items = "); } }

  4. Valintalajitteluohjelman suoritusaika • Käännetään ja suoritetaan edellinen ohjelma: tukki% cc -o selectsort.out selectsort.c tukki% selectsort.out Number of items = 1000 Generating 1000 random numbers in the range 0..32767. Beginning selection sort of 1000 items Done. Time = 0.04 seconds. Number of items = 2000 Generating 2000 random numbers in the range 0..32767. Beginning selection sort of 2000 items Done. Time = 0.16 seconds. Number of items = 3000 Generating 3000 random numbers in the range 0..32767. Beginning selection sort of 3000 items Done. Time = 0.36 seconds. … Number of items = 10000 Generating 10000 random numbers in the range 0..32767. Beginning selection sort of 10000 items Done. Time = 4.14 seconds.

  5. Valintalajitteluohjelman suoritusaika (jatkuu) • Ohjelman suoritusaika-arvot kaaviona (x-aks. lukujen määrä/1000, y-aks. aika sekunteina): • Ohjelman suoritusaika näyttää kasvavan kuten lajiteltavien lukujen määrän neliö. Sanotaan, että suoritusaika on kertaluokkaa n2, tai lyhyesti O(n2) (engl. ”order of”), missä n on lajiteltavien lukujen määrä.

  6. Valintalajittelualgoritmin analyysi • Valintalajitteluohjelman neliöllinen suoritusaika olisi voitu ennustaa myös suoraan käytettyä algoritmia analysoimalla. • Algoritmi aiempaa täsmällisemmässä ”pseudokoodimuodossa”: 1. toista i:n arvoilla 1..n-1: 2. imin ¬ i 3. toista j:n arvoilla i+1 .. n: 4. jos A[j] < A[imin], niin imin ¬ j 5. vaihda alkiot A[i] ja A[imin] keskenään. • Jos oletetaan, että kunkin ”alkeisoperaation” suoritusaika on 1 aikayksikkö, niin kullakin i:n arvolla (i = 1 .. n-1) on: • rivin 2 suoritusaika 1 yksikkö • rivien 3-4 suoritusaika n-i yksikköä • rivin 5 suoritusaika 1 yksikkö • Kaikkiaan algoritmin suoritusaika n alkion syötetaulukolla saadaan tästä summaamalla yli kaikkien i:n arvojen: time(n) = åin= 1 ((n-i)+2) = 1/2n2 + 3/2n - 2 = O(n2).

  7. Lomituslajittelualgoritmi • Toinen menetelmä lukujoukon järjestämiseen on seuraava ”rekursiivinen” (osittava) algoritmi: Olkoot lajiteltavat luvut talletettu taulukon A alkioiksi A[1] ... A[n]. Oletetaan yksinkertaisuuden vuoksi että luku n on muotoa 2k jollakin k = 0,1,2,... 1. Jos n = 1, taulukossa A on vain yksi alkio, eikä mitään tarvitse tehdä. 2. Jos n ³ 1, jaa taulukko A kahteen yhtäsuureen puolikastalukkoon, A’ = A[1..n/2] ja A’’ = A[n/2+1..n] ja käytä tässä kuvattua menetelmää ensin kummankin puolikkaan lajitteluun. 3. Kun puolikastaulukot A’ ja A’’ on lajiteltu, lomita niiden alkiot yhteen taulukkoon A poimimalla alkioita kummastakin vuorollaan suuruus- järjestyksessä. • Esimerkiksi taulukon A = [3 1 4 2] lajittelu tällä menetelmällä sujuu seuraavasti: [3 1 4 2] ositus [3 1] [4 2] ositus [3] [1] [4] [2] lomitus [1 3] [2 4] lomitus [1 2 3 4]

  8. Lomituslajittelu C-ohjelmana • Algoritmin toteutus C-ohjelmana (valintalajittelu- ohjelman kanssa yhteiset osat poistettu): int A[nmax+1], B[nmax+1]; void merge(int m, int h, int n) /* Lomittaa taulukon A järjestetyt osataulukot */ /* A[m..h], A[h+1..n] yhteen taulukoksi A[m..n]. */ { int i, j, k, l; i = m; j = h+1; k = 0; while ((i <= h) && (j <= n)) if (A[i] <= A[j]) { B[k] = A[i]; i++; k++; } else { B[k] = A[j]; j++; k++; }; while (i <= h) { B[k] = A[i]; i++; k++; }; while (j <= n) { B[k] = A[j]; j++; k++; }; k--; for (l = 0; l <= k; l++) A[m+l] = B[l]; } void mergesort(int m, int n) { int h; if (m == n) return; h = (m+n)/2; mergesort(m,h); mergesort(h+1,n); merge(m,h,n); } main() { int n,i; ... mergesort(1,n); ...}

  9. Lomituslajitteluohjelman suoritusaika • Lomituslajittelu on huomattavasti tehokkaampi algoritmi kuin valintalajittelu. Seuraavassa C-toteutuksen suoritusaikakaavio (x-aks. lukujen määrä/1000, y-aks. aika sekunteina; huom. eri mittakaava kuin aiemmin): • Ohjelman suoritusaika näyttää nyt kasvavan lähes lineaarisesti lajiteltavien lukujen määrän suhteen. Onko näin?

  10. Lomituslajittelualgoritmin analyysi • Merkitään lomituslajittelualgoritmin n alkion taulukon A[1..n] lajitteluun tarvitsemaa aikaa T(n):llä. Oletetaan yksinkertaisuuden vuoksi, että n on jokin kakkosen potenssi ja että kunkin ”alkeisoperaation” kesto on 1 aikayksikkö. • Helposti nähdään, että taulukon A[1..n] puolittamiseen ja lajiteltujen puolikastaulukoiden yhdistämiseen kuluva aika on O(n) yksikköä. Ajatellaan yksinkertaisuuden vuoksi, että tämä aika on tasan n yksikköä. • Koko algoritmin suoritusaikaa kuvaa tällöin rekursioyhtälö T(1) = 1, T(n) = 2T(n/2) + n, kun n = 2k, k ³ 1. • Voidaan osoittaa (tai tarkastaa esim. induktiolla), että tämän rekursioyhtälön ratkaisu on T(n) = n log2 n + n. • Lomituslajittelun aikavaativuus ei siis ole aivan lineaarinen, vaan kertaluokkaa O(n log2 n). Kuten nähtiin, tämä on kuitenkin huomattavasti parempi saavutus kuin valintalajittelun O(n2).

  11. Lyhimpien reittien laskeminen • Toisentyyppisenä esimerkkinä tarkastellaan seuraavaa laskentatehtävää: on annettu etäisyystaulukko D[1..n,1..n], joka kuvaa n kaupungin pareittaisia etäisyyksiä. Taulukkoon on kuitenkin talletettu tiedot vain suorista tieyhteyk-sistä kaupunkien välillä; etäisempien kaupunki-parien kohdalla taulukossa on tyhjää. Tehtävänä on täydentää taulukon puuttuvat etäisyydet kaupunkien välisten lyhimpien reittien mukaan.

  12. Lyhimpien reittien laskeminen (jatkuu) • Esimerkiksi syötetaulukko voisi sisältää seuraavat eräiden Suomen kaupunkien etäisyystiedot: Jkl Vaa Jsu Tre Hln Lti Lrt Tku Hki Jkl 0 283 244 151 170 220 Vaa 238 0 244 332 Jsu 244 0 236 Tre 151 244 0 75 153 Hln 75 0 80 139 98 Lti 170 80 0 113 110 Lrt 220 236 113 0 Tku 332 153 139 0 165 Hki 98 110 165 0 • Taulukko pitäisi tällöin täydentää muotoon: Jkl Vaa Jsu Tre Hln Lti Lrt Tku Hki Jkl0 283 244 151 226 170 220 304 280 Vaa 238 0 482 244 319 399 458 332 417 Jsu 244 527 0 395 429 349 236 548 459 Tre 151 244 395 0 75 155 268 153 173 Hln 226 319 429 75 0 80 193 139 98 Lti 170 399 349 155 80 0 113 219 110 Lrt 220 503 236 268 193 113 0 332 223 Tku 304 332 548 153 139 219 332 0 165 Hki 280 417 459 173 98 110 223 165 0

  13. Floydin algoritmi • Tehtävä ratkeaa tyylikkäästi seuraavalla ns. Floydin algoritmilla: • talletetaan taulukon D tyhjiin paikkoihin jokin hyvin suuri luku dmax (”ääretön”, esim. kaikkien D:n epätyhjien alkioiden summa) • suoritetaan seuraavat kolme sisäkkäistä silmukkaa: toista k:n arvoilla 1..n: toista i:n arvoilla 1..n: toista j:n arvoilla 1..n: jos D[i,k] + D[k,j] < D[i,j], niin aseta D[i,j] ¬ D[i,k] + D[k,j] • Algoritmin idea (lyhyesti kuvattuna) on, että kullakin silmukkamuuttujan k arvolla määritetään lyhimmät sellaiset kaupunkiparien i, j väliset reitit, jotka kulkevat enintään kaupunkien 1..k kautta. • Algoritmin aikavaativuus on selvästi luokkaa O(n3): kolme sisäkkäistä silmukkaa, kukin silmukka-muuttujan arvoilla 1..n.

  14. Kauppamatkustajan ongelma • Annettu n kaupungin (täydellinen) etäisyystaulukko D[1..n, 1..n]. Tehtävänä on löytää lyhin sellainen kaupunkikierros, joka kulkee täsmälleen kerran kunkin kaupungin kautta -- siis sellainen lukujen 1,…,n permutaatio p(1),…,p(n), joka minimoi kustannuksen c(p) = å1n-1D[p(i), p(i+1)] + D[p(n), p(1)]. • Tämä ”kauppamatkustajan ongelma” (engl. TSP = ”traveling salesman problem”) esiintyy jossain muodossa lukuisissa käytännön sovelluksissa: jakeluautojen reittisuunnittelussa, piirilevyjen porauksessa, rinnakkaistietokoneiden töiden-järjestelyssä, DNA-jonojen sekvenoinnissa jne. • Vaikka ongelma päällisin puolin hieman muistuttaa lyhimpien reittien määritysongelmaa, se on huomattavasti vaikeampi.

  15. TSP-ongelman ratkaisuyritelmiä • Triviaaliratkaisu: Kokeillaan n kaupungin kartalla kaikki n! mahdollista reittiä ja valitaan niistä lyhin. • Ei onnistu käytännössä: jos esim. n = 22, niin n! on noin 1021. Jos pystyttäisiin tutkimaan esim. 1 reitti millisekunnissa, vaatisi kaikkien reittien tutkiminen noin 36 miljardia vuotta. (Nykykäsityksen mukaan on maailmankaikkeuden tähänastinen ikä 10-20 miljardia vuotta.) • Parannusidea: Ostetaan nopeampi tietokone: esimerkiksi miljoonan prosessorin rinnakkaiskone, jonka kukin prosessori tutkii yhden reitin nano-sekunnissa. • Ei auta: 20 mrd vuotta riittää silti vasta 30 kaupungin karttoihin. • Parempi idea: keksitään tehokkaampi algoritmi. • rajoitusheuristiikat, ”simuloitu jäähdytys”, ”geneettiset algoritmit” • auttavat muutamien kymmenien (joskus satojen) kaupunkien tapauksiin asti, mutta eivät pidemmälle

  16. Polynominen ja eksponentiaalinen aika • Perusvaikeus TSP-ongelmassa (ja muissa samantapaisissa tehtävissä) on tutkittavien ratkaisuvaihtoehtojen (reittien) määrän n! » nn eksponentiaalinen kasvu (”kombinatorinen räjähdys”): • jos ratkaisuvaihtoehtojen määrä kasvaa vain polynomisesti, m £ nk jollakin k, konetehonkin kasvattaminen auttaa: 10 kertaa aiempaa tehok-kaammalla koneella pystytään ratkomaan 101/k kertaa aiempaa suurempia ongelman tapauksia • jos ratkaisuvaihtoehtojen määrä kasvaa eksponen-tiaalisesti, m ³ cn jollakin c > 1, konetehon lisää-minen ei auta: tehon 10-kertaistaminen kasvattaa ratkaistavien tapausten kokoa enintään vakiolla logc 10. • ”Käytännössä ratkeavina” pidetään ongelmia, joilla on jokin syötteen koon n suhteen polynomisessa ajassa toimiva ratkaisumenetelmä, esim.: • lukujoukon järjestäminen (menetelmiä: valintalajittelu O(n2), lomituslajittelu O(n log2 n)) • lyhimpien reittien laskeminen (menetelmä: Floydin algoritmi O(n3)). • Ongelmaluokka P = ”polynomisessa ajassa ratkeavat ongelmat”.

  17. ”P = NP” -ongelma • Kauppamatkustajan ongelmalle ei tunneta yhtään kaupunkien määrän n suhteen polynomisessa ajassa toimivaa ratkaisumenetelmää. • Tällaisen menetelmän olemassaoloa ei kuitenkaan ole myöskään osattu todistaa mahdottomaksi. Siten on mahdollista, joskin hyvin epäuskottavaa, että olisi TSP Î P. • TSP-ongelma kuuluu tiettyyn suureen ”vaikean tuntuisten” ongelmien ekvivalenssiluokkaan, ns. NP-täydellisiin ongelmiin, joilla on se ominaisuus että ne ovat joko kaikki helppoja (luokassa P) tai kaikki vaikeita (luokan P ulkopuolella). • Tällä hetkellä ei tiedetä, kumpi vaihtoehto on tosi. Tämä on kuuluisa ratkaisematon kysymys, ns. ”P = NP” -ongelma.

More Related