Haskell Hero
Interaktivní učebnice pro začínající Haskellisty
|
Časová složitostProč se bavíme o časové složitosti?PříkladUrčete, která z následujících funkcí rychleji počítá umocňování na přirozený exponent. umocni1 _ 0 = 1 umocni1 x n = x * umocni x (n-1) umocni2 _ 0 = 1 umocni2 x n = if even n then r else x * r where r = umocni2 (x * x) (n ‘div‘ 2)
Zkusme si pro představu vyhodnotit výrazy umocni1 5 1 ~> 5 * umocni1 5 (1-1) ~> 5 * umocni1 5 0 ~> 5 * 1 ~> 5 umocni2 5 1 ~> if even 1 then r else 5 * r where r = umocni2 (5 * 5) (1 ‘div‘ 2) ~> if False then r else 5 * r where r = umocni2 (5 * 5) (1 ‘div‘ 2) ~> 5 * umocni2 (5 * 5) (1 ‘div‘ 2) ~> 5 * umocni2 (5 * 5) 0 ~> 5 * 1 ~> 5Umocnění pětky na první za použití funkce umocni1 trvalo 4 kroky. To samé umocnění pomocí funkce umocni2 trvalo 6 kroků. Mohli bychom tedy říci, že funkce umocni2 je časově složitější než funkce umocni1 . Pokud ale budeme chtít umocnic pětku na desátou, výpočet dopadne trochu jinak:
umocni1 5 10 ~>2 5 * umocni 5 9 ~>2 5 * 5 * umocni 5 8 ~>2 5 * 5 * 5 * umocni 5 7 ~>14 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * umocni 5 0 ~> 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 1 ~>10 9765625Celkem 31 kroků. umocni2 5 10 ~>3 umocni2 (5 * 5) (10 ‘div‘ 2) ~> umocni2 (5 * 5) 5 ~>3 5 * 5 * umocni2 (5 * 5 * 5 * 5) (5 ‘div‘ 2) ~> 5 * 5 * umocni2 (5 * 5 * 5 * 5) 2 ~>3 5 * 5 * umocni2 (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5) (2 ‘div‘ 2) ~> 5 * 5 * umocni2 (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5) 1 ~>3 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * umocni2 (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5) (1 ‘div‘ 2) ~> 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * umocni2 (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5) 0 ~>4 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 1 ~>10 9765625Celkem 30 kroků. Pokud bychom exponent ještě navýšili, zjistili bychom, že čím větší exponent zvolíme, tím je definice umocni2 efektivnější.
Časová složitost zkoumá náročnost výpočtu v závislosti na velikosti argumentů. Nyní si povíme základní věci z této problematiky. Konstantní složitostFunkce, jejichž výpočet trvá vždy konstantní počet kroků, mají konstantní časovou složitost.
Příkladem může být funkce head [1] ~> 1 head [1,2,3] ~> 1 head [1,2,3,4,5,6,7,8,9,10] ~> 1Bez ohledu na délku seznamu v argumentu trvá vyhodnocení funkce head konstantní počet kroků. V našem případě jeden krok.
Lineární složitostFunkce, jejichž doba vyhodnocení lineárně stoupá s velikostí argumentů, mají lineární časovou složitost.
Například funkce map (+1) [1] ~> 1+1 : map (+1) [] ~> 1+1 : [] ~> 2 : []Celkem 3 kroky na jednoprvkovém seznamu map (+1) [1,2] ~> 1+1 : map (+1) [2] ~> 1+1 : 2+1 : map (+1) [] ~> 1+1 : 2+1 : [] ~> 2 : 2+1 : [] ~> 2 : 3 : []Celkem 5 kroků na dvouprvkovém seznamu map (+1) [1,2,3] ~> 1+1 : map (+1) [2,3] ~> 1+1 : 2+1 : map (+1) [3] ~> 1+1 : 2+1 : 3+1 : map (+1) [] ~> 1+1 : 2+1 : 3+1 : [] ~> 2 : 2+1 : 3+1 : [] ~> 2 : 3 : 3+1 : [] ~> 2 : 3 : 4 : []Celkem 7 kroků na tříprvkovém seznamu. Obecně tedy můžeme říct, že s každým dalším prvkem v seznamu vzroste časová složitost o konstantní počet kroků, v našem případě o dva. V takovém případě má funkce lineární časovou složitost. Kvadratická složitost
Mějme funkci Místo přesné definice si pouze řekněme, jak bude taková funkce pracovat.
Předpokládejme, že porovnání dvou prvků trvá konstantní počet kroků. S každým prvkem seznamu se projdou ostatní prvky seznamu. Čili se n-krát provede n kroků, kde n je délka seznamu Dále ještě existují funkce, jejichž vyhodnocení trvá n^3 kroků. Takové funkce mají kubickou časovou složitost. Obecně o funkcích se složitostí n^a, kde a je konstanta, říkáme, že mají polynomiální časovou složitost. Logaritmická složitostExistují i funkce, které pracují déle než konstantně, ale kratčeji než lineárně. A to jsou funkce s logaritmickou časovou složitostí. Příkladem takové funkce může být například následující funkce: pocitej x = if x < 1 then 0 else pocitej (x `div` 2)Jak asi sami zjistíte, funkce nic užitečného nedělá. Pokaždé vrátí nulu. Ale vyhodnocení jí bude trvat jinak dlouho v závislosti na argumentu. Například: pocitej 5 ~> pocitej 2 ~> pocitej 1 ~> pocitej 0 ~> 0 pocitej 10 ~> pocitej 5 ~> pocitej 2 ~> pocitej 1 ~> pocitej 0 ~> 0 pocitej 1000 ~> pocitej 500 ~> pocitej 250 ~> pocitej 125 ~> pocitej 62 ~> pocitej 31 ~> pocitej 15 ~> pocitej 7 ~> pocitej 3 ~> pocitej 1 ~> pocitej 0 ~> 0Jak vidíme, vyhodnocení výrazu pocitej 5 trvalo 4 kroky, vyhodnocení pocitej 10 5 kroků a pocitej 1000 trvalo 11 kroků. Můžeme říct, že funkce pocitej má logaritmickou časovou složitost.
|