Sulla complessità Lezione n°2 Prof.ssa Rossella Petreschi Lezione del 3/10/2013 del Corso di Algoritmica
Sfruttare le proprietà del problema Ricerca sequenziale, elementi in ordine casuale: O(n) Input: A: vettore di n elementi; x: elemento noto Output: j: 1 ≤ j ≤ n, se x = A(j), j = 0 altrimenti Passo 1: Si pone j = 0; Passo 2: Si ripete j = j + 1 finchè non si trova j > n o x = A(j) Passo 3: Se j > n allora si pone j = 0 Passo 4: Si fornisce j in output Ricerca dicotomica, elementi ordinati: O(logn) Input: A: vettore di n elementi ordinati in modo non decrescente; x: elemento noto Passo 1: Si pone j = 0, sx = 1, dx = n; Passo 2: Si ripete mezzo = (sx+dx)/2 se x = A(mezzo) allora j = mezzo altrimenti se x < A(mezzo) allora dx = mezzo -1 altrimenti sx = mezzo +1 fintanto che sx ≤ dx e j = 0 Passo 3: Si fornisce j in output
Complessità asintotica grande(limite asintotico superiore) f(n) = (g(n)) se e solo f (n) ≤ c g(n) ∀n ≥ no Omega(limite asintotico inferiore) f(n) = (g(n)) se e solo f (n) ≥ c g(n) ∀n ≥ no Teta(limite asintotico stretto) f(n) =(g(n)) se e solo c1 g(n) ≤ f (n) ≤ c2 g(n) ∀n ≥ no
Andamento di alcune funzioni
Classificazione degli algoritmi rispetto al tempo O(1) : tempo di elaborazione costante O(logn),O(n), O(n2) e O(n3): tempo logaritmico, lineare, quadratico e cubico ,rispettivamente O(nk): tempo polinomiale, k costante O(2n ): tempo esponenziale
P ed NP P ≠ NP ? Uno dei 7 problemi da US$ 1.000.000 selezionati dal Clay Matematics Institute il 24.03.2000
Analizzare con attenzione O(1) < O(log n) < O(n) < O(n2 ) < O(n3 ) < ... < O(2n ) anche se la disuguaglianza può valere solo per valori di n decisamente grandi: n!< n1000 per n < 1165 e ancora bisogna fare attenzione quando ci sono le costanti moltiplicative n2 giorni > n3secondi dato che 1 giorno = 86400 secondi
Ridurre la costante Alg1:: O(n), c.m. = 2 Input: un vettore di n elementi distinti, min =max=1 Output: max, min Alg1:: O(n), c.m. = 2 Passo : for j = 2 to n if A[j ] > A[max] then max ← j else if A[j ] < A[min] then min ← j Alg2:: O(n), c.m. = 3/2 Passo 0 : for (j = 0 to n-2, step 2) if A[j+1 ] > A[j+2] then (cmax ← j+1, cmin ←j+ 2) else (cmax ←j+ 2, cmin ← j+1) if A[cmin] < A[min] then min ← cmin if A[cmax ] > A[max] then max ← cmax Passo 1 : If j = n-1 then if A[j ] > A[max] then max ← j then if A[j ] < A[min] then min ← j
Confronto fra algoritmi fissare una misura comune per la dimensione dell’istanza; fissare quali sono le operazioni elementari da contare; determinare la complessità considerando anche le costanti; considerare gli ordini di grandezza solo se le costanti moltiplicative sono del medesimo ordine. Ma si può anche ragionare in termini di sequenze di istanze
Complessità su sequenze Si definisce complessità ammortizzata su una sequenza di k operazioni, data una struttura dati di dimensione n, la media dei tempi delle operazioni della sequenza. Il tempo così calcolato tiene conto che: in generale i dati non possono sempre presentarsi nelle condizioni più sfavorevoli per k volte consecutive e quindi il costo richiesto per eseguire le operazioni più costose può essere ammortizzato dall’esecuzione delle operazioni meno costose; si deve studiare l’effetto sulla sequenza peggiore di tutte, quindi è un’analisi di caso pessimo sulla catena e non sulla singola operazione; quest’analisi non ha alcuna connotazione probabilistica e quindi differisce dall’analisi del caso medio
3 metodi Consideriamo tre diversi metodi per il calcolo dell’analisi ammortizzata a seconda che il costo ammortizzato di una singola operazione sia calcolato al termine della sequenza di k operazioni e sia uguale per ogni singola operazione (Metodo degli aggregati) sia precalcolato tramite “crediti prepagati” ai singoli oggetti della struttura dati (Metodo degli accantonamenti) o alla struttura dati nel suo complesso (Metodo del potenziale)
Operazioni su pile ( caso peggiore) PUSH(P,x): inserisce l’oggetto x in testa alla pila O(1) POP(P): toglie l’oggetto in testa alla pila O(1) MULTIPOP(P,t): toglie t oggetti dalla testa della pila O(min(t,p)) Analisi del caso peggiore: Una sequenza di k operazioni PUSH,POP e MULTIPOP su una pila di dimensione n costa O(kmin(t,p)) ovvero O(n2).
Operazioni su pile (metodo degli aggregati) PUSH(P,x): inserisce l’oggetto x in testa alla pila O(1) POP(P): toglie l’oggetto in testa alla pila O(1) MULTIPOP(P,t): toglie t oggetti dalla testa della pila O(min(t,p) Analisi ammortizzata: Una sequenza di operazioni PUSH,POP e MULTIPOP su una pila di dimensione n può costare al più O(n). Il tempo ammortizzato di ogni singola operazione, è O(n)/n = O(1)
Operazioni su pile (metodo degli accantonamenti) PUSH(P,x): inserisce l’oggetto x in testa alla pila ca = 2 (contro O(1)) POP(P): toglie l’oggetto in testa alla pila ca = 0 (contro O(1)) MULTIPOP(P,t): toglie t oggetti dalla testa della pila ca = 0 (contro O(min(t,p))) Analisi ammortizzata: Una sequenza di operazioni PUSH,POP e MULTIPOP su una pila di dimensione n può costare al più O(n).
Metodo del potenziale D0:struttura dati iniziale su cui verrà eseguita la sequenza di operazioni Di:struttura dati che si ottiene come risultato della operazione i-esima sulla struttura dati Di-1 :funzione potenziale che associa un numero reale (Di) a Di Analisi ammortizzata: costo ammortizzato della i-esima operazione i = ci + (Di) - (Di-1) costo ammortizzato di n operazioni i = (ci + (Di) - (Di-1)) = ci + (Dn) - (D0)), per i = 1,…n (serie telescopica)
Operazioni su pile (metodo del potenziale) PUSH(P,x): (Di) - (Di-1) = (p + 1) - p = 1; i = ci + (Di) - (Di-1)= 1+1 = 2 POP(P): (Di) - (Di-1) = (p - 1) - p = -1; i = ci + (Di) - (Di-1)= 1-1 = 0 MULTIPOP(P,t): i = ci + (Di) - (Di-1) = t+((p-t)-p)=0 Analisi ammortizzata: Una sequenza di operazioni PUSH,POP e MULTIPOP su una pila di dimensione n ha un costo O(n), in quanto ∑ i = ∑ ci + (Dn) - (D0)) ≤ n + n - 0 = 2n (per i = 1,…n)
Incremento di un contatore binario ( caso peggiore) Il contatore è realizzato da un vettore di bit A dove A(0) rappresenta il bit meno significativo, pertanto: x = A(i)2i, per i = 0,…,k-1 0000 0001 0010 0011 0100 …. INCREMENTO: a partire da i=0 e finchè (i<k e A(i)=1) commuta A(i) in 0 e incrementa i; se i<k poni A(i)=1 Analisi del caso peggiore: Una sequenza di n operazioni INCREMENTO su di un contatore inizialmente a 0 richiede tempo O(nk) perché O(k) è il tempo nel caso pessimo della singola operazione
Incremento di un contatore (metodo degli aggregati) A(i) viene complementato n/2ivolte per i=0,1,…, logn A(i) non viene complementato per i >logn Numero totale di operazioni di modifica di bit n/2i≤ n 1/2 (per i = 0,…, logn)< n 1/2i = 2n (per i = 0,…) (serie geometrica decrescente infinita: xi = 1/1-x, per i=0,…) Analisi ammortizzata: Una sequenza di n operazioni INCREMENTO su di un contatore inizialmente posto a 0 può costare al più O(n). Il tempo ammortizzato di ogni singola operazione, è O(n)/n = O(1)
Incremento di un contatore (metodo degli accantonamenti) Porre un bit a 1 ca = 2 ca= costoammortizzato Porre un bit a 0 ca = 0 Analisi ammortizzata: Una sequenza di n operazioni INCREMENTO su di un contatore inizialmente posto a 0 può costare al più O(n) poiché: INCREMENTO commuta al più un solo bit ad 1 Il totale del credito è sempre ≥ 0 perché il numero totale di 1 non è mai negativo