Download - Prog Din08

Transcript
Page 1: Prog Din08

Wikipedia.org

Programação dinâmica é um método para a construção de algoritmospara a resolução de problemas computacionais, em especial os deoptimização combinatória. Ela é aplicável a problemas no qual a soluçãoóptima pode ser computada a partir da solução óptima previamentecalculada e memorizada - de forma a evitar recalculo - de outros subproblemas que, sobrepostos, compõem o problema original.

Exemplo (Fibonacci):

var m : map(0 1 1 1)var m := map(0 → 1, 1 → 1)function fib(n)

if map m does not contain key nm[n] := fib(n 1) + fib(n 2)m[n] := fib(n − 1) + fib(n − 2)

return m[n]

Programação Dinâmica

Page 2: Prog Din08

Solução Sem Programação Dinâmica:

function fib(n)if n = 0 or n = 1

return 1else

return fib(n − 1) + fib(n − 2)

fib(5)fib(5)fib(4) + fib(3)(fib(3) + fib(2)) + (fib(2) + fib(1))((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

Ou seja, existem inúmeras repetições nos cálculos necessários para determinar o resultado final pretendido.

Programação Dinâmica

Page 3: Prog Din08

No entanto se usarmos o algoritmo anteriormente referido verificamosque não necessitamos de calcular diversas vezes as mesmas parcelas,basta construir a matriz e preenchê-la correctamente.

var m := map(0 → 1, 1 → 1)function fib(n)

if map m does not contain key nm[n] := fib(n − 1) + fib(n − 2)[ ]return m[n]

b( ) b( ) b( ) b( ) b( ) b( )Fib(0) Fib(1) Fib(2) Fib(3) Fib(4) Fib(5)1 1 1+1=2 1+2=3 2+3=5 3+5=8

Programação Dinâmica

Page 4: Prog Din08

Cálculo de combinações sem repetição (coeficiente binomial):

CCC n

r

n

r

n

r

11

1

−−

−+=r

1 - - - -

1 1

n

1 1 - - -

1 1+1 = 2 1 - -

1 1+2 = 3 2+1 = 3 1 -

1 1+3 = 4 3+3 = 6 3+1 = 4 1

Programação Dinâmica

Page 5: Prog Din08

// binomial.c by: Steven Skiena

long binomial_coefficient(n,m) int n,m;{

int i,j;long bc[MAXN][MAXN];

for (i=0; i<=n; i++) bc[i][0] = 1;f (j 0 j j ) b [j][j] 1for (j=0; j<=n; j++) bc[j][j] = 1;

for (i=1; i<=n; i++)for (j 1; j<i; j++)for (j=1; j<i; j++)

bc[i][j] = bc[i-1][j-1] + bc[i-1][j];

return( bc[n][m] );return( bc[n][m] );}

Programação Dinâmica

Page 6: Prog Din08

A programação dinâmica não serve apenas para satisfazer anecessidade de termos diversas formas de resolver um problema. Trata-se também de um método “muito” eficiente, ao nível da complexidade,no entanto é preciso ter em atenção que ele acarreta um custo maior anível do uso de memória.

Este método é assim muito útil para a resolução de problemas deoptimização como o do caminho mais curto, Spanning trees mínimas,

N é id h detc. No entanto nem sempre é evidente reconhecermos quando e comopodemos usar programação dinâmica.

Um dos truques é tentar verificar se existe um algoritmo recursivo paraUm dos truques é tentar verificar se existe um algoritmo recursivo, paraa resolução do problema pretendido, que calcula diversas vezes osmesmos sub problemas. A partir do momento que conseguimosencontrar esse algoritmo temos a certeza de que o problema podeencontrar esse algoritmo temos a certeza de que o problema podealternativamente ser resolvido recorrendo à programação dinâmica.

Programação Dinâmica

Page 7: Prog Din08

A partir daqui só nos resta saber como implementar um algoritmo deprogramação dinâmica. Como em tudo esta etapa requeressencialmente treino e experiência no uso deste tipo de programação.Inicialmente existem algumas dificuldades e tudo parece que acontecepor magia mas com o tempo rapidamente conseguimos chegar asolução quase que intuitivas.

Enquanto isso não vai acontecendo aqui fica uma breve metodologiai l i i f ilpara encontrar tais algoritmos mais facilmente:

1- Caracterizar a estrutura de uma solução óptima.2 Definir recursivamente o valor de uma solução óptima2- Definir recursivamente o valor de uma solução óptima.3- Calcular o valor de uma solução óptima ascendentemente

(Bottom-up).4 Tentar construir a solução recorrendo à informação obtida4- Tentar construir a solução recorrendo à informação obtida.

Programação Dinâmica

Page 8: Prog Din08

Exemplo: Assembly-Line-Scheduling (Linha de Montagem)

Programação Dinâmica

Page 9: Prog Din08

Etapa 1: Estrutura do melhor caminho.

Programação Dinâmica

Page 10: Prog Din08

Etapa 2: Solução Recursiva

f* = min(f1[n]+x1; f2[n]+x2)

Se j = 1 temos:f [1]f1[1] = e1 + a1,1f2[1] = e2 + a2,1

E se j > 1 temos:E se j > 1 temos:f1[j] = min(f1[j-1]+a1,j; f2[j-1]+t2,j-1+a1,j)f2[j] = min(f2[j-1]+a2,j; f1[j-1]+t1,j-1+a2,j)

Programação Dinâmica

Page 11: Prog Din08

Etapa 3: Cálculo do tempo optimal

f1[j] = min (f1[j-1] + a1,j, f2[j-1] + t2,j-1 + a1,j) for j > 1;f2[j] = min (f2[j-1] + a2,j, f1[j-1] + t1,j-1 + a2,j) for j > 1;f1[1] = e1 + a1,1;f2[1] = e2 + a2,1.

function schedule(a[], t[], e[], x[], n)1 f1[1] 1 1 11. f1[1] ← e1 + a1,1;2. f2[1] ← e2 + a2,1;3. for j ← 2 to n do4 f1[j] min (f1[j 1] + a1 j f2[j 1] + t2 j 1 + a1 j);4. f1[j] ← min (f1[j-1] + a1,j, f2[j-1] + t2,j-1 + a1,j);5. f2[j] ← min (f2[j-1] + a2,j, f1[j-1] + t1,j-1 + a2,j);6. /* end for */7 return( min( f1[n] + x1 f2[n] + x2 ));7. return( min( f1[n] + x1, f2[n] + x2 ));

Programação Dinâmica

Page 12: Prog Din08

Etapa 4: Construção do Caminho Óptimo

1. i ← l*;2. print « linha » i « , posto » n;3. for j ← n to 2 do4. i ← mli[j];5. print « linha » i « , posto » j-1;6. /* end for */

Resultado:linha 1, posto 6linha 2 posto 5linha 2, posto 5linha 2, posto 4linha 1, posto 3linha 2 posto 2linha 2, posto 2linha 1, posto 1

Programação Dinâmica