Otimização de softwares antivírus

Arnaldo Gunzi
5 min readJun 14, 2024

Segue um pequeno exercício de otimização.

Você está numa empresa brasileira de alcance nacional, responsável pela aquisição de softwares antivírus para a empresa toda.

Há 30 softwares possíveis (numerados de 1 a 30) e 15 ameaças mapeadas (denominadas de A a O).

Cada software é homologado a prestar somente alguns serviços, e isso é assinalado com o valor 1 na tabela acima.

Cada software tem um custo para executar o pacote de serviços a que ele está homologado, dado pela tabela a seguir.

Quando você contrata o software, ele fornece toda a proteção do pacote. Não é possível contratar apenas um pedaço do software.

Além disso, há algumas restrições adicionais:

  • Software 4 é incompatível com Software 25, somente um dos dois deve ser contratado
  • Software 12 é incompatível com Software 16
  • Software 20 é incompatível com Software 30
  • Software 11 é incompatível com Software 12
  • O Software 21 deve ser contratado, por motivos políticos

Pergunta: Quais os softwares a serem contratados, de modo que todas as ameaças estejam cobertas, todas as restrições sejam atendidas e que o custo total de contratação seja o mínimo possível?

— — -

Resolução

Vamos separar o range (G39:G68) para a variável de decisão. É uma variável binária: 1 para indicar que vamos comprar o software, 0 para indicar que não.

A função objetivo (na célula M38) será dada pelo somarproduto da variável de decisão e o custo de cada alternativa.

Nas linhas de C35:Q35, vamos fazer a conta de quantos softwares estão cobrindo a ameaça.

Para modelar a restrição de incompatibilidade:

Software 4 é incompatível com software 25, equivale a dizer que não podemos comprar ambos os softwares. Pela variável de decisão ser binária, isso quer dizer que a soma deve ser menor ou igual a 1.

O mesmo vale para as demais restrições do tipo.

O software 21 ser obrigatório é indicado pela restrição de que ele deve ser igual a 1.

Vamos utilizar o solver do Excel para resolução.

$C$35:$Q$35 >= 1 (Todas as ameaças devem ser cobertas por algum software) $G$39:$G$68 = binário (Variáveis de decisão binárias) $L$44:$L$47 <= 1 (Softwares incompatíveis) $L$48 = 1 (Software obrigatório)

Resolvendo, temos a função objetivo de 138.000.

— — — —

Para formulação em Pyomo

# Definição dos dados num_softwares = 30 num_ameacas = 15 # Matrizes de cobertura e custos

[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],

[1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],

[0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],

[1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],

[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],

[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],

[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],

[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],

[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],

[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],

[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],

[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],

]

custos = [

18000, 4000, 6000, 22000, 38000, 14000, 4000, 16000, 28000, 10000,

20000, 12000, 4000, 20000, 20000, 6000, 18000, 20000, 8000, 14000,

20000, 18000, 8000, 18000, 36000, 4000, 12000, 30000, 30000, 34000

]

# Conflitos

conflitos = [ (4, 25), (12, 16), (20, 30), (11, 12)]

import pyomo.environ as pyo

model = pyo.ConcreteModel()

#Cria ranges para usar no modelo

model.softwares = range(num_softwares)

model.ameacas= range(num_ameacas)

model.var_decisao = pyo.Var(model.softwares, within = pyo.Binary)

#Definição da Função Objetivo

def funcao_obj(model):

return sum(model.var_decisao[i]*custos[i] for i in model.softwares)

model.objetivo = pyo.Objective(expr = funcao_obj, sense = pyo.minimize)

model.constraints = pyo.ConstraintList()

#Restrição de cobertura das ameaças

for ameaca in model.ameacas:

model.constraints.add(sum(model.var_decisao[i]*cobertura[i][ameaca] for i in model.softwares) >=1)

#Restrição conflito de softwares

for conflito in conflitos:

model.constraints.add(model.var_decisao[conflito[0]-1] + model.var_decisao[conflito[1]-1] <=1)

#Restrição Software_21_Obrigatorio

model.constraints.add(model.var_decisao[21–1]==1)

#Roda o solver

#Trocar pelo solver que estiver disponível

solver = pyo.SolverFactory(‘cbc’, executable = “C:\\CBC\\cbc.exe”)

result = solver.solve(model)

#Print de resultados

print(result)

#Print do modelo (opcional)

#model.pprint()

#Print dos softwares escolhidos

for i in list(model.var_decisao):

print (i+1, “: “, model.var_decisao[i].value)

Este é um caso conhecido na literaturacomo “Problema da Cobertura”.

Originally published at https://ideiasesquecidas.com on June 14, 2024.

--

--

Arnaldo Gunzi

Project Manager - Advanced Analytics, AI and Quantum Computing. Sensei of Analytics.