Proprietà delle notazioni
asintotiche
Mercoledì 1 ottobre 2014
• Punto della situazione
– Cos’è un algoritmo
– Tempo di esecuzione T(n)
– Analisi di algoritmi: analisi asintotica di T(n)
– Notazioni asintotiche
• Argomento di oggi
– Proprietà delle notazioni asintotiche
• Motivazioni
– Confrontare tempi di esecuzione di algoritmi fra
loro o con funzioni standard (lineare, polinomiale,
esponenziale…)
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
Limitazioni più utilizzate
Scaletta:
Man mano che si scende
troviamo funzioni che crescono
più velocemente (in senso stretto):
ogni funzione f(n) della scaletta è
f(n)=o(g(n))
per ogni funzione che sta più in basso.
Quindi potremo utilizzare (negli
esercizi) che per queste funzioni
standard:
f(n)  c g(n) per qualsiasi valore di c, ci
possa servire, da un opportuno nc in
poi.
Asymptotic Bounds for Some Common Functions
• Polynomials. a0 + a1n + … + adnd is (nd) if ad > 0.
• Polynomial time. Running time is O(nd) for some constant d
independent of the input size n.
• Logarithms. log a n = (log b n) for any constants a, b > 0.
can avoid specifying the base
• Logarithms. For every x > 0, log n = o(nx).
log grows slower than every polynomial
• Exponentials. For every r > 1 and every d > 0, nd = o(rn).
6
every exponential grows faster than every polynomial
Più in dettaglio
Informalmente….
Più precisamente:
 Un esponenziale cresce più
velocemente di qualsiasi
polinomio
n d = o(rn) per ogni d>0 e r>1
 Un polinomio cresce più
velocemente di qualsiasi
potenza di logaritmo
log b n k = o (nd)
per ogni k, d>0 e b>1
E ancora
Informalmente….
 Nel confronto fra
esponenziali conta la base
 Nel confronto fra polinomi
conta il grado
 Nel confronto fra logaritmi
… la base non conta
Per esempio:
2n = o(3n)
n2= o(n3)
log10 n = log 2 n (log10 2) = Θ(log 2 n)
Analisi di T(n)
Analizzare il tempo di esecuzione T(n) di un algoritmo
significherà dimostrare che:
T(n)= (f(n)) se possibile
oppure
delimitare T(n) in un intervallo:
T(n)=O(f(n)) e T(n)= (g(n))
(nel caso in cui il caso peggiore sia diverso dal caso migliore).
Algoritmo della ricerca del massimo
• T(n) ≤ (c3 + 2c2 + c1) n + (c1 - c3 - c2 )
T(n) = O(n)
• D’altronde (verificate):
T(n) ≥ n c2
T(n) = (n)
• Da cui: T(n) = (n)
cost
log n
𝑛
T(n) 
n
n log n
n2
n3
2n
lineare!
Algoritmo QuickSort
• Nel caso peggiore è quadratico:
T(n) = O(n2)
cost
• Nel caso migliore è :
T(n) = (n log n)
log n
𝑛
• Da cui: T(n)  ( f(n))
per qualsiasi f(n)
T(n) 

n
n log n
n2
n3
2n
Confronto crescita asintotica funzioni
T1 (n) vs T2(n)
• T1(n) = ( f(n))
• T2(n) = ( g(n))
• Con f(n) e g(n) standard (della scaletta)
e f(n)=o(g(n)) allora:
T1(n) 
cost
log n
𝑛
n
n log n
n2
T2(n) 
T1(n) = o(T2 (n))
Da verificare dopo…
n3
2n
Nella pratica
Per stabilire l’ordine di crescita di una funzione basterà
tenere ben presente la «scaletta» e alcune proprietà
delle notazioni asintotiche
Properties
• Transitivity
(analoga ad a b e b c allora a c per i numeri)
– If f = O(g) and g = O(h) then f = O(h).
– If f = (g) and g = (h) then f = (h).
– If f = (g) and g = (h) then f = (h).
• Additivity.
– If f = O(h) and g = O(h) then f + g = O(h).
– If f = (h) and g = (h) then f + g = (h).
– If f = (h) and g = (h) then f + g = (h).
(Attenzione: l’analoga per i numeri sarebbe
“se a c e b c allora a+b c”, che non è vera!! )
15
Applicazioni
Le proprietà (se vere) ci dicono che:
• Dato che log2(2n+1) = O( n+5 ) e n+5=O(n2) allora
log2(2n+1)=O(n2) (transitività)
• Dato che n2 - 2n +1 = O(n2) e log2(2n+1)=O(n2)
allora n2 - 2n +1 + log2(2n+1)=O(n2) (additività)
• etc etc…..
Transitività
Se f = O(g) e g = O(h) allora f = O(h)
Ipotesi:
esistono costanti c,n0 > 0 tali che per ogni n ≥ n0 si ha f(n) ≤ c · g(n)
esistono costanti c’,n’0 > 0 tali che per ogni n ≥ n’0 si ha g(n) ≤ c’ · h(n)
Tesi (Dobbiamo mostrare che):
esistono costanti c’’,n’’0 > 0 tali che per ogni n ≥ n’’0 si ha f(n) ≤ c’’· h(n)
Quanto valgono c’’, n’’0 ?
f(n) ≤ c · g(n) ≤ c · c’ · h(n) per ogni n ≥ n0 e n ≥ n’0
c‘’= c · c’
n’’ 0 = max {n0, n’0}
Additività
Se f = O(h) e g = O(h) allora f + g = O(h)
Ipotesi:
esistono costanti c,n0 > 0 tali che per ogni n ≥ n0 si ha f(n) ≤ c · h(n)
esistono costanti c’,n’0 > 0 tali che per ogni n ≥ n’0 si ha g(n) ≤ c’ · h(n)
Tesi (Dobbiamo mostrare che):
esistono costanti c’’,n’’0 > 0 tali che per ogni n ≥ n’’0 si ha f(n )+g(n) ≤
c’’· h(n)
Quanto valgono c’’, n’’0 ?
f(n )+g(n) ≤ c · h(n) + c’ · h(n)= (c+c’) h(n) per ogni n ≥ n0 e n ≥ n’0
c’’ = c + c’
n’’0 = max {n0, n’0}
Due regole fondamentali
Nel determinare l’ordine di crescita asintotica di una funzione
1. Possiamo trascurare i termini additivi di ordine inferiore
2. Possiamo trascurare le costanti moltiplicative
ATTENZIONE!
Le regole NON servono però per determinare esplicitamente le
costanti c ed n0.
Applicazioni
• Le due regole (se vere) ci dicono che:
3n + log10 n = (n)
log2 n+ 234 n3 + 100 = ( n3 )
3 2n + 3n =  (2n)
etc etc…..
Prima regola
«Possiamo trascurare i termini additivi di ordine inferiore»
Cosa significa formalmente?
Se g = O(f) allora f + g = (f)
Ipotesi:
g è di ordine inferiore a f: g=O(f):
esistono costanti c,n0 > 0 tali che per ogni n ≥ n0 si ha g(n) ≤ c · f(n)
Tesi (Dobbiamo mostrare che):
f + g = O(f): dato che f=O(f) e g=O(f) per l’additività: f+g=O(f).
f + g =  (f): esistono c’’, n’’0 > 0 tali che per ogni n ≥ n’’0 si ha
f(n )+g(n) ≥ c’’· f(n):
f(n )+g(n) ≥ f(n) essendo g(n) ≥ 0; c’’=1 ed n’’0 = 0
Seconda regola
«Possiamo trascurare le costanti moltiplicative»
Cosa significa formalmente?
Per ogni costante a > 0
allora
a·f = (f)
Ipotesi: a>0
Tesi
esistono costanti c>0, n0≥0 tali che per ogni n ≥ n0 si ha a· f(n) ≤ c · f(n)
esistono costanti c’>0, n’0≥0 tali che per ogni n ≥ n’0 si ha a· f(n) ≥ c’· f(n)
c = c’= a
n0 = n’0 = 0
Per stabilire la crescita di una funzione
Basterà usare:
• La «scaletta»
• Le proprietà di additività e transitività
• Le due regole fondamentali
Per confrontare la crescita di due funzioni
T1 (n) vs T2(n)
• T1(n) = ( f(n))
• T2(n) = ( g(n))
• Con f(n) e g(n) standard (della scaletta)
e f(n)=o(g(n)) allora:
T1(n) 
cost
log n
𝑛
n
n log n
n2
T2(n) 
T1(n) = o(T2 (n))
Verifichiamolo:
n3
2n
Confronto funzioni
• T1(n) = ( f(n))
• T2(n) = ( g(n))
• f(n)= o(g(n))
allora T1(n) = o(T2 (n))
Dimostrazione. Esistono c1,d1, c2,d2, n1, n2 tali che:
c1f(n)  T1(n) d1 f(n) per ogni n ≥ n1 e
c 2g(n)  T 2(n) d2 g(n) per ogni n ≥ n2 e
per ogni c>0, esiste nc tale che f(n) c g(n) per ogni n ≥ nc.
Allora: per ogni c>0, per ogni n ≥ max{n1, n2,nc}:
d1
d1
T1(n)  d1 f(n) d1 c g(n) =
c c 2g (n) 
c T 2(n)
c2
c2
Per ogni k>0, k=
d1
c . Al variare di c>0, otteniamo tutti i valori di k>0
c2
Domanda
Per questo genere di esercizi:
a cosa serve la calcolatrice?
Suggerimento:
ricorda che f(n) = O(g(n)) significa f(n)  c g(n) per ogni n ≥ n0
cioè per un numero infinito di valori di n.
QUINDI: NON basta dimostrare che per qualche costante c
f(1)  c g(1) , f(2)  c g(2) , f(10.000)  c g(10.000) !!!
Perché potrebbe essere invece
f(n) ≥ c g(n) per ogni n ≥ 10.001.
Esercizio 1
Esercizio 2
NOTA: Esistono anche funzioni (particolari) non confrontabili tramite O
Esercizio 1bis
Dimostrare che
3n5- 16n+ 2 =  (n5)
per definizione, cioè mostrando dei possibili
valori per le costanti c ed n0.
Esercizio 3
Esercizio 4
• Esercizio 2 dell’appello 26 gennaio 2010
Esercizi «per casa»
• Esercizi delle slides precedenti
• Es. 3, 4, 5 e 6 di pagg. 67-68 del libro [KT]
• Esercizi di esami (es. 1-9 dall’elenco online)