Processing math: 100%

Notacja asymptotyczna

Funkcja asymptotycznie niewiększa od funkcji g(n) to taka funkcja f:NR, dla której istnieją c>0 i n0N, ż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 nN, 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.

Funkcja asymptotycznie niemniejsza od funkcji g(n) to taka funkcja f:NR, dla której istnieją c>0 i n0N, ż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:NR, dla której istnieją c0,c1>0 i n0N, ż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:NR, że dla każdego c>0 istnieje n0N, 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:NR, że dla każdego c>0 istnieje n0N, 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:NR 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: ni=0i2=13n3+12n2+16n. Możemy teraz napisać ni=0i2=O(n3), ale także ni=0i2=13n2+O(n2), co formalnie oznacza ni=0i213n3O(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:NR 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),
  • 3nO(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 3nO(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,13n,,1lgn,1lglgn,1

i dalej

1,lglgn,lgn,,3n,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)).