Você está na página 1de 72

Um estudo sobre o Problema de

Alocação

Henrique Carvalho de Almeida Soares


Um estudo sobre o Problema de Alocação

Henrique Carvalho de Almeida Soares

Orientador: Prof. Dr. Luis Augusto Angelotti Meira

São José dos Campos – SP


Dezembro, 2011
Aos meus pais.
Agradecimentos

Dedico este trabalho à minha família e amigos, que me apoiaram durante toda a graduação.
Agradeço a meus colegas de universidade e professores, que me auxiliaram na jornada de apren-
dizado.
Resumo

E
S te trabalho contém um estudo sobre o Problema de Alocação,
bem como alguns métodos para sua resolução, em várias instân-
cias do problema. Uma destas é a instância de associação de pro-
fessores à materias em uma universidade brasileira (Universidade Fed-
eral de São Paulo, campus São José dos Campos). São abordadas áreas
específicas e informações básicas relacionadas ao problema em questão,
como Programação Inteira, Modelagem Matemática, Branch and Bound,
Simulated Annealing e outros métodos de solução. São apresentadas,
também, as soluções obtidas e suas avaliações.

Palavras-chave: Problema de Alocação, Otimização Combinatória, alo-


cação professor-matéria, Branch and Bound, Simulated Annealing.

i
Abstract

T
H is work contains a study about the Assignment Problem and some
methods for solving it, applying these concepts to various in-
stances of the problem. A good example is the association of
teacher-subjects on a brazillian university (Federal University of Sao Paulo,
campus São José dos Campos). In this work, specific areas and basic
information related and pertinent to the problem in question will be dis-
cussed, such as Integer Programming, mathemathic modelling, Branch
and Bound, Simulated Annealing and other solution methods. The ob-
tained solutions and its evaluations will also be shown.

Keywords: Assignment Problem, Combinatorial Optimization, teacher-subject


designation, Branch and Bound, Simulated Annealing.

iii
Sumário

Resumo i

Abstract iii

1 Introdução 1
1.1 Problema de Alocação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Revisão Bibliográfica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 Metodologia 5
2.1 Plano de Trabalho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.1 Atividades e Cronograma . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2 Problema de Alocação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Modelagem do Problema de Alocação . . . . . . . . . . . . . . . . . . . . . . 9
2.3.1 Programação Linear . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.2 Programação Inteira . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4 Métodos de Solução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4.1 Força Bruta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4.2 Branch and Bound . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.3 Heurísticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4.4 Simulated Annealing . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 Implementação 17
3.1 Armazenamento de associações . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Força Bruta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3 Branch and Bound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4 Simulated Annealing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.5 Algoritmo Guloso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

4 Resultados Computacionais 27
4.1 Métodos exatos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

v
4.2 Metaheurística . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.3 Otimizações e Comparações Finais . . . . . . . . . . . . . . . . . . . . . . . . 35
4.4 Instância de alocação professor-matéria . . . . . . . . . . . . . . . . . . . . . 40

5 Conclusão 45
5.1 Considerações finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.2 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Referências Bibliográficas 49

A Apêndice 53
A.1 Código Fonte do Força Bruta . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
A.2 Código Fonte do Branch and Bound . . . . . . . . . . . . . . . . . . . . . . . 54
A.3 Código Fonte do Simulated Annealing . . . . . . . . . . . . . . . . . . . . . . 56
A.4 Código Fonte do Algoritmo Guloso . . . . . . . . . . . . . . . . . . . . . . . 57

vi
C APÍTULO

1
Introdução

Neste capítulo apresentaremos uma definição informal do Problema de Alocação e as moti-


vações para resolvê-lo.

1.1 Problema de Alocação


Com a evolução do conhecimento e tecnologia humanos, as atividades que devemos realizar
em nossos trabalhos vêm se tornando cada vez mais complexas e mais numerosas, o que leva
à necessidade de maior eficiência em soluções e decisões, tanto em tempo utilizado, quanto
em qualidade. Há ainda a questão de que várias destas atividades envolvem um número de
variáveis e restrições que impossibilitam que uma pessoa as avalie completamente e sem auxílio
computacional. Este tipo de problema é encontrado com frequência nas mais diversas áreas,
como por exemplo, na administração de uma empresa ou de uma escola. Alguns desses casos
pertencem à classe de problemas da área de Otimização Combinatória, classe à qual o Problema
de Alocação pertence.
O Problema de Alocação é, portanto, encontrado com certa frequência no mundo real, pos-
suindo aplicação prática em várias áreas do conhecimento humano. Porém, sua generalização
é um problema que se enquadra na categoria dos problemas NP-Difíceis, ou seja, é difícil de
se encontrar uma solução ótima para o mesmo em tempo hábil (que varia conforme o tamanho

1
2 1.2. Objetivos

do problema em questão, podendo ser uma questão de minutos, horas, dias e até semanas) em
problemas de larga escala.
Este tipo de problema (que pode ser nomeado também como designação, matching, em-
parelhamento, dentre outros nomes) constitui uma parte importante da Ciência da Computação
e Matemática, com aplicação prática direta. Em um problema deste tipo, tem-se dois conjun-
tos (agentes-tarefas, trabalhadores-empregos, entre outros exemplos) e deve-se encontrar uma
função que ligue elementos destes dois conjuntos. Podem haver (e na maioria dos casos há)
restrições e requisitos para a ligação de um par de elementos, constituindo um custo para a des-
ignação. E o problema está em encontrar a função que minimiza o custo somado de todas as
alocações, respeitando as restrições existentes. O Problema de Alocação se encaixa exatamente
nesta descrição. Uma definição concisa e geral deste, dada segundo (Dasgupta et al., 2008) é:

“Existe um número de agentes e um número de tarefas. Podemos alocar qualquer


agente a qualquer uma das tarefas, porém, cada alocação tem um custo que pode
variar dependendo da tarefa e agente específicos. É necessário que todas as tarefas
sejam feitas, designando exatamente um agente para cada tarefa de modo que o
custo total (a soma) de todas as alocações seja minimizado.”

Neste trabalho, será tratado o estudo geral do Problema de Alocação, aplicando-o a várias
instâncias geradas aleatoriamente. Uma outra instância a ser estudada é um problema ocorrente
no Campus São José dos Campos, da Universidade Federal de São Paulo: a dificuldade de
associar os pares professor-matéria, definindo qual professor ministrará cada disciplina. Cada
professor possui uma preferência e formação, e é necessário que cada um assuma uma disciplina
de modo que o maior número de docentes possível estejam satisfeitos, e a designação seja feita
de forma coerente em relação às especialidades de cada professor.

1.2 Objetivos
Neste trabalho são estudadas áreas como Otimização Combinatória e Programação Linear In-
teira, focando principalmente no Problema de Alocação. Com isto são inclusos também estudos
de modelagem matemática e métodos de resolução utilizados na área. Pode-se, posteriormente,
buscar uma solução ainda mais eficiente para a instância escolhida, incluindo o estudo de prob-
lemas similares ao Problema de Alocação, como, por exemplo, o Problema do Transporte, além
de métodos e heurísticas de resolução mais elaborados.
O objetivo de avaliar métodos de resolução aplicados ao Problema de Alocação utilizando
algumas instâncias geradas aleatoriamente. No caso da instância particular do problema de
Capítulo 1. Introdução 3

designação professor-disciplina na Unifesp, busca-se encontrar uma solução viável para de-
terminar e designar quais professores ministrarão cada disciplina (no Campus São José dos
Campos, da Universidade Federal de São Paulo). Espera-se que sejam geradas alocações
professor-disciplina respeitando os requisitos de modo que o método possa ser aproveitado
dentro da universidade, caso seja assim desejado.

1.3 Revisão Bibliográfica


O Problema de Alocação é um problema já bastante conhecido no meio científico, principal-
mente para profissionais da área de Matemática e Computação. Isto é comprovado pela presença
de não somente artigos, mas seções destinadas ao problema em livros (até mesmo destinados
a alunos de graduação). Alguns dos livros que abordam este problema são as referências uti-
lizadas neste trabalho: (Goldbarg e Luna, 2005), (Wolsey e Nemhauser, 1999), (Wolsey, 1998),
(Beasley, 1996), (Fletcher, 1987), (Bazaraa et al., 2009), (Kolman e Beck, 1995), (Vanderbei,
2008) e (Murthy, 2005). Grande parte destes livros apresenta exemplos e métodos de resolução
recomendados para o problema, e aborda também tópicos úteis à este trabalho como Progra-
mação Linear, Programação Inteira, Modelagem Matemática, dentre outros.
Há também um número grande de artigos que apresentam ou avaliam métodos de resolução
para instâncias do Problema de Alocação. Um dos artigos mais importantes é (Land e Doig,
1960), no qual foi proposto pela primeira vez o método Branch and Bound. Em (Dasgupta
et al., 2008), são comparados alguns algoritmos evolucionistas multiobjetivo (com inicializa-
ção informada) e o algoritmo Kuhn-Munkres na resolução de algumas instâncias grandes do
Problema de Alocação.
Outros artigos similares são (Costa et al., 2005), que desenvolve um modelo de Progra-
mação Linear por metas (goal programming), aplicando-o ao planejamento de produção em
mineração, com objetivo de determinar o ritmo de lavra de cada frente, considerado a alocação
dos equipamentos de carga e transporte, de modo a fornecer à usina de beneficiamento uma
alimentação adequada.
O artigo (Goldbarg e Goldbarg, 2002) utiliza uma abordagem denominada de Transgenética
Computacional. Conforme o próprio artigo explica: “A metáfora baseia-se na utilização de
informações meméticas e no emprego dos fluxos extra e intracelulares para planejar e executar
manipulações genéticas no contexto dos algoritmos evolucionários. A pesquisa desenvolve duas
linhas de algoritmos: a primeira utilizando-se de ambos os fluxos para informar o processo de
busca evolucionária; a segunda utiliza-se exclusivamente da manipulação intracelular”. Esta
4 1.3. Revisão Bibliográfica

abordagem é aplicada ao Problema de Alocação Quadrático, e os resultados computacionais


são apresentados no artigo.
No artigo (Kuhn, 1955) é mostrado que idéias presentes no trabalho de dois matemáticos
húngaros podem ser exploradas para se obter um método diferente para resolver o Problema
de Alocação. Este método ficou posteriormente conhecido como Kuhn-Munkres ou Algoritmo
Húngaro.
No trabalho (Burkard, 2002) são estudados alguns desenvolvimentos nos campos de em-
parelhamentos de grafos bipartidos, dos problemas designados no trabalho como “linear sum
assignment and bottleneck assignment problems” e suas aplicações, o Problema de Alocação
Multidimensional e o Problema de Alocação Quadrático. Em particular, são vistos os limites
inferiores, casos especiais e resultados assintóticos, e os problemas de Alocação Biquadrático e
de Alocação de Comunicação.
O foco da pesquisa nesta área está em obter algoritmos mais eficientes e soluções para
instâncias cada vez maiores e mais complexas, que incluem variações do Problema de Alocação.
C APÍTULO

2
Metodologia

2.1 Plano de Trabalho


Primeiramente, será conduzida a busca por instâncias do Problema de Alocação em repositórios
e bancos de dados relacionados à área de Otimização Combinatória. Baseado nos estudos an-
teriores, será feito modelamento matemático do problema específico (o caso da Unifesp) e a
implementação dos métodos de resolução (Força Bruta, Branch and Bound e Simulated Anneal-
ing). Estes métodos serão utilizados para resolver tanto as instâncias geradas aleatoriamente,
quanto o caso da Unifesp. Há várias informações sobre métodos de solução mais recomendados
em livros e artigos científicos, como (Goldbarg e Luna, 2005), (Wolsey e Nemhauser, 1999),
(Fletcher, 1987), (Beasley, 1996) e (Dasgupta et al., 2008).
No caso da universidade, utilizaremos os parâmetros já fornecidos (um arquivo com as
preferências de cada professor em relação à cada matéria, utilizado para a designação em um
semestre da Universidade) para modelar a função de custo e verificar a necessidade de adap-
tações. Esta "avaliação de afinidade", que define a satisfação do docente ao ministrar cada
matéria será um bom indicador de custo, já que, ao minimizar este custo, obtemos uma asso-
ciação que aumenta a satisfação dos professores em relação às designações. Outro parâmetro
que pode ser utilizado é uma avaliação, feita pelo próprio professor, referente a cada matéria,
especificando (em forma de notas, por exemplo) a proximidade da matéria à sua área de atuação.

5
6 2.2. Problema de Alocação

Finalmente, ao obter as soluções utilizando os métodos citados anteriormente, serão avali-


ados os resultados, focando principalmente em critérios como qualidade de solução (o menor
custo total) e o custo computacional, ou seja, a rapidez com que se obtém a solução para a
instância aplicada.

2.1.1 Atividades e Cronograma


As atividades propostas neste Trabalho de Conclusão de Curso foram, de forma geral:

• Modelagem do Problema de Alocação;

• Modelagem do problema de alocação professor-disciplina;

• Implementação dos métodos escolhidos;

• Análise dos resultados obtidos;

• Elaboração do texto (monografia);

O cronograma de atividades segue representado na Tabela 2.1.


Ago 2011

Nov
Mai

Dez
Abr

Out
Jun

Set
Jul

Atividades
1) Revisão bibliográfica
2) Elaboração do texto
3) Modelagem do problema específico
4) Implementação de métodos
5) Geração das instâncias
6) Execução dos softwares para obter as soluções
7) Avaliação de resultados e conclusão
8) Revisões finais

Tabela 2.1: Cronograma apresentado ao final do TCC1

2.2 Problema de Alocação


Nesta seção será apresentada uma definição formal do Problema de Alocação.
Capítulo 2. Metodologia 7

O Problema de Alocação (ou Problema de Designação) é um caso especial do Problema de


Transporte. Pode ser entendido como “o problema de alocar n células de produção a n tarefas.
Cada uma das células é capaz de atender à tarefa segundo um custo cij peculiar a cada uma
das n células”, segundo descrito em (Goldbarg e Luna, 2005). O objetivo é de encontrar uma
associação tal que a soma dos custos cij adotados seja minimizada, respeitando as restrições.
Assumindo que o conjunto de células de produção seja o conjunto A, e que o conjunto das
tarefas seja o conjunto T, uma definição e sua modelagem matemática para o problema são:

Dados dois conjuntos, A e T, de tamanho igual, com uma função custo c : A × T → R,


achar uma função f : A → T tal que o custo seja mínimo. Com isto, a função buscada pode ser
definida por c(i, f (i)), onde i é um agente em A, e f (i) é a função f associando i a uma tarefa
em T .

A função objetivo é:

!
c(i, f (i)) (2.1)
i∈A

É possível criar uma variável xij da seguinte maneira:


"
1 se f (i) = j
xij
0 caso contrário

Neste caso, a função objetivo é definida da seguinte maneira:

!!
min c(i, j)xij (2.2)
i∈A j∈T

Para garantir que um elemento de A seja associado a exatamente um elemento em T , temos:

!
xij = 1 ∀i ∈ A (2.3)
j∈T

Para garantir que um elemento de T esteja associado a exatamente um elemento em A,


temos:
8 2.2. Problema de Alocação

!
xij = 1 ∀j ∈ T (2.4)
i∈A

Além disso, a variável xij deve ser binária , o que nos leva à restrição:

xij ∈ {0, 1}, i ∈ A, j ∈ T (2.5)

xij assume o valor 1 quando i foi associado a j, e 0 caso contrário.

A formulação completa, portanto, é:


!!
min c(i, j)xij (2.6)
i∈A j∈T
!
xij = 1 ∀j ∈ T (2.7)
i∈A
!
xij = 1 ∀i ∈ A (2.8)
j∈T
xij ∈ {0, 1}, i ∈ A, j ∈ T (2.9)

Pode-se tratar este problema com pequenas variações, como atribuir no máximo K tarefas
a cada agente. Neste caso, haveria a restrição:

!
xij ≤ K, ∀i ∈ A
j∈T

Porém, na variação proposta acima, define-se o Problema de Transporte, o qual permite


mais de uma tarefa designada a uma mesma célula de produção. O Problema de Alocação
só nos permite a relação de um para um nos conjuntos, ou seja, um elemento do conjunto A
se associa somente a um elemento do conjunto T . Esta abordagem pode ser adaptada para
o Problema de Alocação: Suponha a instância da associação professor-disciplina, e suponha
também que é necessário ou possível que um professor ministre duas disciplinas. Podemos
utilizar dois elementos em A que representem o professor em questão. Assim, elimina-se a
necessidade de uma generalização para o Problema de Transporte. Nesta variante, entretanto, é
necessário fixar de antemão quais professores seriam duplicados, em oposição ao Problema do
Transporte, que automatiza esta decisão em tempo de execução.
Capítulo 2. Metodologia 9

É importante ter em mente que, neste problema, o domínio das soluções possui tamanho n!,
ou seja, possui n! candidatos a solução, onde n é o tamanho dos conjuntos A e T , e, portanto, o
número de agentes e tarefas que a instância possui.

2.3 Modelagem do Problema de Alocação


Na modelagem anteriormente apresentada, tem-se somente uma variável: xij . Ela é definida
como uma variável binária, e portanto, é uma variável inteira. O custo c(i, j) é um dado fixo
específico de um par ij da instância do problema. A partir destas informações, o Problema de
Alocação pode ser classificado como um problema de Programação Linear Inteira (ou somente
Programação Inteira), como apresentado a seguir.
Um problema de otimização pertence à classe de problemas de Programação Linear (PL)
caso a sua função objetivo e suas restrições sejam todas lineares, como em (Goldbarg e Luna,
2005). Pela mesma referência, se um problema possui variáveis que só assumem valores no con-
junto Z (dos inteiros), este problema pertence à uma subclasse da Programação Linear, chamada
de Programação Inteira ou Programação Linear Inteira. Este tipo de problema é considerado
NP-difícil. No problema em estudo, tem-se um caso particular no qual a variável é binária,
assumindo os valores 0 ou 1, denotando um caso especial da Programação Linear Inteira.
A seguir são detalhados os conceitos de Programação Linear e Programação Inteira.

2.3.1 Programação Linear


Para um sistema poder ser traduzido em um modelo de Programação Linear, ele deve possuir
as características a seguir, apresentadas em (Goldbarg e Luna, 2005):

• Linearidade: A relação entre as funções e restrições deve ser linear. Pode também ser
chamada de proporcionalidade, como explicado em (Goldbarg e Luna, 2005): “a quanti-
dade de recurso consumido por uma dada atividade deve ser proporcional ao nível dessa
atividade na solução final do problema. Além disso, o custo de cada atividade é propor-
cional ao nível de operação da atividade”.

• Não Negatividade: “Deve ser sempre possível desenvolver dada atividade em qualquer
nível não negativo e qualquer proporção de um dado recurso deve sempre poder ser uti-
lizado”(Goldbarg e Luna, 2005).

• Aditividade: Propriedade na qual o custo total é igual a soma das partes, ou seja, das
parcelas de cada atividade, exemplificado como f (x + y) = f (x) + f (y)
10 2.3. Modelagem do Problema de Alocação

• Separabilidade: É possível identificar o custo específico de cada atividade;

Abaixo mostraremos que o Problema de Alocação respeita estas quatro propriedades:

• Linearidade: Neste quesito, o Problema de Alocação claramente se encaixa, pois a re-


lação entre a função objetivo e o custo é linear, de modo que, quanto maiores os custos
das associações, maior será o resultado da expressão da função objetivo.

• Não Negatividade: Nas restrições não há possibilidade da variável xij assumir valores
negativos. O custo, apesar de também ser positivo na grande maioria das instâncias, não
influencia aqui, pois não é uma variável do problema, e sim, um valor fixo já determinado
para a instância específica.

• Aditividade: O problema se encaixa aqui. A soma de todos os custos equivale à soma de


cada custo individual (para uma determinada alocação).

• Separabilidade: No Problema de Alocação, este custo é claro e é uma função necessária


para a resolução do problema.

Chega-se à conclusão que o Problema de Alocação se encaixa nas restrições, e pertence ao


conjunto dos problemas de Programação Linear. Isto facilita a resolução, pois os algoritmos
para o modelo de Programação Linear possuem grande eficiência e simplicidade de implemen-
tação. Porém, como já apresentado na Seção 2.3, o Problema de Alocação pertence, na verdade,
à um subconjunto (ou especialização) do conjunto de problemas de Programação Linear, pois
ele respeita também os requisitos da Programação Inteira, tornando-se um problema de Progra-
mação Linear Inteira (ou somente Programação Inteira).

2.3.2 Programação Inteira


Como mencionado no início deste capítulo, a classe de problemas de Programação Inteira é
uma subclasse da Programação Linear, na qual as variáveis do problema só assumem valores
em Z, ou seja, valores inteiros.
(Wolsey e Nemhauser, 1999) apresentam uma boa definição de Programação Inteira:

“Suponha que temos o seguinte programa linear:

max cx : Ax ≤ b, x ∈ Z∗+
Capítulo 2. Metodologia 11

onde:
A é uma matriz m por n;
c é um vetor linha n-dimensional;
b é um vetor coluna m-dimensional;
e x é um vetor coluna n-dimensional de variáveis ou valores desconhecidos;
Se todas as variáveis são inteiras, tem-se um Programa Inteiro, que pode ser escrito
como:

max cx
Ax ≤ b
x≥0
x ∈ Z”

Na prática isso significa que todas as variáveis não podem possuir valores contínuos e estare-
mos lidando somente com variáveis discretas.

2.4 Métodos de Solução


Nesta seção são apresentadas as definições e características dos métodos de resolução aborda-
dos.

2.4.1 Força Bruta


Algoritmos de força bruta são um tipo de método resolução que aborda todas as possibilidades
de combinações e valores possíveis (ou seja, de modo exaustivo) para a resolução do problema,
ou seja, para que se determine a solução ótima. Como fica claro por esta definição, algoritmos
deste tipo têm um custo computacional alto, e demoram para apresentar a solução do problema,
mesmo para instâncias pequenas. O custo computacional é da ordem de O(n!) (Cormen et al.,
2009).
No âmbito do Problema de Alocação, um algoritmo força bruta consistiria em testar todas as
possibilidades possíveis de combinações para a variável xij , para todos os elementos i e todos
os elementos j de seus respectivos conjuntos. Uma abordagem é utilizar uma matriz n × n,
12 2.4. Métodos de Solução

onde n é o número de elementos em ambos os conjuntos do problema e as linhas representam


os elementos específicos i e colunas representam os elementos j (ou vice-versa). A idéia é de
se ter o valor 1 na célula da matriz (i; j) se houver a associação do elemento i ao elemento j,
e zero caso contrário. Deve-se restringir o problema determinando que a soma de cada linha
seja 1, assim como a soma de cada coluna seja 1, ou seja, cada elemento i deve estar associado
a somente um elemento j, e vice-versa. Neste caso, após obter uma possibilidade, deve-se
calcular o custo total da função, e compará-lo aos custos já obtidos. Caso este novo custo seja
menor, guarda-se esta permutação como a melhor solução até o momento, e o seu custo como
o menor até o momento. Com isto, ao final do problema, este menor custo é realmente o menor
custo possível, e a solução é a ótima.

elementos j1 j2 j3
i1 1 0 0
i2 0 1 0
i3 0 0 1

Tabela 2.2: Exemplo de uma matriz para n = 3

2.4.2 Branch and Bound


O Branch and Bound, proposto pela primeira vez por (Land e Doig, 1960), é um algoritmo
bastante utilizado para encontrar a solução ótima de vários problemas de Otimização Com-
binatória, principalmente de problemas de Programação Linear e Programação Inteira. Este
método utiliza uma estratégia de “dividir para conquistar”. Em oposição à metodos de força
bruta, o Branch and Bound não necessita explorar efetivamente todo o espaço de soluções, uti-
lizando uma abordagem que descarta grandes quantidades de soluções ineficientes ao utilizar
limites estimados. Este método garante que se encontre a solução ótima, mas pode porven-
tura demorar um tempo muito grande, mesmo para instâncias relativamente pequenas, já que o
Problema de Alocação cresce fatorialmente.
Um algoritmo deste tipo possui dois passos. No primeiro, o branching, é um processo de
particionamento do espaço de soluções. Se o espaço de soluções é S, este processo de divisão
retornará dois ou mais conjuntos disjuntos S1 , S2 , . . . , Sn , cuja união cobre S. Esse processo
eventualmente gera uma árvore, onde o nó raiz representa o problema completo com o espaço
S e os nós abaixo dele representam subconjuntos de S.
O segundo passo é o bounding, que consiste em estimar os limites superior e inferior para
o valor mínimo (caso a função objetivo seja minimizar) ou máximo (caso a função seja de
Capítulo 2. Metodologia 13

maximizar), dado um subconjunto de S. Com estes limites, é possível eliminar subespaços de


S que possuam soluções fracas. A comparação é feita da seguinte maneira: se o problema é
de minimização, por exemplo, e o limite inferior para um nó da árvore é maior que o limite
superior de um outro nó, o primeiro pode ser descartado da busca. O inverso ocorre caso seja
um problema de maximização, ou seja, elimina-se o nó que possui limite superior menor que o
limite inferior de outro nó.
Ao eliminar os nós não desejados, aplica-se novamente o branching nos subconjuntos restantes,
que são considerados subproblemas do problema inicial, que em seguida passam novamente
pelo bounding. Esse processo se repete de modo que são obtidos subconjuntos cada vez menores,
até que seja encontrada a solução desejada.
Existem variantes do algoritmo que abordam maneiras diferentes de se resolver os passos
necessários, como o modo formação da árvore (ou seja, como dividir o espaço de soluções e
encontrar subconjuntos) e modo de percorrê-la, e também técnicas diferentes de estimativa dos
limites.

2.4.3 Heurísticas
As heurísticas (ou modelos heurísticos) não garantem que seja encontrado o ótimo. Geralmente
encontram soluções próximas à ótima, mas algumas vezes, dependendo das circunstâncias, é
possível que sejam obtidos resultados arbitrariamente ruins (ou também o resultado ótimo). Isso
denota uma relação de custo benefício. Ao utilizarmos este tipo de método, não precisamos da
melhor solução possível, mas geralmente obtemos uma solução viável com um tempo computa-
cional aceitável.
Claramente, uma situação na qual opta-se pelo uso de heurísticas é aquela onde há prob-
lemas que, utilizando algoritmos exatos (ou mesmo aproximativos), um tempo computacional
demasiadamente longo é necessário para que se obtenha a solução. Outras vantagens destes
métodos são que a maioria deles é conceitualmente simples, podem ser adaptados a vários
problemas (são não-específicos), e operam sem a imposição de condicionantes ao problema,
como convexidade e linearidade. Estes conceitos estão presentes em vários livros didáticos,
dentre eles (Goldbarg e Luna, 2005).
Dentro da categoria das heurísticas estão alguns métodos caracterizados como metaheurís-
ticas (assunto abordado de modo coeso na referência (Luke, 2009)). São definidos como uma
metaheurística os métodos que otimizam um problema ao iterativamente buscar a melhora de
uma canditada à solução, utilizando alguma medida de qualidade. São métodos de otimiza-
ção estocástica, ou seja, algoritmos e técnicas que utilizam alguma forma de aleatoriedade para
encontrar uma solução ótima ou próxima à ótima em problemas difíceis de serem resolvidos.
14 2.4. Métodos de Solução

Metaheurísticas são utilizadas para encontrar soluções para problemas para os quais não
se tem muitas informações. Não se sabe qual deve ser a solução ótima e o espaço de busca é
vasto. Mas, se existe uma candidata à solução do problema, é possível testá-la e definir o quão
boa ela é. Isto é verdade para muitos problemas de Otimização Combinatória, o que leva uma
metaheurística a ser bastante utilizada para resolver problemas da área.
Estes métodos exploram uma característica do espaço de soluções que se repete em muitos
problemas: soluções similares tendem a se comportar de modo similar, ou seja, têm qualidade
parecida. Pequenas modificações numa solução vão resultar em pequenas modificações na
qualidade. Este método, de começar com uma solução aleatória e fazer iterativamente pequenas
modificações aleatórias na solução, de modo a encontrar soluções melhores, é chamado de Hill
Climbing. Essencialmente, quase todas as metaheurísticas utilizam este conceito.

2.4.4 Simulated Annealing


Esta metaheurística foi escolhida pela facilidade de implementação, pelo seu vasto uso na área
de Otimização Combinatória (é aplicado no problema do Caixeiro Viajante em (Cerný, 1985)), e
por sua eficiência demonstrada em outros trabalhos, além de ser bastante utilizado para resolver
problemas de alocação, como há o exemplo em (S.N.Silva et al., 2005).
O Simulated Annealing é uma metaheurística probabilística e genérica utilizada para en-
contrar uma solução ótima global, ou a sua aproximação, em um grande espaço de busca. É
um método utilizado frequentemente quando o espaço de busca é discreto. Foi proposto por
Scott Kirkpatrick, C. Daniel Gelatt and Mario P. Vecchi em 1983, no artigo (Kirkpatrick et al.,
1983). Foi derivado do Algoritmo Metropolis, desenvolvido pelos cientistas Nicholas Metropo-
lis, Arianna e Marshall Rosenbluth, e Augusta e Edward Teller em 1953 (Metropolis et al.,
1953).
O nome e a inspiração do algoritmo vêm do recozimento de metais, uma técnica de met-
alurgia que envolve esquentar um metal e controlar o seu esfriamento, melhorando a qualidade
do material e reduzindo os defeitos. Neste processo, o calor leva os átomos a se desprenderem
de suas posições iniciais (um mínimo local da energia interna) e se moverem aleatoriamente; o
resfriamento lento aumenta a probabilidade destes átomos acharem configurações com energias
internas menores do que a inicial.
Analogamente a este processo, o Simulated Annealing gera a cada passo uma solução viz-
inha da solução atual (por um método aleatório) e tenta substituir a solução atual pela nova
solução. A nova solução pode ser aceita com uma probabilidade que depende da diferença dos
valores de função correspondentes às soluções, e um parâmetro T (designado de temperatura)
que é gradualmente diminuído durante o processo. Quando T é um valor alto, a aceitação é
Capítulo 2. Metodologia 15

quase aleatória. Conforme T diminui, a aceitação fica mais restrita, eventualmente aceitando
somente soluções melhores. Este processo evita que o Simulated Annealing fique preso em
ótimos locais (o grande problema de métodos gulosos).
C APÍTULO

3
Implementação

Todos os métodos foram implementados na linguagem Java, pela já familiaridade com a mesma.

3.1 Armazenamento de associações


E primeiro momento, faria sentido pensarmos no armazenamento das associações como uma
matriz, conforme exemplifica a tabela 3.1, e como dito no Capítulo 2, subseção 2.4.1:

elementos tarefa 1 tarefa 2 tarefa 3


agente 1 1 0 0
agente 2 0 1 0
agente 3 0 0 1

Tabela 3.1: Exemplo de uma matriz de associação para n = 3

Visualizar todas as permutações válidas para o Problema de Alocação numa matriz assim é
difícil e insere problemas como, por exemplo, verificar se a matriz de associação é válida a cada
nova permutação obtida. Para uma instância de tamanho n = 3, as permutações possíveis são:

17
18 3.1. Armazenamento de associações

• 1,2,3

• 1,3,2

• 2,1,3

• 2,3,1

• 3,1,2

• 3,2,1

ou em forma de árvore:

Figura 3.1: Árvore de permutações para n = 3.

Para a primeira permutação, o agente 1 estaria ligado à tarefa 1, o agente 2 ligado à tarefa 2,
e o agente 3 ligado à tarefa 3, e assim por diante para as outras.
Capítulo 3. Implementação 19

Surge, portanto, a primeira dificuldade: nos algoritmos escolhidos - Branch and Bound,
Simulated Annealing e Força Bruta - a maior parte dos exemplos que se encontram na liter-
atura utilizam vetores, e adaptá-los para trabalhar com uma matriz complicaria o algoritmo e
o deixaria ineficiente. É necessário também que se encontre uma forma de representar cada
permutação possível eficientemente, de modo que a implementação dos métodos seja mais fácil
e menos confusa.
Para resolver este problema, ao invés de armazenar as associações de agente-tarefa em uma
matriz de associação, adota-se um vetor - exemplificado na Tabela 3.2 - cujos índices represen-
tam os agentes e o valor dentro de cada índice indica a qual tarefa aquele agente está associado.
O único detalhe é que deve-se iniciamos a contagem pelo zero, ou seja, para o exemplo anterior,
agora tem-se os agentes 0, 1 e 2, e as tarefas 0, 1 e 2.

valor 2 1 0
índice 0 1 2

Tabela 3.2: Exemplo de um vetor de associação para n = 3

3.2 Força Bruta


Apresentado no Capítulo 2, subseção 2.4.1, este algoritmo deve necessariamente passar por
todas as permutações possíveis, analisando o custo de cada uma e comparando-o com o melhor
custo já encontrado até o momento. Portanto, a base do algoritmo é uma função que gere todas
as permutações possíveis para um certo tamanho de conjuntos.
A forma de implementação encontrada para estas permutações é uma função recursiva, que
recebe um vetor e uma posição (chamada de pos), e permuta o vetor a partir de pos. A idéia
por trás disso é uma indução, onde a base é que sabemos permutar um vetor de tamanho zero
(ou seja, quando pos corresponde ao último índice do vetor). O passo indutivo é colocar cada
elemento do vetor na primeira posição, e chamar recursivamente a função, para permutar da
segunda posição em diante.
Para não obter permutações inválidas, como permutações com números repetidos, a geração
das permutações é feita por meio de trocas entre duas posições do vetor. O vetor inicial é o
equivalente a gerar a matriz de associação como uma identidade, ou seja, agente 0 alocado a
tarefa 0, agente 1 a tarefa 1, e assim por diante. O código deste método está presente na Figura
3.2:
20 3.2. Força Bruta

1 public void permuta(int[] v, int pos, int n){


2 if(pos==n){
3 custo(v);
4 }
5 else{
6 for(int j=pos; j<n; j++){
7 swap(v,pos,j);
8 permuta(v, pos+1, n);
9 swap(v,pos,j);
10 }
11 }
12 }

Figura 3.2: Código do método principal do algoritmo Força Bruta. Neste código, o parâmetro
n é o último índice do vetor.

A cada chamada, o método testa se pos é o final do vetor. Se não for, será executado
um for, de pos até o final do vetor, e a cada iteração deste faremos o swap de pos e o índice
correspondente no for, fazemos uma nova chamada ao método, somando 1 ao pos e desfazemos
a troca feita, para que as permutações seguintes não sejam comprometidas.
Finalmente, para que se torne um algoritmo de força bruta, é necessário que a cada permu-
tação completada (ou seja, a cada vez que uma chamada do método permuta() for executada)
verificar se pos é o final do vetor. Caso positivo, deve-se calcular o custo.
No método de cálculo de custo, percorre-se o vetor com um for, acessando a matriz de
custos (que é um atributo da classe ForcaBruta) utilizando como linhas a variável de iteração
do for e nas colunas o valor contido no índice do vetor correspondente à atual iteração. O valor
contido nesta célula da matriz é somado à variável soma, que, ao final das iterações, conterá o
custo total da solução. Por fim, este custo é comparado com o custo da melhor solução até o
momento (ou seja, a permutação com o menor custo), representados pelos atributos de classe
melhorCusto e melhorSolucao. Caso a nova permutação seja uma solução com menor custo do
que a guardada em melhorSolucao, esta passa a ser a melhor solução. Este método de custo
é apresentado na figura 3.3. O algoritmo continua, até que todas as permutações tenham sido
avaliadas desta forma, varrendo o espaço de soluções por completo, e obtendo a solução ótima.
Capítulo 3. Implementação 21

1 public int custo(int[] v){


2 int soma = 0;
3 for(int i = 0; i < v.length; i++){
4 soma += matrizCusto[i][v[i]];
5 }
6 if(soma < melhorCusto){
7 melhorCusto = soma;
8 copiaVetor(melhorSolucao, v);
9 }
10 return soma;
11 }

Figura 3.3: Código fonte do método que calcula o custo de uma permutação

3.3 Branch and Bound


O Branch and Bound é, assim como o Força Bruta, um método exato, que garante que a solução
fornecida é ótima. Porém, ao contrário do Força Bruta, o Branch and Bound normalmente
não avalia todo o espaço de soluções. Algumas partes do espaço de soluções são eliminadas
automaticamente, pela técnica chamada de Bounding, ao identificar que estas não são eficientes,
e não podem superar o resultado já alcançado até aquele momento.
Ao analisar o método permutacao apresentado na seção anterior (referente ao Força Bruta),
pode-se constatar que este método nos fornece uma estratégia de branching válida, permitindo
desenvolver a árvore que representa as permutações e permitindo a eliminação antecipada de
espaços de solução (ou ramos da árvore) ineficientes. O método também percorre todo o espaço
de soluções, apesar que isto só ocorrerá no Branch and Bound no pior caso, ou seja, se as per-
mutações forem avaliadas em ordem decrescente de custo, do pior para o melhor. Porém, com
as otimizações corretas isto é raro. As otimizações propostas neste trabalho cuidam justamente
de gerar soluções iniciais melhores que as soluções geradas aleatoriamente.
Com isto, tem-se a base do Branch and Bound já finalizada, e a técnica de branching já im-
plementada pelo Força Bruta. A partir disso, o bounding é simples: ao verificar que o parâmetro
pos recebido pelo método permutacao() não é equivalente ao final do vetor, verifica-se uti-
lizando um if se a solução parcial até aquele momento possui um custo menor do que o menor
custo encontrado até o momento. Ao fazer isto, garante-se que serão eliminadas soluções inefi-
cientes frente à já obtida, já que apenas com algumas associações, a nova solução (parcial) já é
pior que a melhor solução encontrada. Isto é exemplificado pelas tabelas 3.3, 3.4 e 3.5.
Suponha que a melhor solução encontrada até o momento é a representada na Tabela 3.4 e
seu custo é 5. Ao colocar a associação do agente 0 com a tarefa 2, como no vetor representado
pela Tabela 3.5, o custo do vetor parcial já é 6 (ao analisar a matriz de custo na Tabela 3.3),
22 3.3. Branch and Bound

indicando que qualquer permutação cujo valor para o índice 0 seja 2 é ineficiente perante à
solução já obtida e, por isto, não precisa ser processada.

elementos tarefa 0 tarefa 1 tarefa 2


agente 0 5 2 6
agente 1 4 9 2
agente 2 1 7 5

Tabela 3.3: Exemplo: matriz de custo.

valor 1 2 0
índice 0 1 2

Tabela 3.4: Exemplo: vetor melhorSolucao com custo 5.

valor 2 x x
índice 0 1 2

Tabela 3.5: Exemplo: vetor de solução parcial, com custo 6.

O método principal do Branch and Bound (apresentado na Figura 3.4) é, portanto, bem
similar ao do Força Bruta nesta implementação.

1 public void permuta(int [] v, int pos, int n){


2 if(pos==n){
3 custo(v);
4 }
5 else{
6 if(custo(v, pos) <= melhorCusto){
7 for(int j=pos; j<n; j++){
8 swap(v,pos,j);
9 permuta(v, pos+1, n);
10 swap(v,pos,j);
11 }
12 }
13 }
14 }

Figura 3.4: Código da função principal do algoritmo Branch and Bound. Neste código, o
parâmetro n é o último índice do vetor

Assim como o Força Bruta, o algoritmo é executado até que todas as permutações tenham
sido avaliadas ou eliminadas. Uma possibilidade de melhora seria atualizar as variável melhor-
Solucao e melhorCusto ao buscar - utilizando uma heurística rápida - uma melhora da melhor
Capítulo 3. Implementação 23

solução que utilize o início de vetor recebido na chamada daquela instância de execução da
função.

3.4 Simulated Annealing


No Simulated Annealing implementado neste trabalho há uma melhoria em relação ao Simu-
lated Annealing padrão: aqui é mantido sempre guardado o melhor resultado encontrado até
o momento. Este tipo de melhoria é uma das melhorias mais simples recomendada em meta-
heurísticas que não guardam a melhor solução já encontrada. É indicada em muitos materiais,
inclusive em (Luke, 2009).
O método, do modo que foi implementado, pode ser dividido em três passos, identificados
nos parágrafos seguintes.
Primeiramente, é gerada uma solução vizinha à solução atual, utilizando o método swap().
Este método gera aleatoriamente dois números, dentro do intervalo de índice do vetor recebido,
e troca os valores presentes nos dois índices do vetor "‘sorteados"’. Este é o primeiro passo.
A seguir, o segundo passo é calcular o custo desta solução vizinha. Caso seja menor, o
vizinho é aceito e é copiado para o vetor atual (e também há o teste para determinar se é a melhor
solução até o momento - se for, a solução nova é copiada para a variável melhorSolucao). Caso
seja maior, ainda há chance de o vizinho ser aceito. Para isto, há uma função de aceitação,
definida por:

−delta
aceitacao = e temperatura

onde delta = custo(vizinho) − custo(atual). Isto corresponde a um número entre 0 e 1. A


seguir, é gerado aleatoriamente um número real entre 0 e 1. Caso o número gerado seja menor
que o resultado da fórmula, o vizinho é aceito.
Até aqui, isto corresponde a uma iteração de uma etapa da heurística, formada pelo primeiro
e segundo passos. Estes dois passos são repetidos até o número de iterações chegar no limite
definido.
Ao completar todas as iterações definidas no parâmetro itera, é feito o terceiro passo, onde
a temperatura é resfriada, ou seja, multiplica-se a temperatura por uma taxa de esfriamento.
O método é executado novamente, voltando ao primeiro passo, e executando todo o processo
descrito novamente, enquanto a temperatura for maior que um valor definido (no código este
valor é 0.001).
24 3.4. Simulated Annealing

Podemos simplificar e resumir a execução da seguinte maneira: a cada queda de temper-


atura, são feitas x iterações de geração e avaliação de vizinhos, sendo x o valor determinado
por um parâmetro (no código é nomeado como itera). Depois de realizadas as iterações, o valor
da temperatura é diminuído segundo a taxa de resfriamento, e novas x iterações são realizadas,
com o novo valor de temperatura. Isto é feito enquanto a temperatura for menor do que um
valor definido.
O código correspondente à função principal do método é descrito na figura 3.5.

1 public void simAnnealing(int[] permutacao){


2 double temperatura = Math.pow(size, 15);
3 double taxaResfriamento = 0.95;
4 int itera = size * 2000;
5 Random r = new Random();
6 int[] atual = permutacao;
7 melhorSolucao = atual;
8 double Cvizinho=0, Catual=0, delta=0, Cmelhor=0;
9 Cmelhor = custo(melhorSolucao);
10 while(temperatura > 0.001){
11 for(int j = 0; j < itera; j++){
12 int[] aux = new int[size];
13 System.arraycopy(atual, 0, aux, 0, atual.length);
14 int[] vizinho = new int[size];
15 System.arraycopy(atual, 0, vizinho, 0, atual.length);
16 vizinho = swap(vizinho);
17 Cvizinho = custo(vizinho);
18 Catual = custo(atual);
19 delta = Cvizinho - Catual;
20
21 if(delta < 0){
22 atual = vizinho;
23 if(Cvizinho < Cmelhor) {
24 melhorSolucao = atual;
25 Cmelhor = custo(melhorSolucao);
26 }
27 }
28 else{
29 double exp = ((-1)*delta)/temperatura;
30 double e = Math.exp(exp);
31 double f = r.nextFloat();
32 if(e > f) {
33 atual = vizinho;
34 }
35 }
36 }
37 temperatura *= taxaResfriamento;
38 }
39 }

Figura 3.5: Código da função principal do Simulated Annealing


Capítulo 3. Implementação 25

3.5 Algoritmo Guloso


Como otimização para o Branch and Bound e para o Simulated Annealing, foi decidida a im-
plementação de um algoritmo guloso, que é bastante rápido e é um bom candidato para gerar
soluções iniciais para estes dois outros métodos.
Este método possui uma estratégia muito simples: para cada agente se escolhe a melhor
associação (a que tem menor custo) e em seguida a elimina da lista de tarefas livres. Isto é feito
da seguinte maneira: é feito um for que percorre as linhas (que correspondem aos agentes) da
matriz de custos. Dentro deste for, há um outro para percorrer a lista de tarefas disponíveis.
Para cada tarefa avalia-se o seu custo com o agente que está sendo alocado e guarda-se o menor
destes custos, e a respectiva tarefa. Ao avaliar todas as tarefas disponíveis, a que tem menor
custo é associada ao agente e removida da lista de tarefas. Assim continua até que todos os
agentes sejam alocados às tarefas.
O código correspondente consta está a seguir, na figura 3.6:

1 public int[] alGuloso(int[][] custos){


2 matrizCusto = custos;
3 size = custos.length;
4
5 melhorSolucao = new int[size];
6 ArrayList<Integer> tarefas = new ArrayList<Integer>();
7 int i, j, menorTarefa = 0, indiceMenorTarefa = 0, tarefaAtual;
8
9 for(i = 0; i < size; i++)
10 tarefas.add(i);
11
12 for(i = 0; i < size; i++){
13 for(j = 0; j < tarefas.size(); j++){
14 tarefaAtual = tarefas.get(j);
15 if(matrizCusto[i][tarefaAtual] < matrizCusto[i][menorTarefa]){
16 menorTarefa = tarefaAtual;
17 indiceMenorTarefa = j;
18 }
19 }
20 melhorSolucao[i] = menorTarefa;
21 tarefas.remove(indiceMenorTarefa);
22 try{
23 menorTarefa = tarefas.get(0);
24 }catch(Exception e){}
25 indiceMenorTarefa = 0;
26 }
27 return melhorSolucao;
28 }

Figura 3.6: Código da função principal do algoritmo guloso


C APÍTULO

4
Resultados Computacionais

As instâncias utilizadas nos testes foram geradas aleatoriamente. Os valores de custo estão
dentro do intervalo de 0 a 99, incluindo ambos. O total de casos de teste utilizados são:

• 4 Instâncias de tamanho 5: 5a, 5b, 5c, 5d

• 3 Instâncias de tamanho 10: 10a, 10b, 10c

• 1 Instância de tamanho 15

• 1 Instância de tamanho 20

• 1 Instância de tamanho 30

• 1 Instância de tamanho 40

• 1 Instância de tamanho 50

Portanto, foram 12 instâncias geradas e testadas no total. As instâncias de tamanho x são as


instâncias que possuem x agentes, para alocar a x tarefas.
Abaixo está a Tabela 4.1, que mostra o número de permutações de cada instância. Este
número, como já citado no Capítulo 2, é n!, sendo n o tamanho da instância a resolver.

27
28 4.1. Métodos exatos

instância permutações
5 120
10 3628800
15 1307674368000
20 2.43290201 ∗ 1018
30 2.6525286 ∗ 1032
40 8.15915283 ∗ 1047
50 3.04140932 ∗ 1064

Tabela 4.1: Número de permutações para cada tamanho de instância

É importante citar que todos os testes foram feitos em um processador Intel Core2Quad
Q6600, de 2.4 GHz, utilizando somente um núcleo. Nenhum algoritmo foi otimizado para
mútiplos processadores ou núcleos. O sistema operacional utilizado foi o Windows 7 32bits.

4.1 Métodos exatos


Nesta seção são apresentados os resultados dos métodos exatos: Força Bruta e Branch and
Bound (não otimizado). Ambos os algoritmos garantem que a solução alcançada é a solução
ótima global.
Cada algoritmo foi executado 10 vezes para as instâncias de tamanho 5 e 10. No caso das
instâncias de tamanho 15 e 20, cada algoritmo foi executado 5 vezes. A partir disto foi calculado
o tempo médio das execuções para cada método e cada instância (que consta na Tabela 4.2), até a
instância de tamanho 20. O desvio padrão foi baixo, sendo menor que 1% do valor da média em
todos os casos. Como nestes métodos o custo da solução final não varia (é sempre encontrada
a ótima a cada execução), o custo das soluções ótimas encontradas para cada instância estão na
terceira linha (Solução Ótima) da Tabela 4.2, que também apresenta os tempos de execução de
ambos os métodos. A Figura 4.1 apresenta a representação gráfica dos tempos presentes nesta
tabela.
5a 5b 5c 5d 10a 10b 10c 15 20
Força Bruta <1 ms <1 ms <1 ms <1 ms 317,5 ms 321,6 ms 318,8 ms N/D N/D
Branch and Bound <1 ms <1 ms <1 ms <1 ms 4,2 ms <1 ms <1 ms 944,6 ms 197268,2 ms
Solução Ótima 48 89 124 91 181 116 84 158 149

Tabela 4.2: Tempos de execução e custo da solução ótima


Capítulo 4. Resultados Computacionais 29

Figura 4.1: Gráfico dos tempos correspondente à Tabela 4.2

Na Tabela 4.2, pode-se notar que, para o método Força Bruta, o tempo está como N/D (não
disponível) para as instâncias de tamanho 15 e 20. Isto é devido ao fato de que, para a instância
de tamanho 15, já é inviável executar uma única vez o algoritmo de Força Bruta.
Como o Força Bruta não executou para n ≥ 15, será feita uma estimativa do tempo necessário
de execução do método Força Bruta. A fórmula que utilizaremos é baseada no cálculo de tempo
de percurso, ou seja, dada a velocidade, e a distância, podemos calcular o tempo que leva para
encontrarmos o tempo necessário para que se complete. Analogamente:

n!
T (n) = (4.1)
cte
onde T (n) é o tempo de execução do algoritmo em milisegundos, n é o tamanho da instância
e cte é a constante de execução, ou seja, quantas permutações são avaliadas por milisegundo.
Esta constante pode ser obtida para o método de Força Bruta utilizando os valores obtidos nas
instâncias menores. Serão avaliados o melhor tempo de execução (instância 10a) e pior tempo
de execução (instância 10b):
30 4.1. Métodos exatos

10! 10!
T (10a) = T (10b) =
cte cte
10!
317, 5 ms = 321, 6 ms = 10!cte
cte
cte ≈ 11429, 3 cte ≈ 11283, 6

Utilizaremos a média do melhor e pior caso como constante de execução para o método de
Força Bruta. Desta forma:

11429, 3 + 11283, 6
cte =
2

cte = 11356, 45

Com isto, obtemos que o Força Bruta analisa, em média, 11356,45 permutações por milise-
gundo. Com isto, calculando o tempo necessário para a execução da instância de tamanho 15
obtemos:

15!
T (15) =
11356, 45

cte ≈ 1.15153 ∗ 108 ms

Este valor equivale a 31h 59min, o que, pelas estimativas, torna a instância de tamanho 15
inviável para o Força Bruta.
O mesmo cálculo pode ser feito para o Branch and Bound não otimizado. Primeiro cal-
culamos a constante de execução, utilizando como base a média do tempo de execução das
instâncias de tamanho 15 e 20:
Capítulo 4. Resultados Computacionais 31

15! 20!
T (15) = T (20) =
cte cte
15!
944, 6 ms = 197268, 2 ms = 20!cte
cte
cte ≈ 1, 38437 ∗ 109 cte ≈ 1, 2333 ∗ 1013

1, 38437 ∗ 109 + 1, 2333 ∗ 1013


cte =
2

cte = 6, 167192185 ∗ 1012

Obtemos a constante de 6, 167192185 ∗ 1012 permutações por milisegundo. Agora estimare-


mos o tempo necessário para a instância de tamanho 30 ser executada:

30!
T (30) =
6, 167192185 ∗ 1012

cte ≈ 4, 301 ∗ 1019 ms

Isto equivale a 5, 974 ∗ 1012 horas, ou seja, sem otimizações, o Branch and Bound é in-
viável para obter a solução para a instância de tamanho 30. Como confirmação, o algoritmo foi
executado por mais de dez horas, mas nenhum resultado foi obtido.

4.2 Metaheurística
Nesta seção é avaliado o desempenho do Simulated Annealing, sendo a do algoritmo guloso
avaliada para efeito de comparação.
Um detalhe que deve ser mencionado é que no Simulated Annealing os parâmetros de tem-
peratura e número de iterações influenciam profundamente no tempo de execução e na quali-
dade de solução, e por isso foram testadas várias configurações destes. Com valores mais altos,
a qualidade das soluções e o tempo de execução aumentam.
Primeiramente são apresentados os resultados para o algoritmo guloso, na Tabela 4.3. As
soluções ótimas foram retiradas dos testes anteriores com os métodos exatos. Não há variação
nas soluções encontradas, pois o algoritmo sempre executa os mesmos cálculos se a instância
32 4.2. Metaheurística

for a mesma. Também há a questão do tempo de execução, que é menor do que 1 ms para
qualquer uma das instâncias, em todas as execuções feitas (e que por isso não está presente
na tabela). A solução ótima para a instância de tamanho 30 foi encontrada com o Branch and
Bound otimizado, que será visto na próxima seção. As soluções ótimas para as instâncias de
tamanho 40 e 50 não foram encontradas com métodos exatos, e por isto não estão disponíveis.

instância solução encontrada solução ótima


5a 91 48
5b 114 89
5c 140 124
5d 163 91
10a 281 181
10b 172 116
10b 209 84
15 240 158
20 229 149
30 175 115
40 303 N/D
50 393 N/D

Tabela 4.3: Resultados para o algoritmo guloso

Fica claro que o algoritmo guloso não gera soluções boas o suficiente. Conforme se ex-
ecutam instâncias maiores, a distância entre o resultado obtido e a solução ótima fica maior.
Esta heurística só é realmente útil para o Problema de Alocação na geração de soluções iniciais
razoáveis para outros métodos mais eficientes.
Nas Tabelas 4.4 e 4.5 são apresentados os resultados para o Simulated Annealing. A heurís-
tica foi executada dez vezes para cada instância, em várias configurações dos parâmetros de
temperatura e número de iterações feitas com uma fórmula baseada no tamanho da instância,
como caracterizados abaixo:

• T emperatura = tamanho2 ; N umero de iteracoes = tamanho ∗ 100;

• T emperatura = tamanho3 ; N umero de iteracoes = tamanho ∗ 200;

• T emperatura = tamanho5 ; N umero de iteracoes = tamanho ∗ 500;

• T emperatura = tamanho6 ; N umero de iteracoes = tamanho ∗ 750;

• T emperatura = tamanho7 ; N umero de iteracoes = tamanho ∗ 1000;


Capítulo 4. Resultados Computacionais 33

• T emperatura = tamanho10 ; N umero de iteracoes = tamanho ∗ 1500;

• T emperatura = tamanho15 ; N umero de iteracoes = tamanho ∗ 2000;

Quanto maiores os valores, mais tempo é executado o método, e maiores as chances de se


obter soluções mais aproximadas à ótima. Primeiramente, são mostrados os tempos de execução
na Tabela 4.4. Cada configuração de parâmetros é definida como SA(x,y), onde x indica o valor
que determinará a temperatura, pela fórmula T emperatura = tamanhox e y é o valor que
determinará o número de iterações, pela fórmula N umero de iteracoes = tamanho ∗ y. A
Figura representa o gráfico equivalente à Tabela 4.4.

Instâncias
parâmetros 5a 5b 5c 5d 10a 10b 10c 15 20 30 40 50
SA(2,100) 0,06 0,05 0,05 0,06 0,16 0,16 0,15 0,26 0,37 0,73 1,14 1,63
SA(3,200) 0,13 0,12 0,12 0,12 0,31 0,31 0,31 0,55 0,84 1,62 2,62 3,84
SA(5,500) 0,38 0,36 0,36 0,36 1,00 1,00 1,00 1,79 2,77 5,48 8,89 13,38
SA(6,750) 0,62 0,60 0,60 0,60 1,68 1,67 1,67 3,02 4,71 9,38 15,44 22,78
SA(7,1000) 0,88 0,86 0,85 0,86 2,40 2,44 2,42 4,45 6,92 14,13 23,02 33,90
SA(10,1500) 1,62 1,60 1,58 1,59 4,64 4,64 4,64 8,47 13,31 27,71 45,75 68,74
SA(15,2000) 2,84 2,80 2,81 2,80 8,37 8,34 8,33 15,44 24,55 49,84 86,17 128,95

Tabela 4.4: Tempo de execução para o SA puro. Os tempos estão em segundos.

É possível notar que o tempo cresce bastante quando se aumenta o tamanho da instância
(devido às fórmulas de determinação da temperatura e de iterações em função do tamanho da
instância), ou quando se aumenta o valor dos parâmetros. A vantagem disso, entretanto, é que
geralmente se obtém melhores soluções, como mostrado na Tabela 4.5. Na Figura 4.3, temos a
melhor solução encontrada em 10 execuções para as instâncias de tamanho 5 até tamanho 30,
enquanto que a Figura 4.4 apresenta o mesmo, só que para as instâncias de tamanho 40 e 50.
34 4.2. Metaheurística

Figura 4.2: Gráfico dos tempos correspondente à Tabela 4.4

É interessante notar que foi encontrada a solução ótima para as instâncias menores. Nestes
casos, é possível notar que a variação de resultados é pequena ou inexistente, nas dez execuções.
Uma estratégia interessante para se obter boas soluções no Simulated Annealing é, portanto,
executá-lo várias vezes, e escolher o melhor resultado obtido (o com o menor custo). Caso
a variação seja zero, é grande a chance de que se trate da solução ótima, porém não é 100%
garantido.
A tabela também indica que, conforme aumentam os valores dos parâmetros, as soluções
obtidas tendem a ser melhores. Porém, a desvantagem clara demonstrada nos testes para o
Simulated Annealing é conseguir determinar cada valor de parâmetro sem a necessidade de se
fazer testes com várias configurações para cada instância, processo que acaba sendo bastante
trabalhoso. Isto é válido, principalmente, para que não se utilize valores de parâmetros maiores
que o necessário para encontrar o ótimo em instâncias pequenas, o que indica um gasto de
tempo e poder de processamento desnecessário, que se torna crítico conforme se necessita de
soluções para instâncias muito grandes.
Capítulo 4. Resultados Computacionais 35
Instâncias
parâmetros 5a 5b 5c 5d 10a 10b 10c 15 20 30 40 50
maior 48 89 124 91 181 116 84 158 152 147 191 219
SA(2,100) mediana 48 89 124 91 181 116 84 158 149 119 163 193
menor 48 89 124 91 181 116 84 158 149 115 157 173
maior 48 89 124 91 181 116 84 158 150 129 169 205
SA(3,200) mediana 48 89 124 91 181 116 84 158 149 119 158 182
menor 48 89 124 91 181 116 84 158 149 115 148 176
maior 48 89 124 91 181 116 84 158 149 121 167 197
SA(5,500) mediana 48 89 124 91 181 116 84 158 149 115 157 179
menor 48 89 124 91 181 116 84 158 149 115 147 165
maior 48 89 124 91 181 116 84 158 149 117 162 188
SA(6,750) mediana 48 89 124 91 181 116 84 158 149 115 154 172
menor 48 89 124 91 181 116 84 158 149 115 151 164
maior 48 89 124 91 181 116 84 158 149 117 155 183
mediana 48 89 124 91 181 116 84 158 149 115 152 177
SA(7,1000)
menor 48 89 124 91 181 116 84 158 149 115 147 168
maior 48 89 124 91 181 116 84 158 149 115 156 184
mediana 48 89 124 91 181 116 84 158 149 115 147 174
SA(10,1500)
menor 48 89 124 91 181 116 84 158 149 115 143 161
maior 48 89 124 91 181 116 84 158 149 115 153 187
mediana 48 89 124 91 181 116 84 158 149 115 148 174
SA(15,2000)
menor 48 89 124 91 181 116 84 158 149 115 142 164
Solução Ótima 48 89 124 91 181 116 84 158 149 115 N/D N/D

Tabela 4.5: Soluções encontradas com o SA puro

Figura 4.3: Gráfico das soluções para instâncias pequenas e médias

4.3 Otimizações e Comparações Finais


Finalmente, falta comparar os dois métodos que melhor resolvem o problema: Simulated An-
nealing e Branch and Bound. Em ambos foram feitas otimizações, como apresentado a seguir.
36 4.3. Otimizações e Comparações Finais

Figura 4.4: Gráfico das soluções para instâncias grandes

Para tentar melhorar o desempenho do Branch and Bound, e tentar resolver instâncias
maiores, foram feitas duas otimizações no método. A idéia para ambas é que com uma solução
inicial melhor o limite para corte fica bem mais restrito pois o custo da solução inicial está
relativamente próximo do custo da solução ótima. Isto faz com que o processo de bounding
ocorra em níveis mais altos da árvore, efetivamente descartando espaços de soluções maiores,
e tornando o algoritmo mais rápido. Isto foi feito gerando uma solução inicial com o algoritmo
guloso, e também com o Simulated Annealing (utilizando parâmetros com valores baixos, para
não aumentar muito o tempo de processamento). A comparação entre o Branch and Bound puro
(BB), o Branch and Bound otimizado com o algoritmo guloso (BBA) e o Branch and Bound
otimizado com o Simulated Annealing (BBS) está na Tabela 4.6, e um gráfico que representa a
tabela está na Figura 4.5

5a 5b 5c 5d 10a 10b 10c 15 20 30


BB <1 ms <1 ms <1 ms <1 ms 4,2 ms <1 ms <1 ms 944,6 ms 197268,2 ms N/D
BBA <1 ms <1 ms <1 ms <1 ms 3,1 ms <1 ms 1,6 ms 190,8 ms 32951,2 ms N/D
BBS 127,1 ms 122,2 ms 120,95 ms 119,4 ms 314 ms 317,2 ms 314,8 ms 718,8 ms 15083 ms 21319104 ms
Solução Ótima 48 89 124 91 181 116 84 158 149 115

Tabela 4.6: Tempos de execução e custo da solução ótima

Apesar de ser mais lento em instâncias pequenas, a otimização com o Simulated Annealing
é muito mais rápida que o Branch and Bound puro, ou o otimizado somente com o algoritmo
Capítulo 4. Resultados Computacionais 37

Figura 4.5: Gráfico de tempos referentes à Tabela 4.6

guloso quando utilizamos instâncias maiores (de tamanho 20 ou mais). Como os tempos para
instâncias pequenas não são problema (todos menores que um segundo), a opção clara é a
otimização com o Simulated Annealing gerando a solução inicial.
A mesma idéia de melhorar a solução inicial é aplicada para o Simulated Annealing, ro-
dando o algoritmo guloso e utilizando a permutação resultante como solução inicial para o SA.
Isto melhora a convergência do método, tornando-a ligeiramente mais rápida. As tabelas de
tempos de execução e qualidade de solução são apresentadas nas Tabelas 4.7 e 4.8, respectiva-
mente:
Instâncias
parâmetros 5a 5b 5c 5d 10a 10b 10c 15 20 30 40 50
SA(2,100) 0,06 0,06 0,06 0,05 0,15 0,14 0,16 0,26 0,37 0,69 1,09 1,59
SA(3,200) 0,12 0,12 0,12 0,12 0,31 0,31 0,31 0,55 0,84 1,64 2,64 3,84
SA(5,500) 0,36 0,36 0,36 0,36 1,00 1,00 1,01 1,78 2,76 5,52 8,92 13,26
SA(6,750) 0,60 0,60 0,60 0,60 1,66 1,67 1,67 3,01 4,69 9,40 15,41 22,67
SA(7,1000) 0,85 0,85 0,85 0,86 2,39 2,39 2,44 4,42 6,88 13,93 22,74 33,67
SA(10,1500) 1,59 1,59 1,59 1,59 4,62 4,63 4,64 8,48 13,28 26,99 44,61 67,23
SA(15,2000) 2,80 2,80 2,79 2,80 8,32 8,32 8,34 15,39 24,53 51,52 86,52 129,30

Tabela 4.7: Tempo de execução para o SA otimizado. Os tempos estão em segundos.


38 4.3. Otimizações e Comparações Finais
Instâncias
parâmetros 5a 5b 5c 5d 10a 10b 10c 15 20 30 40 50
maior 48 89 124 91 181 116 84 158 156 145 173 192
mediana 48 89 124 91 181 116 84 158 150 122 164 211
SAO(2,100)
menor 48 89 124 91 181 116 84 158 149 115 151 184
maior 48 89 124 91 181 116 84 158 150 126 168 207
mediana 48 89 124 91 181 116 84 158 149 118 161 186
SAO(3,200)
menor 48 89 124 91 181 116 84 158 149 115 141 174
maior 48 89 124 91 181 116 84 158 149 120 168 198
mediana 48 89 124 91 181 116 84 158 149 115 150 185
SAO(5,500)
menor 48 89 124 91 181 116 84 158 149 115 146 172
maior 48 89 124 91 181 116 84 158 149 123 162 194
mediana 48 89 124 91 181 116 84 158 149 115 150 182
SAO(6,750)
menor 48 89 124 91 181 116 84 158 149 115 144 164
maior 48 89 124 91 181 116 84 158 149 116 164 185
mediana 48 89 124 91 181 116 84 158 149 115 150 169
SAO(7,1000)
menor 48 89 124 91 181 116 84 158 149 115 141 160
maior 48 89 124 91 181 116 84 158 149 115 153 185
mediana 48 89 124 91 181 116 84 158 149 115 146 172
SAO(10,1500)
menor 48 89 124 91 181 116 84 158 149 115 141 165
maior 48 89 124 91 181 116 84 158 149 115 157 180
mediana 48 89 124 91 181 116 84 158 149 115 149 172
SAO(15,2000)
menor 48 89 124 91 181 116 84 158 149 115 141 163
Solução Ótima 48 89 124 91 181 116 84 158 149 115 N/D N/D

Tabela 4.8: Soluções encontradas com o SA otimizado

Os tempos são bem similares à tabela 4.4 referente ao SA puro, não sendo efetivos para
efeito de comparação. As soluções, porém, tendem a ser ligeiramente melhores no otimizado,
como esperado. A comparação de ambos os métodos é dada na tabela 4.9.
Capítulo 4. Resultados Computacionais 39

instâncias
parâmetros método medida 20 30 40 50
mediana 149 119 163 193
SA menor 149 115 157 173
t(2,100) mediana 150 122 164 211
SAO menor 149 115 151 184
mediana 149 119 158 182
SA menor 149 115 148 176
t(3,200) mediana 149 118 161 186
SAO menor 149 115 141 174
mediana 149 115 157 179
SA menor 149 115 147 165
t(5,500) mediana 149 115 150 185
SAO menor 149 115 146 172
mediana 149 115 154 172
SA menor 149 115 151 164
t(6,750) mediana 149 115 150 182
SAO menor 149 115 144 164
mediana 149 115 152 177
SA menor 149 115 147 168
t(7,1000) mediana 149 115 150 169
SAO menor 149 115 141 160
mediana 149 115 147 174
SA menor 149 115 143 161
t(10,1500) mediana 149 115 146 172
SAO menor 149 115 141 165
mediana 149 115 148 174
SA menor 149 115 142 164
t(15,2000) mediana 149 115 149 172
SAO menor 149 115 141 163

Tabela 4.9: Comparação entre o SA puro e o SA otimizado


40 4.4. Instância de alocação professor-matéria

4.4 Instância de alocação professor-matéria


Nesta seção será resolvida uma instância real: a alocação de professores à disciplinas, na Uni-
versidade Federal de São Paulo, referente ao campus São José dos Campos.
Foram fornecidas a planilha com as opções de cada professor utilizadas para decidir as
alocações e a solução que foi dada para o semestre em questão. Na planilha, cada professor
preenche suas opções com notas de 1 a 6, não necessariamente contendo todas as opções (um
professor pode preencher somente a sua primeira e segunda opções, ou pode ter mais de uma
primeira opção). As disciplinas que o professor não deseja ministrar são deixadas em branco.
Foi necessário dar um valor para as opções em branco (as opções não desejadas pelo docente).
Foi escolhido o valor 10, que é maior o suficiente que a opção 6 a ponto de desencorajar estas
associações.
Nesta instância há algumas peculiaridades. A primeira é que há uma matéria que não con-
stava na planilha de preferências, mas consta na atribuição final fornecida (chamada ’Eletiva
BCT’) e também há três professores na mesma situação: Danieli, Eduardo e Luciana. Estes
foram adicionados à planilha com o custo 10, já que não haviam informações disponíveis sobre
a preferência destes professores e da matéria em questão.
A partir disto, têm-se outro problema: o número de professores e matérias é diferente. Na
planilha, antes das adições, constavam 47 professores e 80 disciplinas. Depois das adições,
temos 50 professores e 81 disciplinas. Isto seria definido como o Problema de Alocação Gener-
alizado (ou também chamado de Problema de Transporte em algumas literaturas, como (Gold-
barg e Luna, 2005)), ou seja, é um Problema de Alocação, mas não há a restrição de ambos os
conjuntos de agentes e tarefas terem o mesmo tamanho.
Isto foi adaptado para o problema abordado neste trabalho, da seguinte maneira: o con-
junto de professores foi duplicado (ou seja, cada professor aparece 2 vezes, tendo dois números
diferentes associados a ele), totalizando (teoricamente) 100 professores. Para igualar, foram
adicionadas 19 matérias “fantasmas” (com nome ’Nenhuma’), totalizando 100 matérias. O
custo de associar os professores a uma destas matérias é definido como 0, para que todos os
professores tenham a chance de ter uma associação “livre”. Portanto, a instância calculada é de
tamanho 100.
Somado a estas inconsistências, foi encontrado um outro detalhe: há algumas matérias que
nenhum professor quer ministrar (segundo a planilha), e que, portanto, seu custo sempre será
o mais alto possível. Estas matérias são: Compiladores, Eletiva BMC, Estrutura e Dinâmica
Social, Cálculo I (vespertino e noturno), Química e Biologia. A Tabela 4.10 mostra o menor
Capítulo 4. Resultados Computacionais 41

custo possível para cada matéria (ou seja, a melhor opção teoricamente possivel, sem levar em
conta as combinações).
Na resolução do problema, foram utilizados apenas o Simulated Annealing otimizado e não
otimizado, devido ao tamanho da instância. Os parâmetros utilizados foram T emperatura =
n2 e N umero de iteracoes = n ∗ 100, onde n é o tamanho da instância. Ambos foram execu-
tados dez vezes, e os tempos de execução presentes estão na Tabela 4.11. Foram encontradas
várias soluções possíveis, todas próximas em termos de custo. Houve mais de uma instância
com o menor custo encontrado (205). Uma destas instâncias está presente na Tabela 4.12. A
solução real dada pela universidade está presente na Tabela 4.13, com custo 240.
A solução encontrada possui, portanto, um custo menor do que a solução definida pela
universidade. Porém, há algumas divergências de opções entre as instâncias, o que afeta o re-
sultado. Com um melhor sistema para cada docente selecionar as opções, de modo que este seja
preenchido por todos e corretamente, é possível utilizar um método como o Simulated Anneal-
ing para gerar estas alocações professor-matéria. Como há professores que foram associados
a matérias vazias, é possível que sejam realizados ajustes em cima de uma solução gerada por
este método apresentado.
É interessante notar que devido à uniformidade da instância (a maior parte dos custos era
alta, com o valor 10), a convergência do método foi mais rápida e a variação das soluções foi
pequena (se comparadas às instâncias geradas aleatoriamente), apesar de ter sido utilizada a
configuração com os menores valores de parâmetros, já definidos anteriormente.
42 4.4. Instância de alocação professor-matéria

Matéria Menor custo possível


Álgebra Linear 1
Álgebra Linear 1
Algoritmos e Estrutura de Dados I 1
Algoritmos e Estrutura de Dados I 1
Algoritmos e Estrutura de Dados I 1
Algoritmos e Estrutura de Dados I 1
Arquitetura e Organização de Computadores 2
Arquitetura e Organização de Computadores 2
Banco de Dados 1
Banco de Dados 1
Bioquimica e Fisiologia Humana 1
Bioquimica e Fisiologia Humana 1
Cálculo II (Função de Várias Variáveis) 1
Cálculo II (Função de Várias Variáveis) 1
Cálculo II (Função de Várias Variáveis) 1
Cálculo Numérico BCC 1
Cálculo Numérico BCC 1
Cálculo Numérico II 1
Compiladores 10
Compiladores 10
Eletiva BCC I 1
Eletiva BCC I 1
Eletiva BCC II 1
Eletiva BCC II 1
Eletiva BCC III 1
Eletiva BCC IV 1
Eletiva BMC I 10
Eletiva BMC II 2
Espaços Métricos 1
Estrutura e Dinamica Social 10
Estrutura e Dinamica Social 10
Fenômenos Mecânicos 1
Fenômenos Mecânicos 1
Física I 1
Física III 1
Física para Computação ("quase"Física III) 3
Física para Computação ("quase"Física III) 3
Funções Analíticas 1
Geometria Analítica II 1
Inferência e Análise de Regressão 1
Introdução à Engenharia de Materiais 1
Introdução à Pesquisa Operacional 1
Introdução à Pesquisa Operacional 1
Matemática Discreta 2
Metodologia da Pesquisa e Comunicação Científica 1
Multimídia 1
Multimídia 1
Otimização não Linear 1
Paradigmas de Programação 2
Paradigmas de Programação 2
Introdução à Engenharia Biomédica 1
Probabilidade II 1
Processamento de Imagens 1
Processamento de Imagens 1
Programação Concorrente e Distribuída 1
Programação Concorrente e Distribuída 1
Programação Orientada a Objetos I 1
Programação Orientada a Objetos I 1
Projeto e Análise de Algoritmos 1
Projeto e Análise de Algoritmos 1
Projeto e Análise de Algoritmos 1
Quimica Geral Experimental 1
Quimica Geral Experimental 1
Quimica Geral Experimental 1
Quimica Geral Experimental 1
Quimica Geral Experimental 1
Quimica Geral Experimental 1
Quimica Geral Experimental 1
Quimica Geral Experimental 1
Teoria dos Grafos 1
Teoria dos Grafos 1
Teoria dos números e Criptografia 1
Verificação e Validação de Software 1
Verificação e Validação de Software 1
Biologia I Curso Prático 4
Cálculo I (Vespertino) 10
Cálculo I (Noturno) 10
Química 10
Química 10
Biologia 10
Eletiva BCT 10

Tabela 4.10: Menor custo possível para cada matéria


Capítulo 4. Resultados Computacionais 43

Método Tempo de execução médio Maior custo Custo mediano Menor custo
SA 5044.5 ms 207 205 205
SA Otimizado 5024.1 ms 209 205 205

Tabela 4.11: Tempos de execução e custos encontrados

Professor Matéria 1 Custo Matéria 2 Custo


Alvaro Programação Concorrente e Distribuída 1 Programação Concorrente e Distribuída 1
Ana Paula Quimica Geral Experimental 1 Quimica Geral Experimental 1
Antonelli Física para Computação ("quase"Física III) 4 Fenômenos Mecânicos 1
Arlindo Multimídia 1 Multimídia 1
Cappabianco Projeto e Análise de Algoritmos 4 Arquitetura e Organização de Computadores 3
Chaves Introdução à Pesquisa Operacional 1 Programação Orientada a Objetos I 2
Claudia Nenhuma 0 Nenhuma 0
Cristovan Quimica Geral Experimental 1 Quimica Geral Experimental 1
Daniela Nenhuma 0 Química 10
Dayane Quimica Geral Experimental 1 Quimica Geral Experimental 1
Dilermando Introdução à Engenharia de Materiais 1 Nenhuma 0
Eliandra Quimica Geral Experimental 1 Quimica Geral Experimental 1
Elizangela Cálculo Numérico BCC 1 Nenhuma 0
Erwin Cálculo Numérico II 1 Matemática Discreta 2
Eudes Nenhuma 0 Cálculo I (Vespertino) 10
Ezequiel Algoritmos e Estrutura de Dados I 1 Algoritmos e Estrutura de Dados I 1
Fabio Verificação e Validação de Software 1 Verificação e Validação de Software 1
Flavio Cálculo I (Noturno) 10 Nenhuma 10
Francisco Compiladores 10 Probabilidade II 1
Gabriel Introdução à Pesquisa Operacional 2 Cálculo Numérico BCC 1
Gama Eletiva BMC II 2 Teoria dos números e Criptografia 1
Gurjao Física para Computação ("quase"Física III) 3 Introdução à Engenharia Biomédica 1
Jaime Processamento de Imagens 2 Processamento de Imagens 2
Juliana Nenhuma 0 Inferência e Análise de Regressão 1
Katia Fenômenos Mecânicos 1 Física I 1
Kelly Cálculo II (Função de Várias Variáveis) 1 Cálculo II (Função de Várias Variáveis) 1
Lilia Nenhuma 0 Nenhuma 0
Manuel Física III 1 Nenhuma 0
Marcio Banco de Dados 1 Banco de Dados 1
Maria Teoria dos Grafos 1 Teoria dos Grafos 1
Mariana Nenhuma 0 Metodologia da Pesquisa e Comunicação Científica 1
Martin Biologia I Curso Prático 4 Nenhuma 0
Meira Projeto e Análise de Algoritmos 1 Projeto e Análise de Algoritmos 1
Nelson Álgebra Linear 1 Álgebra Linear 1
Otavio Eletiva BCC III 2 Programação Orientada a Objetos I 1
Passos Espaços Métricos 1 Nenhuma 0
Quiles Eletiva BCC I 1 Eletiva BCC II 1
Regina Paradigmas de Programação 2 Paradigmas de Programação 2
Ricardo Compiladores 10 Otimização não Linear 1
Silas Nenhuma 0 Funções Analíticas 1
Silvio Estrutura e Dinamica Social 10 Química 10
Tatiana Bioquimica e Fisiologia Humana 1 Bioquimica e Fisiologia Humana 1
Thaciana Nenhuma 0 Geometria Analítica II 1
Tiago Arquitetura e Organização de Computadores 2 Eletiva BCC II 1
Valerio Algoritmos e Estrutura de Dados I 1 Eletiva BCC I 2
Vilhena Nenhuma 0 Cálculo II (Função de Várias Variáveis) 1
Vinicius Algoritmos e Estrutura de Dados I 1 Eletiva BCC IV 2
Danieli Nenhuma 0 Nenhuma 0
Eduardo Nenhuma 0 Biologia 10
Luciana Estrutura e Dinamica Social 10 Eletiva BMC I 10
Custo Total 205

Tabela 4.12: Uma das soluções encontradas para a instância, com custo 205
44 4.4. Instância de alocação professor-matéria

Professor Matéria 1 Custo Matéria 2 Custo


Álvaro Programação Concorrente e Distribuída 1 Programação Concorrente e Distribuída 1
Ana Paula Química Geral Experimental 1 Nenhuma 0
Antonelli Fenômenos Mecânicos 1 Fenômenos Mecânicos 1
Arlindo Multimídia 1 Multimídia 1
Cappabianco Processamento de Imagens 1 Processamento de Imagens 1
Chaves Introdução à Pesquisa Operacional 1 Programação Orientada a Objetos I 2
Cláudia Biologia I Curso Prático 4 Nenhuma 0
Cristovan Química Geral Experimental 1 Química Geral Experimental 1
Daniela Banco de Dados 10 Banco de Dados 10
Danieli Química Geral Experimental 10 Nenhuma 0
Dayane Química Geral Experimental 1 Química Geral Experimental 1
Dilermando Introdução à Engenharia de Materiais 1 Nenhuma 0
Eduardo Compiladores 10 Compiladores 10
Eliandra Química Geral Experimental 1 Química Geral Experimental 1
Elizângela Cálculo II (Função de Várias Variáveis) 2 Cálculo II (Função de Várias Variáveis) 2
Erwin Cálculo Numérico II 1 Nenhuma 0
Eudes Cálculo II (Função de Várias Variáveis) 10 Nenhuma 0
Ezequiel Eletiva BCC II 2 Eletiva BCC II 2
Fábio Programação Orientada a Objetos I 2 Nenhuma 0
Flávio Bioquímica e Fisiologia Humana 1 Nenhuma 0
Francisco Álgebra Linear 2 Probabilidade II 1
Gabriel Cálculo Numérico BCC 1 Cálculo Numérico BCC 1
Gama Eletiva BMC I 2 Teoria dos números e Criptografia 1
Gurjão Física para Computação ("quase"Física III) 3 Nenhuma 0
Jaime Eletiva BCC IV 3 Nenhuma 0
Juliana Inferência e Análise de Regressão 1 Nenhuma 0
Kátia Física I 1 Nenhuma 0
Lília Química Geral Experimental 2 Nenhuma 0
Luciana Estrutura e Dinâmica Social 10 Estrutura e Dinâmica Social 10
Manuel Física III 1 Nenhuma 0
Márcio Eletiva BCC III 2 Projeto e Análise de Algoritmos 3
Mariá Teoria dos Grafos 1 Teoria dos Grafos 1
Mariana Metodologia da Pesquisa e Comunicação Científica 1 Nenhuma 0
Martin Biologia 10 Nenhuma 0
Meira Projeto e Análise de Algoritmos 1 Projeto e Análise de Algoritmos 1
Nelson Cálculo I (Vespertino) 10 Cálculo I (Noturno) 10
Otávio Verificação e Validação de Software 3 Verificação e Validação de Software 3
Passos Álgebra Linear 2 Espaços Métricos 1
Quiles Eletiva BCC I 1 Eletiva BCC I 1
Regina Algoritmos e Estruturas de Dados I 1 Algoritmos e Estruturas de Dados I 1
Ricardo Introdução à Pesquisa Operacional 5 Otimização não Linear 1
Silas Funções Analíticas 1 Matemática Discreta 2
Sílvio Eletiva BCT 10 Introdução à Engenharia Biomédica 10
Tatiana Bioquímica e Fisiologia Humana 1 Nenhuma 0
Thaciana Geometria Analítica II 1 Nenhuma 0
Tiago Arquitetura e Organização de Computadores 2 Arquitetura e Organização de Computadores 2
Valério Algoritmos e Estruturas de Dados I 1 Algoritmos e Estruturas de Dados I 1
Vilhena Eletiva BMC II 10 Nenhuma 0
Vinícius Paradigmas de Programação 3 Paradigmas de Programação 3
Custo Total 240

Tabela 4.13: Solução real dada pela universidade, com custo 240
C APÍTULO

5
Conclusão

5.1 Considerações finais


O Problema de Alocação, como ficou demonstrado pelas referências utilizadas, e também nos
testes e na análise dos resultados destes feita no Capítulo 4, é um problema complexo e de
grande utilidade. Tendo isto em mente, é razoável dizer que, para instâncias pequenas ou mé-
dias, utilizar o Branch and Bound é viável. Para instâncias maiores, é recomendado utilizar uma
heurística, como o Simulated Annealing, deixando de garantir a solução ótima, mas obtendo
uma aproximação que pode ser utilizada para resolver o problema em tempo hábil, principal-
mente se é necessário aplicá-lo no mundo real, como na instância da universidade apresentada
na Seção 4.4.
Além disso, é um problema cuja relaxação, que é permitir conjuntos de agentes e tarefas
com tamanhos diferentes, pode ser aplicada a mais casos reais. A instância pode ser adaptada
de modo a obedecer a restrição de tamanho dos conjuntos, de modo a aproveitar os métodos
utilizados para este problema, com resultados satisfatórios.
Os resultados dos testes feitos foram todos dentro do esperado: o Branch and Bound obteve
as soluções ótimas, porém exigiu bastante tempo de execução, e o Simulated Annealing encon-
trou boas aproximações para as soluções em tempo bem menor. Entretanto, algo que, apesar de
ser esperado, é impressionante, é a velocidade com que o problema aumenta, de modo que para

45
46 5.2. Trabalhos Futuros

instâncias de tamanho 30, obtém-se a resposta ótima com o Branch and Bound otimizado com
Simulated Annealing em algumas horas (aproximadamente seis), enquanto que o de tamanho 40
é impensável para o método da maneira que está implementada, e com o hardware disponível.
O Simulated Annealing foi bastante rápido - ao ser comparado com o Branch and Bound - na
resolução do problema, e obteve soluções muito boas. Com seu reduzido tempo, permite que
possa ser executado diversas vezes e que seja utilizada a melhor solução encontrada dentre to-
das as execuções (e ainda assim tendo um tempo total de execução bem menor que o Branch
and Bound).

5.2 Trabalhos Futuros


Há muitas frentes ainda para desenvolver no assunto discutido. Nos parágrafos seguintes são
abordadas algumas idéias que surgiram após a realização deste trabalho.
Primeiramente, há a otimização dos métodos Branch and Bound e Simulated Annealing. No
caso do primeiro, há muitas formas de desenvolver a árvore de permutações (ou seja, técnicas
de branching) e de obter os limites para o bounding, ou seja, a poda dos ramos ineficientes da
árvore, além de outras técnicas pertinentes. Algumas das variantes encontradas na literatura
são:

• Formação da árvore:

– Variante de Dank
– Variante de Land e Doig
– Variante de Spielberg
– Método das Penalidades
– Método de Taha
– Estratégias dinâmicas

• Desenvolvimento da árvore (como percorrê-la):

– Busca em Profundidade
– Busca em Largura
– Variantes Híbridas

• Técnicas para obtenção dos limites:


Capítulo 5. Conclusão 47

– Relaxação Linear
– Relaxação Lagrangeana
– Algoritmos heurísticos e metaheurísticos
– Cortes

Há ainda a otimização do código fonte em si para melhorar o tempo de execução. Pode


ser utilizada uma estratégia de multithreading, para tirar proveito dos processadores atuais com
múltiplos núcleos, tanto no caso do Branch and Bound como do Simulated Annealing.
Para o Simulated Annealing, a idéia é realizar mais testes com diferentes configurações de
parâmetros, de modo a obter uma função matemática que possa aproximar o número de iter-
ações necessário para uma boa convergência para um resultado, de modo a melhorar a variação
das soluções encontradas, obtendo soluções menores no geral. Isto pode ser feito utilizando os
pontos obtidos nos testes, e interpolando uma função onde se entra com o tamanho de instân-
cia e se obtém os valores recomendados para os parâmetros. Entretanto, apesar de útil, este é
um caminho difícil, pois esta função depende de muitas variáveis e características de instâncias
diferentes.
Outra frente a ser desenvolvida é a relaxação do problema, denominada Problema de Alo-
cação Generalizado ou Problema do Transporte. Como já citado, pode ser aplicado a ainda
mais instâncias reais. É possível adaptar os métodos para a relaxação e analisar os resultados.
Existem vários materiais abordando este problema, como (Pigatti, 2003), e os outros trabalhos
presentes na Seção 1.3.
Referências Bibliográficas

BAZARAA , M.; JARVIS , J.; S HERALI , H. Linear programming and network flows. John
Wiley & Sons, 2009.
Disponível em http://books.google.com/books?id=2DKKHvV\_xVwC

B EASLEY, J. E., ed. Advances in linear and integer programming. New York, NY, USA:
Oxford University Press, Inc., 1996.

B URKARD , R. E. Selected topics on assignment problems. Discrete Appl. Math., v. 123,


p. 257–302, 2002.
Disponível em http://dx.doi.org/10.1016/S0166-218X(01)00343-2

C ERNÝ, V. Thermodynamical approach to the traveling salesman problem: An efficient


simulation algorithm. Journal of Optimization Theory and Applications, v. 45, p. 41–51,
10.1007/BF00940812, 1985.
Disponível em http://dx.doi.org/10.1007/BF00940812

C ORMEN , T.; L EISERSON , C.; R IVEST, R.; S TEIN , C. Introduction to algorithms. MIT
Press, 2009.
Disponível em http://books.google.com/books?id=h2xRPgAACAAJ

C OSTA , F. P. D .; S OUZA , M. J. F.; P INTO , L. R. Um modelo de programação matemática


para alocação estática de caminhões visando ao atendimento de metas de produção e
qualidade. Rem: Revista Escola de Minas, v. 58, p. 77 – 81, 2005.
Disponível em http://www.scielo.br/scielo.php?script=sci_
arttext&pid=S0370-44672005000100013&nrm=iso

DASGUPTA , D.; H ERNANDEZ , G.; G ARRETT, D.; V EJANDLA , P. K.; K AUSHAL , A.; Y ER -
NENI , R.; S IMIEN , J. A comparison of multiobjective evolutionary algorithms with in-
formed initialization and kuhn-munkres algorithm for the sailor assignment problem. In:
Proceedings of the 2008 GECCO conference companion on Genetic and evolutionary com-
putation, New York, NY, USA: ACM, 2008, p. 2129–2134 (GECCO ’08, v.1).
Disponível em http://doi.acm.org/10.1145/1388969.1389035

49
50 Referências Bibliográficas

F LETCHER , R. Practical methods of optimization; (2nd ed.). New York, NY, USA:
Wiley-Interscience, 1987.

G OLDBARG , M. C.; G OLDBARG , E. F. G. Transgenética computacional: uma aplicação ao


problema quadrático de alocação. Pesquisa Operacional, v. 22, p. 359 – 386, 2002.
Disponível em http://www.scielo.br/scielo.php?script=sci_
arttext&pid=S0101-74382002000300005&nrm=iso

G OLDBARG , M. C.; L UNA , H. P. L. Otimização combinatória e programação linear: mod-


elos e algoritmos. Elsevier Editora LTDA., 2005.

K IRKPATRICK , S.; G ELATT, C. D.; V ECCHI , M. P. Optimization by simulated annealing.


Science, v. 220, n. 4598, p. 671–680, 1983.
Disponível em http://www.sciencemag.org/content/220/4598/671.
abstract

KOLMAN , B.; B ECK , R. Elementary linear programming with applications. Computer


science and scientific computing. Academic Press, 1995.
Disponível em http://books.google.com/books?id=3iZznGJq4ZMC

K UHN , H. W. The hungarian method for the assignment problem. Naval Research Logistics
Quarterly, v. 2, n. 1-2, p. 83–97, 1955.
Disponível em http://dx.doi.org/10.1002/nav.3800020109

L AND , A. H.; D OIG , A. G. An automatic method of solving discrete programming problems.


Econometrica, v. 28, n. 3, p. 497–520, 1960.
Disponível em http://jmvidal.cse.sc.edu/library/land60a.pdf

L UKE , S. Essentials of metaheuristics. Lulu, available for free at


http://cs.gmu.edu/∼sean/book/metaheuristics/, 2009.

M ETROPOLIS , N.; ROSENBLUTH , A. W.; ROSENBLUTH , M. N.; T ELLER , A. H.; T ELLER ,


E. Equation of State Calculations by Fast Computing Machines. The Journal of Chemical
Physics, v. 21, n. 6, p. 1087–1092, 1953.
Disponível em http://dx.doi.org/10.1063/1.1699114

M URTHY, P. Operations research (linear programming). New Age International (P) Ltd.,
2005.
Disponível em http://books.google.com.pe/books?id=u-eRHBbJW7AC

P IGATTI , A. A. Modelos e algoritmos para o problema de alocação generalizada (pag) e


aplicações. Dissertação de Mestrado, Pontifícia Universidade Católica do Rio de Janeiro -
PUC-RIO, 2003.

S.N.S ILVA , A.; S AMPAIO , R. M.; A LVARENGA , G. B. Uma aplicação de simulated anneal-
ing para o problema de alocação de salas. INFOCOMP Journal of Computer Science, v. 4,
n. 3, p. 59–66, 2005.
Referências Bibliográficas 51

VANDERBEI , R. Linear programming: foundations and extensions. International series in


operations research & management science. Springer, 2008.
Disponível em http://books.google.com/books?id=T-BW1g69wbYC

W OLSEY, L. Integer programming. Wiley-Interscience series in discrete mathematics and


optimization. Wiley, 1998.
Disponível em http://books.google.com/books?id=x7RvQgAACAAJ

W OLSEY, L. A.; N EMHAUSER , G. L. Integer and combinatorial optimization. 1 ed.


Wiley-Interscience, 1999.
Disponível em http://www.amazon.com/exec/obidos/redirect?tag=
citeulike07-20\&path=ASIN/0471359432
A PÊNDICE

A
Apêndice

A.1 Código Fonte do Força Bruta


1 public class ForcaBruta{
2 private int melhorCusto;
3 private int[] melhorSolucao;
4 private int size;
5 private int[][] matrizCusto;
6
7 public void permuta(int[] v, int pos, int n){
8 if(pos==n){
9 custo(v);
10 }else{
11 for(int j=pos; j<n; j++){
12 swap(v,pos,j);
13 permuta(v, pos+1, n);
14 swap(v,pos,j);
15 }
16 }
17 }
18
19 public void swap(int[] v, int i, int j){
20 int aux = v[i];
21 v[i]=v[j];
22 v[j]=aux;
23 }
24
25 public int getMelhorCusto() {
26 return melhorCusto;
27 }
28
29 public int[] getMelhorSolucao() {
30 return melhorSolucao;
31 }
32
33 public void copiaVetor(int[] v1, int[] v2){ //copia de v2 para v1
34 for(int i = 0; i < v1.length; i++)
35 v1[i] = v2[i];

53
54 A.2. Código Fonte do Branch and Bound

36 }
37
38 public int custo(int[] v){
39 int soma = 0;
40 for(int i = 0; i < v.length; i++)
41 soma += matrizCusto[i][v[i]];
42 if(soma < melhorCusto){
43 melhorCusto = soma;
44 copiaVetor(melhorSolucao, v);
45 }
46 return soma;
47 }
48
49 public int forcaBruta(int[][] custos){
50 size = custos.length;
51
52 int[] v = new int[size];
53 for(int i=0; i<size; i++){ //geracao da solucao inicial
54 v[i]=i;
55 }
56
57 matrizCusto = custos;
58
59 melhorCusto = custo(v);
60 melhorSolucao = new int[size];
61 copiaVetor(melhorSolucao, v); //copia v para melhorSolucao
62 permuta(v, 0, size); //executa o metodo propriamente dito
63 return melhorCusto;
64 }
65 }

A.2 Código Fonte do Branch and Bound


1 public class BranchAndBound {
2 private int melhorCusto;
3 private int[] melhorSolucao;
4 private int size;
5 private int[][] matrizCusto;
6
7 public void permuta(int [] v, int pos, int n){
8 if(pos==n){
9 custo(v);
10 }else{
11 if(custo(v, pos) <= melhorCusto){
12 for(int j=pos; j<n; j++){
13 swap(v,pos,j);
14 permuta(v, pos+1, n);
15 swap(v,pos,j);
16 }
17 }
18 }
19 }
20
21 public void swap(int[]v, int i, int j){
22 int aux = v[i];
23 v[i]=v[j];
24 v[j]=aux;
25 }
26
27 public int getMelhorCusto() {
28 return melhorCusto;
29 }
30
Capítulo A. Apêndice 55

31 public int[] getMelhorSolucao() {


32 return melhorSolucao;
33 }
34
35 public void copia(int[] v1, int[] v2){
36 for(int i = 0; i < v1.length; i++)
37 v1[i] = v2[i];
38 }
39
40 public int custo(int[] v){
41 int soma = 0;
42 for(int i = 0; i < v.length; i++)
43 soma += matrizCusto[i][v[i]];
44 if(soma < melhorCusto){
45 melhorCusto = soma;
46 copia(melhorSolucao, v);
47 }
48 return soma;
49 }
50
51 public int custo(int[] v, int n){
52 int soma = 0;
53 for(int i = 0; i < n; i++)
54 soma += matrizCusto[i][v[i]];
55 return soma;
56 }
57
58 public int branchNbound(int[][] custos){
59 size = custos.length;
60 matrizCusto = custos;
61
62 int[] v = new int[size];
63 for(int i=0; i<size; i++){
64 v[i]=i;
65 }
66 melhorCusto = custo(v);
67 melhorSolucao = new int[size];
68 copia(melhorSolucao, v);
69
70 permuta(v, 0, size);
71 }
72
73 public int boundOtimizado(int[][] custos){
74 size = custos.length;
75 matrizCusto = custos;
76
77 AlgoritmoGuloso ag = new AlgoritmoGuloso();
78 int[] v = ag.alGuloso(custos);
79
80 melhorCusto = custo(v);
81 melhorSolucao = new int[size];
82 copia(melhorSolucao, v);
83
84 permuta(v, 0, size);
85
86 return melhorCusto;
87 }
88
89 public int boundOtimizado2(int[][] custos){
90 size = custos.length;
91 matrizCusto = custos;
92
93 SimulatedAnnealing sa = new SimulatedAnnealing();
94
95 melhorCusto = sa.SA(custos, 1);
96 int[] v = sa.getMelhorSolucao();
97 melhorSolucao = new int[size];
56 A.3. Código Fonte do Simulated Annealing

98 copia(melhorSolucao, v);
99
100 permuta(v, 0, size);
101 return melhorCusto;
102 }
103 }

A.3 Código Fonte do Simulated Annealing


1 import java.util.*;
2 public class SimulatedAnnealing{
3 private int melhorCusto;
4 private int[] melhorSolucao;
5 private int[][] matrizCusto;
6 private int size;
7
8 public int SA(int[][] custos, int optimised){
9 size = custos.length;
10 matrizCusto = custos;
11 int[] v;
12
13 if(optimised == 1){
14 AlgoritmoGuloso ag = new AlgoritmoGuloso();
15 v = ag.alGuloso(matrizCusto);
16 }
17 else
18 v = geraSolucaoInicial();
19
20 melhorCusto = custo(v);
21 melhorSolucao = new int[size];
22 copia(melhorSolucao, v);
23
24 simAnnealing(v);
25
26 melhorCusto = custo(melhorSolucao);
27 return melhorCusto;
28 }
29
30 public void simAnnealing(int[] permutacao){
31 double temperatura = Math.pow(size, 2);
32 double taxaResfriamento = 0.95;
33 int itera = size * 100;
34 Random r = new Random();
35 int[] atual = permutacao;
36 melhorSolucao = atual;
37 double Cvizinho=0, Catual=0, delta=0, Cmelhor=0;
38 Cmelhor = custo(melhorSolucao);
39 while(temperatura > 0.001) {
40 for(int j = 0; j < itera; j++){
41 int[] aux = new int[size];
42 System.arraycopy(atual, 0, aux, 0, atual.length);
43 int[] vizinho = new int[size];
44 System.arraycopy(atual, 0, vizinho, 0, atual.length);
45 vizinho = swap(vizinho);
46 Cvizinho = custo(vizinho);
47 Catual = custo(atual);
48 delta = Cvizinho - Catual;
49
50 if(delta < 0){
51 atual = vizinho;
52 if(Cvizinho < Cmelhor) {
53 melhorSolucao = atual;
54 Cmelhor = custo(melhorSolucao);
Capítulo A. Apêndice 57

55 }
56 }
57 else{
58 double exp = ((-1)*delta)/temperatura;
59 double e = Math.exp(exp);
60 double f = r.nextFloat();
61 if(e > f) {
62 atual = vizinho;
63 }
64 }
65 }
66 temperatura *= taxaResfriamento;
67 }
68 }
69
70 public int[] swap(int[] vetor){
71 Random r = new Random();
72 int j = r.nextInt(vetor.length);
73 int i = r.nextInt(vetor.length);
74
75 int a = vetor[i];
76 int b = vetor[j];
77
78 vetor[i] = b;
79 vetor[j] = a;
80
81
82 return vetor;
83 }
84
85 public int custo(int[] vetor){
86 int soma = 0;
87 for(int i = 0; i < vetor.length; i++)
88 soma += matrizCusto[i][vetor[i]];
89 return soma;
90 }
91
92 public int[] geraSolucaoInicial(){
93 int[] vetor = new int[size];
94 for(int i = 0; i < vetor.length; i++)
95 vetor[i]=i;
96 return vetor;
97 }
98
99 public void copia(int[] v1, int[] v2){
100 for(int i = 0; i < v1.length; i++)
101 v1[i] = v2[i];
102 }
103
104 public int getMelhorCusto() {
105 return melhorCusto;
106 }
107
108 public int[] getMelhorSolucao() {
109 return melhorSolucao;
110 }
111
112 }

A.4 Código Fonte do Algoritmo Guloso


1 import java.util.ArrayList;
2
58 A.4. Código Fonte do Algoritmo Guloso

3 public class AlgoritmoGuloso {


4 private int melhorCusto;
5 private int[] melhorSolucao;
6 private int size;
7 private int[][] matrizCusto;
8
9 public int[] alGuloso(int[][] custos){
10 matrizCusto = custos;
11 size = custos.length;
12
13 melhorSolucao = new int[size];
14 ArrayList<Integer> tarefas = new ArrayList<Integer>();
15 int i, j, menorTarefa = 0, indiceMenorTarefa = 0, tarefaAtual;
16
17 for(i = 0; i < size; i++)
18 tarefas.add(i);
19
20 for(i = 0; i < size; i++){
21 for(j = 0; j < tarefas.size(); j++){
22 tarefaAtual = tarefas.get(j);
23 if(matrizCusto[i][tarefaAtual] < matrizCusto[i][menorTarefa]){
24 menorTarefa = tarefaAtual;
25 indiceMenorTarefa = j;
26 }
27 }
28 melhorSolucao[i] = menorTarefa;
29 tarefas.remove(indiceMenorTarefa);
30
31 try{
32 menorTarefa = tarefas.get(0);
33 }catch(Exception e){}
34 indiceMenorTarefa = 0;
35 }
36 return melhorSolucao;
37 }
38
39 public int custo(){
40 int soma = 0;
41 for(int i = 0; i < melhorSolucao.length; i++)
42 soma += matrizCusto[i][melhorSolucao[i]];
43 return soma;
44 }
45
46 public int getMelhorCusto() {
47 return melhorCusto;
48 }
49 }

Você também pode gostar