Escolar Documentos
Profissional Documentos
Cultura Documentos
Agosto de 2022
Sumário
I Conteúdo programático
1 Programa da disciplina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1 Objetivo 6
1.2 Ementa 6
1.3 Tópicos abordados 6
1.4 Ferramentas e ambiente computacional 7
II Heurísticas
2 Métodos Heurísticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1 Introdução 9
2.2 Representação de uma Solução 9
2.3 Heurísticas Construtivas 11
2.4 Busca Local 13
2.4.1 Busca em Regiões inviáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.2 Tipos de Busca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Referências . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
I
Conteúdo programático
1 Programa da disciplina . . . . . . . . . . . . . . . 6
1.1 Objetivo
1.2 Ementa
1.3 Tópicos abordados
1.4 Ferramentas e ambiente computacional
1. Programa da disciplina
1.1 Objetivo
Ao final do curso o estudante deve ser capaz de resolver problemas de otimização aplicando
heurísticas e metaheurísticas. Deve ser capaz ainda de analisar o desempenho de heurísticas e
metaheurísticas aplicados a problemas de otimização.
1.2 Ementa
Tecnicas para solução de problemas de otimização, em especial problemas de otimização combina-
tória: Heurísticas clássicas, Metaheurísticas. Principais metaheurísticas: Recozimento Simulado
(Simulated Annealing), Busca Tabu, Busca Local Iterada (Iterated Local Search - ILS), Busca em
Vizinhanc¸a Variavel (Variable Neighborhood Search - VNS), Procedimentos de Busca Adapta-
tiva Aleatoria e Gulosa (Greedy Randomized Adaptive Search Procedures - GRASP), Algoritmos
Geneticos, Colônia de Formigas.
2 Métodos Heurísticos . . . . . . . . . . . . . . . . . . 9
2.1 Introdução
2.2 Representação de uma Solução
2.3 Heurísticas Construtivas
2.4 Busca Local
Referências . . . . . . . . . . . . . . . . . . . . . . . 32
2. Métodos Heurísticos
2.1 Introdução
Para os autores Arroyo et al. (2002) os algoritmos heurísticos de otimização são métodos que visam
alcançar soluções aproximadas para problemas de otimização. O seu desenvolvimento surge em
resposta a incapacidade de se resolver de modo eficiente diversos problemas da classe N P-difícil.
Ou seja, as heurísticas buscam resolver os problemas com a mesma eficiência que os métodos
exatos de programação, porém, em um tempo reduzido.
Em geral, usamos os métodos heurísticos quando o tempo necessário para resolver um problema
de forma exata é superior ao tempo que temos disponível para obter uma resposta, ou até mesmo
quando não há ainda nenhum método exato disponível. Neste sentido, vemos que uma das vantagens
dos métodos heurísticos é no tempo para gerar uma solução viável e de boa qualidade. Como
desvantagem estes métodos não garantem que a solução encontrada seja ótima.
De maneira simplificada, podemos dividir os métodos heurísticos em duas categorias principais:
Métodos Construtivos e Métodos de Refinamento.
As heurísticas construtivas, como o nome sugere, constroem uma solução, passo a passo,
elemento por elemento até que se obtenha uma solução viável ou que nenhum elemento possa ser
inserido na solução.
Já as de refinimento partem de uma solução inicial ou de um conjunto de soluções iniciais e
utilizam mecanismos específicos para obterem soluções melhores.
Uma solução é representada por um conjunto de variáveis de decisão, as quais podem estar
dentro de intervalos determinados.
Exemplo 2.2.1 Problema da Mochila
• Imagine que um mochileiro precise viajar e nesta viagem deseja levar alguns objetos
• Para guardar esses objetos ele pode usar uma mochila, que, no entanto, só pode levar b quilos
• Cada objeto i tem um certo peso wi
• Cada objeto i proporciona um benefício ci se for levado
• O problema consiste em escolher os objetos que trarão o maior benefício possível sem
ultrapassar a capacidade da mochila
Objeto 0 1 2 3 4 5 6 7
Benefício 4 3 2 6 2 3 5 4
Peso 5 4 3 9 4 2 6 7
b = 20
Instância do problema
A primeira pergunta que devemos fazer para a resolução do problema é: Qual a variável de
decisão?
No caso do problema da mochila temos já disponível na literatura um modelo para sua resolução
em que a variável de decisão é dada por xi ∈ {0, 1}. Seja n o número de objetos disponíveis o
modelo é dado por:
n
Maximize Q(x) = ∑ ci xi (2.1)
i=1
Sujeito a:
n
∑ wi xi ≤ b (2.2)
i=1
xi ∈ {0, 1} ∀ i = {1, . . . , n} (2.3)
Outra questão que podemos nos fazer é a seguinte: Como podemos representar uma solução
deste problema no computador?
Repare que, como o Problema da Mochila já possui um modelo de otimização definido, uma
representação computacional natural pode ser dada por um vetor x em que cada posição é 0 ou 1,
como no modelo. Mas também podemos representar uma solução desse problema por uma lista
com os objetos que serão levados.
A Figura 2.1 mostra a mesma solução para o Problema da Mochila com duas representações
diferentes.
2.3 Heurísticas Construtivas 11
Pensarmos em como iremos representar uma solução computacional é importante porque isso
pode influenciar no próprio desempenho computacional. No caso do exemplo, uma representação
natural já é oferecida pelo próprio modelo, mas existem problemas que nem mesmo possuem
modelos matemáticos para sua resolução.
Além da representação de uma solução precisamos determinar como iremos verificar se uma
dada solução é viável e qual o valor da função objetivo. Veja que a codificação para que isso seja
realizado está diretamente ligado à forma como representamos a solução.
A Figura 2.2 mostra o código em Python para se calcular o valor da função objetivo em um vetor.
Na mesma função é também verificada a viabilidade da solução. Caso o código seja executado para
a solução que é mostrada na Figura 2.1 a mensagem de "Solução inviável!!!" será retornada.
A Figura 2.3 mostra o código em Python para se calcular o valor da função objetivo em uma
Lista. Assim como no código anterior na mesma função é também verificada a viabilidade da
solução.
Figura 2.3: Código para o calculo da função objetivo e viabilidade em uma lista
Voltando ao Exemplo do Problema da Mochila como queremos maximizar a soma dos benefí-
cios poderíamos usar como critério para criação a cada passo inserir o elemento de maior benefício
que ainda não está na mochila. Repare que neste problema a mochila vazia já é viável, logo é
interessante inserir elementos até que não seja mais possível inserir nenhum devido à capacidade.
A Figura 2.4 apresenta o pseudocódigo genérico para a geração de uma solução usando o
método guloso. Como entrada o procedimento recebe os dados do problema. Na Linha 1 o conjunto
de candidatos a entrar na solução é estabelecido. Na Linha 2 uma solução vazia é criada. Na Linha
4 é escolhido o melhor elemento do conjunto de C que é adicionado à solução na linha 5. Na Linha
6 o conjunto C é atualizado e o método verifica se irá repetir o processo ou se já tem uma solução
inicial adequada.
Exemplo 2.3.1 Problema da Mochila - Gerando uma Solução
s′ ← s ⊕ m
Seja N uma função que associa a cada solução s ∈ S, sua vizinhança N(s) ⊆ S. Qualquer
solução s′ obtida a partir de s com um ’movimento’ é chamada vizinha de s.
O movimento introduz uma noção de proximidade entre as soluções em S. Duas soluções
podem ser vizinhas ou não. Uma solução s é um ótimo local se f (s) é melhor ou igual a todo
f (s′ ) : s′ ∈ N(s). Uma solução s é um ótimo global se f (s) é melhor ou igual a todo f (s′ ) : s′ ∈ S.
A Busca Local se baseia na noção de vizinhança. Seja S o espaço de pesquisa de um problema
de otimização e f a função objetivo a otimizar (minimizar ou maximizar), seja s uma solução
qualquer do problema, isto é, s ∈ S, a busca local consiste em encontrar uma solução s′ , dentro da
vizinhança de s, que seja melhor que s. Em geral, a busca termina quando nenhum vizinho de s seja
melhor que ele, o que caracteriza que um ótimo local foi obtido.
De maneira simplificada, podemos definir o mecanismo de funcionamento de uma busca local
como: Partir de uma solução inicial qualquer; Caminhar, a cada iteração, de vizinho para vizinho
de acordo com a definição de vizinhança adotada, tentando melhorar a solução construída; Parar
quando não existir nenhum vizinho que seja melhor à solução atual.
Exercício 2.4.1
Dado um conjunto com n produtos que devem ser levados em uma mochila. Cada produto tem um
valor Vi e um peso Pi . A mochila tem capacidade C. O problema consiste em levar os produtos
buscando maximizar o valor sem, no entanto, ultrapassar a capacidade da mochila.
Seja n = 4 e dado que: P = {4, 10, 8, 5}; V = {5, 7, 8, 6} e C = 18
a) Dada a solução s = {0, 1, 0, 1} identificar o conjunto N(s), tal que o movimento seja a
mudança de um bit;
b) Existe vizinho melhor que s?
Uma coisa importante a se notar é que o movimento pode variar de problema para problema
e pode variar até mesmo para o mesmo problema. Para o Problema da Mochila, por exemplo,
poderíamos escolher utilizar como movimento a troca de um produto que está na mochila por outro
que não está. Repare agora que a vizinhança muda e que neste caso não há variação na quantidade
de objetos que já estão na solução. Ou seja, a escolha deste movimento impede que muitas soluções
sejam encontradas. Isso é uma situação recorrente em problemas mais complexos e a escolha do
movimento é crucial para um bom desempenho de uma busca local.
3.1 Multi-Start
Em geral, uma heurística de busca local parte de uma solução inicial e após uma busca retorna
uma solução que é um ótimo local. Veja que, se construírmos uma solução de maneira gulosa a
solução inicial será sempre a mesma e não importa quantas vezes executarmos esse procedimento,
chegaremos sempre à mesma solução final.
3.2 GRASP 17
Uma maneira simples de obter ótimos locais diferentes, ou seja, de escaparmos de um ótimo
local, é gerar soluções aleatórias e aplicar uma busca local. A este método damos o nome de
Multi-Start que como o próprio nome diz gera múltiplas soluções iniciais de maneira aleatória e a
elas aplica uma busca.
3.2 GRASP
A metaheurística GRASP (Greedy Randomized Adaptive Search) foi proposta por Feo e Resende
[7] e tem sido aplicada para a resolução de vários problemas de Otimização Combinatória (veja [14]
e [13]). GRASP é um método iterativo onde cada iteração é composta de duas etapas: construção
de uma solução e busca local. A fase de construção do GRASP é iterativa, gulosa, randômica
e adaptativa. Ela é iterativa porque constrói uma solução elemento a elemento e é adaptativa,
pois a escolha do próximo elemento da solução parcial é influenciada pelas escolhas anteriores.
Para a seleção do próximo elemento da solução parcial, a princípio todos os candidatos são
considerados, contudo o número de candidatos pode em muitos casos ser extremamente elevado,
por isso, normalmente, é considerada apenas uma lista restrita de candidatos (LRC). Em geral
essa LRC é composta pelos melhores candidatos disponíveis, isso define a parte gulosa do método.
Dentre os melhores elementos presentes na LRC um é escolhido de maneira aleatória.
A LRC é construída da seguinte forma:
• Calcula o item de menor valor para a função objetivo (Min);
• Calcula o item de maior valor para a função objetivo (Max);
18 Capítulo 3. Metaheurísticas baseadas em Buscas Locais
A Figura 3.2 apresenta o pseudocódigo do GRASP. Repare que o método é muito próximo do
Multi-Start apresentado na Seção anterior. A diferença básica entre os dois métodos é na geração da
solução inicial. No GRASP a função de geração de soluções recebe o critério guloso para classificar
os elementos candidatos a entrar na solução e o al pha. Se fazemos α = 1 temos na verdade o
Multi-Start, onde a solução inicial é aleatória.
cada iteração um vizinho aleatório é gerado e verificado. Ao fim do primeiro loop a temperatura é
resfriada de acordo com o parâmetro α. O parâmetro α varia entre 0 e 1. Quanto mais próximo
de 1 mais lento é o resfriamento. Os melhores valores para os parâmetros devem ser ajustados ao
problema tratado.
Exercício 3.3.1
não é suficiente para escapar de ótimos locais, uma vez que pode haver retorno a uma solução
previamente gerada. Para evitar isso, o algoritmo usa o conceito de lista tabu. Esta lista define
todos os movimentos que têm um certo atributo como sendo tabu por um determinado número de
iterações, conhecido como ’tempo tabu’. Tais movimentos são proibidos a menos que a solução
satisfaça a um certo critério de aspiração A, em geral que essa solução seja melhor que a melhor
solução encontrada até então. Os atributos são escolhidos para prevenir o retorno a soluções
visitadas recentemente e são escolhidos por características que são fáceis para detectar.
Assim, além dos mecanismos tradicionais existentes em uma busca local devemos também
criar uma memória de curto prazo para armazenar as regras de proibição (lista Tabu), o número
de iterações que um atributo selecionado permanece tabu e um critério de aspiração. A Figura 3.5
apresenta o pseudocódigo do algoritmo Busca Tabu com o critério de aspiração por objetivo.
Em geral, o BT usa como critério de parada o número de iterações sem melhora da melhor
solução (BTmax). Diferentemente da Busca Local convencional, na linha 7 a BT utiliza o melhor
vizinho que não esteja na lista tabu ou que esteja mas atenda ao critério de aspiração. Na linha 8 a
lista é atualizada, ou seja, insere um novo atributo na lista e retira os atributos que já estiveram na
lista por um número determinado de iterações. O resto do algoritmo tem o mesmo funcionamento
de uma busca local.
Exercício 3.4.1
objetivo de se escapar de um ótimo local. Em geral, se começa com vizinhanças mais simples e
caso a solução não melhore geramos um vizinho através de movimentos mais complexos.
Até então, tratamos de metaheurísticas que usam mecanismos de buscas locais para escapar dos
ótimos locais dos problemas. Nesta e nas próximas seções iremos tratar de métodos que utilizam
buscas populacionais, sendo a primeira delas o Algoritmo Genético (AG).
Na fase de mutação uma porcentagem, geralmente baixa, dos filhos é selecionada para sofrer
alguma modificação que não é herdada de nenhum dos pais, por isso o nome mutação.
Ao final do processo de cruzamente e mutação temos uma população com os pais e os filhos,
em geral de tamanaho 2n. Dessa forma, devemos selecionar quem irá para a próxima geração. Uma
maneira simples é escolher os n melhores indivíduos, mas isso pode fazer o método convergir para
um ótimo local de baixa qualidade. Assim, é importante criar mecanismos que garantam que a
população terá diversidade. A Figura 4.1 apresenta o pseudocódigo do AG.
Dorigo e Stützle [5] distinguem seis passos, sendo os quatro primeiros cruciais para o bom
funcionamento do ACO:
1. Representar o problema usando conjunto de componentes e transições, ou um grafo onde as
formigas irão operar
2. Definir o que será a trilha de feromônio
3. Definir o que será a informação heurística, associada ao problema, que afetará a decisão das
formigas
4. Sempre que possível, implementar uma busca local eficiente para o problema
5. Escolher/Adaptar algoritmos já existentes para o problema
6. Ajustar os parâmetros de acordo com aplicações similares já feitas previamente
Um antígeno é toda molécula capaz de iniciar uma resposta imune, a qual começa pelo
reconhecimento pelos linfócitos e cumula com a produção de um anticorpo específico.
As células existentes no sistema imunológico (inato e adaptativo) possuem moléculas capazes
de reconhecer antígenos, conforme Figura 4.4.
• Memória (algumas células-B são convertidas em células de memória com maior tempo de
vida)
A partir das ideias dos sistemas imunológicos reais foram desenvolvidos os sistemas imu-
nológicos artificiais. Estes sistemas Apareceram na década de 1990 como um novo paradigma
computacional inicialmente com as seguintes aplicações:
• Detecção de anomalias
• Reconhecimento de padrões
• Mineração de dados
• Segurança de computadores
• Detecção de falhas
A primeira aplicação em otimização foi proposta em 2002 por de Castro e Von Zuben [3].
O algoritmo, chamado CLONALG, utiliza os princípios de seleção clonal e maturação de afi-
nidade como os principais mecanismos para manipular uma população de soluções candidatas,
denominadas anticorpos.
As características importantes para o desenvolvimento de um bom algoritmo clonal imunológico
são:
• A taxa de proliferação de cada célula imune é proporcional à sua afinidade em relação
ao antígeno selecionado: quanto maior a afinidade, maior o número de clones gerados; e
vice-versa
• A mutação sofrida por cada célula imune durante a reprodução é inversamente proporcional
à afinidade do receptor da célula com o antígeno: quanto maior a afinidade, menor a taxa de
mutação e vice-versa
O pseudocódigo do Algoritmo Clonal Imunológico é apresentado na Figura 4.6. A geração
de soluções é realizada com aleatoriedade nas linhas 1 e 7. A seleção dos n melhores soluções,
linha 3, é feita com base na função objetivo. Na reprodução os melhores pais geram mais clones. A
hipermutação, linha 5, ocorre de maneira que os melhores clones mutam menos. Novas soluções
4.3 Algoritmo Clonal Imunológico 31