Funkcja asymptotycznie niewiększa od funkcji g(n) to taka funkcja f:N⟶R, dla której istnieją c>0 i n0∈N, że |f(n)|≤c⋅|g(n)| dla wszystkich n≥n0.
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
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∈N, jako że skończenie wiele wartości |f(n)| dla początkowych n daje się ograniczyć przez stałą.
Więcej przykładów i ogólniejszych obserwacji poznamy po prezentacji pozostałych pojęć i symboli notacji asymptotycznej.
Funkcja asymptotycznie niemniejsza od funkcji g(n) to taka funkcja f:N⟶R, dla której istnieją c>0 i n0∈N, że c⋅|g(n)|≤|f(n)| dla wszystkich n≥n0.
Zbiór funkcji asymptotycznie niemniejszych niż g(n) oznaczamy przez Ω(g(n)).
Funkcja asymptotycznie podobna do funkcji g(n) to taka funkcja f:N⟶R, dla której istnieją c0,c1>0 i n0∈N, że c0⋅|g(n)|≤|f(n)|≤c1⋅|g(n)| dla wszystkich n≥n0.
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:N⟶R, że dla każdego c>0 istnieje n0∈N, przy którym |f(n)|<c⋅|g(n)| dla wszystkich n≥n0.
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 limn→∞f(n)g(n)=0.
Funkcja asymptotycznie większa od funkcji g(n) to taka funkcja f:N⟶R, że dla każdego c>0 istnieje n0∈N, przy którym c⋅|g(n)|<|f(n)| dla wszystkich n≥n0.
Zbiór funkcji asymptotycznie większych niż g(n) oznaczamy przez ω(g(n)). A zatem f(n)=ω(g(n)) wtedy i tylko wtedy, gdy limn→∞g(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:N⟶R mamy:
Symbole asymptotyczne mogą pojawić się w złożonych wyrażeniach arytmetycznych. Dla przykładu wspomnijmy jeszcze raz sumę kolejnych kwadratów: n∑i=0i2=13n3+12n2+16n. Możemy teraz napisać n∑i=0i2=O(n3), ale także n∑i=0i2=13n2+O(n2), co formalnie oznacza n∑i=0i2−13n3∈O(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 n3∈O(n3), ale n3∉13n3+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:NR mamy:
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 ak≠0. Wtedy
|p(n)|=|aknk+…+a1n+a0|≤|ak|nk+…+|a1|n+|a0|=ak⋅O(nk)+…+a1⋅O(n)+a0⋅O(1)boni=O(ni)=O(nk)+…+O(n)+O(1)boc⋅O(ni)=O(ni)=O(nk)+…+O(nk)+O(nk)boO(ni)=O(nk),dlai≤k=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|,…,|ak−1|). Wtedy
|ak|nk≥2kank−1≥2(|ak−1|nk−1+|ak−2|nk−2+…+|a0|)
dla n≥2ka|ak|. Mamy zatem
|p(n)|=|aknk+ak−1nk−1+…+a0|≥|ak|nk−(|ak−1|nk−1+…+|a0|)≥|ak|nk−kank−1≥|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=1logba⋅logbn,
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 a≤b
Na przykład:
Przykład
Mamy n∈O(2n). Istotnie łatwo dowieść indukcyjnie, że n≤2n.
Podobnie n2∈O(2n). Wiemy już, że każda funkcja liniowa jest w O(2n), istnieje więc stała c taka, że od pewnego miejsca 2n+1≤c⋅2n.
Pokażemy, że wtedy też n2≤c⋅2n. Indukcyjnie
(n+1)2=n2+2n+1≤c⋅2n+(2n+1)≤c⋅2n+c⋅2n=c⋅2n+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+1≤c⋅2n}, możemy pokazać indukcyjnie, że n3≤c⋅2n. Istotnie
(n+1)3=n3+3n2+3n+1≤c⋅2n+c⋅2n=c⋅2n+1.
Ogólnie, dla dowolnego stopnia d mamy nd∈O(an), o ile tylko a>1.
Przykład
Oczywiście 2n≤3n, więc 2n∈O(3n).
Ale 3n∉O(2n). Gdyby bowiem 3n≤c⋅2n to
(32)n=3n2n≤c,
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 an∈O(bn) wtedy i tylko wtedy, gdy a≤b.
Przykład
Mamy 2n∈O(n!) oraz n!∈O(nn).
Istotnie 2n≤2⋅1⋅2⋅3⋅…⋅n=2⋅n!, bo każdy czynnik (poza pierwszym) w n! jest równy co najmniej 2. Pokazuje to, że 2n∈O(n!).
Podobnie n!=1⋅2⋅3⋅…⋅n≤n⋅n⋅n⋅…⋅n=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,1√n,13√n,…,1lgn,1lglgn,1
i dalej
1,lglgn,lgn,…,3√n,√n,nlgn,n,nlgn,n√n,n2,n3,…,nlgn,2n,3n,n!,nn,22n.
W istocie, gdy g(n) występuje w tym ciagu wczesniej niż f(n), to
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)).