Presentasjon lastes. Vennligst vent

Presentasjon lastes. Vennligst vent

Alg. Dat Øvingsforelesning 5 Kompleksitetsanalyse Torbjørn Moralnd

Liknende presentasjoner


Presentasjon om: "Alg. Dat Øvingsforelesning 5 Kompleksitetsanalyse Torbjørn Moralnd"— Utskrift av presentasjonen:

1 Alg. Dat Øvingsforelesning 5 Kompleksitetsanalyse Torbjørn Moralnd

2 Dagens tema Motivasjon -notasjon O- og -notasjon
Relasjoner mellom O,  og  Litt om kompleksitetsklasser Rekursive algoritmer Kjøretidsanalyse Rekurrensregning Øving 4: Prinsessejakt Øving 5: Veibygging i Ogligogo

3 Motivasjon Vi ønsker å måle hvor rask en algoritme er
:: Motivasjon Vi ønsker å måle hvor rask en algoritme er Lite mening i å måle kjøretid i sekunder Forskjeller i programmeringsspråk og maskinvare Kjøretiden kan variere drastisk med dataene algoritmen blir brukt på Datamaskiner blir kraftigere, og algoritmer vil bli brukt på større data Hvordan ser kjøretiden ut når inputstørrelsen nærmer seg uendelig?

4 :: Analyse Vi trenger et matematisk uttrykk for hva kjøretiden blir, gitt inputstørrelsen – altså tiden som en funksjon av inputstørrelsen Vi analyserer trinnene i algoritmen for i in xrange(n): doSomething() for i in xrange(n): for j in xrange(n): doSomethingElse() Kjøretid: f(n) = c1 · n + c2 · n2, hvor c1 er kjøretiden til doSomething(), og c2 er kjøretiden til doSomethingElse()

5 Største ledd c1 og c2 kommer an på maskinvaren
:: Største ledd c1 og c2 kommer an på maskinvaren La oss anta at c1 = 100 og c2 = 2 Når bare n blir stor nok (n > 50), blir 2n2 større enn 100n, og når n vokser mer og mer, blir 2n2 MYE større enn 100n Kun det største leddet (2n2) er interessant, fordi dette leddet vil dominere de andre når n blir stor nok Siden konstanten foran n2 kan variere fra maskin til maskin, kutter vi ut den også Ignorerer derfor c1 og c2 fordi de er vanskelige å regne ut og avhenger av teknologi (maskinvare og språk). La oss for eksempelets skyld si at vi har klart å måle disse. Konstantledd foran er altså uinteressante, både fordi de endrer seg med teknologien, og fordi de ikke hjelper små ledd til å vinne over store ledd når n blir stor

6 -notasjon Hvordan uttrykke dette? Vi sier at 2n2 + 100n = (n2)
:: -notasjon Hvordan uttrykke dette? Vi sier at 2n n = (n2) Viktig: (n2) er en mengde! (n2) består av alle funksjoner som vokser ”like raskt” som n2 når n går mot uendelig Likhetstegnet misbrukes – det skulle egentlig ha vært f(n)  (g(n)) f(n) = (g(n)) betyr altså: ”f(n) er en av de funksjonene som vokser like raskt som g(n)” Vi trenger nå en måte å uttrykke at n^2 er den viktigste delen av funksjonen vår – til dette bruker vi Theta-notasjon. En forenklet forklaring er at Theta(n^2) er en mengde av alle funksjoner som har n^2 som det dominerende leddet. Eksempler på dette er n^2, 100n^2 – 1000 og n^2 + n + 1. n eller n^3 er IKKE med i Theta(n^2) ”vokser like raskt som” er en forenkling. Nå vil vi ta den formelle definisjonen, som (i dette eksempelet) går på at n^2 kan brukes som en grense for n^ n Grunnen til misbruket er at Theta(n^2) leses som ”en eller annen funksjon som har n^2 som dominerende ledd”. Man kan f.eks si h(n) = n^3 + Theta(n^2)

7 :: Definisjon (g(n)) = {f(n) : det finnes positive konstanter c1, c2 og n0 slik at 0  c1g(n)  f(n)  c2g(n) for alle n  n0} Altså: (g(n)) består av alle funksjoner som g(n) kan brukes som både øvre og nedre grense for Hvis vi skal vise at f(n) = (g(n)), må vi bevise ulikhetene og finne c1, c2 og n0 Nå skal vi ta den formelle definisjonen. Konseptet er at en funksjon skal kunne brukes til å ”sperre inne” en annen. Hvis vi bare ganger g med en passe liten faktor, vil den holde seg under f, men hvis vi ganger den med en passe stor faktor, vil den holde seg over f. g skal altså kunne ligge og ”vokte” f på begge sider.

8 Eksempel – polynomer Gitt f(n) = n3 – 100n2 + n
:: Eksempel – polynomer Gitt f(n) = n3 – 100n2 + n Vi trikser med leddene: f(n) = n3 – 100n2 + n  n3 + n  n3 + n3 = 2n3 f(n) = n3 – 100n2 + n  n3 – n3 / 2 + n  n3 / 2 Vi finner ut når overgangene gjelder: –100n2  0 : uansett n  n3 : for n  1 –100n2  –n3 / 2 : for n  200 n  0 : for n  0 Altså kan vi sette n0 = 200 Vi ser at det er n^3 som er det dominerende leddet her, og at f(n) derfor er Theta(n^3). Men vi kan bli bedt om å vise det formelt, og da må vi gjøre som følger. Merk nå at dette her hadde funket om det så stod foran n^2 – det gjelder bare å velge n_0 stor nok

9 :: Eksempel – polynomer Nå vet vi at 0  n3 / 2  f(n)  2n3 når n > n0 = 200 Vi kan nå sette c1 = ½, c2 = 2 og g(n) = n3 Kravene for at f(n) = (g(n)) er oppfylt Altså er n3 – 100n2 + n = (n3) Grunnen til at vi ikke kan bytte ut –100n^2 med –100n^3 er at da blir uttrykket negativt, og det er ikke lov

10 Grafisk fremstilling 2n3 n3 – 100n2 + n n3 / 2 ::
Grenser: n=100, n=200, n=400, n = For små datasett er det –100n^2 som dominerer kjøretiden.

11 Grafisk fremstilling 2n3 n3 – 100n2 + n n3 / 2 ::
Grenser: n=100, n=200, n=400, n = For små datasett er det –100n^2 som dominerer kjøretiden.

12 Grafisk fremstilling 2n3 n3 – 100n2 + n n3 / 2 ::
Grenser: n=100, n=200, n=400, n = For små datasett er det –100n^2 som dominerer kjøretiden.

13 Grafisk fremstilling 2n3 n3 – 100n2 + n n3 / 2 ::
Grenser: n=100, n=200, n=400, n = For små datasett er det –100n^2 som dominerer kjøretiden.

14 :: O - og -notasjon f(n) = (g(n)) sier at g er både en øvre og en nedre grense for f Hvis vi bare vil si at g er en øvre grense for f, bruker vi O-notasjon: f(n) = O(g(n)) Hvis vi bare vil si at g er en nedre grense for f, bruker vi -notasjon: f(n) = (g(n)) Disse grensene er ikke tette: f.eks er n = O(2n), og n100 = (n) Se Cormen kap. 3.1 for definisjoner. Regning med O og  er helt tilsvarende det vi gjorde med 

15 Relasjoner mellom O,  og 
:: Relasjoner mellom O,  og  f(n) = O(g(n))  g(n) = (f(n)) f(n) = (g(n))  f(n) = O(g(n))  f(n) = (g(n)) f(n) = (g(n))  g(n) = (f(n))  (f(n)) = (g(n)) (f(n)) = O(f(n))  (f(n) Se side 49 i Cormen for nyttige relasjoner Prøv å bevise disse selv! Bruk definisjonene av O (side 44),  (side 45) og  (side 42)

16 Kompleksitetsklasser
:: Kompleksitetsklasser Grovinndeling i stigende rekkefølge: Konstant: 1 Logaritmisk: logb n Polynomisk: nk Eksponentiell: 2n Faktoriell: n! Alt som er enda verre, f.eks. nn ALLE polynomer med k > 0 vokser raskere enn polylogaritmer ALLE eksponentialfunksjoner med gruntall > 1 vokser raskere enn polynomer

17 Kompleksitetsklasser
:: Kompleksitetsklasser Eksempler – alle på samme linje er ”like raske” (de er  av hverandre) 1, 2, e, lg n, ln n, log10 n, lg n100 (lg n)2, (ln n)2, (log10 n)2, (lg n100)2 n, n lg n n lg n, n log42 n n2 2n 3n n! nn Uansett hvor stor en konstant er, har det ikke noe å si Grunntallet til en logaritme har ikke noe å si Hva logaritmer er opphøyd i har betydning Konstanter foran eller langsommere ledd har ikke noe å si Vær så snill å passe på at i produkter kan man IKKE stryke langsommere ledd!

18 :: Fallgruver Grunntallet til en logaritme har ikke noe å si for kompleksiteten: lga n = (lgb n) Grunntallet til en potens har mye å si for kompleksiteten: an  (bn) hvis a  b Er 2n + c = (2n)? Er 2cn = (2n)? Vær forsiktig med transitivitet: Følgende er korrekt: f(n) = O(g(n))  g(n) = O(h(n))  f(n) = O(h(n)) Men kan vi slutte noe av det følgende? f(n) = O(g(n))  g(n) = (h(n)) (2) med mindre a = b, naturligvis... (3) 2^(n+c)=2^c * 2^n, 2^(cn) = (2^c)^n (4) nei; g kan være hva som helst som er >= h, og f kan være hva som helst som er <= g, så f kan godt være < h

19 Fallgruver Ikke alle funksjoner kan sammenlignes med O,  og 
:: Fallgruver Ikke alle funksjoner kan sammenlignes med O,  og  Eksempel: n og n1 + sin n 1 + sin n oscillerer mellom 0 og 2, så n1 + sin n veksler hele tiden mellom å være større enn og mindre enn n O angir en mengde funksjoner Det er ikke i seg selv et mål på worst case-kjøretid, selv om det ofte brukes til å angi dette Å si ”kjøretiden er minst O(n)” er meningsløst Det samme gjelder for  og best case-kjøretid Spør folk om n^2 kan sammenlignes med n^(2 sin n) (ja, n^(2 sin n) = O(n^2)) O(g(n)) angir ikke worst case-kjøretid, men den sier noe om en hvilken som helst slags kjøretid. Kan godt si at best-case-kjøretiden er f.eks. O(n^2) – da sier du at kjøretiden i beste tilfelle er en eller annen funksjon som ikke vokser raskere enn n^2

20 Fallgruver O,  og  er rent matematiske konsepter
:: Fallgruver O,  og  er rent matematiske konsepter De beskriver funksjoner, og bryr seg ikke om hva funksjonene representerer Derfor: O er ikke knyttet til worst case,  er ikke knyttet til best case, og  er ikke knyttet til algoritmer hvor worst case = best case Men: O brukes ofte for å angi kjøretiden i worst case, og  brukes ofte for best case Merk at hvis en algoritme er O(f(n)) i worst case og (g(n)) i best case, er algoritmen O(f(n)) og (g(n)) i alle tilfeller

21 Pseudopolynomialitet
:: Pseudopolynomialitet Gitt en algoritme som tar tallet n som input og har kjøretid O(n) – hvilken kompleksitetsklasse er dette? n betegner her ikke størrelsen på input, men er selv en del av inputen Størrelsen til n = antall bits som kreves = lg n n = 2lg n = 2w Oi sann – eksponentiell kjøretid! Dukker ofte opp som lureoppgave på eksamen! Vær altså veldig obs på om et tall angir antall elementer i inputen, eller er en del av inputen selv!

22 Pseudopolynomialitet
:: Pseudopolynomialitet Merk: omskrivningen på forrige side (n = 2lg n) er det alltid lov å foreta – spørsmålet er bare hvilken form som er mest hensiktsmessig: Hvis n faktisk beskriver inputstørrelsen, bør uttrykket baseres på n Hvis n er et tall som er en del av input, bør uttrykket baseres på lg n Eksempel fra eksamen 2006: En algoritme for å sjekke om tallet n er et primtall er (lg n). Er dette subpolynomisk? Nei, siden inputstørrelsen er lg n, så dette er en lineær kjøretid ifht. inputstørrelsen Vær altså veldig obs på om et tall angir antall elementer i inputen, eller er en del av inputen selv!

23 Pseudopolynomialitet
:: Pseudopolynomialitet Til de oppvakte som sier "men en talliste av lengde n består jo av tallene a1, a2, ..., an – bør ikke størrelsen på disse tallene tas med i beregningen?" Bra observasjon! Strengt tatt burde de det, men det hadde ført til ekstremt tungvinte uttrykk I alle situasjoner vi vil komme borti vil vi anta at alle tallene i en liste er av begrenset størrelse (typisk 32 eller 64 bit) og således opptar konstant plass Vær altså veldig obs på om et tall angir antall elementer i inputen, eller er en del av inputen selv!

24 Hvordan velge algoritme?
Analyser algoritmene du vurderer å bruke Finn ut hvordan inputen din forventes å være (vil det oftest være best case, average case eller worst case?) Hvor stor forventes inputen å være? Vil den være så liten at konstantleddene blir viktige? (I sortering går man ofte over til insertion sort når listene er små nok.) Har du råd til worst case-kjøretiden? (dette har du ikke alltid i real-time-applikasjoner)

25 Kjøretidsanalyse av rekursive algoritmer
En algoritme er rekursiv hvis den kaller seg selv en eller flere ganger Kjøretidsanalyse av rekursive algoritmer består av fire steg 1. Velg en metrikk som indikerer inputstørrelse 2. Bestem algoritmens grunnleggende operasjonsfunksjon f(n) som en funksjon av inputstørrelsen 3. Sett opp en rekurrensligning T(n) = ...T(...) f(n), T(1) = ... 4. Løs rekurrensen på en eller en annen måte

26 Rekurrensregning Iterasjonsmetoder Variabelskifte Substitusjonsmetoden
Foroversubstitusjon Bakoversubstitusjon Variabelskifte Substitusjonsmetoden Tremetoden Masterteoremet

27 Foroversubstitusjon Ganske rett frem
Regner T(1), T(2), T(3) osv til vi ser et generelt mønster Løsningen kommer ved å finne ut hva det n-te elementet blir

28 Tower of Hanoi Gitt tre staver (A,B,C) og N klosser. Klossene skal flyttes fra stav A til stav C via stav B. Det er forbudt å sette en større kloss opp på en som er mindre. Man kan bare flytte en kloss om gangen Hvor mange flytt trenger man, og hvordan går man frem?

29 Tower of Hanoi Løsning: def Hanoi (N, A, B, C) : if N > 1 :
Hanoi (N−1, A, C, B) print "Move one disk from " + A + " to " + C Hanoi (N−1, B, A, C) else :

30 Tower of Hanoi 1. Inputstørreslse: hvor mange disker som skal flyttes, N 2. Operasjonskostnadene er å skrive ut at vi flytter en disk – f(n) = 1 3. For hver Hanoi(N, …) kalles Hanoi(N-1, …) nøyaktig to ganger –T(N) = 2T(N-1) + 1, T(1) = 1 4. Da gjenstår det bare å løse dette…

31 Tower of Hanoi Finner T(2) ved hjelp av T(1), T(3) ved hjelp av T(2) osv: T(1) = 1 T(2) = 2*T(1) + 1 = = 3 T(3) = 2*T(2) + 1 = = 7 T(4) = 2*T(3) + 1 = = 15

32 Tower of Hanoi Hvis vi fortsetter lenge nok, får vi følgende utvikling: 1, 3, 7, 15, 31, 63, 127, 255, 511,… Dette ligner veldig mye på en ekspotensiell rekke, nemlig: 21 − 1, 22 − 1, 23 − 1, ... Tilsynelatende blir det n-te tallet i denne utviklingen 2n − 1. Følgelig: T(n) = 2n − 1 = (2n)

33 Tilbakesubstitusjon Går fra T(n) mot T(1)
Uttrykker en større instans med en mindre Akkumulerer alle resterende ledd til en matematisk rekke, og løser den

34 Tilbakesubstitusjon – Tower of Hanoi
Vet at T(n) = 2T(n−1)+1, T(n−1) = 2T(n−2)+1, T(n − 2) = 2T(n − 3) + 1 osv T(n) = 2T(n − 1) + 1 T(n) = 2(2T(n − 2) + 1) + 1 T(n) = 2(2(2T(n − 3) + 1) + 1) + 1 osv

35 Tilbakesubstitusjon – Tower of Hanoi
Hvis vi ganger ut, får vi T(n) = 2T(n − 1) + 1 T(n) = 4T(n − 2) T(n) = 8T(n − 3) osv

36 Tilbakesubstitusjon – Tower of Hanoi
”Gjetter” følgende løsning for T(n) som uttrykk av T(N-j): T(n) = 2jT(n − j) + 2j−1 + 2j− Vi vet at T(1) = 1. La T(N-j) = T(1), altså j=n-1 T(n) = 2n-1T(1) + 2n-2 + 2n− Siden T(1) = 1: T(n) = 2n-1 + 2n-2 + 2n− = Rottman gir oss at T(n) = 2n - 1 = (2n)

37 Variabelskifte Samme idé som variabelskifte for integralregning
Vi erstatter en variabel med en annen som gir enklere rekurrensligning

38 Variabelskifte T(n) = 2T(n/2) + O(1), T(1) = 1
La n = 2m for en eller annen m, slik at T(n)=T(2m): T(2m) = 2T(2m-1) + 1, T(20)=1 Definerer i tillegg S(m) = T(2m), S(m-1) = T(2m-1) osv Får da: S(m) = 2S(m-1) +1, S(0) = 1

39 Variabelskifte Dette ligner veldig mye på ligningen vi hadde for Tower of Hanoi. Da vet vi også at S(m) = (2m) Siden 2m = n, er T(n) = (n) Denne teknikken kan også benyttes på rekurrenser som inneholder kvadratrøtter osv.

40 Substitusjonsmetoden
Gjett en løsning, og bruk induksjon til å vise at det stemmer Må være forsiktig og presis Egner seg best som gjette/bevismetode Krever mer forståelse og innsikt enn iterasjonsmetodene

41 Tremetoden Tegn et rekursjonstre for T(n) og nedover
Hver node får verdien f(n) i en tilsvarende T(n) Deretter summeres alle noder for hele treet Som regel er det to tilfeller

42 Summen av alle f(n) for et nivå i treet er konstant
Da kan vi bare gange denne verdien med høyden til treet Eksempel: T(n) = 2T(n/2) + n, T(1) = 1 Høyden til treet er lg(n). Summen på hvert nivå er n. Den totale summen er derfor n*lg(n)

43 Summen av alle f(n) for et nivå i treet er en funksjon av dybden til noden
Setter opp en summasjon og løser den Eksempel: T(n) = 2T(n/2) + 1, T(1) = 1 Summen for et nivå med dybde i er 2i Den totale summen er i så fall

44 Masterteoremet La T(n) være definert for ikke-negative heltall med rekurrensen T(n) = aT(n/b) + f(n) Da sier masterteoremet følgende: Hvis f(n) = for en ε > 0, T(n) = Hvis f(n) = , T(n) = Hvis f(n) = for en ε > 0 hvor af(n/b) ≤ cf(n) for en konstant c < 1for alle store n, T(n) = Hva betyr dette?

45 Øving 4 - Prinsessejakt Kjør et søk fra startnoden
Husk hvilke noder du har funnet For alle andre noder: Tell antall kanter mellom disse Regn ut kanter/noder2 Tweak: Alle søkene er i samme graf Husk på hvilke noder du kan nå fra tidligere søk. Da slipper du å gjøre like mange søk.

46 Øving 5 - Veibygging Ganske rett frem Oversett fra pseudokode i boka
Både Prim og Kruskal fungerer Prim er lettest å implementere Tips for å klatre på lista: Regn på kjøretid for når de forskjellige algoritmene er best


Laste ned ppt "Alg. Dat Øvingsforelesning 5 Kompleksitetsanalyse Torbjørn Moralnd"

Liknende presentasjoner


Annonser fra Google