Matematyka dyskretna 1/Wykład 9: Asymptotyka: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
 
(Nie pokazano 14 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 1: Linia 1:
Widzieliśmy już, że wskazanie postaci zwartej dla ciągu zadanego równaniem rekurencyjnym jest często zadaniem niełatwym. Do tej pory nie jest znana zwarta postać wielu równań. Na szczęście często jesteśmy w sytuacji, w której zadowoli nas przybliżenie odpowiedzi. Wróćmy do rozważanej wielokrotnie sumy kolejnych kwadratów <math>\displaystyle \sum_{i=0}^ni^2</math>. Fakt, że jest to wielomian <math>3</math>-go stopnia zmiennej <math>n</math>, to już wartościowa informacja, często zupełnie wystarczająca. Spotkaliśmy się już nie raz z oszacowaniami poprzez zwykłe nierówności. To podejście często wymaga użycia narzędzi z analizy matematycznej, w szczególności znajdowania ekstremum funkcji.
Widzieliśmy już, że wskazanie postaci zwartej dla ciągu zadanego równaniem rekurencyjnym jest często zadaniem niełatwym. Do tej pory nie jest znana zwarta postać wielu równań. Na szczęście często jesteśmy w sytuacji, w której zadowoli nas przybliżenie odpowiedzi. Wróćmy do rozważanej wielokrotnie sumy kolejnych kwadratów <math>\sum_{i=0}^ni^2</math>. Fakt, że jest to wielomian <math>3</math>-go stopnia zmiennej <math>n</math>, to już wartościowa informacja, często zupełnie wystarczająca. Spotkaliśmy się już nie raz z oszacowaniami poprzez zwykłe nierówności. To podejście często wymaga użycia narzędzi z analizy matematycznej, w szczególności znajdowania ekstremum funkcji.


{{przyklad|||
{{przyklad|||
Linia 7: Linia 7:




<center><math>\displaystyle (n!)^2=(1\cdot\ldots\cdot n)(n\cdot\ldots\cdot1)=\prod_{i=1}^ni(n+1-i).</math></center>
<center><math>(n!)^2=(1\cdot\ldots\cdot n)(n\cdot\ldots\cdot1)=\prod_{i=1}^ni(n+1-i)</math>.</center>




Linia 13: Linia 13:




<center><math>n^n\leqslant(n!)^2\leqslant\left(\frac{1}{4}(n+1)^2\right)^n,
<center><math>n^n\leqslant(n!)^2\leqslant\left(\frac{1}{4}(n+1)^2\right)^n</math>,</center>
</math></center>




Linia 20: Linia 19:




<center><math>n^{\frac{n}{2}}\leq n!\leqslant\left(\frac{n+1}{2}\right)^n.
<center><math>n^{\frac{n}{2}}\leq n!\leqslant\left(\frac{n+1}{2}\right)^n</math></center>
</math></center>




Linia 32: Linia 30:


==Notacja asymptotyczna==
==Notacja asymptotyczna==
<div class="thumb tright"><div style="width:350px;">
[[File:SW_7.1.svg|350x350px|thumb|right|SW_7.1.swf]]
<flash>file=SW_7.1.swf|width=350|height=350</flash>
<div.thumbcaption>SW_7.1.swf</div></div>
</div>


{{kotwica|funasymptw|'''Funkcja asymptotycznie niewiększa'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, dla której istnieją <math>c>0</math> i <math>n_0\in\mathbb{N}</math>, że <math>\left\vert f(n)\right\vert\leq c\cdot\left\vert g(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
{{kotwica|funasymptw|'''Funkcja asymptotycznie niewiększa'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, dla której istnieją <math>c>0</math> i <math>n_0\in\mathbb{N}</math>, że <math>\left\vert f(n)\right\vert\leq c\cdot\left\vert g(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
Linia 70: Linia 65:
Więcej przykładów i ogólniejszych obserwacji poznamy po prezentacji pozostałych pojęć i symboli notacji asymptotycznej.
Więcej przykładów i ogólniejszych obserwacji poznamy po prezentacji pozostałych pojęć i symboli notacji asymptotycznej.


<div class="thumb tright"><div style="width:350px;">
[[File:SW_7.2.svg|350x350px|thumb|right|SW_7.2.swf]]
<flash>file=SW_7.2.swf|width=350|height=350</flash>
<div.thumbcaption>SW_7.2.swf</div></div>
</div>


{{kotwica|funasymptm|'''Funkcja asymptotycznie niemniejsza'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, dla której istnieją <math>c>0</math> i <math>n_0\in\mathbb{N}</math>, że <math>c\cdot\left\vert g(n)\right\vert\leq \left\vert f(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
{{kotwica|funasymptm|'''Funkcja asymptotycznie niemniejsza'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, dla której istnieją <math>c>0</math> i <math>n_0\in\mathbb{N}</math>, że <math>c\cdot\left\vert g(n)\right\vert\leq \left\vert f(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
Linia 86: Linia 78:


{{kotwica|funasymptmn|'''Funkcja asymptotycznie mniejsza'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, że dla każdego <math>c>0</math> istnieje <math>n_0\in\mathbb{N}</math>, przy którym <math>\left\vert f(n)\right\vert<c\cdot\left\vert g(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
{{kotwica|funasymptmn|'''Funkcja asymptotycznie mniejsza'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, że dla każdego <math>c>0</math> istnieje <math>n_0\in\mathbb{N}</math>, przy którym <math>\left\vert f(n)\right\vert<c\cdot\left\vert g(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
Zbiór funkcji asymptotycznie mniejszych niż <math>g(n)</math> oznaczamy przez <math>o(g(n))</math>. A zatem <math>f(n)= o(g(n))</math> wtedy i tylko wtedy, gdy <math>\displaystyle \lim_{n \rightarrow \infty} \frac{f(n)}{g(n)}=0</math>.
Zbiór funkcji asymptotycznie mniejszych niż <math>g(n)</math> oznaczamy przez <math>o(g(n))</math>. A zatem <math>f(n)= o(g(n))</math> wtedy i tylko wtedy, gdy <math>\lim_{n \rightarrow \infty} \frac{f(n)}{g(n)}=0</math>.


{{kotwica|funasymptwi|'''Funkcja asymptotycznie większa'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, że dla każdego <math>c>0</math> istnieje <math>n_0\in\mathbb{N}</math>, przy którym <math>c\cdot\left\vert g(n)\right\vert<\left\vert f(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
{{kotwica|funasymptwi|'''Funkcja asymptotycznie większa'''}} od funkcji <math>g(n)</math> to taka funkcja <math>f: \mathbb{N} \longrightarrow \mathbb{R}</math>, że dla każdego <math>c>0</math> istnieje <math>n_0\in\mathbb{N}</math>, przy którym <math>c\cdot\left\vert g(n)\right\vert<\left\vert f(n)\right\vert</math> dla wszystkich <math>n\geq n_0</math>.<br>
Zbiór funkcji asymptotycznie większych niż <math>g(n)</math> oznaczamy przez <math>\omega(g(n))</math>. A zatem <math>f(n)=\omega(g(n))</math> wtedy i tylko wtedy, gdy <math>\displaystyle \lim_{n \rightarrow \infty} \frac{g(n)}{f(n)}=0</math>.
Zbiór funkcji asymptotycznie większych niż <math>g(n)</math> oznaczamy przez <math>\omega(g(n))</math>. A zatem <math>f(n)=\omega(g(n))</math> wtedy i tylko wtedy, gdy <math>\lim_{n \rightarrow \infty} \frac{g(n)}{f(n)}=0</math>.


Oto kilka prostych faktów wiążących kolejne symbole asymptotyczne. Pozostawiamy je bez dowodu.
Oto kilka prostych faktów wiążących kolejne symbole asymptotyczne. Pozostawiamy je bez dowodu.
Linia 111: Linia 103:


Symbole asymptotyczne mogą pojawić się w złożonych wyrażeniach arytmetycznych.
Symbole asymptotyczne mogą pojawić się w złożonych wyrażeniach arytmetycznych.
Dla przykładu wspomnijmy jeszcze raz sumę kolejnych kwadratów: <math>\displaystyle \sum_{i=0}^n i^2=\frac{1}{3}n^3+\frac{1}{2}n^2+\frac{1}{6}n</math>. Możemy teraz napisać <math>\displaystyle \sum_{i=0}^ni^2=O(n^3)</math>, ale także <math>\displaystyle \sum_{i=0}^ni^2=\frac{1}{3}n^2+O(n^2)</math>, co formalnie oznacza <math>\displaystyle \sum_{i=0}^ni^2-\frac{1}{3}n^3\in O(n^2)</math>. Co więcej okazuje się, że symbol <math>=</math> może pełnić nie tylko rolę <math>\in</math>, ale czasami także rolę <math>\subseteq</math>. Na przykład wyrażenie
Dla przykładu wspomnijmy jeszcze raz sumę kolejnych kwadratów: <math>\sum_{i=0}^n i^2=\frac{1}{3}n^3+\frac{1}{2}n^2+\frac{1}{6}n</math>. Możemy teraz napisać <math>\sum_{i=0}^ni^2=O(n^3)</math>, ale także <math>\sum_{i=0}^ni^2=\frac{1}{3}n^2+O(n^2)</math>, co formalnie oznacza <math>\sum_{i=0}^ni^2-\frac{1}{3}n^3\in O(n^2)</math>. Co więcej okazuje się, że symbol <math>=</math> może pełnić nie tylko rolę <math>\in</math>, ale czasami także rolę <math>\subseteq</math>. Na przykład wyrażenie




<center><math>\frac{1}{3}n^3+O(n^2)=O(n^3),
<center><math>\frac{1}{3}n^3+O(n^2)=O(n^3)</math>,</center>
</math></center>




Linia 125: Linia 116:


{{obserwacja|9.2|obs 9.2|
{{obserwacja|9.2|obs 9.2|
Dla funkcji <math>\displaystyle f,g,f_1,f_2,g_1,g_2: \mathbb{N} \map \mathbb{R}</math> mamy:
Dla funkcji <math>f,g,f_1,f_2,g_1,g_2: \mathbb{N} \mathbb{R}</math> mamy:
* <math>\displaystyle f(n)=O(f(n))</math>,
* <math>f(n)=O(f(n))</math>,


* <math>\displaystyle f(n)=O(O(g(n)))</math> wtedy i tylko wtedy, gdy <math>\displaystyle f(n)=O(g(n))</math>,
* <math>f(n)=O(O(g(n)))</math> wtedy i tylko wtedy, gdy <math>f(n)=O(g(n))</math>,


* <math>\displaystyle f(n)=O\left\vert (g(n)) \right\vert</math> wtedy i tylko wtedy, gdy <math>\displaystyle f(n)= O(g(n))</math>,
* <math>f(n)=O\left\vert (g(n)) \right\vert</math> wtedy i tylko wtedy, gdy <math>f(n)= O(g(n))</math>,


* <math>\displaystyle f(n)=c\cdot O(g(n))</math> wtedy i tylko wtedy, gdy <math>\displaystyle f(n)=O(g(n))</math>,
* <math>f(n)=c\cdot O(g(n))</math> wtedy i tylko wtedy, gdy <math>f(n)=O(g(n))</math>,


* jeśli <math>\displaystyle f_1(n)= O(g_1(n))</math> i <math>\displaystyle f_2(n)=O(g_2(n))</math>, to <math>\displaystyle f_1(n)+f_2(n)=O(g_1(n))+O(g_2(n))</math>,
* jeśli <math>f_1(n)= O(g_1(n))</math> i <math>f_2(n)=O(g_2(n))</math>, to <math>f_1(n)+f_2(n)=O(g_1(n))+O(g_2(n))</math>,


* jeśli <math>\displaystyle f_1(n)= O(g_1(n))</math> i <math>\displaystyle f_2
* jeśli <math>f_1(n)= O(g_1(n))</math> i <math>f_2
(n)=O(g_2(n))</math>, to <math>\displaystyle f_1(n)\cdot f_2(n)=O(g_1(n)g_2(n))</math>.
(n)=O(g_2(n))</math>, to <math>f_1(n)\cdot f_2(n)=O(g_1(n)g_2(n))</math>.
   
   
}}
}}


{{przyklad|||
{{przyklad|||
Pokażemy, że wielomiany <math>\displaystyle k</math>-tego stopnia są <math>\displaystyle \Theta(n^k)</math>.
Pokażemy, że wielomiany <math>k</math>-tego stopnia są <math>\Theta(n^k)</math>.


Zauważmy najpierw, że jeśli <math>\displaystyle k<l</math> to <math>\displaystyle O(n^k)=O(n^l)</math>, czyli jeśli <math>\displaystyle f(n)\in O(n^k)</math> to <math>\displaystyle f(n)\in O(n^l)</math>. Rozważmy zatem dowolny wielomian <math>\displaystyle k</math>-tego stopnia <math>\displaystyle p(n)=a_kn^k+\ldots+a_1n+a_0</math>, gdzie <math>\displaystyle a_k\neq0</math>. Wtedy  
Zauważmy najpierw, że jeśli <math>k<l</math> to <math>O(n^k)=O(n^l)</math>, czyli jeśli <math>f(n)\in O(n^k)</math> to <math>f(n)\in O(n^l)</math>. Rozważmy zatem dowolny wielomian <math>k</math>-tego stopnia <math>p(n)=a_kn^k+\ldots+a_1n+a_0</math>, gdzie <math>a_k\neq0</math>. Wtedy  




<center><math> \begin{array} {rlll}
<center><math>\begin{array} {rlll}
\left\vert p(n) \right\vert &=\left\vert a_kn^k+\ldots+a_1n+a_0 \right\vert &&\\
\left\vert p(n) \right\vert &=\left\vert a_kn^k+\ldots+a_1n+a_0 \right\vert &&\\
&\leqslant \left\vert a_k \right\vert n^k+\ldots+\left\vert a_1 \right\vert n+\left\vert a_0 \right\vert &\\
&\leqslant \left\vert a_k \right\vert n^k+\ldots+\left\vert a_1 \right\vert n+\left\vert a_0 \right\vert &\\
&=a_k\cdot O(n^k)+\ldots+a_1\cdot O(n)+a_0\cdot O(1)&\textrm{bo}\quad n^i=O(n^i)\\
&=a_k\cdot O(n^k)+\ldots+a_1\cdot O(n)+a_0\cdot O(1)&\text{bo}\quad n^i=O(n^i)\\
&=O(n^k)+\ldots+O(n)+O(1)&\textrm{bo}\quad c\cdot O(n^i) = O(n^i)\\
&=O(n^k)+\ldots+O(n)+O(1)&\text{bo}\quad c\cdot O(n^i) = O(n^i)\\
&=O(n^k)+\ldots+O(n^k)+O(n^k)&\textrm{bo}\quad O(n^i)=O(n^k), \textrm{dla}\quad i\leqslant k\\
&=O(n^k)+\ldots+O(n^k)+O(n^k)&\text{bo}\quad O(n^i)=O(n^k), \text{dla}\quad i\leqslant k\\
&=O(n^k),&\textrm{bo}\quad O(n^k)+O(n^k)= O(n^k)
&=O(n^k),&\text{bo}\quad O(n^k)+O(n^k)= O(n^k)
\end{array}  
\end{array}  
</math></center>
</math></center>




co dowodzi, że <math>\displaystyle p(n)=O(n^k)</math>.
co dowodzi, że <math>p(n)=O(n^k)</math>.


Dla dowodu <math>\displaystyle p(n)=\Omega(n^k)</math>,  
Dla dowodu <math>p(n)=\Omega(n^k)</math>,  
niech <math>\displaystyle a=\max(\left\vert a_{0} \right\vert,\left\vert a_{1} \right\vert,\ldots,\left\vert a_{k-1} \right\vert)</math>.  
niech <math>a=\max(\left\vert a_{0} \right\vert,\left\vert a_{1} \right\vert,\ldots,\left\vert a_{k-1} \right\vert)</math>.  
Wtedy
Wtedy




<center><math>\displaystyle \left\vert a_k \right\vert n^k\geq 2kan^{k-1}\geq 2(\left\vert a_{k-1} \right\vert n^{k-1}+\left\vert a_{k-2} \right\vert n^{k-2}+\ldots+\left\vert a_0 \right\vert)
<center><math>\left\vert a_k \right\vert n^k\geq 2kan^{k-1}\geq 2(\left\vert a_{k-1} \right\vert n^{k-1}+\left\vert a_{k-2} \right\vert n^{k-2}+\ldots+\left\vert a_0 \right\vert)
</math></center>
</math></center>




dla <math>\displaystyle n\geq \frac{2ka}{\left\vert a_k \right\vert}</math>.  
dla <math>n\geq \frac{2ka}{\left\vert a_k \right\vert}</math>.  
Mamy zatem
Mamy zatem




<center><math>\displaystyle \aligned \left\vert p(n) \right\vert &=\left\vert a_kn^k+a_{k-1}n^{k-1}+\ldots+a_0 \right\vert \geqslant\left\vert a_k \right\vert n^k-(\left\vert a_{k-1} \right\vert n^{k-1}+\ldots+\left\vert a_0 \right\vert)\\
<center><math>\begin{align} \left\vert p(n) \right\vert &=\left\vert a_kn^k+a_{k-1}n^{k-1}+\ldots+a_0 \right\vert \geqslant\left\vert a_k \right\vert n^k-(\left\vert a_{k-1} \right\vert n^{k-1}+\ldots+\left\vert a_0 \right\vert)\\
&\geqslant\left\vert a_k \right\vert n^k-kan^{k-1}\geqslant\frac{\left\vert a_k \right\vert n^k}{2},
&\geqslant\left\vert a_k \right\vert n^k-kan^{k-1}\geqslant\frac{\left\vert a_k \right\vert n^k}{2},
\endaligned</math></center>
\end{align}</math></center>




co dowodzi <math>\displaystyle p(n)=\Omega(n^k)</math>.
co dowodzi <math>p(n)=\Omega(n^k)</math>.
}}
}}


{{przyklad|||
{{przyklad|||
Często pojawiają się logarytmy o różnych podstawach.  
Często pojawiają się logarytmy o różnych podstawach.  
Najczęściej są to <math>\displaystyle \lg{n},\ln{n},\log{n}</math>.  
Najczęściej są to <math>\lg{n},\ln{n},\log{n}</math>.  
Z asymptotycznego punktu widzenia wszystkie te funkcje są podobne tzn.  
Z asymptotycznego punktu widzenia wszystkie te funkcje są podobne tzn.  
np. <math>\displaystyle \ln{n}=\Theta(\lg{n})</math> i <math>\displaystyle \log{n}=\Theta(\lg{n})</math>, lub ogólniej:
np. <math>\ln{n}=\Theta(\lg{n})</math> i <math>\log{n}=\Theta(\lg{n})</math>, lub ogólniej:




<center><math>\displaystyle \log_a{n}=\Theta(\log_b{n}),\quad \textrm{dla}\quad a,b>1.</math></center>
<center><math>\log_a{n}=\Theta(\log_b{n}),\quad \text{dla}\quad a,b>1</math>.</center>




Linia 194: Linia 185:




<center><math>\displaystyle \log_a{n}=\frac{1}{\log_b{a}}\cdot\log_b{n},
<center><math>\log_a{n}=\frac{1}{\log_b{a}}\cdot\log_b{n}</math>,</center>
</math></center>




gdzie ta sama stała <math>\displaystyle \frac{1}{\log_b{a}}</math> jest dobra do dolnego i górnego ograniczenia.
gdzie ta sama stała <math>\frac{1}{\log_b{a}}</math> jest dobra do dolnego i górnego ograniczenia.
}}
}}


{{przyklad|||
{{przyklad|||
Dla wielomianów <math>\displaystyle f(n),g(n)</math> rząd ich wielkości wyznaczony jest przez stopień:
Dla wielomianów <math>f(n),g(n)</math> rząd ich wielkości wyznaczony jest przez stopień:
   
   


<center><math>\displaystyle f = O(g)</math> wtedy i tylko wtedy, gdy <math>\displaystyle \deg(f)\leq \deg(g)</math></center>.
<center><math>f = O(g)</math> wtedy i tylko wtedy, gdy <math>\deg(f)\leq \deg(g)</math></center>.
   
   


Linia 211: Linia 201:




<center><math>\displaystyle n, n^2, n^3, n^4, \ldots, n^d, n^{d+1}, \ldots
<center><math>n, n^2, n^3, n^4, \ldots, n^d, n^{d+1}, \ldots
</math></center>
</math></center>


Linia 218: Linia 208:
   
   


<center><math>\displaystyle n^a = O(n^b)</math> wtedy i tylko wtedy, gdy <math>\displaystyle a \leq b</math></center>
<center><math>n^a = O(n^b)</math> wtedy i tylko wtedy, gdy <math>a \leq b</math></center>


   
   
Na przykład:
Na przykład:


*<math>\displaystyle \sqrt{n} \in O(n)</math>,
*<math>\sqrt{n} \in O(n)</math>,


* <math>\displaystyle \sqrt[3]{n} \in O(\sqrt{n})</math>.  
* <math>\sqrt[3]{n} \in O(\sqrt{n})</math>.  


}}
}}


{{przyklad|||
{{przyklad|||
Mamy <math>\displaystyle n \in O(2^n)</math>.  
Mamy <math>n \in O(2^n)</math>.  
Istotnie łatwo dowieść indukcyjnie, że <math>\displaystyle n \leq 2^n</math>.
Istotnie łatwo dowieść indukcyjnie, że <math>n \leq 2^n</math>.


Podobnie <math>\displaystyle n^2 \in O(2^n)</math>. Wiemy już, że każda funkcja liniowa jest w <math>\displaystyle O(2^n)</math>,  
Podobnie <math>n^2 \in O(2^n)</math>. Wiemy już, że każda funkcja liniowa jest w <math>O(2^n)</math>,  
istnieje więc stała <math>\displaystyle c</math> taka, że od pewnego miejsca <math>\displaystyle 2n+1 \leq c\cdot 2^n</math>.
istnieje więc stała <math>c</math> taka, że od pewnego miejsca <math>2n+1 \leq c\cdot 2^n</math>.
<br>
<br>
Pokażemy, że wtedy też <math>\displaystyle n^2 \leq c\cdot 2^n</math>.
Pokażemy, że wtedy też <math>n^2 \leq c\cdot 2^n</math>.
Indukcyjnie  
Indukcyjnie  




<center><math>\displaystyle (n+1)^2 = n^2 +2n +1 \leq c \cdot 2^n +(2n +1) \leq c \cdot 2^n + c \cdot 2^n = c \cdot 2^{n+1}
<center><math>(n+1)^2 = n^2 +2n +1 \leq c \cdot 2^n +(2n +1) \leq c \cdot 2^n + c \cdot 2^n = c \cdot 2^{n+1}
</math></center>
</math></center>




Analogicznie, wiedząc już, że każda funkcja kwadratowa jest w <math>\displaystyle O(2^n)</math>,  
Analogicznie, wiedząc już, że każda funkcja kwadratowa jest w <math>O(2^n)</math>,  
czyli że dla pewnej stałej <math>\displaystyle c</math> od pewnego miejsca mamy { <math>\displaystyle  3n^2 +3n +1 \leq c \cdot 2^n</math>},
czyli że dla pewnej stałej <math>c</math> od pewnego miejsca mamy { <math>3n^2 +3n +1 \leq c \cdot 2^n</math>},
możemy  pokazać indukcyjnie, że <math>\displaystyle n^3 \leq c \cdot 2^n</math>.  
możemy  pokazać indukcyjnie, że <math>n^3 \leq c \cdot 2^n</math>.  
Istotnie
Istotnie




<center><math>\displaystyle (n+1)^3 = n^3 + 3n^2 +3n +1 \leq c \cdot 2^n + c \cdot 2^n = c \cdot 2^{n+1}.
<center><math>(n+1)^3 = n^3 + 3n^2 +3n +1 \leq c \cdot 2^n + c \cdot 2^n = c \cdot 2^{n+1}</math></center>
</math></center>




Ogólnie, dla dowolnego stopnia <math>\displaystyle d</math> mamy <math>\displaystyle n^d \in O(a^n)</math>, o ile tylko <math>\displaystyle a>1</math>.  
Ogólnie, dla dowolnego stopnia <math>d</math> mamy <math>n^d \in O(a^n)</math>, o ile tylko <math>a>1</math>.  
}}
}}


{{przyklad|||
{{przyklad|||
Oczywiście <math>\displaystyle 2^n \leq 3^n</math>, więc <math>\displaystyle 2^n \in O(3^n)</math>.
Oczywiście <math>2^n \leq 3^n</math>, więc <math>2^n \in O(3^n)</math>.
<br>
<br>
Ale <math>\displaystyle 3^n \not\in O(2^n)</math>.  
Ale <math>3^n \not\in O(2^n)</math>.  
Gdyby bowiem <math>\displaystyle 3^n \leq c \cdot 2^n</math> to
Gdyby bowiem <math>3^n \leq c \cdot 2^n</math> to




<center><math>\displaystyle \left(\frac{3}{2}\right)^n = \frac{3^n}{2^n} \leq c,
<center><math>\left(\frac{3}{2}\right)^n = \frac{3^n}{2^n} \leq c</math>,</center>
</math></center>




podczas gdy funkcja wykładnicza <math>\displaystyle \left(\frac{3}{2}\right)^n</math> rośnie do nieskończoności.   
podczas gdy funkcja wykładnicza <math>\left(\frac{3}{2}\right)^n</math> rośnie do nieskończoności.   
Nie może zatem być ograniczona przez żadną stałą <math>\displaystyle c</math>.
Nie może zatem być ograniczona przez żadną stałą <math>c</math>.
<br>
<br>
Ogólnie dla <math>\displaystyle a,b >1</math>, mamy <math>\displaystyle a^n \in O(b^n)</math> wtedy i tylko wtedy, gdy <math>\displaystyle a\leq b</math>.
Ogólnie dla <math>a,b >1</math>, mamy <math>a^n \in O(b^n)</math> wtedy i tylko wtedy, gdy <math>a\leq b</math>.
}}
}}


{{przyklad|||
{{przyklad|||
Mamy <math>\displaystyle 2^n \in O(n!)</math> oraz <math>\displaystyle n! \in O(n^n)</math>.
Mamy <math>2^n \in O(n!)</math> oraz <math>n! \in O(n^n)</math>.
<br>
<br>
Istotnie  
Istotnie  
<math>\displaystyle 2^n \leq 2 \cdot 1 \cdot 2 \cdot 3 \cdot \ldots \cdot n = 2 \cdot n!</math>,  
<math>2^n \leq 2 \cdot 1 \cdot 2 \cdot 3 \cdot \ldots \cdot n = 2 \cdot n!</math>,  
bo każdy czynnik (poza pierwszym) w <math>\displaystyle n!</math> jest równy co najmniej <math>\displaystyle 2</math>.
bo każdy czynnik (poza pierwszym) w <math>n!</math> jest równy co najmniej <math>2</math>.
Pokazuje to, że <math>\displaystyle 2^n \in O(n!)</math>.
Pokazuje to, że <math>2^n \in O(n!)</math>.
<br>
<br>
<br>
<br>
Podobnie  
Podobnie  
<math>\displaystyle n! = 1 \cdot 2 \cdot 3 \cdot \ldots \cdot n \leq n \cdot n \cdot n \cdot \ldots \cdot n = n^n</math>,
<math>n! = 1 \cdot 2 \cdot 3 \cdot \ldots \cdot n \leq n \cdot n \cdot n \cdot \ldots \cdot n = n^n</math>,
bo każdy czynnik w <math>\displaystyle n!</math> jest nie większy niż <math>\displaystyle n</math>.  
bo każdy czynnik w <math>n!</math> jest nie większy niż <math>n</math>.  
}}
}}


Linia 291: Linia 279:


{{obserwacja|9.3|obs 9.3|
{{obserwacja|9.3|obs 9.3|
Oto ciąg funkcji, z których każda jest <math>\displaystyle O</math> od następnej, ale nie od poprzedniej:
Oto ciąg funkcji, z których każda jest <math>O</math> od następnej, ale nie od poprzedniej:




<center><math>\displaystyle \frac{1}{n^n}, \frac{1}{n!}, \ldots, \frac{1}{3^n}, \frac{1}{2^n}, \ldots,
<center><math>\frac{1}{n^n}, \frac{1}{n!}, \ldots, \frac{1}{3^n}, \frac{1}{2^n}, \ldots,
\frac{1}{n^3}, \frac{1}{n^2}, \frac{1}{n \lg n}, \frac{1}{n},
\frac{1}{n^3}, \frac{1}{n^2}, \frac{1}{n \lg n}, \frac{1}{n},
\frac{\lg{n}}{n}, \frac{1}{\sqrt{n}}, \frac{1}{\sqrt[3]{n}}, \ldots,  
\frac{\lg{n}}{n}, \frac{1}{\sqrt{n}}, \frac{1}{\sqrt[3]{n}}, \ldots,  
Linia 304: Linia 292:




<center><math>\displaystyle 1, \lg\lg{n}, \lg{n}, \ldots,
<center><math>1, \lg\lg{n}, \lg{n}, \ldots,
\sqrt[3]{n}, \sqrt{n}, \frac{n}{\lg{n}}, n, n\lg{n}, n\sqrt{n}, n^2, n^3, \ldots,  
\sqrt[3]{n}, \sqrt{n}, \frac{n}{\lg{n}}, n, n\lg{n}, n\sqrt{n}, n^2, n^3, \ldots,  
n^{\lg{n}}, 2^n, 3^n, n!, n^n, 2^{2^n}.
n^{\lg{n}}, 2^n, 3^n, n!, n^n, 2^{2^n}</math></center>
</math></center>




W istocie, gdy <math>\displaystyle g(n)</math>  występuje w tym ciagu wczesniej niż <math>\displaystyle f(n)</math>, to  
W istocie, gdy <math>g(n)</math>  występuje w tym ciagu wczesniej niż <math>f(n)</math>, to  


*<math>\displaystyle g(n)=O(f(n))</math>,
*<math>g(n)=O(f(n))</math>,


*<math>\displaystyle f(n)=o(g(n))</math>.
*<math>f(n)=o(g(n))</math>.


}}
}}
Linia 323: Linia 310:




<center><math>\displaystyle f(n)=
<center><math>f(n)=
\left\{
\left\{
\begin{array} {cl}
\begin{array} {cl}
n,& \textrm{dla} \quad n \quad \textrm{parzystych}\\  
n,& \text{dla} \quad n \quad \text{parzystych}\\  
n^3,& \textrm{dla}\quad n\quad \textrm{nieparzystych}
n^3,& \text{dla}\quad n\quad \text{nieparzystych}
\end{array}  
\end{array}  
\right.
\right.</math></center>
</math></center>




i <math>\displaystyle g(n)=n^2</math> mamy <math>\displaystyle f(n)\neq\Omega(g(n))</math> i <math>\displaystyle f(n)\neq O(g(n))</math>.
i <math>g(n)=n^2</math> mamy <math>f(n)\neq\Omega(g(n))</math> i <math>f(n)\neq O(g(n))</math>.
}}
}}


Linia 342: Linia 328:
w szczególności procedur rekurencyjnych,  
w szczególności procedur rekurencyjnych,  
których złożoność łatwo opisać równaniem rekurencyjnym.  
których złożoność łatwo opisać równaniem rekurencyjnym.  
Niech <math>\displaystyle T(n)</math> będzie funkcją opisującą złożoność czasową pewnego programu,  
Niech <math>T(n)</math> będzie funkcją opisującą złożoność czasową pewnego programu,  
czyli zwracającą liczbę wykonywanych operacji dla danych wielkości <math>\displaystyle n</math>.  
czyli zwracającą liczbę wykonywanych operacji dla danych wielkości <math>n</math>.  
Zazwyczaj nie jesteśmy zainteresowani dokładną liczbą wykonywanych operacji,  
Zazwyczaj nie jesteśmy zainteresowani dokładną liczbą wykonywanych operacji,  
a jedynie dobrym oszacowaniem z góry i czasem z dołu.  
a jedynie dobrym oszacowaniem z góry i czasem z dołu.  
Linia 349: Linia 335:
co na ogół jest zadaniem beznadziejnym,  
co na ogół jest zadaniem beznadziejnym,  
dopuszczamy użycie notacji asymptotycznej  
dopuszczamy użycie notacji asymptotycznej  
i szukamy pewnej "dobrze znanej" funkcji <math>\displaystyle g(n)</math> takiej,  
i szukamy pewnej "dobrze znanej" funkcji <math>g(n)</math> takiej,  
że <math>\displaystyle T(n)=\Theta(g(n))</math>.  
że <math>T(n)=\Theta(g(n))</math>.  
Znając <math>\displaystyle g(n)</math> wiemy w jaki sposób rośnie długość działania programu  
Znając <math>g(n)</math> wiemy w jaki sposób rośnie długość działania programu  
wraz z wzrostem wielkości danych.
wraz z wzrostem wielkości danych.


Równania, o których mówimy często są postaci  
Równania, o których mówimy często są postaci  
<math>\displaystyle T(n)=a\cdot T\left( \left\lfloor\frac{n}{b}\right\rfloor \right)+f(n)</math>,  
<math>T(n)=a\cdot T\left( \left\lfloor\frac{n}{b}\right\rfloor \right)+f(n)</math>,  
czyli aby rozwiązać problem dla danych wielkości <math>\displaystyle n</math>,  
czyli aby rozwiązać problem dla danych wielkości <math>n</math>,  
rozwiązujemy <math>\displaystyle a</math> podproblemów wielkości <math>\displaystyle \left\lfloor\frac{n}{b}\right\rfloor</math>  
rozwiązujemy <math>a</math> podproblemów wielkości <math>\left\lfloor\frac{n}{b}\right\rfloor</math>  
i składamy z nich rozwiązanie całości w dodatkowym czasie <math>\displaystyle f(n)</math>.  
i składamy z nich rozwiązanie całości w dodatkowym czasie <math>f(n)</math>.  
Twierdzenie o rekurencji uniwersalnej wskazuje funkcję asymptotycznie podobną do <math>\displaystyle T(n)</math>  
Twierdzenie o rekurencji uniwersalnej wskazuje funkcję asymptotycznie podobną do <math>T(n)</math>  
w bardzo wielu przypadkach.
w bardzo wielu przypadkach.


{{twierdzenie|9.4 [o rekurencji uniwersalnej]|tw 9.4|
{{twierdzenie|9.4 [o rekurencji uniwersalnej]|tw 9.4|
Dla funkcji <math>\displaystyle T(n)</math> zadanej przez
Dla funkcji <math>T(n)</math> zadanej przez




<center><math>\displaystyle T(n)=
<center><math>T(n)=
\left
\left
\{\begin{array} {ll}
\{\begin{array} {ll}
\Theta(1),& \textrm{dla}\quad n\in \{0,1\}\\  
\Theta(1),& \text{dla}\quad n\in \{0,1\}\\  
a\cdot T\left( \left\lfloor\frac{n}{b}\right\rfloor \right)+f(n),& \textrm{dla}\quad n>1
a\cdot T\left( \left\lfloor\frac{n}{b}\right\rfloor \right)+f(n),& \text{dla}\quad n>1
\end{array}  
\end{array}  
\right.
\right.</math></center>
</math></center>




zachodzi:
zachodzi:
* jeśli <math>\displaystyle f(n)=O(n^{\log_b{a}-\epsi})</math> dla pewnego <math>\displaystyle \epsi>0</math>, to <math>\displaystyle T(n)=\Theta(n^{\log_b{a}})</math>,
* jeśli <math>f(n)=O(n^{\log_b{a}-\epsilon})</math> dla pewnego <math>\epsilon>0</math>, to <math>T(n)=\Theta(n^{\log_b{a}})</math>,


* jeśli <math>\displaystyle f(n)=\Theta(n^{\log_b{a}})</math>, to <math>\displaystyle T(n)=\Theta(n^{\log_b{a}}\lg{n})</math>,
* jeśli <math>f(n)=\Theta(n^{\log_b{a}})</math>, to <math>T(n)=\Theta(n^{\log_b{a}}\lg{n})</math>,


* jeśli <math>\displaystyle f(n)=\Omega(n^{\log_b{a}+\epsi})</math> dla pewnego <math>\displaystyle \epsi>0</math> oraz <math>\displaystyle a f(\frac{n}{b})\leq c f(n)</math> dla pewnego <math>\displaystyle c<1</math> i prawie wszystkich <math>\displaystyle n</math>, to <math>\displaystyle T(n)=\Theta(f(n))</math>.
* jeśli <math>f(n)=\Omega(n^{\log_b{a}+\epsilon})</math> dla pewnego <math>\epsilon>0</math> oraz <math>a f(\frac{n}{b})\leq c f(n)</math> dla pewnego <math>c<1</math> i prawie wszystkich <math>n</math>, to <math>T(n)=\Theta(f(n))</math>.
   
   
}}
}}
Linia 388: Linia 373:
poczynimy kilka uwag i prześledzimy kilka przykładów.
poczynimy kilka uwag i prześledzimy kilka przykładów.


W praktyce na ogół pomijamy opis początkowych wartości funkcji <math>\displaystyle T(n)</math>  
W praktyce na ogół pomijamy opis początkowych wartości funkcji <math>T(n)</math>  
domyślnie przyjmując, że są one <math>\displaystyle \Theta(1)</math>.  
domyślnie przyjmując, że są one <math>\Theta(1)</math>.  
Nie będziemy też używać podłóg w wyrażeniach typu <math>\displaystyle T(\frac{n}{b})</math>,  
Nie będziemy też używać podłóg w wyrażeniach typu <math>T(\frac{n}{b})</math>,  
traktując występujące tu dzielenie jako całkowito-liczbowe.  
traktując występujące tu dzielenie jako całkowito-liczbowe.  
Twierdzenie o rekurencji uniwersalnej jest silnym i praktycznym narzędziem.  
Twierdzenie o rekurencji uniwersalnej jest silnym i praktycznym narzędziem.  
Jednak trzeba podkreślić, że nie szacuje ono rozwiązań  
Jednak trzeba podkreślić, że nie szacuje ono rozwiązań  
wszystkich równań typu <math>\displaystyle T(n)=aT\left( \frac{n}{b} \right)+f(n)</math>.  
wszystkich równań typu <math>T(n)=aT\left( \frac{n}{b} \right)+f(n)</math>.  
Taka niemożność oszacowania może mieć miejsce z jednego z trzech powodów,  
Taka niemożność oszacowania może mieć miejsce z jednego z trzech powodów,  
przy czym drugi z nich jest istotny i zdarza się w praktyce:
przy czym drugi z nich jest istotny i zdarza się w praktyce:
* W każdym z trzech przypadków opisanym w twierdzeniu, porównujemy funkcje <math>\displaystyle n^{\log_b{a}}</math> i <math>\displaystyle f(n)</math>. Może się zdarzyć (jak widzieliśmy w jednym z przykładów), iż <math>\displaystyle n^{\log_b{a}}</math> i <math>\displaystyle f(n)</math> są asymptotycznie nieporównywalne i wobec tego nie będzie można zastosować żadnego z tych trzech przypadków. Na szczęście w praktyce takie funkcje raczej zdarzają się niezmiernie rzadko.
* W każdym z trzech przypadków opisanym w twierdzeniu, porównujemy funkcje <math>n^{\log_b{a}}</math> i <math>f(n)</math>. Może się zdarzyć (jak widzieliśmy w jednym z przykładów), iż <math>n^{\log_b{a}}</math> i <math>f(n)</math> są asymptotycznie nieporównywalne i wobec tego nie będzie można zastosować żadnego z tych trzech przypadków. Na szczęście w praktyce takie funkcje raczej zdarzają się niezmiernie rzadko.
* Po drugie, w przypadku pierwszym (i trzecim), tak naprawdę, porównujemy <math>\displaystyle f(n)</math> z funkcją istotnie mniejszą (wiekszą) od <math>\displaystyle n^{\log_b{a}}</math>, tzn. z funkcją <math>\displaystyle n^{\log_b{a}\pm\epsilon}</math> dla pewnego <math>\displaystyle \epsilon</math>. Ten warunek już może przeszkadzać w praktyce. Dla przykładu <math>\displaystyle n\lg{n}\in\Omega(n)</math>, ale <math>\displaystyle n\lg{n}\notin\Omega(n^{1+\epsilon})</math> dla dowolnego <math>\displaystyle \epsilon>0</math>. Pełny przykład takiego równania przedstawimy poniżej.
* Po drugie, w przypadku pierwszym (i trzecim), tak naprawdę, porównujemy <math>f(n)</math> z funkcją istotnie mniejszą (wiekszą) od <math>n^{\log_b{a}}</math>, tzn. z funkcją <math>n^{\log_b{a}\pm\epsilon}</math> dla pewnego <math>\epsilon</math>. Ten warunek już może przeszkadzać w praktyce. Dla przykładu <math>n\lg{n}\in\Omega(n)</math>, ale <math>n\lg{n}\notin\Omega(n^{1+\epsilon})</math> dla dowolnego <math>\epsilon>0</math>. Pełny przykład takiego równania przedstawimy poniżej.
* Po trzecie, w ostatnim warunku dla <math>\displaystyle f(n)\in\Omega(n^{\log_b{a}+\epsilon})</math> dla dowolnego <math>\displaystyle \epsilon>0</math> wymagamy dodatkowo, żeby <math>\displaystyle af(\frac{n}{b})\leq c f(n)</math> dla pewnego <math>\displaystyle c<1</math> i dla wszystkich <math>\displaystyle n\geq n_0</math> dla pewnego <math>\displaystyle n _0</math>. Znów, na szczęście, w większości spotykanych sytuacji ten warunek "regularności" jest spełniony. Jednak zawsze trzeba go sprawdzić.
* Po trzecie, w ostatnim warunku dla <math>f(n)\in\Omega(n^{\log_b{a}+\epsilon})</math> dla dowolnego <math>\epsilon>0</math> wymagamy dodatkowo, żeby <math>af(\frac{n}{b})\leq c f(n)</math> dla pewnego <math>c<1</math> i dla wszystkich <math>n\geq n_0</math> dla pewnego <math>n _0</math>. Znów, na szczęście, w większości spotykanych sytuacji ten warunek "regularności" jest spełniony. Jednak zawsze trzeba go sprawdzić.
   
   
{{przyklad|||
{{przyklad|||
Linia 405: Linia 390:




<center><math>\displaystyle T(n)=16T\left( \frac{n}{4} \right)+n\lg{n},
<center><math>T(n)=16T\left( \frac{n}{4} \right)+n\lg{n}</math>,</center>
</math></center>




dostajemy kolejno:
dostajemy kolejno:
* <math>\displaystyle a=16</math>, <math>\displaystyle b=4</math>, <math>\displaystyle f(n)=n\lg{n}</math>,
* <math>a=16</math>, <math>b=4</math>, <math>f(n)=n\lg{n}</math>,
* <math>\displaystyle n^{\log_4{16}}=n^2</math>, <math>\displaystyle f(n)=O(n^{2-\epsilon})</math>, np. dla <math>\displaystyle \epsilon=0.5</math>,
* <math>n^{\log_4{16}}=n^2</math>, <math>f(n)=O(n^{2-\epsilon})</math>, np. dla <math>\epsilon=0.5</math>,
* zatem z pierwszego punktu [[#tw 9.4|Twierdzenia 9.4]] mamy <math>\displaystyle T(n)=\Theta(n^2)</math>.
* zatem z pierwszego punktu [[#tw 9.4|Twierdzenia 9.4]] mamy <math>T(n)=\Theta(n^2)</math>.
   
   
Podobnie dla funkcji
Podobnie dla funkcji




<center><math>\displaystyle T(n)=2T\left( \frac{n}{2} \right)+5n-15,
<center><math>T(n)=2T\left( \frac{n}{2} \right)+5n-15</math>,</center>
</math></center>




mamy:
mamy:
* <math>\displaystyle a=2</math>, <math>\displaystyle b=2</math>, <math>\displaystyle f(n)=5n-15</math>,
* <math>a=2</math>, <math>b=2</math>, <math>f(n)=5n-15</math>,
* <math>\displaystyle n^{\log_2{2}}=n</math>, <math>\displaystyle f(n)=\Theta(n)</math>,
* <math>n^{\log_2{2}}=n</math>, <math>f(n)=\Theta(n)</math>,
* zatem z drugiego punktu [[#tw 9.4|Twierdzenia 9.4]] mamy <math>\displaystyle T(n)=\Theta(n\lg{n})</math>.
* zatem z drugiego punktu [[#tw 9.4|Twierdzenia 9.4]] mamy <math>T(n)=\Theta(n\lg{n})</math>.
   
   
Niech teraz  
Niech teraz  




<center><math>\displaystyle T(n)=2T\left( \frac{n}{3} \right)+n\lg{n}.
<center><math>T(n)=2T\left( \frac{n}{3} \right)+n\lg{n}</math></center>
</math></center>




Wtedy
Wtedy
* <math>\displaystyle a=2</math>, <math>\displaystyle b=3</math>, <math>\displaystyle f(n)=n\lg{n}</math>,
* <math>a=2</math>, <math>b=3</math>, <math>f(n)=n\lg{n}</math>,
* <math>\displaystyle n^{\log_3{2}}\approx n^{0.6309}</math>, <math>\displaystyle f(n)\in\Omega(n^{\log_3{2}-\epsilon})</math> dla <math>\displaystyle \epsilon=0.1</math>,
* <math>n^{\log_3{2}}\approx n^{0.6309}</math>, <math>f(n)\in\Omega(n^{\log_3{2}-\epsilon})</math> dla <math>\epsilon=0.1</math>,
* <math>\displaystyle af(\frac{n}{b})\leq 2\cdot \frac{n}{3}\lg{\frac{n}{3}}\leq \frac{2}{3}n\lg{n}=\frac{2}{3}f(n)</math>,
* <math>af(\frac{n}{b})\leq 2\cdot \frac{n}{3}\lg{\frac{n}{3}}\leq \frac{2}{3}n\lg{n}=\frac{2}{3}f(n)</math>,
* zatem z trzeciego punktu [[#tw 9.4|Twierdzenia 9.4]] mamy <math>\displaystyle T(n)=\Theta(n\lg{n})</math>.
* zatem z trzeciego punktu [[#tw 9.4|Twierdzenia 9.4]] mamy <math>T(n)=\Theta(n\lg{n})</math>.
   
   
Z kolei dla funkcji spełniającej  
Z kolei dla funkcji spełniającej  




<center><math>\displaystyle T(n)=2T\left( \frac{n}{2} \right)+n\lg{n},
<center><math>T(n)=2T\left( \frac{n}{2} \right)+n\lg{n}</math>,</center>
</math></center>




dostajemy
dostajemy
* <math>\displaystyle a=2</math>, <math>\displaystyle b=2</math>, <math>\displaystyle f(n)=n\lg{n}</math>,
* <math>a=2</math>, <math>b=2</math>, <math>f(n)=n\lg{n}</math>,
* <math>\displaystyle n^{\log_2{2}}=n</math>,
* <math>n^{\log_2{2}}=n</math>,
* <math>\displaystyle n\lg{n}\in\Omega(n)</math> ale dla dowolnego <math>\displaystyle \epsilon>0</math>, <math>\displaystyle n\lg{n}\notin\Omega(n^{1+\epsilon})</math>,
* <math>n\lg{n}\in\Omega(n)</math> ale dla dowolnego <math>\epsilon>0</math>, <math>n\lg{n}\notin\Omega(n^{1+\epsilon})</math>,
* i ... nie można zaaplikować [[#tw 9.4|Twierdzenia 9.4]].  
* i ... nie można zaaplikować [[#tw 9.4|Twierdzenia 9.4]].  
}}
}}
Linia 457: Linia 438:
{{dowod|||
{{dowod|||
Rozumowanie nasze przeprowadzimy tylko w przypadku,  
Rozumowanie nasze przeprowadzimy tylko w przypadku,  
gdy liczba <math>\displaystyle b</math> występująca w rekurencyjnym równaniu zadającym funkcję <math>\displaystyle T(n)</math>  
gdy liczba <math>b</math> występująca w rekurencyjnym równaniu zadającym funkcję <math>T(n)</math>  
jest potęgą liczby naturalnej, czyli dla liczb postaci <math>\displaystyle 1,b,b^2,\ldots</math>.
jest potęgą liczby naturalnej, czyli dla liczb postaci <math>1,b,b^2,\ldots</math>.
Rozszerzenie tego rozumowania na cały zbiór <math>\displaystyle \mathbb{N}</math> jest dość techniczne  
Rozszerzenie tego rozumowania na cały zbiór <math>\mathbb{N}</math> jest dość techniczne  
i wymaga szacowania podłóg.
i wymaga szacowania podłóg.
Ponadto, symboli asymptotycznych będziemy używać tylko dla <math>\displaystyle n\in\left\lbrace 1,b,b^2,\ldots \right\rbrace</math>.
Ponadto, symboli asymptotycznych będziemy używać tylko dla <math>n\in\left\lbrace 1,b,b^2,\ldots \right\rbrace</math>.
To nieformalne nadużycie nie ogranicza poprawności rozumowania --  
To nieformalne nadużycie nie ogranicza poprawności rozumowania --  
wymaga wszakże rozszerzenia notacji asymptotycznej na funkcje postaci
wymaga wszakże rozszerzenia notacji asymptotycznej na funkcje postaci
<math>\displaystyle f: \mathbb{R} \map \mathbb{R}</math>.
<math>f: \mathbb{R} \mathbb{R}</math>.


Rozwijając rekurencyjną formułę <math>\displaystyle T(n)</math> dla <math>\displaystyle n=b^k</math> otrzymujemy:
Rozwijając rekurencyjną formułę <math>T(n)</math> dla <math>n=b^k</math> otrzymujemy:




<center><math>\displaystyle \aligned T(n)&=T(b^k)=f(b^k)+aT(b^{k-1})=f(n)+af(b^{k-1})+a^2T(b^{k-2})=\ldots\\
<center><math>\begin{align} T(n)&=T(b^k)=f(b^k)+aT(b^{k-1})=f(n)+af(b^{k-1})+a^2T(b^{k-2})=\ldots\\
&=f(b^k)+af(b^{k-1})+a^2f(b^{k-2})+\ldots+a^{k-1}f(b)+a^kT(1).
&=f(b^k)+af(b^{k-1})+a^2f(b^{k-2})+\ldots+a^{k-1}f(b)+a^kT(1).
\endaligned</math></center>
\end{align}</math></center>




Ponieważ <math>\displaystyle a^k=a^{\log_b{n}}=a^{\frac{\log_a{n}}{\log_a{b}}}=n^{\log_b{a}}</math> możemy kontynuować:
Ponieważ <math>a^k=a^{\log_b{n}}=a^{\frac{\log_a{n}}{\log_a{b}}}=n^{\log_b{a}}</math> możemy kontynuować:




<center><math>\displaystyle \aligned T(n)&=f(b^k)+af(b^{k-1})+a^2f(b^{k-2})+\ldots+a^{k-1}f(b)+a^kT(1).\\
<center><math>\begin{align} T(n)&=f(b^k)+af(b^{k-1})+a^2f(b^{k-2})+\ldots+a^{k-1}f(b)+a^kT(1).\\
&=\Theta(n^{\log_b{n}})+\sum_{i=0}^{k-1}a^if(b^{k-i}).
&=\Theta(n^{\log_b{n}})+\sum_{i=0}^{k-1}a^if(b^{k-i}).
\endaligned</math></center>
\end{align}</math></center>




Dalsze szacowanie rozbijamy na <math>\displaystyle 3</math> przypadki zgodnie z warunkami na zachowanie  
Dalsze szacowanie rozbijamy na <math>3</math> przypadki zgodnie z warunkami na zachowanie  
funkcji <math>\displaystyle f(n)</math> wobec <math>\displaystyle n^{\log_b{a}}</math>:
funkcji <math>f(n)</math> wobec <math>n^{\log_b{a}}</math>:
* <math>\displaystyle f(n)=O(n^{\log_b{a}-\epsilon})</math>,
* <math>f(n)=O(n^{\log_b{a}-\epsilon})</math>,


<center><math>\displaystyle \aligned T(n)&=\Theta(n^{\log_b{n}})+\sum_{i=0}^{k-1}a^if(b^{k-i})\\
<center><math>\begin{align} T(n)&=\Theta(n^{\log_b{n}})+\sum_{i=0}^{k-1}a^if(b^{k-i})\\
&=\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}a^i\cdot O((b^{k-i})^{\log_b{a}-\epsilon})\\
&=\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}a^i\cdot O((b^{k-i})^{\log_b{a}-\epsilon})\\
&=\Theta(n^{\log_b{a}})+O\left( b^{k(\log_b{a}-\epsilon)}\sum_{i=0}^{k-1}\left( \frac{a}{b^{\log_b{a}-\epsilon}} \right)^i \right)\\
&=\Theta(n^{\log_b{a}})+O\left( b^{k(\log_b{a}-\epsilon)}\sum_{i=0}^{k-1}\left( \frac{a}{b^{\log_b{a}-\epsilon}} \right)^i \right)\\
Linia 493: Linia 474:
&=\Theta(n^{\log_b{a}})+n^{\log_b{a}-\epsilon}\cdot O\left( \frac{b^{k\epsilon}-1}{b^\epsilon-1} \right)\\
&=\Theta(n^{\log_b{a}})+n^{\log_b{a}-\epsilon}\cdot O\left( \frac{b^{k\epsilon}-1}{b^\epsilon-1} \right)\\
&=\Theta(n^{\log_b{a}})+n^{\log_b{a}-\epsilon}\cdot O\left( \frac{n^{\epsilon}-1}{b^\epsilon-1} \right).
&=\Theta(n^{\log_b{a}})+n^{\log_b{a}-\epsilon}\cdot O\left( \frac{n^{\epsilon}-1}{b^\epsilon-1} \right).
\endaligned</math></center>
\end{align}</math></center>




Ponieważ <math>\displaystyle b</math> i <math>\displaystyle \epsilon</math> są stałymi, ostatni składnik redukuje się do  
Ponieważ <math>b</math> i <math>\epsilon</math> są stałymi, ostatni składnik redukuje się do  
<math>\displaystyle n^{\log_b{a}-\epsilon}\cdot O(n^{\epsilon})=O(n^{\log_b{a}})</math>. Zatem
<math>n^{\log_b{a}-\epsilon}\cdot O(n^{\epsilon})=O(n^{\log_b{a}})</math>. Zatem




<center><math>\displaystyle T(n)=\Theta(n^{\log_b{a}})+O(n^{\log_b{a}})=\Theta(n^{\log_b{a}}).
<center><math>T(n)=\Theta(n^{\log_b{a}})+O(n^{\log_b{a}})=\Theta(n^{\log_b{a}})</math></center>
</math></center>


* <math>\displaystyle f(n)=\Theta(n^{\log_b{a}})</math>,
* <math>f(n)=\Theta(n^{\log_b{a}})</math>,


<center><math>\displaystyle \aligned T(n)&=\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}a^if(b^{k-i})\\
<center><math>\begin{align} T(n)&=\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}a^if(b^{k-i})\\
&=\Theta(n^{\log_b{a}})+\Theta\left( \sum_{i=0}^{k-1}\frac{a^ib^{k\lg_b{a}}}{b^{i\log_b{a}}} \right)\\
&=\Theta(n^{\log_b{a}})+\Theta\left( \sum_{i=0}^{k-1}\frac{a^ib^{k\lg_b{a}}}{b^{i\log_b{a}}} \right)\\
&=\Theta(n^{\log_b{a}})+\Theta\left( n^{\log_b{a}}\sum_{i=0}^{k-1}1 \right)\\
&=\Theta(n^{\log_b{a}})+\Theta\left( n^{\log_b{a}}\sum_{i=0}^{k-1}1 \right)\\
&=\Theta(n^{\log_b{a}})+\Theta\left( n^{\log_b{a}}\log_b{n} \right)\\
&=\Theta(n^{\log_b{a}})+\Theta\left( n^{\log_b{a}}\log_b{n} \right)\\
&=\Theta\left( n^{\log_b{a}}\lg{n} \right).
&=\Theta\left( n^{\log_b{a}}\lg{n} \right).
\endaligned</math></center>
\end{align}</math></center>


* <math>\displaystyle af(\frac{n}{b})\leq cf(n)</math> dla pewnego <math>\displaystyle c</math> i prawie wszystkich <math>\displaystyle n</math> <br>
* <math>af(\frac{n}{b})\leq cf(n)</math> dla pewnego <math>c</math> i prawie wszystkich <math>n</math> <br>
oraz <math>\displaystyle f(n)=\Omega(n^{\log_b{a}})</math>.
oraz <math>f(n)=\Omega(n^{\log_b{a}})</math>.


Z założeń tego przypadku mamy <math>\displaystyle a^if(b^{k-i})\leq c^if(n)</math>. Zatem
Z założeń tego przypadku mamy <math>a^if(b^{k-i})\leq c^if(n)</math>. Zatem




<center><math>\displaystyle \aligned T(n)&=\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}a^if(b^{k-i})\\
<center><math>\begin{align} T(n)&=\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}a^if(b^{k-i})\\
&\leqslant\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}c^if(n)\\
&\leqslant\Theta(n^{\log_b{a}})+\sum_{i=0}^{k-1}c^if(n)\\
&\leqslant\Theta(n^{\log_b{a}})+f(n)\sum_{i=0}^{\infty}c^i\\
&\leqslant\Theta(n^{\log_b{a}})+f(n)\sum_{i=0}^{\infty}c^i\\
Linia 524: Linia 504:
&=\Theta(n^{\log_b{a}})+\Theta{f(n)}\\
&=\Theta(n^{\log_b{a}})+\Theta{f(n)}\\
&=\Theta({f(n)}).
&=\Theta({f(n)}).
\endaligned</math></center>
\end{align}</math></center>




Linia 540: Linia 520:




<center><math>\displaystyle \aligned a_0&=1,\\
<center><math>\begin{align} a_0&=1,\\
a_{n+1}&=\frac{1}{n^3}\sum_{i=0}^{n-1}a_i,
a_{n+1}&=\frac{1}{n^3}\sum_{i=0}^{n-1}a_i,
\endaligned</math></center>
\end{align}</math></center>




najpierw dowodzimy indukcyjnie, że <math>\displaystyle 0<a_n\leq 1</math>, czyli <math>\displaystyle a_n=O(1)</math>.  
najpierw dowodzimy indukcyjnie, że <math>0<a_n\leq 1</math>, czyli <math>a_n=O(1)</math>.  
Podstawiając uzyskane oszacowanie do równania rekurencyjnego otrzymujemy:
Podstawiając uzyskane oszacowanie do równania rekurencyjnego otrzymujemy:




<center><math>\displaystyle a_n=\frac{1}{n^3}\sum_{i=0}^{n}a_i=\frac{1}{n^3}\cdot \sum_{i=0}^n O(1)=\frac{1}{n^3}\cdot O\left( \sum_{i=0}^n1 \right)=\frac{1}{n^3}\cdot O(n)=O\left( \frac{1}{n^2} \right).
<center><math>a_n=\frac{1}{n^3}\sum_{i=0}^{n}a_i=\frac{1}{n^3}\cdot \sum_{i=0}^n O(1)=\frac{1}{n^3}\cdot O\left( \sum_{i=0}^n1 \right)=\frac{1}{n^3}\cdot O(n)=O\left( \frac{1}{n^2} \right)</math></center>
</math></center>




Linia 556: Linia 535:




<center><math>\displaystyle \aligned a_n&=\frac{1}{n^3}\sum_{i=0}^na_i=\frac{1}{n^3}\left( a_0+\sum_{i=1}^na_i \right)=\frac{1}{n^3}+\frac{1}{n^3}\sum_{i=1}^{n}O\left( \frac{1}{n^2} \right)= \frac{1}{n^3}+\frac{1}{n^3}O(1)\\
<center><math>\begin{align} a_n&=\frac{1}{n^3}\sum_{i=0}^na_i=\frac{1}{n^3}\left( a_0+\sum_{i=1}^na_i \right)=\frac{1}{n^3}+\frac{1}{n^3}\sum_{i=1}^{n}O\left( \frac{1}{n^2} \right)= \frac{1}{n^3}+\frac{1}{n^3}O(1)\\
&=O\left( \frac{1}{n^3} \right).
&=O\left( \frac{1}{n^3} \right).
\endaligned</math></center>
\end{align}</math></center>




Wykorzystaliśmy tu fakt, iż szereg <math>\displaystyle \sum_{i=0}^{\infty}\frac{1}{i^2}</math> jest zbieżny.
Wykorzystaliśmy tu fakt, iż szereg <math>\sum_{i=0}^{\infty}\frac{1}{i^2}</math> jest zbieżny.
Zauważmy też, że następne powtórzenie podobnej procedury szacującej już nam nic nie da.
Zauważmy też, że następne powtórzenie podobnej procedury szacującej już nam nic nie da.




<center><math>\displaystyle a_n=\frac{1}{n^3}\sum_{i=0}^na_i=\frac{1}{n^3}+\frac{1}{n^3}\sum_{i=1}^nO\left( \frac{1}{n^3} \right)=\frac{1}{n^3}+\frac{1}{n^3}\cdot O\left( \frac{1}{n^2} \right)=O\left( \frac{1}{n^3} \right).
<center><math>a_n=\frac{1}{n^3}\sum_{i=0}^na_i=\frac{1}{n^3}+\frac{1}{n^3}\sum_{i=1}^nO\left( \frac{1}{n^3} \right)=\frac{1}{n^3}+\frac{1}{n^3}\cdot O\left( \frac{1}{n^2} \right)=O\left( \frac{1}{n^3} \right)</math></center>
</math></center>




Linia 572: Linia 550:


{{przyklad|||
{{przyklad|||
Niech ciąg <math>\displaystyle b_n</math> spełnia
Niech ciąg <math>b_n</math> spełnia




<center><math>\displaystyle b_n\cdot\ln{b_n}=n.
<center><math>b_n\cdot\ln{b_n}=n</math></center>
</math></center>




Z monotoniczności funkcji <math>\displaystyle n\ln{n}</math> dostajemy, że <math>\displaystyle 0<b_n<n</math>.  
Z monotoniczności funkcji <math>n\ln{n}</math> dostajemy, że <math>0<b_n<n</math>.  
Podstawiając to oszacowanie za drugie wystąpienie <math>\displaystyle b_n</math> w równaniu otrzymujemy:
Podstawiając to oszacowanie za drugie wystąpienie <math>b_n</math> w równaniu otrzymujemy:




<center><math>\displaystyle n=b_n\cdot\ln{b_n}< b_n\ln{n},
<center><math>n=b_n\cdot\ln{b_n}< b_n\ln{n}</math>,</center>
</math></center>




czyli <math>\displaystyle b_n>\frac{n}{\ln{n}}</math>. Podstawiając powtórnie dostajemy:
czyli <math>b_n>\frac{n}{\ln{n}}</math>. Podstawiając powtórnie dostajemy:




<center><math>\displaystyle n=b_n\ln{b_n}>b_n\cdot\ln{\frac{n}{\ln{n}}},
<center><math>n=b_n\ln{b_n}>b_n\cdot\ln{\frac{n}{\ln{n}}}</math>,</center>
</math></center>




czyli <math>\displaystyle b_n<\frac{n}{\ln{n}-\ln{\ln{n}}}</math>.  
czyli <math>b_n<\frac{n}{\ln{n}-\ln{\ln{n}}}</math>.  
Uzyskaliśmy zatem, że <math>\displaystyle b_n=\Theta\left( \frac{n}{\ln{n}} \right)</math>.
Uzyskaliśmy zatem, że <math>b_n=\Theta\left( \frac{n}{\ln{n}} \right)</math>.
}}
}}


Na zakończenie tego wykładu poznamy jeszcze jeden symbol asymptotyczny.
Na zakończenie tego wykładu poznamy jeszcze jeden symbol asymptotyczny.
Jest on podobny do <math>\displaystyle \Theta</math> lecz znacznie precyzyjniejszy.
Jest on podobny do <math>\Theta</math> lecz znacznie precyzyjniejszy.


{{kotwica|fasymprowne|'''Funkcje asymptotycznie równe'''|}} to takie funkcje  <math>\displaystyle f(n)</math> i <math>\displaystyle g(n)</math>, że   
{{kotwica|fasymprowne|'''Funkcje asymptotycznie równe'''|}} to takie funkcje  <math>f(n)</math> i <math>g(n)</math>, że   




<center><math>\displaystyle \lim_{n\rightarrow\infty}\frac{f(n)}{g(n)}=1.
<center><math>\lim_{n\rightarrow\infty}\frac{f(n)}{g(n)}=1</math></center>
</math></center>




Fakt, że funkcje <math>\displaystyle f(n)</math> i <math>\displaystyle g(n)</math> są asymptotycznie równe zapisujemy jako <math>\displaystyle f(n)\sim g(n)</math>.
Fakt, że funkcje <math>f(n)</math> i <math>g(n)</math> są asymptotycznie równe zapisujemy jako <math>f(n)\sim g(n)</math>.


Jednym z najbardziej znanych przybliżeń asymptotycznych jest  
Jednym z najbardziej znanych przybliżeń asymptotycznych jest  
Linia 616: Linia 590:




<center><math>\displaystyle n!\sim \sqrt{2\pi n}\left( \frac{n}{e} \right)^n.
<center><math>n!\sim \sqrt{2\pi n}\left( \frac{n}{e} \right)^n</math></center>
</math></center>




Linia 625: Linia 598:




<center><math>\displaystyle n!\sim c \cdot n^{n+1/2} e^{-n},
<center><math>n!\sim c \cdot n^{n+1/2} e^{-n}</math>,</center>
</math></center>




dla pewnej stałej <math>\displaystyle c</math>.   
dla pewnej stałej <math>c</math>.   
Wkładem Jamesa Stirlinga było pokazanie, że stałą tą jest <math>\displaystyle c=\sqrt{2\pi}</math>.  
Wkładem Jamesa Stirlinga było pokazanie, że stałą tą jest <math>c=\sqrt{2\pi}</math>.  
Dowód tego oszacowania wykracza poza metody tego kursu.  
Dowód tego oszacowania wykracza poza metody tego kursu.  
W oszacowaniach przez nierówności przydatna jest następująca wersja wzoru Stirlinga:
W oszacowaniach przez nierówności przydatna jest następująca wersja wzoru Stirlinga:




<center><math>\displaystyle \sqrt{2\pi n}\left( \frac{n}{e} \right)^ne^{-(12n+1)}\leq n!\leq \sqrt{2\pi n}\left( \frac{n}{e} \right)^{n}e^{-12n}
<center><math>\sqrt{2\pi n}\left( \frac{n}{e} \right)^ne^{-(12n+1)}\leq n!\leq \sqrt{2\pi n}\left( \frac{n}{e} \right)^{n}e^{-12n}
</math></center>
</math></center>




Innym ważnym przybliżeniem asymptotycznym jest wzór na liczbę podziałów liczby naturalnej <math>\displaystyle n</math> na sumy dodatnich liczb naturalnych, tzn. asymptotyczne przybliżenie funkcji <math>\displaystyle p_n = \sum_{k=1}^n P(n,k) </math> .
Innym ważnym przybliżeniem asymptotycznym jest wzór na liczbę podziałów liczby naturalnej <math>n</math> na sumy dodatnich liczb naturalnych, tzn. asymptotyczne przybliżenie funkcji <math>p_n = \sum_{k=1}^n P(n,k)</math> .


{{twierdzenie|9.6|tw 9.6|
{{twierdzenie|9.6|tw 9.6|




<center><math>\displaystyle p_n \sim \frac{e^{\pi\sqrt{\frac{2n}{3}}}}{4n\sqrt{3}}
<center><math>p_n \sim \frac{e^{\pi\sqrt{\frac{2n}{3}}}}{4n\sqrt{3}}
</math></center>
</math></center>


Linia 650: Linia 622:
}}
}}


Podamy też asymptotyczne przybliżenie na liczbę liczb pierwszych nie większych niż <math>\displaystyle n</math>.
Podamy też asymptotyczne przybliżenie na liczbę liczb pierwszych nie większych niż <math>n</math>.


{{twierdzenie|9.7|tw .7|
{{twierdzenie|9.7|tw .7|
Jeśli <math>\displaystyle \pi(n)</math> oznacza liczbę liczb pierwszych w zbiorze <math>\displaystyle \left\lbrace 1,2,3,\ldots,n \right\rbrace</math>, to
Jeśli <math>\pi(n)</math> oznacza liczbę liczb pierwszych w zbiorze <math>\left\lbrace 1,2,3,\ldots,n \right\rbrace</math>, to




<center><math>\displaystyle \pi(n) \sim \frac{n}{\ln n}  
<center><math>\pi(n) \sim \frac{n}{\ln n}  
</math></center>
</math></center>




}}
}}

Aktualna wersja na dzień 09:09, 12 wrz 2023

Widzieliśmy już, że wskazanie postaci zwartej dla ciągu zadanego równaniem rekurencyjnym jest często zadaniem niełatwym. Do tej pory nie jest znana zwarta postać wielu równań. Na szczęście często jesteśmy w sytuacji, w której zadowoli nas przybliżenie odpowiedzi. Wróćmy do rozważanej wielokrotnie sumy kolejnych kwadratów i=0ni2. Fakt, że jest to wielomian 3-go stopnia zmiennej n, to już wartościowa informacja, często zupełnie wystarczająca. Spotkaliśmy się już nie raz z oszacowaniami poprzez zwykłe nierówności. To podejście często wymaga użycia narzędzi z analizy matematycznej, w szczególności znajdowania ekstremum funkcji.

Przykład

Silnię liczby naturalnej można trywialnie oszacować przez n!=1nnn. Przyjrzyjmy się delikatniejszemu oszacowaniu wskazującemu także dolne ograniczenie na n!.

Najpierw zauważmy, że


(n!)2=(1n)(n1)=i=1ni(n+1i).


Potraktujmy i(n+1i)=14(n+1)2(i12(n+1))2 jako wielomian drugiego stopnia zmiennej i. Łatwo zauważyć, że dla i[1,,n] przybiera on najmniejszą wartość w punkcie i=1, a największą w punkcie i=12(n+1). Zatem dla i{1,,n}  mamy ni(n+1i)14(n+1)2 i dalej


nn(n!)2(14(n+1)2)n,


czyli


nn2n!(n+12)n


Nierówności w oszacowaniach bywają niepotrzebnie krępujące. Zaś wyniki w ten sposób otrzymane, często skupiają naszą uwagę na zbędnych i czasem nieinteresujących detalach. Często bowiem wystarczają nam przybliżone, asymptotyczne oszacowania ciągów lub ogólniej funkcji. Opisują one zachowanie funkcji wraz ze wzrostem argumentu. Podczas przekształceń rachunkowych celowo ograniczamy naszą wiedzę o funkcji, dzięki czemu łatwiej jest rachować i otrzymać zadowalającą postać przybliżającą.

W oszacowaniach asymptotycznych posługujemy się ogólnie przyjętymi symbolami opisującymi asymptotyczne zachowanie jednej funkcji wobec drugiej. Najpowszechniej używany jest symbol O przydatny w analizie górnej granicy asymptotycznej. Po raz pierwszy tego symbolu użył niemiecki teorio-liczbowiec Paul Bachmann w 1894. Prace Edmunda Landau'a (także niemieckiego teorio-liczbowca) spopularyzowały tę notację, stąd czasami O jest nazywany symbolem Landau'a. Notację asymptotyczną wprowadzimy jedynie dla funkcji zdefiniowanych na zbiorze (lub jego podzbiorach postaci k) o wartościach w .

Notacja asymptotyczna

SW_7.1.swf

Funkcja asymptotycznie niewiększa od funkcji g(n) to taka funkcja f:, dla której istnieją c>0 i n0, że |f(n)|c|g(n)| dla wszystkich nn0.
Będziemy też często mówić, że |f(n)|c|g(n)| zachodzi dla prawie wszystkich liczb naturalnych n.
Zbiór funkcji asymptotycznie niewiększych niż g(n) oznaczamy przez O(g(n)).

Ponieważ O(g(n)) jest zbiorem funkcji, poprawnie powinniśmy zapisywać f(n)O(g(n)), gdy f spełnia warunek podany w definicji. Jednak przyjęło się zapisywać f(n)=O(g(n)). Jest to pewne nadużycie symbolu równości =. Jednak tradycja, a jak się niebawem okaże, również i wygoda użycia, są wystarczającym usprawiedliwieniem dla tego nadużycia. W związku z tym napis f(n)=O(g(n)) czytamy "f(n) jest O-duże od g(n)".

Przykład

  • O(1), to zbiór funkcji ograniczonych.

Istotnie warunek |f(n)|c zachodzący dla prawie wszystkich n łatwo jest, poprzez zamianę stałej c na inną c, sprowadzić do warunku |f(n)|c zachodzącego już dla wszystkich n, jako że skończenie wiele wartości |f(n)| dla początkowych n daje się ograniczyć przez stałą.

    • każda funkcja stała jest O(1) np. f(n)=1000 jest O(1), bo |f(n)|=10001000 dla dowolnego n,
    • (1)n=O(1), bo |(1)n|1 dla dowolnego n,
    • 1n=O(1), bo 1n1 dla dowolnego n1,
    • lognn=O(1), bo logn<n dla n1, zatem lognn1 dla n1.
  • O(n) to zbiór funkcji ograniczonych przez funkcję liniową:
    • wszystkie funkcje O(1) są też O(n),
    • 10n+25=O(n), bo |10n+25|11n dla n25,
    • 2n+3logn100=O(n), bo |2n+3logn100|3n dla dowolnego n.
  • O(n2)
    • 3n2+10n1=O(n2),
    • n(n+1)2=O(n2),
    • 3logn+2=O(n2) (funkcja ta jest także O(n) i O(logn)).
  • O(2n)
    • 32n+n=O(2n), bo n2n, a zatem 32n+n42n dla dowolnego n.

Więcej przykładów i ogólniejszych obserwacji poznamy po prezentacji pozostałych pojęć i symboli notacji asymptotycznej.

SW_7.2.swf

Funkcja asymptotycznie niemniejsza od funkcji g(n) to taka funkcja f:, dla której istnieją c>0 i n0, że c|g(n)||f(n)| dla wszystkich nn0.
Zbiór funkcji asymptotycznie niemniejszych niż g(n) oznaczamy przez Ω(g(n)).

Funkcja asymptotycznie podobna do funkcji g(n) to taka funkcja f:, dla której istnieją c0,c1>0 i n0, że c0|g(n)||f(n)|c1|g(n)| dla wszystkich nn0.
Zbiór funkcji asymptotycznie podobnych do g(n) oznaczamy przez Θ(g(n)). A zatem Θ(g(n))=O(g(n))Ω(g(n)).

Pozostałe dwa symbole: o,ω są rzadziej stosowane w informatyce. Wyznaczają one funkcje asymptotycznie, ściśle mniejsze [większe] od podanej funkcji.

Funkcja asymptotycznie mniejsza od funkcji g(n) to taka funkcja f:, że dla każdego c>0 istnieje n0, przy którym |f(n)|<c|g(n)| dla wszystkich nn0.
Zbiór funkcji asymptotycznie mniejszych niż g(n) oznaczamy przez o(g(n)). A zatem f(n)=o(g(n)) wtedy i tylko wtedy, gdy limnf(n)g(n)=0.

Funkcja asymptotycznie większa od funkcji g(n) to taka funkcja f:, że dla każdego c>0 istnieje n0, przy którym c|g(n)|<|f(n)| dla wszystkich nn0.
Zbiór funkcji asymptotycznie większych niż g(n) oznaczamy przez ω(g(n)). A zatem f(n)=ω(g(n)) wtedy i tylko wtedy, gdy limng(n)f(n)=0.

Oto kilka prostych faktów wiążących kolejne symbole asymptotyczne. Pozostawiamy je bez dowodu.

Obserwacja 9.1

Dla funkcji f,g: mamy:

  • jeśli f(n)=O(g(n)), g(n)=O(h(n)), to f(n)=O(h(n)),
  • jeśli f(n)=Ω(g(n)), g(n)=Ω(h(n)), to f(n)=Ω(h(n)),
  • jeśli f(n)=o(g(n)), g(n)=o(h(n)), to f(n)=o(h(n)),
  • jeśli f(n)=ω(g(n)), g(n)=ω(h(n)), to f(n)=ω(h(n)),
  • f(n)=Θ(g(n)) wtedy i tylko wtedy, gdy g(n)=Θ(f(n)),
  • f(n)=O(g(n)) wtedy i tylko wtedy, gdy g(n)=Ω(f(n)),
  • f(n)=o(g(n)) wtedy i tylko wtedy, gdy g(n)=ω(f(n)).

Symbole asymptotyczne mogą pojawić się w złożonych wyrażeniach arytmetycznych. Dla przykładu wspomnijmy jeszcze raz sumę kolejnych kwadratów: i=0ni2=13n3+12n2+16n. Możemy teraz napisać i=0ni2=O(n3), ale także i=0ni2=13n2+O(n2), co formalnie oznacza i=0ni213n3O(n2). Co więcej okazuje się, że symbol = może pełnić nie tylko rolę , ale czasami także rolę . Na przykład wyrażenie


13n3+O(n2)=O(n3),


ma po obu stronach"równości" zbiory funkcji, przy czym po lewej stronie są to wszystkie funkcje postaci 13n3+f(n) dla f(n)=O(n2). W tej sytuacji znak = powinien być formalnie rozumiany jako inkluzja .

Nadużywając znaku "równości" musimy jednak uważać i pamiętać, że w konwencji asymptotycznej taki nadużyty znak = nie jest relacją symetryczną. Rzeczywiście, O(n3)13n3+O(n2), gdyż np. funkcja n3O(n3), ale n313n3+O(n2). Jednak pożytki płynące z takiego "przeciążenia" znaku równości sprawiedliwiają te nadużycia. W następnej Obserwacji w taki właśnie sposób sformułujemy (bez oczywistego dowodu) kilka własności notacji O. Z nich mozna łatwo otrzymać analogiczne własności dla Ω i Θ.

Obserwacja 9.2

Dla funkcji f,g,f1,f2,g1,g2: mamy:

  • f(n)=O(f(n)),
  • f(n)=O(O(g(n))) wtedy i tylko wtedy, gdy f(n)=O(g(n)),
  • f(n)=O|(g(n))| wtedy i tylko wtedy, gdy f(n)=O(g(n)),
  • f(n)=cO(g(n)) wtedy i tylko wtedy, gdy f(n)=O(g(n)),
  • jeśli f1(n)=O(g1(n)) i f2(n)=O(g2(n)), to f1(n)+f2(n)=O(g1(n))+O(g2(n)),
  • jeśli f1(n)=O(g1(n)) i f2(n)=O(g2(n)), to f1(n)f2(n)=O(g1(n)g2(n)).

Przykład

Pokażemy, że wielomiany k-tego stopnia są Θ(nk).

Zauważmy najpierw, że jeśli k<l to O(nk)=O(nl), czyli jeśli f(n)O(nk) to f(n)O(nl). Rozważmy zatem dowolny wielomian k-tego stopnia p(n)=aknk++a1n+a0, gdzie ak0. Wtedy


|p(n)|=|aknk++a1n+a0||ak|nk++|a1|n+|a0|=akO(nk)++a1O(n)+a0O(1)boni=O(ni)=O(nk)++O(n)+O(1)bocO(ni)=O(ni)=O(nk)++O(nk)+O(nk)boO(ni)=O(nk),dlaik=O(nk),boO(nk)+O(nk)=O(nk)


co dowodzi, że p(n)=O(nk).

Dla dowodu p(n)=Ω(nk), niech a=max(|a0|,|a1|,,|ak1|). Wtedy


|ak|nk2kank12(|ak1|nk1+|ak2|nk2++|a0|)


dla n2ka|ak|. Mamy zatem


|p(n)|=|aknk+ak1nk1++a0||ak|nk(|ak1|nk1++|a0|)|ak|nkkank1|ak|nk2,


co dowodzi p(n)=Ω(nk).

Przykład

Często pojawiają się logarytmy o różnych podstawach. Najczęściej są to lgn,lnn,logn. Z asymptotycznego punktu widzenia wszystkie te funkcje są podobne tzn. np. lnn=Θ(lgn) i logn=Θ(lgn), lub ogólniej:


logan=Θ(logbn),dlaa,b>1.


Rzeczywiście, jest to po prostu wzór na zamianę podstaw logarytmu,


logan=1logbalogbn,


gdzie ta sama stała 1logba jest dobra do dolnego i górnego ograniczenia.

Przykład

Dla wielomianów f(n),g(n) rząd ich wielkości wyznaczony jest przez stopień:


f=O(g) wtedy i tylko wtedy, gdy deg(f)deg(g)
.


Ustala to hierarchię rzędów funkcji:


n,n2,n3,n4,,nd,nd+1,


Również dla "stopni" będącymi dowolnymi liczbami dodatnimi mamy:


na=O(nb) wtedy i tylko wtedy, gdy ab


Na przykład:

  • nO(n),
  • n3O(n).

Przykład

Mamy nO(2n). Istotnie łatwo dowieść indukcyjnie, że n2n.

Podobnie n2O(2n). Wiemy już, że każda funkcja liniowa jest w O(2n), istnieje więc stała c taka, że od pewnego miejsca 2n+1c2n.
Pokażemy, że wtedy też n2c2n. Indukcyjnie


(n+1)2=n2+2n+1c2n+(2n+1)c2n+c2n=c2n+1


Analogicznie, wiedząc już, że każda funkcja kwadratowa jest w O(2n), czyli że dla pewnej stałej c od pewnego miejsca mamy { 3n2+3n+1c2n}, możemy pokazać indukcyjnie, że n3c2n. Istotnie


(n+1)3=n3+3n2+3n+1c2n+c2n=c2n+1


Ogólnie, dla dowolnego stopnia d mamy ndO(an), o ile tylko a>1.

Przykład

Oczywiście 2n3n, więc 2nO(3n).
Ale 3n∉O(2n). Gdyby bowiem 3nc2n to


(32)n=3n2nc,


podczas gdy funkcja wykładnicza (32)n rośnie do nieskończoności. Nie może zatem być ograniczona przez żadną stałą c.
Ogólnie dla a,b>1, mamy anO(bn) wtedy i tylko wtedy, gdy ab.

Przykład

Mamy 2nO(n!) oraz n!O(nn).
Istotnie 2n2123n=2n!, bo każdy czynnik (poza pierwszym) w n! jest równy co najmniej 2. Pokazuje to, że 2nO(n!).

Podobnie n!=123nnnnn=nn, bo każdy czynnik w n! jest nie większy niż n.

Jako ćwiczenie pozostawiamy dowód następnej obserwacji.

Obserwacja 9.3

Oto ciąg funkcji, z których każda jest O od następnej, ale nie od poprzedniej:


1nn,1n!,,13n,12n,,1n3,1n2,1nlgn,1n,lgnn,1n,1n3,,1lgn,1lglgn,1


i dalej


1,lglgn,lgn,,n3,n,nlgn,n,nlgn,nn,n2,n3,,nlgn,2n,3n,n!,nn,22n


W istocie, gdy g(n) występuje w tym ciagu wczesniej niż f(n), to

  • g(n)=O(f(n)),
  • f(n)=o(g(n)).

Przykład

Nie każde dwie funkcje są porównywalne asymptotycznie. Na przykład dla funkcji


f(n)={n,dlanparzystychn3,dlannieparzystych


i g(n)=n2 mamy f(n)Ω(g(n)) i f(n)O(g(n)).

Twierdzenie o rekursji uniwersalnej

Podstawowym zastosowaniem notacji asymptotycznej w informatyce jest szacowanie długości działania programów, w szczególności procedur rekurencyjnych, których złożoność łatwo opisać równaniem rekurencyjnym. Niech T(n) będzie funkcją opisującą złożoność czasową pewnego programu, czyli zwracającą liczbę wykonywanych operacji dla danych wielkości n. Zazwyczaj nie jesteśmy zainteresowani dokładną liczbą wykonywanych operacji, a jedynie dobrym oszacowaniem z góry i czasem z dołu. Dlatego zamiast szukać postaci zwartej rozwiązania rekurencyjnego, co na ogół jest zadaniem beznadziejnym, dopuszczamy użycie notacji asymptotycznej i szukamy pewnej "dobrze znanej" funkcji g(n) takiej, że T(n)=Θ(g(n)). Znając g(n) wiemy w jaki sposób rośnie długość działania programu wraz z wzrostem wielkości danych.

Równania, o których mówimy często są postaci T(n)=aT(nb)+f(n), czyli aby rozwiązać problem dla danych wielkości n, rozwiązujemy a podproblemów wielkości nb i składamy z nich rozwiązanie całości w dodatkowym czasie f(n). Twierdzenie o rekurencji uniwersalnej wskazuje funkcję asymptotycznie podobną do T(n) w bardzo wielu przypadkach.

Twierdzenie 9.4 [o rekurencji uniwersalnej]

Dla funkcji T(n) zadanej przez


T(n)={Θ(1),dlan{0,1}aT(nb)+f(n),dlan>1


zachodzi:

  • jeśli f(n)=O(nlogbaϵ) dla pewnego ϵ>0, to T(n)=Θ(nlogba),
  • jeśli f(n)=Θ(nlogba), to T(n)=Θ(nlogbalgn),
  • jeśli f(n)=Ω(nlogba+ϵ) dla pewnego ϵ>0 oraz af(nb)cf(n) dla pewnego c<1 i prawie wszystkich n, to T(n)=Θ(f(n)).

Zanim podamy dowód Twierdzenia 9.4, poczynimy kilka uwag i prześledzimy kilka przykładów.

W praktyce na ogół pomijamy opis początkowych wartości funkcji T(n) domyślnie przyjmując, że są one Θ(1). Nie będziemy też używać podłóg w wyrażeniach typu T(nb), traktując występujące tu dzielenie jako całkowito-liczbowe. Twierdzenie o rekurencji uniwersalnej jest silnym i praktycznym narzędziem. Jednak trzeba podkreślić, że nie szacuje ono rozwiązań wszystkich równań typu T(n)=aT(nb)+f(n). Taka niemożność oszacowania może mieć miejsce z jednego z trzech powodów, przy czym drugi z nich jest istotny i zdarza się w praktyce:

  • W każdym z trzech przypadków opisanym w twierdzeniu, porównujemy funkcje nlogba i f(n). Może się zdarzyć (jak widzieliśmy w jednym z przykładów), iż nlogba i f(n) są asymptotycznie nieporównywalne i wobec tego nie będzie można zastosować żadnego z tych trzech przypadków. Na szczęście w praktyce takie funkcje raczej zdarzają się niezmiernie rzadko.
  • Po drugie, w przypadku pierwszym (i trzecim), tak naprawdę, porównujemy f(n) z funkcją istotnie mniejszą (wiekszą) od nlogba, tzn. z funkcją nlogba±ϵ dla pewnego ϵ. Ten warunek już może przeszkadzać w praktyce. Dla przykładu nlgnΩ(n), ale nlgnΩ(n1+ϵ) dla dowolnego ϵ>0. Pełny przykład takiego równania przedstawimy poniżej.
  • Po trzecie, w ostatnim warunku dla f(n)Ω(nlogba+ϵ) dla dowolnego ϵ>0 wymagamy dodatkowo, żeby af(nb)cf(n) dla pewnego c<1 i dla wszystkich nn0 dla pewnego n0. Znów, na szczęście, w większości spotykanych sytuacji ten warunek "regularności" jest spełniony. Jednak zawsze trzeba go sprawdzić.

Przykład

Dla funkcji zadanej przez:


T(n)=16T(n4)+nlgn,


dostajemy kolejno:

  • a=16, b=4, f(n)=nlgn,
  • nlog416=n2, f(n)=O(n2ϵ), np. dla ϵ=0.5,
  • zatem z pierwszego punktu Twierdzenia 9.4 mamy T(n)=Θ(n2).

Podobnie dla funkcji


T(n)=2T(n2)+5n15,


mamy:

  • a=2, b=2, f(n)=5n15,
  • nlog22=n, f(n)=Θ(n),
  • zatem z drugiego punktu Twierdzenia 9.4 mamy T(n)=Θ(nlgn).

Niech teraz


T(n)=2T(n3)+nlgn


Wtedy

  • a=2, b=3, f(n)=nlgn,
  • nlog32n0.6309, f(n)Ω(nlog32ϵ) dla ϵ=0.1,
  • af(nb)2n3lgn323nlgn=23f(n),
  • zatem z trzeciego punktu Twierdzenia 9.4 mamy T(n)=Θ(nlgn).

Z kolei dla funkcji spełniającej


T(n)=2T(n2)+nlgn,


dostajemy

  • a=2, b=2, f(n)=nlgn,
  • nlog22=n,
  • nlgnΩ(n) ale dla dowolnego ϵ>0, nlgnΩ(n1+ϵ),
  • i ... nie można zaaplikować Twierdzenia 9.4.

Po tych uwagach i przykładach podamy dowód Twierdzenia o rekurencji uniwersalnej.

Dowód

Rozumowanie nasze przeprowadzimy tylko w przypadku, gdy liczba b występująca w rekurencyjnym równaniu zadającym funkcję T(n) jest potęgą liczby naturalnej, czyli dla liczb postaci 1,b,b2,. Rozszerzenie tego rozumowania na cały zbiór jest dość techniczne i wymaga szacowania podłóg. Ponadto, symboli asymptotycznych będziemy używać tylko dla n{1,b,b2,}. To nieformalne nadużycie nie ogranicza poprawności rozumowania -- wymaga wszakże rozszerzenia notacji asymptotycznej na funkcje postaci f:.

Rozwijając rekurencyjną formułę T(n) dla n=bk otrzymujemy:


T(n)=T(bk)=f(bk)+aT(bk1)=f(n)+af(bk1)+a2T(bk2)==f(bk)+af(bk1)+a2f(bk2)++ak1f(b)+akT(1).


Ponieważ ak=alogbn=aloganlogab=nlogba możemy kontynuować:


T(n)=f(bk)+af(bk1)+a2f(bk2)++ak1f(b)+akT(1).=Θ(nlogbn)+i=0k1aif(bki).


Dalsze szacowanie rozbijamy na 3 przypadki zgodnie z warunkami na zachowanie funkcji f(n) wobec nlogba:

  • f(n)=O(nlogbaϵ),
T(n)=Θ(nlogbn)+i=0k1aif(bki)=Θ(nlogba)+i=0k1aiO((bki)logbaϵ)=Θ(nlogba)+O(bk(logbaϵ)i=0k1(ablogbaϵ)i)=Θ(nlogba)+nlogbaϵO(i=0k1(abϵa)i)=Θ(nlogba)+nlogbaϵO(i=0k1biϵ)=Θ(nlogba)+nlogbaϵO(bkϵ1bϵ1)=Θ(nlogba)+nlogbaϵO(nϵ1bϵ1).


Ponieważ b i ϵ są stałymi, ostatni składnik redukuje się do nlogbaϵO(nϵ)=O(nlogba). Zatem


T(n)=Θ(nlogba)+O(nlogba)=Θ(nlogba)
  • f(n)=Θ(nlogba),
T(n)=Θ(nlogba)+i=0k1aif(bki)=Θ(nlogba)+Θ(i=0k1aibklgbabilogba)=Θ(nlogba)+Θ(nlogbai=0k11)=Θ(nlogba)+Θ(nlogbalogbn)=Θ(nlogbalgn).
  • af(nb)cf(n) dla pewnego c i prawie wszystkich n

oraz f(n)=Ω(nlogba).

Z założeń tego przypadku mamy aif(bki)cif(n). Zatem


T(n)=Θ(nlogba)+i=0k1aif(bki)Θ(nlogba)+i=0k1cif(n)Θ(nlogba)+f(n)i=0ci=Θ(nlogba)+f(n)11c=Θ(nlogba)+Θf(n)=Θ(f(n)).


Metoda przybliżeń

W pewnych sytuacjach łatwiejsze do uzyskania, ale słabsze oszacowanie zastosowane w odpowiedni sposób może prowadzić do lepszego końcowego szacowania zachowania asymptotycznego. Poznamy tę metodę w kilku kolejnych przykładach.

Przykład

Dla ciągu zadanego przez


a0=1,an+1=1n3i=0n1ai,


najpierw dowodzimy indukcyjnie, że 0<an1, czyli an=O(1). Podstawiając uzyskane oszacowanie do równania rekurencyjnego otrzymujemy:


an=1n3i=0nai=1n3i=0nO(1)=1n3O(i=0n1)=1n3O(n)=O(1n2)


Operację tę możemy powtórzyć uzyskując jeszcze lepsze oszacowanie


an=1n3i=0nai=1n3(a0+i=1nai)=1n3+1n3i=1nO(1n2)=1n3+1n3O(1)=O(1n3).


Wykorzystaliśmy tu fakt, iż szereg i=01i2 jest zbieżny. Zauważmy też, że następne powtórzenie podobnej procedury szacującej już nam nic nie da.


an=1n3i=0nai=1n3+1n3i=1nO(1n3)=1n3+1n3O(1n2)=O(1n3)


Przykład

Niech ciąg bn spełnia


bnlnbn=n


Z monotoniczności funkcji nlnn dostajemy, że 0<bn<n. Podstawiając to oszacowanie za drugie wystąpienie bn w równaniu otrzymujemy:


n=bnlnbn<bnlnn,


czyli bn>nlnn. Podstawiając powtórnie dostajemy:


n=bnlnbn>bnlnnlnn,


czyli bn<nlnnlnlnn. Uzyskaliśmy zatem, że bn=Θ(nlnn).

Na zakończenie tego wykładu poznamy jeszcze jeden symbol asymptotyczny. Jest on podobny do Θ lecz znacznie precyzyjniejszy.

Funkcje asymptotycznie równe to takie funkcje f(n) i g(n), że


limnf(n)g(n)=1


Fakt, że funkcje f(n) i g(n) są asymptotycznie równe zapisujemy jako f(n)g(n).

Jednym z najbardziej znanych przybliżeń asymptotycznych jest tzw. Wzór Stirlinga przybliżający zachowanie silni.

Twierdzenie 9.5 [wzór Stirlinga]


n!2πn(ne)n


Wzór ten został odkryty przez Abrahama de Moivre w postaci


n!cnn+1/2en,


dla pewnej stałej c. Wkładem Jamesa Stirlinga było pokazanie, że stałą tą jest c=2π. Dowód tego oszacowania wykracza poza metody tego kursu. W oszacowaniach przez nierówności przydatna jest następująca wersja wzoru Stirlinga:


2πn(ne)ne(12n+1)n!2πn(ne)ne12n


Innym ważnym przybliżeniem asymptotycznym jest wzór na liczbę podziałów liczby naturalnej n na sumy dodatnich liczb naturalnych, tzn. asymptotyczne przybliżenie funkcji pn=k=1nP(n,k) .

Twierdzenie 9.6


pneπ2n34n3


Podamy też asymptotyczne przybliżenie na liczbę liczb pierwszych nie większych niż n.

Twierdzenie 9.7

Jeśli π(n) oznacza liczbę liczb pierwszych w zbiorze {1,2,3,,n}, to


π(n)nlnn