Programmazione dinamica Algoritmi golosi Analisi ammortizzata

Slides:



Advertisements
Presentazioni simili
Ricorrenze Il metodo di sostituzione Il metodo iterativo
Advertisements

Master Bioinformatica 2002: Grafi Problema: cammini minimi da tutti i vertici a tutti i vertici Dato un grafo pesato G =(V,E,w), trovare un cammino minimo.
Programmazione dinamica: problema della sottosequenza più lunga
Sottoprogrammi: funzioni e procedure
Ricorsione Procedure e funzioni ricorsive. Definizioni Un oggetto si dice ricorsivo se è definito totalmente o parzialmente in termini di sé stesso La.
Procedure e funzioni ricorsive
Programmazione dinamica
Alberi binari di ricerca
Introduzione agli algoritmi. Definizione Sistema di regole e procedure di calcolo ben definite che portano alla soluzione di un problema con un numero.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Ordinamenti ottimi.
Capitolo 1 Unintroduzione informale agli algoritmi Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Iterazione enumerativa (for)
Capitolo 10 Tecniche algoritmiche Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Capitolo 10 Tecniche algoritmiche Algoritmi e Strutture Dati.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
Algoritmi e Strutture Dati (Mod. B)
Algoritmi e Strutture Dati (Mod. A)
Alberi di Ricorrenza Gli alberi di ricorrenza rappresentano un modo conveniente per visualizzare i passi di sostitu- zione necessari per risolvere una.
Algoritmi e Strutture Dati (Mod. B)
Algoritmi e Strutture Dati (Mod. B)
Algoritmi e Strutture Dati (Mod. B)
Trovare il percorso minimo da b ad ogni altro vertice
APPUNTI SUL LINGUAGGIO C
ITERAZIONE e RICORSIONE (eseguire uno stesso calcolo ripetutamente) ITERAZIONE: ripetere piu volte una sequenza di operazioni istruzioni: for, while, do.
Algoritmi e Strutture Dati
ITERAZIONE e RICORSIONE (eseguire uno stesso calcolo ripetutamente)
Intelligenza Artificiale
Esercizio 10.* Un cassiere vuole dare un resto di n centesimi di euro usando il minimo numero di monete. a) Descrivere un algoritmo goloso per fare ciò.
Radix-Sort(A,d) // A[i] = cd...c2c1
Studieremo alcune tecniche per il progetto di algoritmi e di strutture dati: Programmazione dinamica Algoritmi golosi Analisi ammortizzata Vedremo poi.
Passo 3: calcolo del costo minimo
Cerchiamo di rispondere alla seconda domanda 2)La soluzione trovata con lalgoritmo goloso è ottima o esistono anche soluzioni con più di quattro attività?
Per valutare la complessità ammortizzata scomponiamo ogni Union: nelle due FindSet e nella Link che la costituiscono e valuteremo la complessità in funzione.
Terzo passo: lunghezza di una LCS LCS-Length(X, Y, m, n) for i = 0 to m c[i, 0] = 0 for j = 1 to n c[0, j] = 0 for j = 1 to n for i = 1 to m if x i ==
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati
Esercizi La distanza di hamming tra due interi x e y si definisce come il numero di posizioni nella rappresentazione binaria di x e y aventi bit differenti.
ND-partizione (A) n   A  somma  0 M  1/2 (  a i ) for i  1 to n do S[i]  choice ({true, false}) if S[i] then somma  somma + a i if somma > M then.
Cammini minimi da un sorgente
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 1 Cicli ed asserzioni Corso di Informatica 2 a.a. 2003/04 Lezione 1.
Ricorsione CORDA – Informatica A. Ferrari Testi da Alessandro Bugatti
Didattica e Fondamenti degli Algoritmi e della Calcolabilità Quarta giornata Risolvere efficientemente un problema in P: la sequenza di Fibonacci Guido.
Allievi Elettrici - AA Le funzioni ricorsive in C
Ordinamento in tempo lineare Il limite inferiore Ω(n log n) vale per tutti gli algoritmi di ordinamento generali, ossia per algoritmi che non fanno alcuna.
Capitolo 13 Cammini minimi: Algoritmo di Floyd e Warshall Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
4/25/2015E. Giovannetti -- OI09.1 Olimpiadi di Informatica 2010 Giornate preparatorie Dipartimento di Informatica Università di Torino marzo –
Algoritmi e strutture Dati - Lezione 7 1 Algoritmi di ordinamento ottimali L’algoritmo Merge-Sort ha complessità O(n log(n))  Algoritmo di ordinamento.
Capitolo 10 Tecniche algoritmiche Algoritmi e Strutture Dati.
Capitolo 10 Tecniche algoritmiche Algoritmi e Strutture Dati.
1 Analisi ammortizzata Si considera il tempo richiesto per eseguire, nel caso pessimo, una intera sequenza di operazioni. Se le operazioni costose sono.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Capitolo 1 Un’introduzione.
1 Informatica Generale Marzia Buscemi Ricevimento: Giovedì ore , Dipartimento di Informatica, stanza 306-PS o per posta.
Codici prefissi Un codice prefisso è un codice in cui nessuna parola codice è prefisso (parte iniziale) di un’altra Ogni codice a lunghezza fissa è ovviamente.
Informatica 4 La ricorsione. Definizione di ricorsione Ricorsione è la proprietà di quei programmi che, all’interno delle istruzioni che li compongono,
Problemi risolvibili con la programmazione dinamica Abbiamo usato la programmazione dinamica per risolvere due problemi. Cerchiamo ora di capire quali.
Algoritmi golosi Tecniche di soluzione dei problemi viste finora:
Complessità Computazionale
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Capitolo 1 Un’introduzione.
Divide et Impera Parte 11 - Risoluzione di problemi per divisione in sottoproblemi “bilanciati” Corso A: Prof. Stefano Berardi
Algoritmi e Strutture Dati HeapSort. Select Sort: intuizioni L’algoritmo Select-Sort  scandisce tutti gli elementi dell’array a partire dall’ultimo elemento.
Algoritmi e Strutture Dati Università di Camerino Corso di Laurea in Informatica (12 CFU) I periodo didattico Emanuela Merelli
Algoritmi e Strutture Dati Luciano Gualà
Rudimenti di Complessità Corso di Programmazione II Prof. Dario Catalano.
Sistemi di equazioni lineari. Sistemi di primo grado di due equazioni a due incognite Risolvere un sistema significa trovare la coppia di valori x e y.
Algoritmi Avanzati a.a.2011/2012 Prof.ssa Rossella Petreschi Simulazione di lettura e scrittura concorrente Tecnica dell’accelerated cascading Lezione.
Algoritmi Avanzati a.a.2014/2015 Prof.ssa Rossella Petreschi Lezione n°9.
Transcript della presentazione:

Studieremo alcune tecniche per il progetto di algoritmi e di strutture dati: Programmazione dinamica Algoritmi golosi Analisi ammortizzata Vedremo poi alcuni tipi di strutture dati importanti per le applicazioni: B-alberi Strutture dati per insiemi disgiunti

Programmazione Dinamica Esempio: taglio delle aste Problema del taglio delle aste E’ data un’asta metallica di lunghezza n che deve essere tagliata in pezzi di lunghezza intera (con un costo di taglio trascurabile). Per ogni lunghezza l = 1,…,n è dato il prezzo pl a cui si possono vendere i pezzi di quella lunghezza. Si vuole decidere come tagliare l’asta in modo da rendere massimo il ricavo della vendita dei pezzi ottenuti.

Esempio l 1 2 3 4 5 6 7 8 9 10 pl 17 20 24 30 Lunghezza asta n Ricavo massimo rn Suddivisione ottima 1 2 5 3 8 4 10 2+2 5 13 2+3 6 17 7 18 1+6 o 2+2+3 8 22 2+6 9 25 3+6 10 30

Un’asta di lunghezza n può essere tagliata in 2n-1 modi distinti in quanto abbiamo una opzione tra tagliare o non tagliare in ogni posizione intera 1,…,n-1. Ad esempio per n = 4 abbiamo i seguenti 8 modi Suddivisioni 4 1+1+2 1+3 1+2+1 2+2 2+1+1 3+1 1+1+1+1

In generale il ricavo massimo rn o è il costo pn dell’asta intera oppure si ottiene effettuando un primo taglio in posizione i e quindi sommando i ricavi massimi del primo e del secondo pezzo, ossia rn= ri + rn-i Quindi Osserviamo che la soluzione ottima del problema di ottiene da soluzioni ottime di sottoproblemi. Diciamo che il problema ha sottostruttura ottima.

Otteniamo una struttura ricorsiva più semplice se invece di scegliere la posizione i di un primo taglio intermedio scegliamo la lunghezza i del primo pezzo per cui rn= pi + rn-i Cut-Rod(p, n) if n == 0 return 0 q = -1 for i =1 to n q = max(q, p[i]+Cut-Rod(p, n-i)) return q

Albero di ricorsione per n = 4 1 2 3 4 Lo stesso problema di dimensione 2 viene risolto due volte, quello di dimensione 1 quattro volte e quello di dimensione 0 otto volte. Questo spiega la complessità 2n. Ripetizione dei sottoproblemi!!

Possiamo ridurre la complessità evitando di risolvere più volte gli stessi problemi. Un primo modo per farlo è dotare l’algoritmo di un blocco note in cui ricordare le soluzioni dei problemi già risolti: metodo top-down con annotazione. Un secondo modo per farlo è calcolare prima i problemi più piccoli memorizzandone le soluzioni e poi usare tali soluzioni per risolvere i problemi più grandi: metodo bottom-up.

Versione top-down con annotazione: Memoized-Cut-Rod(p, n) for i = 0 to n // inizializza il blocco note r[i] = -1 return Cut-Rod-Aux(p, n, r) Cut-Rod-Aux(p, j, r) if r[j] ≥ 0 // il problema è già stato risolto return r[j] if j == 0 q = 0 else q = -1 for i = 1 to j q = max(q, p[i] + Cut-Rod-Aux(p, j-i, r)) r[j] = q return q

Versione bottom-up: Bottom-Up-Cut-Rod(p, n) r[0] = 0 // il problema più semplice for j = 1 to n q = -1 for i = 1 to j q = max(q, p[i] + r[j-i]) r[ j] = q return r[n]

Versione bottom-up estesa per calcolare la soluzione ottima e non solo il suo valore Extended-Bottom-Up-Cut-Rod( p, n) r[0] = 0 for j = 1 to n q = -1 for i = 1 to j if q < p[i]+r[ j - i] q = p[i]+r[ j - i] s[ j] = i // memorizzo il taglio ottimo r[ j] = q return r ed s

La seguente procedura calcola e stampa la soluzione ottima: Print-Cut-Rod-Solution( p, n) (r, s) = Extended-Bottom-Up-Cut-Rod( p, n) j = n while j > 0 print s[j] j = j - s[j]

Moltiplicazione di matrici L’algoritmo per moltiplicare due matrici A e B di dimensioni pq e qr è: Matrix-Multiply(A, B) for i = 1 to A.rows for j = 1 to B.columns C[i, j] = 0 for k = 1 to A.columns C[i, j] = C[i, j] + A[i, k] B[k, j] return C Esso richiede pqr prodotti scalari

Problema della moltiplicazione di matrici Si deve calcolare il prodotto A1 A2 ... An di n matrici di dimensioni p0p1 , p1p2 , ... , pn-1pn Poiché il prodotto di matrici è associativo possiamo calcolarlo in molti modi.

Esempio: Per calcolare il prodotto A1 A2 A3 di 3 matrici di dimensioni 2005, 5100, 1005 possiamo: a) moltiplicare A1 per A2 (100000 prodotti scalari) e poi moltiplicare per A3 la matrice 200100 ottenuta (100000 prodotti scalari). In totale 200000 prodotti scalari. b) moltiplicare A2 per A3 (2500 prodotti scalari) e poi moltiplicare A1 per la matrice 55 ottenuta (5000 prodotti scalari). In totale 7500 prodotti scalari.

Vogliamo trovare il modo per minimizzare il numero totale di prodotti scalari. In quanti modi possiamo calcolare il prodotto? Tanti quante sono le parentesizzazioni possibili del prodotto A1 A2 ... An . Ad esempio per n = 4: (A1 (A2 (A3 A4))) (A1 ((A2 A3) A4)) ((A1 A2) (A3 A4)) ((A1 (A2 A3)) A4) (((A1 A2) A3) A4)

Il numero P(n) di parentesizzazioni possibili del prodotto A1 A2 Il numero P(n) di parentesizzazioni possibili del prodotto A1 A2 ... An di n matrici si esprime ricorsivamente come segue: Si può dimostrare che P(n) cresce in modo esponenziale. Quindi, tranne per valori di n molto piccoli, non è possibile enumerare tutte le parentesizzazioni.

Passo 1: struttura di una parentesizzazione ottima Supponiamo che una parentesizzazione ottima di A1 A2 ... An preveda come ultima operazione il prodotto tra la matrice A1..k (prodotto delle prime k matrici A1 ... Ak) e la matrice Ak+1..n (prodotto delle ultime n-k matrici Ak+1 ... An). Le parentesizzazioni di A1 ... Ak e di Ak+1 ... An sono parentesizzazioni ottime per il calcolo di A1..k e di Ak+1..n . Perché?

Passo 2: soluzione ricorsiva Prendiamo come sottoproblemi il calcolo dei prodotti parziali Ai..j delle matrici Ai ... Aj . Ricordiamo che la generica matrice Ai ha dimensioni pi-1pi . Di conseguenza la matrice prodotto parziale Ai..j è una matrice pi-1pj con lo stesso numero pi-1 di righe della prima matrice Ai e lo stesso numero pj di colonne dell’ultima matrice Aj .

Se i = j allora Ai..j = Ai ed m[i,i] = 0. Se i < j allora Ai..j = Ai ... Aj si può calcolare come prodotto delle due matrici Ai..k e Ak+1..j con k compreso tra i e j-1. Il costo di questo prodotto è pi-1 pk pj . Quindi

Passo 3 Esempio i 1 6 5 4 3 2 A1..1 A2..2 A3..3 A4..4 A5..5 A6..6 j 30 35 15 10 20 p 25 m k A1..2 15750 1 A1..3 7900 1 A1..4 9400 3 A1..5 11900 3 A1..6 15125 3 A1 3035 A2 3515 A3 155 A4 510 A5 1020 A6 2025 A2..3 2625 2 A2..4 4375 3 A2..5 7125 3 A2..6 10500 3 A3..4 750 3 A3..5 1500 4 A3..6 5375 3 A4..5 1000 4 A4..6 3500 5 A5..6 5000 5 A5..5A6..6: 0+0+102025 = 5000 A1..1A2..5: 0+7125+303520 = 28125 A1..2A3..5: 15750+1500+301520 = 26250 A1..3A4..5: 7900+1000+30520 = 11900 A1..4A5..5: 9400+0+301020 = 15400 A4..4A5..6: 0+5000+51025 = 6250 A4..5A6..6: 1000+0+52025 = 3500 A1..1A2..6: 0+10500+303525 = 36750 A1..2A3..6: 15750+5375+301525 = 32375 A1..3A4..6: 7900+3500+30525 = 15150 A1..4A5..6: 9400+5000+301025 = 21900 A1..5A6..6: 11900+0+302025 = 26900 A2..2A3..5: 0+1500+351520 = 12000 A2..3A4..5: 2625+1000+35520 = 7125 A2..4A5..5: 4375+0+351020 = 11375 A2..2A3..6: 0+5375+351525 = 18500 A2..3A4..6: 2625+3500+35525 = 10500 A2..4A5..6: 750+5000+351025 = 14500 A2..5A6..6: 1500+0+352025 = 19000 A3..3A4..6: 0+3500+15525 = 5375 A3..4A5..6: 750+5000+151025 = 9500 A3..5A6..6: 1500+0+152025 = 9000 A2..2A3..4: 0+750+351510 = 6000 A2..3A4..4: 2625+0+35510 = 4375 A2..2A3..3: 35155 = 2625 A1..1A2..2: 303515 = 15750 A1..1A2..3: 0+2650+30355 = 7900 A1..2A3..3: 15750+0+30155 = 18000 A3..3A4..4: 15510 = 750 A4..4A5..5: 0+0+51020 = 1000 A1..1A2..4: 0+4375+303510 = 14875 A1..2A3..4: 15750+750+301510 = 21000 A1..3A4..4: 7900+0+30510 = 9400 A3..3A4..5: 0+1000+15520 = 2500 A3..4A5..5: 750+0+15105 = 1500

Passo 3: calcolo del costo minimo Matrix-Chain-Order(p, n) for i = 1 to n m[i, i] = 0 for j = 2 to n for i = j-1 downto 1 m[i, j] =  for k = i to j-1 q = m[i, k] + m[k+1, j] + pi-1 pk pj if q < m[i, j] m[i, j] = q s[i, j] = k return m, s Complessità: O(n3)

Passo 4 Esempio 1 2 3 4 5 6 j A1..1 A1..2 1 A1..3 1 A1..4 3 A1..5 3 A1..6 3 1 2 3 4 5 6 m s A1 3035 A2 3515 A3 155 A4 510 A5 1020 A6 2025 A2..2 A2..3 2 A2..4 3 A2..5 3 A2..6 3 m s A3..3 A3..4 3 A3..5 3 A3..6 3 m s A4..4 A4..5 4 A4..6 5 m s A1..6 A5..5 A5..6 5 (A1..3 A4..6) m s ((A1 A2..3) (A4..5 A6)) A6..6 m s ((A1 (A2 A3 )) ((A4 A5) A6)) i

Passo 4: stampa della soluzione ottima Print-Optimal-Parens(s, i, j) if i == j print “Ai” else k = s[i, j] print “(” Print-Optimal-Parens(s, i, k) print “” Print-Optimal-Parens(s, k+1, j) print “)” Complessità: O(n)

Calcolo del prodotto di una sequenza di matrici Matrix-Chain-Multiply(A1...An , i, j, s) if i == j return Ai else k = s[i, j] A = Matrix-Chain-Multiply(A1...An, i, k, s) B = Matrix-Chain-Multiply(A1...An, k+1, j, s) return Matrix-Multiply(A, B)

Si potrebbe anche usare direttamente la definizione ricorsiva del costo minimo per il prodotto di matrici per calcolarlo ricorsivamente senza usare le matrici m ed s.

Rec-Matrix-Chain-Cost(p, i, j) if i = j return 0 else cmin =  for k = i to j-1 q = Rec-Matrix-Chain-Cost(p, i, k) + Rec-Matrix-Chain-Cost(p, k+1, j) + pi-1 pk pj if q < cmin cmin = q return cmin Complessità T(n) con n = j-i+1

Per sostituzione si può dimostrare che dove c = min(a,b). Quindi T(n) = Ω(2n).

Causa della complessità esponenziale: Rec-Matrix-Chain-Cost(p,1,4) 1,4 1,1 2,4 k = 1 k = 2 k = 3 1,2 3,4 1,3 4,4 k = 2 k = 3 3,4 2,3 4,4 1,1 2,2 3,3 4,4 k = 3 1,1 2,2 3,3 2,3 k = 2 k = 1 k = 2 1,1 2,2 1,2 k = 1 3,3 k = 1 2,2 3,3 4,4 2,2 3,3 k = 3 k = 2 La complessità diventa esponenziale perché vengono risolti più volte gli stessi sottoproblemi.

Possiamo evitare il ricalcolo dei costi minimi dei sottoproblemi dotando la procedura ricorsiva di un blocco notes (una matrice m di dimensione nn) in cui annotare i costi minimi dei sottoproblemi già risolti. Memoized-Matrix-Chain-Order(p, n) for i = 1 to n for j = i to n do m[i, j] =  return Memoized-Chain-Cost(p,1, n, m)

Memoized-Chain-Cost(p, i, j, m) if m[i, j] =  if i == j m[i, j] = 0 else for k = i to j-1 q = Memoized-Chain-Cost(p, i, k, M) + Memoized-Chain-Cost(p, k+1, j, M) + pi-1 pk pj if q < m[i, j] m[i, j] = q return m[i, j] Complessità: O(n3)