Esercizio - algoritmo ibrido con soglia ottima e confronto con la versione ricorsiva (compito del 4 settembre 2024, es. 1)
In questa pagina 3
Testo (compito d'esame del 4 settembre 2024 di Algoritmi per l'Ingegneria, Ing. Informatica UniPD, seconda parte, esercizio 1, 16 punti). Dato un problema , si consideri un algoritmo ricorsivo per la cui complessità in tempo obbedisce alla ricorrenza, per valori della taglia che siano potenze di due, Sia inoltre un ulteriore algoritmo per di complessità .
- (a) [3 punti] Si delinei lo pseudocodice dell'algoritmo ibrido , ottenuto combinando la strategia ricorsiva di con l'uso di per risolvere sottoistanze di taglia .
- (b) [8 punti] Si scriva e si risolva la ricorrenza parametrica , con potenze di due, associata all'algoritmo sviluppato al punto (a).
- (c) [5 punti] Si determini il valore che determina la migliore complessità in tempo per .
Teoria usata: Albero della ricorrenza e formula generale per le ricorrenzeL'albero della ricorrenza ha la forma dell'albero delle chiamate dell'istanza peggiore e T(n) è la somma dei lavori dei nodi. Per la famiglia T(n) = s(n)T(f(n)) + w(n) con base T0 per n <= n0, contando i nodi per livello con le iterate di f e il livello f*(n,n0) si ottiene la formula chiusa T(n) = somma_l [prodotto_j s(f^(j)(n))] w(f^(l)(n)) + [prodotto s] T0, verificata per induzione e applicata a esempi (merge sort, Hanoi, ricorrenze con radice).Albero della ricorrenza e formula generale per le ricorrenze → (formula generale con taglia di base ), Master Theorem - enunciato, casi e applicazioniMaster Theorem per T(n) = aT(n/b) + w(n): si confronta w(n) con la funzione soglia n^(log_b a). Caso 1 (w minore di una potenza polinomiale): Theta(n^(log_b a)); caso 2 (w della stessa taglia): Theta(n^(log_b a) log n); caso 3 (w maggiore e regolare): Theta(w(n)). Prova completa dai livelli dell'albero, versione estesa (parti intere, n0 qualsiasi), esempi, e l'uso scorretto quando nessun caso si applica (w = n log n).Master Theorem - enunciato, casi e applicazioni →. Stessa struttura dell'esercizio Esercizio - algoritmo ibrido e valore ottimo della soglia (compito del 27 gennaio 2025, es. 1), con costanti diverse e un'ottimizzazione più semplice.
(a) Pseudocodice di
Si modifica il caso base di : sotto la soglia si passa a . genera quattro sottoistanze di taglia (da , ) e il suo lavoro per istanza è .
H(i, n0) {n0 potenza di due, costante}
n <- size(i)
[B]: if n <= n0 then return A2(i) // costo 2 n^3
[D]: <i_1, ..., i_4> <- A_D(i) // Divide di A1: quattro sottoistanze di taglia n/2
[R]: for j <- 1 to 4 do s_j <- H(i_j, n0)
[C]: return A_C(s_1, ..., s_4) // Conquer di A1(Il codice è quello di con le chiamate ricorsive a , passando sempre lo stesso .)
(b) La ricorrenza parametrica e la sua soluzione
Per e potenze di due: Formula generale con , , , costo di base (le foglie hanno taglia ). Con si ha : i livelli non di base sono , le foglie sono al livello . Al livello ci sono nodi, ciascuno di lavoro , quindi il livello costa . Le foglie sono : dove si sono usati , e . Sviluppando: Verifica per induzione sul numero di livelli (omessa nel testo): il caso dà ✓; il passo ✓. Con Python, per () e ogni la ricorrenza coincide con la formula.
(c) La soglia ottima
Per fisso si minimizza rispetto a (trattato come reale) : Quindi decresce per e cresce per (indipendentemente da ): il minimo è in , che è già una potenza di due. Valore:
Confronto con . coincide con per (per vale ): . Il rapporto è quindi per l'ibrido è più di quattro volte più veloce (per : contro , cioè volte; il valore è il costo di stesso).
Perché proprio . Confronto locale tra risolvere direttamente con e fare un passo di ricorsione per poi usare sulle quattro metà: per , costa e un passo di ricorsione : conviene . Per , costa e un passo di ricorsione : conviene ricorrere. La soglia sta quindi tra e , e si ferma la ricorsione a .
Osservazione. Il costo è simmetrico rispetto a : per esempio e danno lo stesso costo, (verificato), peggiore di .
from functools import lru_cache
@lru_cache(None)
def TH(n, n0):
return 2 * n**3 if n <= n0 else 4 * TH(n // 2, n0) + 128 * n
n = 2**12
print({2**j: TH(n, 2**j) for j in range(0, 8)})
assert min(range(13), key=lambda j: TH(n, 2**j)) == 3 # n0 = 8
assert all(TH(2**k, 8) == 32 * 4**k - 128 * 2**k for k in range(3, 20))
assert all(TH(2**k, 1) == 130 * 4**k - 128 * 2**k for k in range(0, 20))Versione ripasso
Testo. , ; . (a) pseudocodice di [3 punti]; (b) scrivere e risolvere [8]; (c) ottimo [5].
Teoria: Albero della ricorrenza e formula generale per le ricorrenzeL'albero della ricorrenza ha la forma dell'albero delle chiamate dell'istanza peggiore e T(n) è la somma dei lavori dei nodi. Per la famiglia T(n) = s(n)T(f(n)) + w(n) con base T0 per n <= n0, contando i nodi per livello con le iterate di f e il livello f*(n,n0) si ottiene la formula chiusa T(n) = somma_l [prodotto_j s(f^(j)(n))] w(f^(l)(n)) + [prodotto s] T0, verificata per induzione e applicata a esempi (merge sort, Hanoi, ricorrenze con radice).Albero della ricorrenza e formula generale per le ricorrenze →, Master Theorem - enunciato, casi e applicazioniMaster Theorem per T(n) = aT(n/b) + w(n): si confronta w(n) con la funzione soglia n^(log_b a). Caso 1 (w minore di una potenza polinomiale): Theta(n^(log_b a)); caso 2 (w della stessa taglia): Theta(n^(log_b a) log n); caso 3 (w maggiore e regolare): Theta(w(n)). Prova completa dai livelli dell'albero, versione estesa (parti intere, n0 qualsiasi), esempi, e l'uso scorretto quando nessun caso si applica (w = n log n).Master Theorem - enunciato, casi e applicazioni →.
- (a) Come con base
if n <= n0 then return A2(i); 4 chiamate ricorsive . - (b) (), . , , , , . Livello : ; foglie .
- (c) : minimo in (potenza di due). . con : ; rapporto (per ).
- Perché 8: : (un passo di ricorsione); : . Simmetria : danno .
- Errori tipici: foglie con costo invece di ; dimenticare ; scrivere il numero di foglie invece di ; non controllare che sia potenza di due.
- Verifiche: per induzione ; con Python e per .