Problema da Mochila 0-1 (Knapsack problem)

mcastrosouza 13,946 views 47 slides Nov 24, 2015
Slide 1
Slide 1 of 47
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47

About This Presentation

Problema da Mochina 0-1 (Knapsack problem)


Slide Content

Problema da mochila 0-1 Curso de Maratona de Programação ICT-Unifesp – SJC

Paradigmas Guloso Realiza a escolha que parece ser a melhor no momento, ou seja, faz uma escolha ótima local na esperança de que escolha leve até a solução ótima global. Será que sempre garante chegar a uma solução ótima global? Curiosidade: o algoritmo Dijkstra é guloso... (só guloso ??)

Paradigmas Backtracking Refinamento de busca por força bruta! Várias soluções podem ser eliminadas sem serem explicitamente examinadas.

Programação dinâmica Vários algoritmos eficientes utilizam esse paradigma. O termo “programação” significa planejamento. Estrutura recursiva: A solução de qualquer instância deve conter soluções de subinstâncias da instância. Representação por uma recorrência (algoritmo recursivo). O algoritmo recursivo é normalmente ineficiente porque refaz cálculos. Temos que construir uma tabela para memorizar os resultados de soluções de subinstâncias (subproblemas) para evitar o recálculo!

Programação dinâmica Decomposição do problema em subproblemas. Pense na solução para cada subproblema. Subproblemas sobrepostos: resolve um determinado subproblema e mais a frente precisa do resultado daquele subproblema que já foi resolvido. Reutilização das soluções (eficiência): podemos sair de um problema exponencial para polinomial... Otimalidade: solução ótima é composta de soluções ótimas dos subproblemas O Dijkstra é só guloso? Não, é uma combinação de guloso e PD! Discussão: http://codeforces.com/blog/entry/20503

Programação dinâmica Hello World – não adianta, sempre Fibonacci estará presente! Normalmente o cálculo de Fibonacci é feito da seguinte forma: Isso é eficiente?

Programação dinâmica fib (6) 6 5 4 4 3 3 2 Ineficiente, já calculou o fib (3)... vai calcular novamente?

Programação dinâmica fib (6) 6 5 4 4 3 3 2 Temos repetições de subproblemas...

Programação dinâmica fib (6) 6 5 4 4 3 3 2 A abordagem é exponencial 

Programação dinâmica fib (6) 6 5 4 4 3 3 2 Se os subproblemas se repetem, basta guardar os resultados dos problemas já resolvidos!

Programação dinâmica Como usar PD? Basta fazer uma memorização dos resultados: memorizando o resultado... já calculei?

Programação dinâmica Como usar PD? Basta fazer uma memorização dos resultados: Transformamos algo exponencial em linear.

Programação dinâmica Essa é uma abordagem top- down , ou seja, tentamos calcular o fib (n) antes de todo mundo...

Programação dinâmica Abordagem bottom-up : Removemos a chamada recursiva, criamos um array para guardar os resultados e fomos construindo de trás para frente!

Problema da mochila 0-1 Digamos que você possui objetos onde cada objeto possui um peso e valor . Digamos que você também possui uma mochila que possui uma capacidade máxima ( peso máximo suportado). Seu objetivo é: levar um conjunto de objetos cujo valor total seja máximo e o peso total não ultrapasse a capacidade da mochila. Resumindo: você quer maximizar o valor de forma que não ultrapasse a capacidade máxima da mochila.

Problema da mochila 0-1 Objetos: X1, X2, ... , Xn Valores: V1, V2, ... , Vn Pesos: P1, P2, ... , Pn Peso máximo da mochila: P Qual aplicação disso? Maximizar o lucro... Maximizar a quantidade de brinquedos... Maximizar a felicidade...

Problema da mochila 0-1 Trata-se de um problema difícil, vários refinamentos foram feitos até se chegar a uma solução legal... Don’t panic ! Como encontrar uma composição de objetos que maximize o valor respeitando a restrição da capacidade máxima da mochila? Uma abordagem: guloso.

Problema da mochila 0-1 Utilizando abordagem gulosa: Ordena os objetos pelo valor máximo e vai pegando cada objeto se não ultrapassar a capacidade máxima da mochila. Também pode-se ordenar pelo (valor / peso)... Garante chegar a solução ótima global? De acordo com a estratégia gulosa de pegar pelo maior valor, colocaria o item X3 (maior valor), mas não poderia colocar nenhum item a mais. Uma solução melhor é pegar os itens X1 e X2 totalizando o valor 35 (> 30). Capacidade: 20 X1 X2 X3 Pi 10 10 20 Vi 15 20 30

Problema da mochila 0-1 Por que 0-1 ? Ou o objeto está ou não está na mochila. Estratégia gulosa pode garantir uma boa aproximação, mas não garante a solução ótima global. Vamos tentar por programação dinâmica... Temos que reduzir o problema, chegarmos a uma solução recursiva. Com a redução do problema, teremos subproblemas. Resolve os subproblemas (cálculos menores)... Faz-se uma observação e... É difícil esboçar um algoritmo!

Problema da mochila 0-1 Qual a observação ? “O objeto Xn pode está ou não está na solução ótima.” 20

Problema da mochila 0-1 Se um objeto Xn está na mochila, então a composição ótima da mochila é esse objeto mais os demais descontando o peso desse objeto! Considere P (capacidade da mochila) = 20. Pn = 8 (peso do objeto “n”). A mochila terá ( Xn + (n – 1)) objetos cujo peso máximo é 12 (descontou peso do objeto). É como se tivesse compondo uma outra mochila... Se o objeto não está na solução ótima, então a solução ótima é a mochila com peso original composta pelos (n – 1) elementos. Compara-se o máximo desses dois casos, queremos maximizar... 21

Problema da mochila 0-1 Se Xn pertence à solução, então o valor dessa solução será: Vn + (valor de uma solução ótima com uma mochila de capacidade P – Pn ) considerando os (n – 1) primeiros itens. Como descrevemos isso? Como transformar numa solução? 22

Problema da mochila 0-1 Temos os parâmetros: Conjuto dos objetos Peso da mochila Como captar esses parâmetros? f(i, p) -> valor ótimo considerando os “i” primeiros itens e uma mochila de capacidade p. f(i, p) 23 objetos que estou considerando, os “i” primeiros objetos p é p peso que a mochila suporta

Problema da mochila 0-1 Se Xn está na solução ótima: f(n – 1, p – pn ) + Vn (n – 1) -> considera agora somente os “n – 1” primeiros itens. (p – pn ) -> desconta o peso ( pn ) do objeto “n”. “p” é a capacidade da mochila. Se o objeto “n” está na solução ótima, ele leva o valor dele, por isso o “+ Vn ”. Se Xn não está na solução ótima: f(n – 1, p) (n – 1) -> considera agora somente os “n – 1” primeiros itens. p -> não desconta o peso dele, pois ele não está na solução ótima... Resolva fazendo o máximo ( max ) desses dois casos... 24

Problema da mochila 0-1 O objetivo é o cálculo do f(n), ou seja, para “n” objetos. Iremos resolver de baixo para cima ( bottom-up ). Calculando valores pequenos e aumentando os valores da função “f” até chegar no f(n, p). 25

Problema da mochila 0-1 Recorrência: f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p f(i, p) = f(i – 1, p) se pi > p O i- ésimo item cabe na mochila? Se pi > p, então ele não cabe na mochila, esqueça ele e olhe para os “i – 1” primeiros itens. f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p Se pi <= p, calcula-se o máximo dos 2 casos: está ou não na mochila? O primeiro considera o item na mochila e o segundo não considera o item na mochila. 26

Problema da mochila 0-1 27 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p

Problema da mochila 0-1 28 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p f(0, p) = f(i, 0) = 0 1 2 3 4 5 6 7 P 1 2 3 4 i

Problema da mochila 0-1 29 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p Vamos calcular o f(1, 1): 1 item e mochila de peso 1 1 2 3 4 5 6 7 P 1 ? 2 3 4 i

Problema da mochila 0-1 30 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p P1 > P? 2 > 1? Sim, então não cabe, resposta: f(i – 1, 1) = f(1 – 1, 1) = f(0, 1) = 0 1 2 3 4 5 6 7 P 1 ? 2 3 4 i

Problema da mochila 0-1 31 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p Vamos calcular o f(1, 2): 1 item e mochila de peso 2 1 2 3 4 5 6 7 P 1 ? 2 3 4 i

Problema da mochila 0-1 32 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p P1 > P ? 2 > 2 ? Não, então vamos calcular o max ... 1 2 3 4 5 6 7 P 1 ? 2 3 4 i

Problema da mochila 0-1 33 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p f(i – 1, p – pi ) + vi = f(0, 0) + 10 = 0 + 10 = 10 1 2 3 4 5 6 7 P 1 ? 2 3 4 i

Problema da mochila 0-1 34 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p e f(i – 1, p) = f(0, 2) = 0 1 2 3 4 5 6 7 P 1 ? 2 3 4 i

Problema da mochila 0-1 35 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p max (10, 0) = 10 1 2 3 4 5 6 7 P 1 10 2 3 4 i

Problema da mochila 0-1 36 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p depois de implementar e olhar o resultado da matriz... 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 ? i

Problema da mochila 0-1 37 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p f(4, 7) é o valor máximo 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 ? i

Problema da mochila 0-1 38 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p P4 > P ? 5 > 7 ? Não, então vamos calcular o max ... 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 ? i

Problema da mochila 0-1 39 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p f(3, 2) + v4 = 10 + 24 = 34 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 ? i

Problema da mochila 0-1 40 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p f(3, 7) = 32 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 ? i

Problema da mochila 0-1 41 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p max ( f(3, 2) + 24 ; f(3, 7) ) = max (34, 32) = 34 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 ? i

Problema da mochila 0-1 42 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p 34 é o valor máximo! 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 34 i

Problema da mochila 0-1 43 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p Qual a composição? Guarde os apontadores  1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 34 i

Problema da mochila 0-1 44 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p De onde o 34 veio? Do f(3, 2), então o X4 faz parte da solução. 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 34 i

Problema da mochila 0-1 45 P: 7 X1 X2 X3 X4 Vi 10 7 25 24 Pi 2 1 6 5 f(i, p) = f(i – 1, p) se pi > p f(i, p) = max { f(i – 1, p – pi ) + vi, f(i – 1, p) } se pi <= p De onde veio f(1, 2) ? Veio do f(0, 0) + 10, então o X1 faz parte da solução. 1 2 3 4 5 6 7 P 1 10 10 10 10 10 10 2 7 10 17 17 17 17 17 3 7 10 17 17 17 25 32 4 7 10 17 17 24 31 34 i

Problema da mochila 0-1 Complexidade: O(n * P) “n” é a quantidade de itens. “P” é a capacidade máxima da mochila. Depende do “P”, portanto, é pseudo-polinomial .

Problema da mochila 0-1 Implementação em C++: https://goo.gl/87o8U9 Vídeo-aula: https://goo.gl/9syeQP Dúvidas? [email protected]