Skip to content

Instantly share code, notes, and snippets.

@anselmobattisti
Created December 29, 2020 02:21
Show Gist options
  • Save anselmobattisti/972b1ac1411041c8a5d33820334a53a2 to your computer and use it in GitHub Desktop.
Save anselmobattisti/972b1ac1411041c8a5d33820334a53a2 to your computer and use it in GitHub Desktop.
Implementação do problema das múltiplas mochilas em Python.
from mip import *
import random
# Constantes
RANDOM_SEED = 1
NUM_PRODUTOS = 10
NUM_MOCHILAS = 2
# Variável que armazena os Dados
produtos = {}
mochilas = {}
gerar_produtos(produtos)
gerar_mochilas(mochilas)
# Todos os produtos
imprimir_produtos(produtos)
# Todas as mochilas
imprimir_mochilas(mochilas)
# Modelo
modelo = Model(sense=MAXIMIZE)
# Variáveis de decisão
carga = {} # qual produto será colcoado em cada mochila
for m in mochilas:
for p in produtos:
carga[(m, p)] = modelo.add_var(var_type=BINARY)
# Restrições
# a) O mesmo produto não pode ser colocado nas duas mochilas
for p in produtos:
modelo += xsum(carga[(m, p)] for m in mochilas) <= 1
# b) A soma dos pesos dos produtos alocados em uma mochila não devem ser maior do que a carga máxima suportada pela mochila
for m in mochilas:
modelo += xsum(carga[(m, p)] * produtos[p]['peso'] for p in produtos) <= mochilas[m]['carga_maxima']
# Função Objetivo
modelo.objective = maximize(
xsum(carga[(m, p)] * produtos[p]['valor']
for m in mochilas
for p in produtos
if (m, p) in carga
)
)
modelo.optimize()
# Resultado
print("\n=====")
print("Valor Total em Todas as Mochilas {}".format(modelo.objective_values))
print("=====")
for m in mochilas:
print("\nCarga da Mochila {} com capacidade de {}g".format(m, mochilas[m]['carga_maxima']))
valor_total = 0
carga_total = 0
for p in produtos:
if (carga[(m, p)].x == 1):
valor_total += produtos[p]['valor']
carga_total += produtos[p]['peso']
print("{} \tR$ {},00 \t{}g".format(p, produtos[p]['valor'], produtos[p]['peso']))
print("-\nValor Total: R$ {},00 \nCarga Total: {}g\nCapacidade Ociosa: {}g".format(valor_total, carga_total, (mochilas[m]['carga_maxima']-carga_total)))
# Gerar produtos com peso e valor aleatórios
def gerar_produtos(prod):
random.seed(RANDOM_SEED)
for i in range(NUM_PRODUTOS):
cod = 'p_{}'.format(i)
valor = random.choice(range(1,10)) # Valor em reais
peso = random.choice(range(100,999)) # Valor em reais
prod[cod] = {
'valor': valor,
'peso': peso
}
# Imprimir os produtos
def imprimir_produtos(prod):
print("PRODUTOS")
print("Cód \tValor \t\tPeso")
for p in prod:
print("{}\tR$ {},00 \t{}g".format(p, prod[p]['valor'], prod[p]['peso']))
# Gera mochilas com pesos aleatórias
def gerar_mochilas(moc):
random.seed(RANDOM_SEED)
for i in range(NUM_MOCHILAS):
cod = 'm_{}'.format(i)
carga_maxima = random.choice(range(500,2000)) # Carga máxima em gramas
moc[cod] = {
'carga_maxima': carga_maxima
}
# Imprime as mochilas
def imprimir_mochilas(moc):
print("\nMOCHILAS")
print("Cód \tCarga Máxima")
for m in moc:
print("{} \t{}g".format(m, moc[m]['carga_maxima']))
@MarioDhiego
Copy link

#=========================================================================#

ATIVAR OS PACOTES

from mip import *
import random
import pandas as pd
import matplotlib.pyplot as plt
from tabulate import tabulate
#=========================================================================#

#=========================================================================#

CONSTANTES

RANDOM_SEED = 120
NUM_PRODUTOS = 12
NUM_MOCHILAS = 5
#=========================================================================#

#=========================================================================#

Inicializa o gerador aleatório

random.seed(RANDOM_SEED)
#=========================================================================#

#=========================================================================#

GERAR PRODUTOS E MOCHILAS

produtos = {
f'p_{i}': {'valor': random.randint(10, 150), # valores(R$)
'peso': random.randint(100, 250)} # valores(gramas)
for i in range(NUM_PRODUTOS)
}
#-------------------------------------------------------------------------#
mochilas = {
f'm_{i}': {'carga_maxima': random.randint(1500, 5000)} # valor(gramas)
for i in range(NUM_MOCHILAS)
}
#=========================================================================#

#=========================================================================#

FUNÇÃO PARA IMPRIMIR TABELA FORMATADA

def imprimir_tabela(titulo, dados):
print("\n" + "=" * 50)
print(f"{titulo}")
print("=" * 50)
df = pd.DataFrame.from_dict(dados, orient='index')
print(tabulate(df, headers='keys', tablefmt='fancy_grid'))
print("=" * 50)
#=========================================================================#

#=========================================================================#

FUNÇÃO OBJETIVO (MODELO MATEMÁTICO)

modelo = Model(sense=MAXIMIZE)
#=========================================================================#

VARIÁVEIS DE DECISÃO

carga = {(m, p): modelo.add_var(var_type=BINARY)
for m in mochilas
for p in produtos}
#=========================================================================#

RESTRIÇÕES

Mesmo Produto Não Pode Ser Colocado em DUAS Mochilas ao Mesmo Tempo

for p in produtos:
modelo += xsum(carga[m, p] for m in mochilas) <= 1

Soma Peso dos Produtos NÃO deve ser Maior Carga Máxima

for m in mochilas:
modelo += xsum(carga[m, p] * produtos[p]['peso']
for p in produtos) <= mochilas[m]['carga_maxima']
#=========================================================================#

#=========================================================================#

FUNÇÃO OBJETIVO

modelo.objective = maximize(
xsum(carga[m, p] * produtos[p]['valor']
for m in mochilas
for p in produtos)
)
modelo.optimize()
#=========================================================================#

#=========================================================================#
#----------------------------- RESULTADOS --------------------------------#

Imprimir Produtos/Mochilas de forma Organizada

imprimir_tabela("PRODUTOS DISPONÍVEIS", produtos)
imprimir_tabela("MOCHILAS DISPONÍVEIS", mochilas)

print("\n" + "="*50)
print(f"VALOR TOTAL DAS MOCHILAS: R$ {modelo.objective_value:.2f}")
print("="*50)

Criar listas para o gráfico

nomes_mochilas = []
cargas_totais = []
capacidades = []
data_mochilas = []
#=========================================================================#

#=========================================================================#

Alocação dos Produtos nas Mochilas

print("\nDISTRIBUIÇÃO DOS PRODUTOS NAS MOCHILAS:")

for m in mochilas:
produtos_mochila = [
(p, produtos[p]['valor'], produtos[p]['peso'])
for p in produtos if carga[m, p].x == 1
]
carga_total = sum(peso for _, _, peso in produtos_mochila)
valor_total = sum(valor for _, valor, _ in produtos_mochila)

nomes_mochilas.append(m)
cargas_totais.append(carga_total)
capacidades.append(mochilas[m]['carga_maxima'])
data_mochilas.append([m, valor_total, carga_total, mochilas[m]['carga_maxima'] - carga_total])

if produtos_mochila:
    df_mochila = pd.DataFrame(produtos_mochila, columns=['Produto', 'Valor (R$)', 'Peso (g)'])
    print(f"\n📦 Mochila {m} (Capacidade: {mochilas[m]['carga_maxima']}g)")
    print(tabulate(df_mochila, headers='keys', tablefmt='fancy_grid'))
    print("="*50)
    print(f"💰 Valor Total: R$ {valor_total},00 | ⚖️ Carga Total: {carga_total}g | 🔴 Ociosidade: {mochilas[m]['carga_maxima'] - carga_total}g")
    print("="*50)
else:
    print(f"\n🚫 Mochila {m} está vazia! (Capacidade: {mochilas[m]['carga_maxima']}g)")
    print("="*50)

#=========================================================================#

#=========================================================================#

TABELA DE RESUMO DAS MOCHILAS

df_resumo = pd.DataFrame(data_mochilas,
columns=['Mochila',
'Valor Total (R$)',
'Carga Total (g)',
'Espaço Livre (g)'])
print("\n📊 RESUMO DAS MOCHILAS")
print(tabulate(df_resumo, headers='keys',
tablefmt='fancy_grid'))
print("="*50)
#=========================================================================#

#=========================================================================#

📊 GRÁFICO DE BARRAS EMPILHADAS (CARGA POR MOCHILA)

plt.figure(figsize=(10, 6))
plt.bar(nomes_mochilas, capacidades, color='gray',
alpha=0.5, label='Capacidade Total')
plt.bar(nomes_mochilas, cargas_totais, color='blue',
alpha=0.8, label='Carga Utilizada')

Adicionar Valores nas Barras

for i, v in enumerate(cargas_totais):
plt.text(i, v + 50, f"{v}g", ha='center', fontsize=12, fontweight='bold')

plt.xlabel("Mochilas", fontsize=14)
plt.ylabel("Peso (g)", fontsize=14)
plt.title("Distribuição de Carga nas Mochilas", fontsize=16, fontweight='bold')
plt.legend()
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.show()
#=========================================================================#

@MarioDhiego
Copy link

boa tarde Prof, assistir sua aula no youtube, utilizei seu script, e inclui alguns ajustes, e gerei um grafico.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment