PG4200 Algoritmer og datastrukturer Forelesning 2 Lars Sydnes, NITH 15. januar 2014
I. Forrige gang
Praktisk eksempel: Live-koding
II. Innlevering
Innlevering 1 2.februar Offentliggjøring: 22.januar Innhold: (i) Estimering av kjøretid med O-notasjon. (gitt java-program) (ii) Måling av kjøretid (jfr. Lab 1, 6.januar) (gitt java-program) (iii) Sammenligning av måling og estimat. (iv) Rekursive funksjoner i programmeringsprosjekt. Grunnleggende web-crawling: wikipedia. Dronningproblemet: wikipedia.
Innlevering 1 Dere leverer Kjøretidsestimater som kommentarer i java-kode. for(int i = 0 ; i < n; i++) { // O(n) visits dosomework(i); // O(n) } // INNER: O(n), VISITS: O(n), TOTAL: O(n^2) En kort tekst/regneark som presenterer kjøretidsmålingene grafisk og sammenligner med teoretiske estimater. Løsning av programmeringsoppgaver i java. Detaljer: Se oppgaveteksten som kommer 22.januar.
III. Hovedtema: Algoritmer
Algoritmer Utgangspunkt: Praktisk problem / Spørsmål. Siktemål: Løsning / Svar. Algoritmen: En oppskrift på å løse problemet. Krav: (i) Algoritmen lar oss løse problemet med et endelig antall steg. (ii) De foreskrevne stegene er spesifikke og gjennomførbare med de gitte ressursene. (iii) Vi er garantert å komme i mål.
Kakeeksempel: Problem: Må ha sjokoladekake. Løsning: Ha en tilgjengelig sjokoladekake. Algoritmen: Finner vi i Ingrid Espelids kokebok. Har vi bakepulver? Er det å smelte smør en elementær operasjon?
Algoritmeeffektivitet Ressursbruk: Tidsbruk Minnebruk Annet: Kommunikasjonsressurser, lagringskapasitet, et c. Vi ønsker å holde oversikt over og styre ressursbruken. Kakeeksempel: Vi vil ikke kaste bort tid og penger.
Algoritmer i praktisk programmering Når vi skal bruke teorien i praktisk programmering, kan vi noe uformelt oversette algoritme med Noen linjer med kode. Hvilke ressurser kreves for å utføre instruksjonene? Metoder, funksjoner: Hvilke ressurser kreves for å utføre et metodekall?
Fast problemstørrelse Noen problemer kommer i én utgave: Fast problemstørrelse. Vi kan drøfte absolutt ressursbruk.
Varierende problemstørrelse Noen problemer kommer i mange varianter: Vi kan drøfte hvordan ressursbruken varierer. Verktøy: Nummerer variantene: P 1, P 2,..., P n,.... Forsøk å se på ressursbruken som en funksjon av n: Tidsbruk = t(n). Forsøk å si noe fornuftig om t(n): Vekst, trender.
Problemstørrelsen Kaker Fast problemstørrelse. Lag kake til én person. Lag kake til 2 personer, eller, 3,..., n,... personer. Her har vi en hel klasse med problemer: K 1, K 2, K 3,..., K n,... Problemet K n : Lag kake til n personer Vi vil si: K n har problemstørrelse n. Det n-te i rekken slik vi valgte å klassifisere problemene.
Problemstørrelsen Eksempler Online-spill: n = antall deltakere. Sjakk: n = antall simulerte trekk fremover i tid. Slå opp i en katalog: n = antall oppføringer i katalogen. Multiplisere to store tall: n = antall bits i sluttresultatet. Multiplisere to store tall: n = sluttresultatet. Det finnes ingen fasit på hvilken størrelse vi skal fokusere på. Hva er det vi ønsker å oppnå?
Problemstørrelsen Advarsel! I dette kurset forholder vi oss veldig fritt til begrepet problemstørrelse. I andre kontekster kan begrepet problemstørrelsen ha veldig spesifikk betydning. Typisk: Problemstørrelse = antall bits i inndata og/eller utdata.
Eksempel: Telefonkatalogen Generelt problem: P: Å slå opp i en telefonkatalog. Klassifisering: P n : Slå opp i katalog med n oppføringer. Ressurser: Tid, korttidsminne. Beskriv algoritme for å løse problemet. Estimér ressursene algoritmen krever for å løse P n.
Ulike synspunkter Verste tilfelle: Hva er den verste situasjonen vi kan forestille oss? (worst case) Beste tilfelle: Hva er den mest gunstige situasjonen vi kan forestille oss? (best case) Gjennomsnitt: Gjennomsnittlig ressursbruk. (average case) Vi vil konsentrere oss om det verste tilfellet worst case.
Katalogalgoritme 1 Les gjennom hele katalogen, oppføring for oppføring helt til du finner riktig persjon. Lineært søk I verste fall må vi lese alle oppføringene. Hvis det tark sekunder å lese 1 oppføring, blir tidsbruken t 1 (n) K n (sekunder). Observasjon: Verdien av K varierer fra person til person. Formen på formelen er den samme for alle.
Katalogalgoritme 2 Gå til midten av katalogen. Finn ut hvilken halvdel av katalogen personen befinner seg i. Gjenta prosedyren med den aktuelle halvdelen. Binært søk / Halveringsalgoritme P n Pn 2 = P n 2 1 P n 4 = P n 2 2 P n 2 k Helt til n 2 k 1, i.e. 2 k n, i.e. k log n log 2. t 2 (n) = Kk = K log 2 log(n)
Vekstfunksjonen Problemer klassifisert etter problemstørrelse: P 1, P 2,..., P k,.... Algoritme for å løse problemene. Vi tenker oss at ressursbruken er en funksjon av problemstørrelsen: Kjøretid = f(n), Ressursbruk = g(n). f(n) og g(n) kalles vekstfunksjoner for henholdsvis tidsbruk og ressursbruk.
Noen typer estimater: Best case: Kjøretid f(n) Average case: Gjennomsnittlig kjøretid = f(n) Worst case: Kjøretid f(n)
IV. O-notasjon
O-notasjon Et grovkornet bilde av situasjonen kan ofte gi adekvat informasjon Situasjonen er for komplisert for en detajert analyse. Vi har for usikre forutsetninger for å kunne gjøre en detaljert analyse. Vi er ikke interessert i detaljene. O-notasjon er velegnet for worst case-analyse.
O-notasjon: Formelt. La f(n) og g(n) være positive funksjoner. (Typisk: Vekstfunksjoner for ressursbruk) Vi sier at f(n) har orden O(g(n)) dersom Det finnes tall M, N > 0 slik at f(n) < M g(n) for alle n > N D.v.s: Etter et visst punkt n = N klarer ikke f(n) å ta igjen den skalerte versjonen Mg(n) av g(n).
O-notasjon: Praktisk regning
Sammenligning av vekstfunksjoner I
sammenligning av vekstfunksjoner II
Ordenen tar seg av det store bildet f(n) er av orden O(g(n)) dersom det finnes tall M, N slik at f(n) < M g(n) for allen > N Vi legger altså vekt på de store tallene. Eksempel: 100n < 100n 2 for alle n > 1. Her er M = 100 og N = 1. Vi sier: 100n har orden O(n 2 ). Eksempel: 1000n < 10n 2 for alle n > 10. Her er M = 10 og N = 10. Vi sier. 1000n har orden O(n 2 ).
Sammenligning av vekstfunksjoner II
Ordensklassenes hierarki O(1) < O(log n) < O(n) < O(n log n) < O(n 2 ) < O(n 3 ) < O(A n ). Generell regel I: O(n k ) < O(n k log n) < O(n k+1 ) k = 0, 1, 2,... Høyere eksponenter gir høyere orden. Generell regel II: O(n k ) < O(A n ) k = 0, 1, 2, 3,... Eksponentiell orden slår alle potenser. Generell regel III: O(A n ) < O(B n ) hvis A < B. Høyere grunntall slår lavere grunntall.
Klassifisering av vekstfunksjoner Vekstfunksjon: Orden: Tilnavn: f(n) = K O(1) konstant f(n) = K log n O(log(n) logaritmisk f(n) = K n O(n) lineær f(n) = K n log n O(n log n) n-log-n f(n) = K n 2 O(n 2 ) kvadratisk f(n) = K n 3 O(n 3 ) kubisk f(n) = K A n O(A n ) eksponentiell Vekstfunksjonen f(n) har orden O(n 2 ) Algoritmen løser problemet med lineær kjøretid.
Regning: Multiplikasjon Hvis f 1 (n) har orden O(g 1 (n)) og f 2 (n) har orden O(g 2 (n)), så har f 1 (n) f 2 (n) orden O(g 1 (n) g 2 (n)). Slagord :O(g 1 (n)) O(g 2 (n)) = O(g 1 (n) g 2 (n)).
Regning: Addisjon Hvis f 1 (n) har orden O(g 1 (n)) og f 2 (n) har orden O(g 2 (n)), så har f 1 (n) + f 2 (n) orden O(g 1 (n) + g 2 (n)). Slagord :O(g 1 (n)) + O(g 2 (n)) = O(g 1 (n) + g 2 (n)).
Regning: Dominans: Hvis f 1 (n) har orden O(g 1 (n) + g 2 (n)) og g 1 (n) har orden O(g 2 (n)), så har f 1 (n) orden O(g 2 (n)). Slagord :O(g 1 (n)+g 2 (n)) = O(g 2 (n)) når g 1 (n) har orden O(g 2 (n)).
Regning: Ignorer faktorer Hvis f(n) har orden O(a g(n)), så har f(n) orden O(g(n)). Slagord :O(ag(n)) = O(g(n))
Regning: Refleksivitet f(n) har orden O(f(n)). Sjekk av dette stemmer, utifra definisjonen: Her er M = 2 og N = 1. f(n) < 2 f(n) for alle n > 1
Regning: Eksempel f 1 (n) = (3n 2 + 200), f 2 (n) = log n + 3, f(n) = f 1 (n) f 2 (n) f 1 (n) har orden O(3n 2 +200) = f 1 (n) har orden O(3n 2 ) = f 1 (n) har orden O(n 2 ) f 2 (n) har orden O(log n+3) = f 2 (n) har orden O(log n) = f(n) = f 1 (n) f 2 (n) har orden O(n 2 log n)
Telefonkatalogen revisited Algoritme 1: Les gjennom hele katalogen. Lineært søk. Tidsbruken følger vekstfunksjonen der K 1 er av ukjent størrelse. t 1 (n) = K 1 n, Heretter vil vi si at tidsbruken er av orden O(n). Algoritme 2: Utelukk halvparten av de gjenværende oppføringene. Binært søk: t 2 = K 2 log n, der K 2 er av ukjent størrelse. Heretter vi vi si at tidsbruken er av orden O(log n).
Praktisk arbeid public static int sumfromoneto(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return sum; }
Notasjonsmetode: Regel 1: Antallet runder i løkke: Angis med kommentar // VISITS: O(n) Regel 2: For hver linje angir vi orden ved kommentar //O(f(n)) Regel 3: Ved slutten av hver kode-blokk gis kommentar: //INNER: O(f(n)), VISITS: O(n), TOTAL: O(n*f(n)) Kjøretid for kode inneholdt i blokk = Kjøretiden for det elementet med høyest orden. Total kjøretid for blokk = (indre kjøretid) (antall iterasjoner)
Praktisk arbeid public static int sumfromoneto(int n) { int sum = 0; // O(1) for (int i = 1; i <= n; i++) {// VISITS : O(n) sum += i;// O(1) }// INNER: O(1), VISITS: O(n), TOTAL: O (n) return sum; // O(1) } //O(n) For tilstrekkelig store n vil for-lokken dominere kjøretiden. Vi konkluderer med at kjøretiden til sumfromoneto(n) har kjøretid av orden O(n).
Praktisk arbeid Husk på: public static int sumfromoneto(int n) {...} //O(n) Se nå på: public static void printsums(int n) { for (int i = 1; i <= n ; i ++ ) { System.out.println(sumFromOneTo(i)); } }
Praktisk arbeid public static void printsums(int n) { for (int i = 1; i <= n ; i ++ ) { // VISITS: O(n) System.out.println(sumFromOneTo(i));// O(n) } //INNER: O(n), VISITS: O(n), TOTAL: O(n^2) } // O(n^2) Vi vil si: printsums har kjøretid av orden O(n 2 ) printsums har tidskompleksitet O(n 2 ). Legg merke til at Alt uttrykkes ved n.
Knep Potenser: for (int i = a, i <=n; i++) {//O(n) funksjonskall(i);// O(n^k) }//O(n^(k+1)) Potenser og Logaritmer: for (int i = a i <= n; i++) {//O(n) funksjonskall(i); //O(n^k log n) }//O(n^(k+1)log n)
Logaritmiske løkker for(int i = 1; i< n; i*=4){ funksjonskall(i); // O(f(n)) }// INNER: O(f(n)) Her går i gjennom verdiene I iterasjon k har i verdien 4 k. 1, 4, 4 4 = 4 2,..., 4 k,... Iterasjonene fortsetter så lenge 4 k < n, altså så lenge log(4 k ) < log n i.e. k log 4 < log n i.e. k < log n log 4 Antall iterasjoner har orden O(log n).
Logaritmiske løkker for(int i = 1; i< n; i*=4){// visits o( log(n)) funksjonskall(i); // o(f(n)) }// inner: o(f(n)), visits o(log(n)), total: o(f(n)*log(n)) for(int i = 1; i< n; i*=23){// visits O( log(n)) funksjonskall(i); // O(f(n)) }// inner: O(f(n)), visits O(log(n)), total: O(f(n)*log(n))
Praktisk betydning av ulike ordensklasser I n betegner problemstørrelsen. r betegner ressursbruken. O(1): Problemstørrelsen n har ingen praktisk betydning. O(log n): n n 2 gir r 2r. O(n): n 2n gir r 2r. O(n 2 ): n 2n gir r 4r O(n 3 ): n 2n gir r 8r O(A n ): n n + 1 gir r Ar
Praktisk betydning av ulike ordensklasser II La n betegne problemstørrelsen. Dersom vi dobler ressurstilgangen kan vi gjøre følgende økninger av problemstørrelsen: O(log n): n n 2 100 10000 O(n): n 2n 100 200 O(n 2 ): n 1.414n 100 141 O(n 3 ): n 1.26n 100 126 O(2 n ): n n + 1 100 101
Eksempel For et onlinespill med ressursbruk O(log(antall deltakere)) er det nærliggende å forvente at man ved å doble ressurstilgangen kan gå fra 100 til 10000 deltakere. OBS: Dette vil fungere som et første grov-estimat.
Målsetninger: (i) Bli kjent med de ulike ordensklassene: O(f(n)) (ii) Gjøre overslag overslag over ressursbruk ved hjelp av O-notasjonen: Tidsbruken til denne kodesnutten er av orden O(f(n)). (iii) Bruke vår notasjonsmetode i kodeeksempler: for (int i = a i <= n; i++) {//O(n) funksjonskall(i); //O(i^k log i) }//O(n^(k+1)log n)
Men, Ordenen til ressursbruken er viktig når vi er interessert i store variasjoner i For små variasjoner i problemstørrelsen er vi mer interessert i andre typer informasjon: Nøyaktige beregninger. Praktiske tester, statistikk. Vi må la oss lede av praktiske spørsmål. Hvilke problemer ønsker vi å bruke koden på? Er vi interessert i å skalere opp systemet? Hvor mye er det naturlig at problemstørrelse varierer? Hvor ligger flaskehalsene?
Kart Algoritme / Program / programelement Problemstørrelse Vekstfunksjon (growth function) Vekstfunksjonens orden. Kjøretidens orden Minnebrukens orden Algoritmens tidskompleksitet
Oppgaver Oppgaver: 2.1, 2.2, 2.6 Lab: 2.3, 2.4, 2.5 + Ekstraoppgave på it s learning. Trykkfeil i oppgave 2.5. Riktig kode i linje 3: for (int count2=1; count2 < n; count2= count2*2) { Hva skjer dersom vi kjører den koden som står oppført i boka?
O-notasjon Eksempler i stigende orden: 100 + 13 sin n 100 O(1) 34 log n + 42 O(log n) n + 100 + log n 2 O(n) n + 100 n log n 3 O(n log n) 1000 n + 0.001 n 2 O(n 2 ) log n + 0.001 n 2 log n 3 O(n 2 log n) a 0 + a 1 n + a 2 n 2 + + a k n k O(n k ) 2 n 1000 + 10000 O(2n ) 3 n 100 + 100 2n O(3 n )