Jak porównywać algorytmy? Kryteria • prostota • czytelność • długość kodu • poprawność • czas realizacji złożoność obliczeniowa • zajętość pamięci Idealny algorytm to taki, który ma prosty kod, jest napisany w ogólnie dostępnym języku programowania, łatwo go zrozumieć, liczy szybko, nie wymaga dużo miejsca w pamięci i zawsze daje poprawne wyniki. AiSD - Wykład 2 Slajd 1 Koszt algorytmu Miary kosztu Pamięć Czas • liczba zmiennych • liczba instrukcji • ilość miejsca potrzebna dla danych • liczba operacji arytmetycznych • liczba wywołań procedury Złożoność pamięciowa Złożoność czasowa Ogólnie: wybór miary zależy od typu problemu, rodzaju rozwiązania. AiSD - Wykład 2 Slajd 2 Rozmiar danych wejściowych Rozmiar danych wejściowych (input size) - liczba elementów w ciągu wejściowym lub całkowita liczba bitów potrzebnych do reprezentowania tych danych. Przykłady 1. W problemie sortowania, wyszukiwania, dodawania elementów macierzy, mnożenie macierzy – liczba elementów w ciągu wejściowym, np. liczba n elementów do posortowania 2. Gdy na wejściu algorytmu jest graf – liczba jego wierzchołków |V| i krawędzi |E| 3. Poszukiwanie n-tego wyrazu ciągu Fibonacciego lub obliczanie n! – n jest daną a nie rozmiarem! W tym przypadku rozmiarem jest liczba bitów wymaganych do zakodowania wartości n: ln n 1 AiSD - Wykład 2 Slajd 3 Przykład analizy algorytmu Insertion-Sort(A) 1. for j:=2 to N 2. do key:=A[j] 3. i:= j-1 4. while i>0 i A[i] > key 5. do A[i+1] := A[i] 6. 7. i:= i-1 A[i+1] := key koszt liczba wykonań c1 n c2 n-1 c3 n-1 n t j c4 j 2 c5 c6 c7 n (t j 1) j 2 n (t j 1) j 2 n-1 tj - liczba sprawdzeń warunku wejścia do pętli while (wiersz 4) dla danej wartości j Animacja 1 AiSD - Wykład 2 Animacja 2 Slajd 4 Przykład analizy algorytmu cd. T (n) c1n c2 (n 1) c3 (n 1) c4 n n n j 2 j 2 j 2 t j c5 (t j 1) c6 (t j 1) c7 (n 1) W najgorszym przypadku: n(n 1) 1 j 2 j 2 n n ( j 1) j 2 n(n 1) 2 Wtedy: n(n 1) n(n 1) n(n 1) T (n) c1n c2 (n 1) c3 (n 1) c4 1 c5 c 6 c7 (n 1) 2 2 2 c c c c c c 4 5 6 n 2 c1 c2 c3 4 5 6 c7 n (c2 c3 c4 c7 ) 2 2 2 2 2 2 T (n) an2 bn c (n 2 ) AiSD - Wykład 2 Slajd 5 Uproszczenia w określaniu złożoności Zliczanie tylko operacji dominujących Operacja dominująca to taka operacja o, że liczba wszystkich operacji wykonanych przez algorytm jest nie większa niż cliczba operacji o, dla pewnej stałej c. Przykłady 1. W algorytmach sortowania jako operację dominującą przyjmuje się zwykle porównanie elementów ciągu wejściowego (czasem przestawienie elementów). 2. W algorytmach grafowych jako dominującą operację przyjmuje się przejście do dowiązanego węzła. Asymptotyczne oszacowanie funkcji T(n) AiSD - Wykład 2 Slajd 6 Notacja asymptotyczna cg(n) f(n) Mówimy, że f jest co najwyżej rzędu g, co zapisujemy jako f(n) = O(g(n)), jeśli istnieją stała rzeczywista c > 0 i stała naturalna n0 takie, że dla każdego n n0 zachodzi nierówność f(n) cg(n). Np. n2 + 2n = O(n2) , bo n2 + 2n 3n2 dla każdego naturalnego n. f(n)=O(g(n)) n n0 Mówimy, że f jest co najmniej rzędu g, co zapisujemy jako f(n) = (g(n)), jeśli g(n) = O(f(n)), c2g(n) f(n) Mówimy, że f jest dokładnie rzędu g, co zapisujemy jako f(n) = (g(n)), jeśli zarówno f(n) = O(g(n)), jak i f(n) = (g(n)), tzn. istnieją takie stałe rzeczywiste dodatnie c1 i c2 oraz stała naturalna n0, że dla każdego n n0 zachodzi nierówność c1g(n) f(n) c2g(n) Mówimy też, że f jest asymptotycznie równoważne g i piszemy f(n) g(n) AiSD - Wykład 2 c1g(n) f(n)=(g(n)) n0 n Slajd 7 Notacja asymptotyczna c.d. Używa się też oznaczenia f(n) = g(n) + O(h(n)), gdy f(n) - g(n) = O(h(n)) Np. ½n2 + 5n +1 = ½n2 +O(n) ← zachowujemy w ten sposób współczynnik przy najbardziej znaczącym składniku sumy Rzędy wielkości dwóch funkcji f(n) i g(n) mogą być porównywane przez obliczenie granicy: f (n) E lim n g(n) Jeśli E = +∞, to g(n) = O(f(n)), ale nie f(n) = O(g(n)) Jeśli E = c > 0, to f(n) g(n) Jeśli E = 0, to f(n) = O(g(n)), ale nie g(n) = O(f(n)) Np. nlog n ln n 1/ n lim lim 0 2 n n n nln2 n ln2 lim czyli nlogn = O(n2), ale nie n2 = O(nlogn) Dla każdego wielomianu p(n) d ai ni mamy p(n) = (nd) i 0 AiSD - Wykład 2 Slajd 8 Typowe złożoności czasowe 1 – złożoność stała – liczba wykonanych operacji nie zależy od rozmiaru zadania lg n – złożoność logarytmiczna (algorytmy typu: zadanie rozmiaru n zostaje sprowadzone do zadania rozmiaru n/2 + pewna stała liczba działań, np. poszukiwanie binarne w ciągu uporządkowanym) n – złożoność liniowa (algorytmy, w których jest wykonywana stała liczba działań dla każdego z n elementów danych wejściowych, np. algorytm Hornera wyznaczania wartości wielomianu) n lgn – złożoność liniowo-logarytmiczna (algorytmy typu: zadanie rozmiaru n zostaje sprowadzone do dwóch podzadań rozmiaru n/2 plus pewna liczba działań liniowa względem n, potrzebnych do wykonania najpierw rozbicia, a następnie scalenia rozwiązań rozmiaru n/2 w rozwiązanie rozmiaru n, np. algorytm sortowania przez scalanie – mergesort) n2 – złożoność kwadratowa (np. algorytmy, w których stała liczba działań jest wykonywana dla każdej pary elementów danych wejściowych) n3, n4 itd. – złożoności wielomianowe nlgn – złożoność podwykładnicza 2n – złożoność wykładnicza 2n (stała liczba działań dla każdego podzbioru danych) n! – złożoność wykładnicza n! (algorytm, w którym wykonywana jest stała liczba działań dla każdej permutacji danych wejściowych) AiSD - Wykład 2 Slajd 9 Złożoność a czas Ile czasu potrzeba na rozwiązanie zadania o ustalonym rozmiarze i złożoności? T(n) lg n n n lg n n2 n3 2n 102 6.6 ms 0.1 ms 0.6 ms 10 ms 1s 106 lat 104 13.3 ms 10 ms 0.1 s 100 s 11 dni 10100 lat n Jaki jest maksymalny rozmiar problemu, który można rozwiązać w ustalonym czasie, znając złożoność algorytmu? T(n) czas 1s 1 godz AiSD - Wykład 2 lg n n n lg n n2 n3 2n 2 1000000 106 63·103 103 102 19 13·107 60·103 15·102 31 23600000000 36·108 Slajd 10 Czy szybkość może pokonać złożoność? Mamy 5 algorytmów A1, A2, A3, A4, A5 rozwiązujących ten sam problem. Niech si oznacza maksymalny rozmiar problemu, który można rozwiązać na komputerze 1 przy pomocy algorytmu Ai w ustalonym czasie t. Jaki jest maksymalny rozmiar problemu, który można rozwiązać w tym samym czasie t na drugim komputerze 100 razy szybszym? lg n n n2 n3 2n Komputer 1 s1 s2 s3 s4 s5 Komputer 2 s1 100 100·s2 10·s3 4,642·s4 6,644+s5 Przykład A5. Dla komputera 1: Dla komputera 2: Szukamy takiego x, że T(A5,x)= t. Mamy więc 2x = 100·2s5 = 2 s5+lg100 . T(A5,s5) = 2s5 = t . T(A5,x) = 2x = t *100. Czyli x = s5 + lg100 ≈ s5 + 6,644 Dla komputera 1000000-krotnie szybszego rozmiar problemu dla algorytmu A5 wzrasta o lg 1000000 ≈ 19,932 AiSD - Wykład 2 Slajd 11 Zależność złożoności czasowej od danych Przykład (wyszukiwanie sekwencyjne) Problem: czy klucz x znajduje się w tablicy S, zawierającej n kluczy? Dane wejściowe: całkowita liczba dodatnia n, tablica kluczy S indeksowana od 1 do n oraz klucz x. Dane wyjściowe: location – lokalizacja klucza x w tablicy S (0, jeśli x nie występuje w S) int seqsearch ( int n, const keytype S[], keytype x) { int location = 1; while (location <= n && S[location] != x) location++; if (location > n) location = 0; operacja podstawowa return location; } AiSD - Wykład 2 Slajd 12 Zależność złożoności czasowej od danych Przypadek najgorszy: operacja podstawowa jest wykonywana n razy, co odpowiada przypadkowi, gdy x jest ostatnim elementem w tablicy lub nie występuje w tablicy. W(n) – złożoność czasową w najgorszym przypadku (worst-case time complexity) definiujemy jako maksymalną liczbę wykonań operacji podstawowej przez algorytm dla danych wejściowych o rozmiarze n. W przykładzie seqsearch: W(n) = n A(n) – złożoność czasową w średnim przypadku (average-case time complexity) definiujemy jako średnią (wartość oczekiwaną) liczbę wykonań operacji podstawowej przez algorytm dla danych wejściowych o rozmiarze n. Proces określania A(n) to analiza złożoności czasowej w średnim przypadku (average-case time complexity analysis) Jaka jest złożoność czasowa w średnim przypadku algorytmu seqsearch? AiSD - Wykład 2 Slajd 13 Analiza złożoności czasowej w średnim przypadku Złożoność czasowa w średnim przypadku algorytmu seqsearch Przypadek 1. Zakładamy, że x na pewno występuje w S oraz, że wystąpienie x w S na każdej pozycji jest tak samo prawdopodobne. Oznacza to, że dla 1 k n prawdopodobieństwo tego, że x występuje na pozycji k wynosi 1/n. Zatem złożoność czasowa w przypadku średnim n n 1 1 1 n(n 1) n 1 A(n) k k n n n 2 2 k 1 k 1 Zgodnie z intuicją średnio przeszukiwana jest połowa tablicy. Przypadek 2. Zakładamy, że x występuje w S z prawdopodobieństwem p i że wystąpienie x w S na każdej pozycji jest nadal tak samo prawdopodobne. Oznacza to, że dla 1 k n prawdopodobieństwo tego, że x występuje na pozycji k wynosi p/n. Prawdopodobieństwo tego, że x nie występuje w tablicy S wynosi 1 – p. Zatem złożoność czasowa w przypadku średnim n p p n(n 1) p p A(n) k n(1 p) n(1 p) n 1 n n 2 2 2 k 1 Dla p = ½: A(n) = 3n/4 + ¼ , tzn. średnio przeszukiwane jest około ¾ tablicy. AiSD - Wykład 2 Slajd 14 Porównanie złożoności – przykład z egzaminu AiSD - Wykład 2 Slajd 15 Porównanie złożoności – przykład z egzaminu Niech A będzie algorytmem, którego złożoność wyraża się funkcją n2, gdzie n jest rozmiarem zadania. Czas wykonania tego algorytmu (na pewnym komputerze) dla problemu o rozmiarze 10 wynosi 1 sek. a) Ile czasu zajmie wykonanie algorytmu dla problemu o rozmiarze 30? Odp. 9 sek. b) Jaki jest maksymalny rozmiar zadania, które można rozwiązać przy pomocy tego algorytmu (na tym samym komputerze) w ciągu 196 sek ? Odp. 140 c) Ile czasu zajmie wykonanie algorytmu dla danych o rozmiarze 40 na komputerze 2 razy szybszym? Odp. 8 sek. A 102 ~ 1 s A 302 ~ x s A 302 1 s = A 102 x x = 302/ 102 s = 9 s A 102 ~ 1 s A n2 ~ 196 s A 102 196 s = A n2 1 s n2 = 102 142 n = 140 AiSD - Wykład 2 Slajd 16