Programmazione dinamica
Introduzione.
Prodotto di una sequenza di matrici.
Caratterizzazione soluzione ottima.
Definizione ricorsiva soluzione ottima.
Calcolo del valore di una soluzione ottima.
Costruzione di una soluzione ottima.
Programmazione dinamica
La programmazione dinamica, generalmente, viene adottata
per risolvere problemi di ottimizzazione.
Questo vuol dire:
•il problema ammette diverse soluzioni
•ogni soluzione ha un costo
•si sta cercando una soluzione che mi dia il valore ottimo
(il massimo o il minimo dei costi)
Nota: non si cerca la soluzione ottima, ma una soluzione
ottima, dato che possono esistere varie soluzioni ottime.
Prodotto di una sequenza di matrici
Problema:
Si vuole effettuare il prodotto di una sequenza di matrici
<A1, A2,…, An> minimizzando il numero di moltiplicazioni
scalari effettuati.
Il costo dipende dalla sua parentesizzazione:
((A1 ((A2 A3) (A4 …)))An)
Per esempio: <A1, A2, A3>
dim(A1)=10x100; dim(A2)=100x5; dim(A3)=5x50;
E’ meglio ((A1 A2) A3) ?
Oppure
(A1 (A2 A3)) ?
Costo moltiplicazione di due matrici
MATRIX-MULTIPLY(A, B)
1.
if columns[A] ≠ rows[B]
2.
then error “dimensioni non compatibili”
3.
else for i ← 1 to rows[A]
4.
do for j ← 1 to columns[B]
5.
do C[i,j] ← 0
6.
for k ← 1 to columns[A]
7.
do C[i,j] ← C[i,j] + A[i,k] B[k,j]
8.
return C
Sostanzialmente:
Se si moltiplica A con dimensioni p x q e B con dimensioni q
x r, si ottiene una nuova matrice C con dimensioni p x r.
Il costo è determinato dal numero di moltiplicazioni scalari
effettuati, ossia p • q • r. Per ogni elemento della matrice C
(p x r) bisogna effettuare q moltiplicazioni scalari.
Prodotto di una sequenza di matrici
Ritornando all’esempio: <A1, A2, A3>
dim(A1)=10x100; dim(A2)=100x5; dim(A3)=5x50;
(A1 A2) → (10 • 100 • 5) = 5000 molt.
((A1 A2) A3) → (10 • 100 • 5) + (10 • 5 • 50) = 7500 molt.
(A2 A3) → (100 • 5 • 50) = 25000 molt.
(A1 (A2 A3)) → (100 • 5 • 50) + (10 • 100 • 50) = 75000 molt.
Quindi: ((A1 A2) A3) costa meno di (A1 (A2 A3))!
Numero di parentesizzazioni
Supponiamo che per risolvere il problema si controlli in
maniera esaustiva tutte le soluzioni.
P(n) = tutte le possibili parentesizzazioni di una sequenza di
n matrici
1
se n  1

 n 1
P ( n)  
P (k ) P (n  k ) se n  2

k 1
prodotto di sottoparentesizzazioni
P(n)  C (n  1)
sequenza dei numeri Catalani
1  2n 
   (4n / n3 / 2 )
C ( n) 
Nota: la ricerca esaustiva risulta
n 1  n 
essere molto dispendiosa!
Soluzione in programmazione
dinamica
Lo sviluppo di un algoritmo in programmazione dinamica
può essere diviso in quattro fasi o passi:
1. Caratterizzazione della struttura di una soluzione
ottima.
2. Definizione ricorsiva del valore di una soluzione ottima.
3. Calcolo del valore di una soluzione ottima con una
strategia bottom-up.
4. Costruzione di una soluzione ottima a partire dalle
informazioni calcolate.
1. Caratterizzazione della struttura
di una soluzione ottima.
Per il nostro problema una soluzione ottima è del tipo:
((A1 A2… Ak) (Ak+1 Ak+2… An)) con 1 ≤ k ≤ n
tale che
(A1 A2… Ak) → la sua parentizzazione è ottima per la
sequenza <A1, A2,… Ak> (altrimenti scelgo quella ottima,
costa meno!). Dimensione matrice finale = p x q
(Ak+1 Ak+2… An) → la sua parentizzazione è ottima per la
sequenza <Ak+1, Ak+2,… An> (altrimenti scelgo quella ottima).
Dimensione matrice finale = q x r
Inoltre il costo della soluzione ottima è
costo = costo(A1 A2… Ak) + costo(Ak+1 Ak+2… An) + p•q•r
2. Definizione ricorsiva del valore di
una soluzione ottima.
Si determina una soluzione ottima ricorsivamente in
termini dei valori delle soluzioni ottime dei sottoproblemi.
Sottoproblema: <Ai, Ai+1,… Aj> con 1 ≤ i ≤ j ≤ n
m[i,j] = costo minimo per la sottosequenza
<Ai, Ai+1,… Aj>
m[i,i] = costo minimo per la sottoseq. <Ai,… Aj> = Ai = 0
m[1,n] = costo minimo per la sequenza <A1, A2,… An>
0
se i  j


m[i, j ]  
min m[i, k ]  m[k  1, j ]  pi 1 pk p j  se i  j

i  k  j
2. Definizione ricorsiva del valore di
una soluzione ottima.
0
se i  j


m[i, j ]  
min m[i, k ]  m[k  1, j ]  pi 1 pk p j  se i  j

i  k  j
E’ facile vedere che il valore di m[i,j] è ottenuto
sommando i costi minimi del calcolo dei sottoprodotti Ai..k
e Ak+1..j con il costo del prodotto delle due matrici
risultanti (pari a pi-1pkpj).
Nota: definiamo s[i,j] = k, per tenere traccia del valore k
che costituisce una soluzione ottima per il sottoproblema
<Ai, A2,… Aj>.
3. Calcolo del valore di una soluzione
ottima con strategia bottom-up.
Bottom-up vuol dire che si parte a calcolare i costi ottimi
per le sottosequenze lunghe 1, poi quelle lunghe 2 e così
via…
UP
lung=n
m[1,n]
…
…
m[1,3]
lung=3
lung=2
lung=1
BOTTOM
m[1,2]
m[1,1] = 0
m[2,4]
m[2,3]
m[2,2] = 0
…
m[3,5]
m[3,4]
m[3,3] = 0
m[4,5]
m[4,4] = 0
m[n-2,n]
…
…
m[n-1,n]
m[n,n] = 0
3. Calcolo del valore di una soluzione
ottima con strategia bottom-up.
MATRIX-CHAIN-ORDER(p) // INPUT: p = <p0, p1, …, pn> dimensioni
matrici in ingresso, lunghezza(p) = n+1
1. n ← length[p] – 1
// n = lunghezza(p) – 1
2. for i ← 1 to n
3.
do m[i,i] ← 0
// costo 0 sottoseq. lunghe 1
4. for l ← 2 to n
// l = lunghezza sottoseq., da 2 a n !!!
5.
do for i ← 1 to n-l+1
// i = inizio sottoseq.
6.
do j ← i+ l -1
// j = fine sottoseq.
7.
m[i,j] ← ∞
// costo sottoseq. [i,j] inizializzato a ∞
8.
for k ← i to j-1
// calcolo k soluzione ottima m[i,j]
9.
do q ← m[i,k] + m[k+1,j] + pi-1pkpj
10.
if q < m[i,j]
// se costo calcolato è minore del
costo ottimo attuale
11.
then m[i,j] ← q
// aggiorna matrice costi
12.
s[i,j] ← k
// aggiorna matrice indici k
13. return m e s
3. Calcolo del valore di una soluzione
ottima con strategia bottom-up.
m
1
6
matrice
dimensione
A1
30 x 35
A2
35 x 15
A3
15 x 5
A4
5 x 10
A5
10 x 20
A6
20 x 25
15125
5
j
4
9375
3
2
7875
15750
1
11875
2
10500
7125
4375
2625
3
4
5375
2500
750
i
3500
1000
5
6
5000
0
0
0
0
0
0
A1
A2
A3
A4
A5
A6
3. Calcolo del valore di una soluzione
ottima con strategia bottom-up.
s
1
6
matrice
dimensione
A1
30 x 35
A2
35 x 15
A3
15 x 5
A4
5 x 10
A5
10 x 20
A6
20 x 25
3
5
j
3
4
3
3
1
2
1
3
3
3
2
2
3
3
4
3
3
i
5
5
4
5
((A1 ) (A2 A3)) ((A4 A5) A6) → s[1,6]=3; s[1,3]=1; s[4,6]=5.
3. Calcolo del valore di una soluzione
ottima con strategia bottom-up.
Osservazione importante:
Il numero di sottoproblemi è relativamente basso: un
problema per ogni scelta di i e j, con 1 ≤ i ≤ j ≤ n, per un totale
di  n 
   n  (n 2 )
numero di sottoproblemi
 2
2
Θ(n ) =memoria necessaria per m e s
Sottoproblemi comuni
Se si facesse una ricerca esaustiva potrebbe succedere di
risolvere più volte lo stesso sottoproblema. Per esempio, la
soluzione ((A1 ) (A2 A3)) ((A4 A5) A6) e la soluzione
(A1) (((A2 A3) (A4 A5)) A6) hanno in comune (A2 A3) e (A4 A5).
4. Costruzione di
una soluzione ottima
La strategia per la costruzione di una soluzione ottima
dipende dalle informazioni dei sottoproblemi calcolate nelle
fasi precedenti.
Nel nostro caso specifico utilizziamo la matrice s:
A1 A2… An
A1 A2… As[1,n]
A1… As[1,s[1,n]] As[1,s[1,n]]+1… As[1,n]
As[1,n]+1As[1,n]+2… An
4. Costruzione di
una soluzione ottima
Nel nostro caso specifico utilizziamo la matrice s:
A1 A2 A3 A4 A5 A6
s[1,6]=3.
A1 A2 A3
s[1,3]=1;
s[4,6]=5.
A1
s[2,3]=2;
s[4,5]=4.
A4 A5 A6
A2 A3
A2
A3
Soluzione: ((A1 ) (A2 A3)) ((A4 A5) A6).
A4 A5
A4
A5
A6
4. Costruzione di
una soluzione ottima
MATRIX-CHAIN-MULTIPLY(A, s, i, j)
1. if j > i
2.
then X ← MATRIX-CHAIN-MULTIPLY(A, s, i, s[i,j])
3.
Y ← MATRIX-CHAIN-MULTIPLY(A, s, s[i,j]+1, j)
4.
return MATRIX-MULTIPLY(X,Y)
5.
else return Ai
MATRIX-CHAIN-MULTIPLY(A, s, 1, 6) calcola il prodotto
della sequenza di matrici secondo la parentizzazione:
((A1 ) (A2 A3)) ((A4 A5) A6).
Altri problemi
• La più lunga sottosequenza in comune
Dati due sequenze X e Y si cerca una sottosequenza Z
comune di lunghezza massima.
• Il problema della zaino
Dato degli oggetti O1, O2, …, On che hanno volume
V1, V2, …, Vn e valore Val1, Val2, …, Valn, si cerca di
riempire lo zaino di volume V massimizzando la somma
dei valori. Il problema consiste nel scegliere i vari oggetti in
modo che il volume complessivo sia al massimo V e la
somma dei loro valori sia ottimo.
Scarica

ppt