Föreläsning 7 Analys av algoritmer T(n) och ordo Problemlösning tillsammans
Varför? Behöver vi verkligen analysera algoritmer med dagens och morgondagens snabba datorer? Om tiden för en algoritm växer som n2 kommer en 100 gånger så snabb dator bara att hinna med 10 gånger så stort problem. Om ett problem växer som 2n är n = 100 olösligt (21001030). En 100 gånger så snabb dator gör att problemet ”bara” tar lika lång tid som 1028 skulle gjort på den gamla datorn. Kan man inte bara testa algoritmerna? Förvisso en mycket bra ide som man inte bör glömma bort. Den har några problem (och en del fördelar): Man måste koda algoritmen (och göra det bra/rättvist) Vilka indata ska vi använda? typiska/slumpmässiga/extrema Med fel algoritm tar problemet för lång tid att testa Det gäller att tänka på overhead om vi använder små dataset.
Ett exempel m = 0 ger T(n) =1 if-satsen ger T(n) = n-1 Vi väljer en karaktäristisk operation och bestämmer hur många gånger den kommer att utföras som funktion av n. Denna funktion kallas komplexitetsfunktionen och skrivs T(n) m = 0 ger T(n) =1 if-satsen ger T(n) = n-1 m = i ger ? …beror på a
Ett exempel till W(n) – worst case, W(n) = n väljer vi if-satsen som karaktäristisk operation W(n) – worst case, W(n) = n B(n) – best case, B(n) = 1 A(n) – average, A(n) = (n+1)/2 A(n) är normalt svår eller omöjlig att bestämma då vi inte vet hur indata kommer att variera. I många tillämpningar är det viktigaste att veta maximal tid. Vi kommer därför att fokusera på W(n) och ofta sätta T(n) = W(n)
Ordo (big-Oh) notation Vi kommer normalt inte veta hur snabb en karaktäristisk operation är då den beror på kompilator, operativsystem och hårdvara. Vi är också mest intresserade av hur problemet växer för stora värden på n. Då kommer den term som växer snabbast att vara den enda viktiga för tillräckligt stora värden på n: T(n) = 3n2 + 2n + 3 3n2 Eftersom vi inte intresserar oss exakt för tidsåtgången för operationen utan vill analysera vår algoritm blir konstanten framför den största termen också ointressant: T(n) = 3n2 + 2n + 3 3n2 n2 Detta resonemang fångas matematiskt upp av ordo-begreppet där T(n) = 3n2 + 2n – 3 = O(n2)
Karakteristiska operationen tar 10-9 s:
Vilken term dominerar Man kan visa och ni kan pröva att: 2n växer snabbare än n7 n7 växer snabbare än n6 om x>y n1,1 växer snabbare än nlogn n0,1 (roten ur n) växer snabbare än logn
Empirisk analys Vi väljer r++ som karaktäristisk operation och kör programmet för olika n: Vi anpassar nu ett generellt tredjegradspolynom till våra data med tex mathematica eller maple: Maple ger oss då: eller: Alltså får vi T(n) = O(n3)
Binär sökning Vi ska nu försöka analysera algoritmen för att bestämma T(n) eller snarare W(n). Vi börjar med observationen att i värsta fall är: T(n) = 1 +T(n/2) och T(1) = 1 Vilket ger: En dubbling av n ökar resultatet med 1 vilket vi kan visa ger: Alltså får vi T(n)=O(log(n))
Analys av rekursiv algoritm
Lösning T(0)=0
Inlämningsuppgifter 7.1 redovisas senast fredag den 15 februari och kan inte redovisas senare.