Notazioni asintotiche
Martedì 30 settembre 2014
• Punto della situazione
– Cos’è un algoritmo
– Tempo di esecuzione T(n)
– Analisi di algoritmi: analisi asintotica di T(n)
• Argomento di oggi:
– Notazioni asintotiche: matematica!
• Motivazioni:
– Confrontare tempi di esecuzione di algoritmi fra
loro o con funzioni standard (lineare, polinomiale,
esponenziale…)
• Argomento lezione precedente: Tempo di
esecuzione di un algoritmo
E’ tutto chiaro?
Ricerca del massimo
Esempio: ricerca del massimo fra n numeri a1, … , an.
Un algoritmo (in pseudocodice):
max = a1
For i = 2 to n
If (ai > max) then
max = ai
Endif
Endfor
Pseudocodice di [KT]
max  a1
for i = 2 to n {
if (ai > max)
max  ai
}
Pseudocodice di [CLRS]
Struttura di un algoritmo (non ricorsivo)
Può essere costituito da:
• Una singola istruzione elementare
• Un blocco sequenziale di istruzioni (allo stesso livello di
indentazione)
• Un’istruzione if: If(cond) then istr1
Else istr2 Endif
• Un ciclo o loop for, while, repeat:
– For i=a to b {istr} Endfor
– While (cond){istr}
– Repeat {istr} until (cond)
Struttura dell’esempio
1.
2.
3.
4.
5.
6.
max = a1
For i = 2 to n
If (ai > max) then
max = ai
Endif
Endfor
E’ un blocco di 2 istruzioni:
1. Assegnamento
2-6. For
L’istruzione For delle linee 2-6 è:
For i=a to b {istr0} Endfor
dove istr0 è l’istruzione if delle linee 3-5
L’istruzione If delle linee 3-5 è:
If(cond) then istr1 Else istr2 Endif
dove cond è il confronto: ai > max
istr1 è l’assegnamento: max = ai
istr2 è vuota
Regole per il calcolo di T(n) (caso non ricorsivo)
• il costo di un blocco sequenziale di istruzioni è pari
alla somma dei costi delle singole istruzioni
Altri esempi
• Insertion-Sort su CLRS
• In seguito semplificheremo l’analisi con
notazioni asintotiche
Tempo di esecuzione
Tempo di esecuzione T(n) sarà misurato in termini del
numero di operazioni elementari per eseguire l’algoritmo su un
input di taglia n
Assegnamento, incremento, confronto sono considerate
operazioni elementari all’interno dell’algoritmo della ricerca del
massimo.
Richiedono tempo costante (= non dipendente dalla taglia n
dell’input) ma a priori non quantificabile
Analisi asintotica
Vogliamo analizzare l’efficienza dell’algoritmo
• Indipendentemente da implementazione, hardware etc.
• Al crescere della taglia dell’input
Studieremo il tempo in funzione della taglia dell’input : T(n)
Studieremo la crescita della funzione T(n) al crescere di n
•
•
•
•
«asintotica»:
per n arbitrariamente grande
per n che tende a infinito
da un certo punto in poi
per ogni n ≥ n0
Vantaggi dell’analisi asintotica
• Indipendente da hardware
• Effettuabile con pseudocodice prima di
implementare l’algoritmo
• Considera infiniti input
Alternativa? Analisi su dati campione.
Svantaggi: bisogna avere già implementato l’algoritmo;
analizza numero finito di dati
Caso peggiore, migliore, medio
Analisi del caso peggiore: qualunque sia la distribuzione
dell’input T(n) è limitata superiormente da f(n)
Analisi del caso migliore: qualunque sia la distribuzione
dell’input T(n) è limitata inferiormente da g(n) (poco
significativa)
Analisi del caso medio: nel caso di una distribuzione media o
random (difficile da determinare)
Notazioni asintotiche
Nell’analisi asintotica analizziamo T(n)
1. A meno di costanti moltiplicative (perché non quantificabili)
2. Asintoticamente (per considerare input di taglia arbitrariamente
grande, quindi in numero infinito)
Le notazioni asintotiche:
O, Ω, Θ, o, ω
ci permetteranno il confronto tra funzioni, mantenendo queste
caratteristiche.
Idea di fondo: O, Ω , Θ, o, ω rappresentano rispettivamente
≤ , ≥ , =, <, >
in un’analisi asintotica
Funzioni T(n)
Se T(n) rappresenta un tempo di esecuzione su
un input di taglia n, allora:
n è un intero positivo
T(n) è un reale positivo
T: N R+
Inoltre T(n) è una funzione non decrescente
Funzioni standard
Fra le funzioni non decrescenti T: N R+ ci
interesseranno principalmente le seguenti (e le
loro combinazioni):
T1(n) = c, con c costante
T2 (n)=log n
T3 (n)=n
T4 (n)=n2
T5 (n)= 2n
Ordini di infinito
Le funzioni c, log n, n, n2, 2n sono tutte funzioni
positive di variabile positiva e non decrescenti,
ma hanno una diversa crescita asintotica, ovvero
un diverso ordine di infinito (come si dice in
analisi matematica).
Le notazioni O, Ω, Θ, o, ω misurano questo.
Grafici delle funzioni
2n
log 2 0 tende a -
log 2 1 = 0
log 2 2 =1
log 2 n ≤ n per ogni n ≥ 1
n
T(n)
n2
log 2 n
3
3 ≤ log 2 n per ogni n ≥ 8
n
Approssimativamente….
n ≤ n2 per ogni n ≥ 1
Un altro esempio
log2(2n+1) = O( n+5 )
 c, n0, t.c. log2(2n+1) ≤ c ( n+5 ) per ogni n ≥n0
Se 1 ≤ n
log2 (2n+1) ≤
≤ log2 (2n+n) = log2 (3n) = log2 (3)+ log2 (n) ≤ 1,585+ log2 n≤
≤ 5 + log2 n ≤ 5+n
Se log 2 n ≤ n
n≥1
c=1
n 0 =1
Esempio
n2 - 2n +1 = O(n2)
1. (tecnica per i polinomi)
n2 - 2n +1 ≤ n2 + 2n +1 ≤ n2 + 2n2 +1 ≤ n2 +2n2+n2 = 4 n2
c = 4, n0=1
2. n2 - 2n +1 ≤ n2 +1 ≤ n2 + n2 =2n2
c = 2, n0=1
3. (disequazioni) n2 - 2n +1 ≤ 2 n2 sse n2 + 2n - 1 ≥ 0
n ≤ -1-√2 ed n ≥ -1+ √2
c = 2, n0=1
4. n2 - 2n +1 =(n-1) 2 ≤ n2
c = 1, n0=1
Nota: se esiste un coppia (c, n0), ne esistono infinite, ma per
dimostrare O ne basta esibire 1 sola.
Esempio (errore tipico)
n2 + 5 = O(10n) ?
Dimostrazione (forse)
L’affermazione è Vera, perché per c=1, n2 + 5 ≤ 10 n per ogni n ≥ 1.
Infatti:
per n=1, 12 + 5 ≤ 10; per n=2, 22 + 5 ≤ 20; per n=3, 32 + 5 ≤ 30; per n=9, 92 + 5 ≤ 90.
Fine della prova!
La dimostrazione non è corretta perché ho dimostrato l’affermazione solo per
alcuni valori di n ≥ 1, e non per ogni n ≥ 1.
Si può dimostrare che n2 + 5 ≤ 10 n, solo per i valori compresi fra 1 e 9, risolvendo la
disequazione di secondo grado.
Inoltre …..
Esempio (continua)
Inoltre si può dimostrare che:
non esistono costanti c > 0, n0 ≥0, tali che n2 + 5 ≤ c n per ogni n ≥ n0.
Infatti:
n2 + 5 ≤ c n per ogni n ≥ n0 sse c ≥ (n2 + 5 )/n per ogni n ≥ n0, cioè sse
c ≥ n + 5 /n per ogni n ≥ n0: assurdo! Una costante non può superare
una quantità che cresce all’infinito, per ogni n ≥ n0 !
n2 + 5 ≠ O(n)
Notazione asintotica Ω
Notazione duale di O:
f(n) = Ω (g(n))
se esistono costanti c > 0, n0 ≥0 tali che per ogni n ≥ n0
si ha f(n) ≥ c · g(n)
ovvero hanno lo stesso ordine di infinito
Θ limitazione esatta
Θ è una limitazione esatta (tight bound)
Esempio
log 2 n = (log3 n)
 c, n0, t.c. c1 log3 n ≤ log2 n ≤ c2 log3 n per ogni n ≥n0
log2 n ≥ log3 n = c1  log3 n, per n≥1
log2 n = log2 3  log3 n = c2  log3 n, per n≥1
c1=1, c2= log2 3, n0 = 1
Notazione «o piccolo»
Per indicare che f(n)=O(g(n)) ma f(n) ≠ Θ (g(n)) si scrive:
f(n)=o(g(n)) (o «piccolo»)
Equivale a dire che:
per ogni costante c > 0, esiste nc ≥0, tale che
f(n)≤ c g(n) per ogni n ≥ nc.
Esempio: n=o(n2)
Per ogni valore di c,
n ≤ c n2 non appena c n2 ≥ n, c n ≥ 1, n ≥ 1/c.
Quindi fissato c basterà scegliere come nc un intero nc ≥ 1/c.
Per c=2, sceglierò un intero n2 ≥ 1/2, n2 = 1.
Per c=1/10, sceglierò un intero nc ≥ 10, nc = 10.
etc.
Notazione «o piccolo» (continua)
Per indicare che f(n)=O(g(n)) ma f(n) ≠ Θ (g(n)) si scrive:
f(n)=o(g(n)) (o «piccolo»)
Equivale a dire che:
per ogni costante c > 0, esiste nc ≥0, tale che
f(n)≤ c g(n) per ogni n ≥ nc.
Esempio: 2n+1=o(n) ?
Dimostro che: 2n+1=O(n).
2n+1 ≤ 2n+n=3n quindi 2n+1 ≤ c (n) é vera con c=3, n0=1.
Ma 2n+1 ≤ c (n) non é vera per ogni valore di c:
per c=1, 2, non esistono valori di n0 opportuni.
Infatti 2n+1= Θ (n)
Notazione «omega piccolo»
Notazione duale di «o piccolo»:
f(n) = ω (g(n))
f(n)=(g(n)) ma f(n) ≠ Θ (g(n))
ovvero
per ogni costante c > 0, esiste nc ≥0, tale che
f(n) ≥ c g(n) per ogni n ≥ nc.
f(n) = ω (g(n)) se e solo se g(n) = o(f(n))
In termini di analisi …. matematica
(ovvero f(n)=o(g(n)) )
(ovvero g(n)=o(f(n)))
più precisamente:
log n=o(radice(n))
Notation
• Slight abuse of notation. T(n) = O(f(n)).
– Asymmetric:
• f(n) = 5n3; g(n) = 3n2
• f(n) = O(n3) = g(n)
• but f(n)  g(n).
– Better notation: T(n)  O(f(n)).
Mettendo in
evidenza che c’è
una classe di
funzioni O(f(n)).
• Meaningless statement: “Any comparison-based
sorting algorithm requires at least O(n log n)
comparisons”.
– Use  for lower bounds.
36
Analisi asintotica di T(n)
T(n) = O(g(n)) significa che il tempo di esecuzione, anche nel caso
peggiore, è limitato superiormente da g(n)
T(n) = Ω(g(n)) significa che il tempo di esecuzione, anche nel caso
migliore, è limitato inferiormente da g(n)
T(n) = Θ(g(n)) significa che nel caso peggiore è O(g(n)) e nel caso
migliore è Ω(g(n))
(in pratica non vi è distinzione fra tempo di esecuzione nel caso
peggiore e migliore)
Esempio.
TI(n), tempo di esecuzione di InsertionSort è TI(n)= Ω(n) e TI(n) =O(n2)
TM(n ), tempo di esecuzione di MergeSort è TM (n)= Θ(n log n)
Asymptotic Order of Growth
• Upper bounds. T(n) is O(f(n)) if there exist constants c > 0
and n0  0 such that for all n  n0 we have T(n)  c · f(n).
• Lower bounds. T(n) is (f(n)) if there exist constants c > 0
and n0  0 such that for all n  n0 we have T(n)  c · f(n).
• Tight bounds. T(n) is (f(n)) if T(n) is both O(f(n)) and
(f(n)).
• Ex: T(n) = 32n2 + 17n + 32.
– T(n) is O(n2), O(n3), (n2), (n), and (n2) .
– T(n) is not O(n), (n3), (n), or (n3).
38
Esercizio 1
Esercizio 2
I calcoli riusciranno più semplici
dopo che avremo studiato le
proprietà delle notazioni asintotiche
NOTA: Esistono anche funzioni (particolari) non confrontabili tramite O