Czyli odrobina hardkoru na podstawie Cormena i moich własnych rozważań nad istotą tego świata.
Jako że za niedługo pojawi się zapewne strona nt. techniki "divide et impera" (w szczególności zadania W), zamierzam ubiec jej autora z tym oto referatem zawierającym dowód twierdzenia podanego na lekcji. Ale o co właściwie chodzi?
Twierdzenie
Założenie
Dany jest algorytm, który dzieli problem na $a$ $b$-tych części, a do ich scalania używa procedury działającej w czasie $f(n)$. Oznaczmy jego czas działa nią przez funkcję $T(n)$. Czyli:
(1)Gdzie $n \in \mathbb{R}, a,b \in \mathbb{Z_{+}}$, a ułamek zaokrąglamy do podłogi albo sufitu.
Teza
- $f(n)=O(n^{\log_{b}a-q}) \Rightarrow T(n)=\Theta(n^{\log_{b}a})$
- $f(n)=\Theta(n^{\log_{b}a}) \Rightarrow T(n)=\Theta(n^{\log_{b}a}\log n)$
- $f(n)=\Omega(n^{\log_{b}a+q}) \Rightarrow T(n)=\Theta(f(n))$, przy czym ten przypadek jest obostrzony warunkiem, że istnieje taka stała $0<c<1$, że dla dostatecznie dużych n $af\left(\frac{n}{b}\right)\leqslant cf(n)$, co jest dość logiczne dla funkcji wielomianowych, które rozpatrujemy: jako że b jest całkowite dodatnie, to po lewej stronie dzielimy przez b do potęgi zawartej w funkcji $f$, a po prawej zawsze przez $\frac{1}{c}>1$ do pierwszej, czyli przez większą liczbę, a więc w rozsądnych przypadkach otrzymamy liczbę mniejszą. Z tego punktu widzenia ten warunek jest idiotycznie trywialny, ale inaczej twierdzenie nie zadziała.
Obecne w tezie $q$ jest dodatnią stałą.
Przykład działania: Karatsuba
Cokolwiek by nie robił, dzieli on problem na trzy podproblemy operujące na połówkach danych, których rozwiązania potem scala w czasie $\Theta(n).$. Mamy więc $T(n) = 3T\left(\frac{n}{2}\right) + \Theta (n)$. Oczywiście $\Theta (n)=O(n^{\log_{2}3-q})$ (bo $\log_{2}3 > 1$, a więc mamy przypadek 1, czyli $T(n)=\Theta(n^{\log_{2}3-q})$.
++Żeby było jasne:
- intuicyjnie, $\Theta$ to "asymptotycznie =", $O$ to "asymptotycznie <", zaś $\Omega$ to "asymptotycznie >", na przykład $2n^{2}= \Theta(n^{2}), 2n^{2}= O(n^{3}), 2n^{2}= \Omega(n).$
- Będę korzystał z definicji logarytmu, czyli równości $a^{log_{a}b}=b$, oraz z własności $a^{\log_{b}n} = n^{\log_{b}a}$
Dowód
Prawie dowód
Dowiedziemy na razie prawdziwość naszego twierdzenia dla n będących dokładnie równe $b^{k}$ dla pewnego dodatniego k. W ty,m celu zmienimy też definicje asymptotycznych oszacowań ($O, \Theta , \Omega$) tak żeby szacowały tylko potęgi b.
Intuicyjnie widać, że jeżeli będzie działało dla takich n, to dla reszty też będzie działało, no bo niby z jakiej racji czas ma dla n z jakiegoś przedziału wystrzelić w górę, podczas gdy dla reszty rośnie rozsądnie…
No ale do rzeczy. Narysujemy sobie drzewo rekursji, przy czym (jedynie dla ustalenia uwagi) przyjmujemy, że koszt $f(n)$ jest kosztem po prostu związanym z konkretnym elementem tego drzewa, nieważne, czy go wydatkujemy przy scaleniu (MergeSort, Karatsuba), czy przy rozdzielaniu (nie wiem, czy takie algorytmy istnieją, musiałyby scalać w czasie stałym…). Drzewo to wygląda tak, że w korzeniu jest cały problem, a jego dzieci to podproblemy, na które go dzielimy.
A więc z korzeniem jest związany "pełny" koszt $f(n)$, z każdym z jego a dzieci - koszt $f(\frac{n}{b})$, i tak dalej… Ogólnie, jak widać, każdy element niebędący liściem dzielimy na a b-tych części, czyli każdy ma a dzieci o koszcie b razy mniejszym (tego zdania prosimy nie czytać publicznie). A więc element na j-tym poziomie (gdzie korzeń to poziom zerowy) ma koszt:
Ponieważ przejście do niższego o 1 poziomu polega na dzieleniu przez b, to poziomów w drzewie jest:
(3)(od numeru $0$ do $\log_{b} n$). Tu właśnie przydaje się założenie, że n jest potęgą b, inaczej liczba poziomów nie byłaby naturalna, a takie drzewo trudno by było narysować…
Na każdym poziomie znajduje się tyle elementów, ile było na poprzednim, razy a, bowiem każdy z nich został podzielony na a części. Ponieważ na zerowym poziomie jest jeden , to na j-tym poziomie jest elementów:
A więc koszt wszystkich scalań, tzn koszt związany ze wszystkimi węzłami wynosi:
(5)No dobra, rozpatrzyliśmy sobie wszystkie scalania, ale przecież same liście też coś kosztują. Jak już policzyliśmy, koszt liścia wynosi $f\left(\frac{n}{b^{\log_{b}n}}\right) = f(1)= \Theta(1)$. Liści jest, co też już mamy policzone, $a^{\log_{b}n}$, a więc do naszej sumy należy jeszcze dorzucić sumę kosztów liści, czyli $\Theta(a^{\log_{b}n}) = \Theta(n^{\log_{b}a})$. Podsumowując nasze dotychczasowe rozważania, mamy, że:
(6)Dla wszystkich trzech przypadków.
No to wstawmy $f(n)=O(n^{\log_{b}a-q})$, gdzie q jest nieujemną liczbą rzeczywistą. Oszacujmy sobie naszą sumę (5). Mamy:
Teraz nadszedł czas na skorzystanie z naszej wiedzy kiełbasianej:
(8)Jeżeli q=0, to mamy przypadek 2 z tezy. Wtedy powyższe wynosi:
(10)Co kończy dowód przypadku 2.
Jeżeli zaś q jest dodatnie, wtedy mamy przypadek 1.wtedy suma w powyższym wyrażeni jest sumą $\log_{b}n$ kolejnych wyrazów ciągu geometrycznego (ach, kochamy to sformułowanie), a więc całe wyrażenie przyjmuje postać:
(11)A więc, na mocy (6), również mamy:
(12)Co z kolei kończy dowód przypadku 1.
Przypadek trzeci jest ciekawszy. Najpierw skorzystamy z własności zawartej w założeniu, czyli: $f\left(\frac{n}{b}\right)\leqslant \frac{c}{a}f(n)$ dla n będącego dowolną potęgą b . Ale dla j-tego poziomu mamy z niej, że:
(13)Pamiętając że $0<c<1$, podstawimy to do sumy (5). A więc mamy:
(14)Co jest… sumą kolejnych wyrazów ciągu geometrycznego! Wyrazy te są dodatnie, więc wraz z dodawaniem kolejnych ta suma będzie się zwiększać. Można przeto oszacować ją przez sumę nieskończonego ciągu (bo $0<c<1$), a zatem przez wyrażenie:
(15)Czyli mamy pół sukcesu, bo oszacowaliśmy sobie tą sumę z dołu. Ale przyjrzyjmy się sumie (5). n jest potęgą b, wszystkie wyrazy są dodatnie, dodajemy do siebie f(n/stała), czyli w zasadzie niżej niż f(n) nie zejdziemy, bo dla dostatecznie dużych n ta stała traci znaczenie, więc w zasadzie
(16)No bo z założenia mamy, że $f(n) = \Omega(n^{\log_{b}a})$.
Co kończy dowód przypadku 3, a zarazem tezy. Przypominam, że cały czas n było całkowitą potęgą b.
Dowód tak naprawdę
Jak już wspomniałem, przypadek musiałby być naprawdę patologiczny, jeżeliby tak się nie działo. Dlatego też dowód dla każdego n opiera się na dowodzeniu, że wzięcie podłogi czy sufitu z wyrażenia $\frac{n}{b^{j}}$ nie zmienia poprawności powyższego dowodu.
Ja go tu wkrótce umieszczę, na razie tyle.
Konkluzja
Jeżeli doszedłeś (doszłaś) do tego miejsca, przeczytawszy wszystko powyżej, gratuluję wolnego czasu ;). Jeżeliby się znalazł tam jakiś błąd - krzyczeć. No nic, jak widać, dowód ten nie jest trudny, trzeba umieć liczyć sumę ciągu… ;P