Igor M. Coelho
13 de Julho de 2020
Esses slides foram possÃveis devido a contribuições de diversas pessoas/materiais, em especial:
Caso não se sintam confiantes nos tópicos abaixo, façam uma revisão antes de aprofundar neste material:
Diversos problemas podem ser modelados por desigualdades lineares, no formato padrão de um Problema de Programação Linear (PPL).
Considere um problema da mochila com capacidade Q, na qual um conjunto de itens i∈I pode ser selecionado, acarretando lucros pi​∈Z+, mas também incorrendo em pesos wi​∈Z+.
Note que, no PPL abaixo, as variáveis xi​ podem assumir valores fracionários:
maximizari∈I∑​pi​xi​
Sujeito a:
∑i∈I​wi​xi​≤Q0≤xi​≤1xi​∈R≥0​​∀i∈I∀i∈I​
Na prática, pode ser desejável que os itens não possam ser divididos. Em outras palavras, gostarÃamos que as variáveis xi​ assumam valores no conjunto dos inteiros não-negativos.
maximizari∈I∑​pi​xi​
Sujeito a:
∑i∈I​wi​xi​≤Q0≤xi​≤1xi​∈Z≥0​​∀i∈I∀i∈I​
O Simplex serve para resolver problemas fracionários, porém não resolve problemas inteiros.
Ressaltamos que o Problema de Programação Inteira ou Programação Inteira Mista (MIP) é NP-DifÃcil, então não é conhecido um algoritmo que resolva todo tipo de MIP em tempo polinomial.
A abordagem padrão consiste em utilizar uma estratégia de enumeração, chamada Branch&Bound, que utiliza o Simplex para efetuar podas inteligentes na árvore de ramificação.
Veja o slide complementar do prof. Marcone, para uma apresentação com exemplo do método Branch&Bound.
A biblioteca python-mip
é desenvolvida por pesquisadores da Universidade Federal de Ouro Preto (UFOP) e pode ser utilizada para modelar e testar problemas MIP.
O resolvedor integrado Coin CBC é bastante eficiente e de código-aberto, sendo capaz de resolver problemas de pequeno e médio porte. Para problemas maiores (e mais complexos) é recomendada a instalação de solvers proprietários como CPLEX e Gurobi, integrando ao python-mip
.
Para instalar o python-mip
no python3: pip install mip
.
Documentação online: https://python-mip.readthedocs.io/en/latest/examples.html
É recomendável a instalação do Gurobi, para acelerar o processo de busca. Veja o link (linux, windows e mac):
Para Linux com Gurobi 9.0.2: (LINK para gurobi.com)
gurobi9.0.2_linux64.tar.gz
, e então:
tar xvfz gurobi9.0.2_linux64.tar.gz gurobi902/
sudo mv gurobi902 /opt/
(instala na pasta /opt
)~/.bashrc
os seguintes ambientes:export GUROBI_HOME=/opt/gurobi902/linux64
export PATH=$GUROBI_HOME/bin:$PATH
export LD_LIBRARY_PATH=$GUROBI_HOME/lib:$LD_LIBRARY_PATH
Pedindo licença acadêmica (LINK para gurobi.com).
Você obterá um código tipo a13f503a-c5f6-11ea-b1bb-xxxxxxxxxxxx
, então basta executar:
source ~/.bashrc
(carrega variáveis de ambiente)grbgetkey a13f503a-c5f6-11ea-b1bb-xxxxxxxxxxxx
gurobi.sh
(executa o gurobi)O python-mip
automaticamente usará o Gurobi se ele estiver disponÃvel no sistema.
from mip import Model, xsum, maximize, BINARY
# dados do problema
p = [10, 13, 9, 31, 7, 15]
w = [11, 15, 10, 35, 10, 33]
Q, I = 47, range(len(w))
# cria um modelo
m = Model("knapsack")
# adiciona variáveis 'x' ao modelo 'm'
x = [m.add_var(var_type=BINARY) for i in I]
# especifica a função objetivo do modelo 'm'
m.objective = maximize(xsum(p[i] * x[i] for i in I))
# adiciona restrições ao modelo 'm'
m += xsum(w[i] * x[i] for i in I) <= Q
# resolve o modelo 'm'
status = m.optimize()
# Imprime a solução final obtida.
# Note que variáveis da relaxação assumem valores
# tipo 'float', então precisamos ter certa tolerância
# para inferir respectivos valores inteiros '0' e '1'
selected = [i for i in I if x[i].x >= 0.99]
print("selected items: {}".format(selected))
# imprime a situação da otimização e valor objetivo
print("status =", status, " obj =", m.objective_value)
# imprime o valor para cada variável na solução
for i in I:
print("i=", i, "->", x[i].x)
O valor ótimo esperado é 41, com x=(1,0,0,1,0,0).
Tarefa: efetue as seguintes modificações no exemplo anterior, e verifique os valores obtidos na solução ótima:
BINARY
por INTEGER
nas variáveis (e faça a devida importação no python) e obtenha ótimo 42 com x=(2,1,1,0,0,0).BINARY
por CONTINUOUS
nas variáveis (e faça a devida importação no python) e obtenha ótimo 42.7273 com x=(4.273,0,0,0,0,0).Analise o significado dessas modificações, bem como os valores de solução obtidos.
Implemente os modelos do Problema do Caminho MÃnimo e Problema do Fluxo Máximo utilizando o python-mip
.
Dica: observe os modelos existentes no material complementar do curso (apostila do prof. Marcone Jamilson Freitas Souza).
A lista de exercÃcios está disponibilizada no site.