You are on page 1of 78

CURSO SUPERIOR DE TECNOLOGIA EM DESENVOLVIMENTO DE

SOFTWARE

CLAUDIA NASCIMENTO DE BRITO


GRACIANA GOMES SILVA
PHILIPPE LEAL FREIRE DOS SANTOS

ALGORITMOS GENÉTICOS APLICADOS AO PROBLEMA DA


MOCHILA BINÁRIA: um estudo comparativo dos métodos de seleção

Campos dos Goytacazes/RJ


2007
CLAUDIA NASCIMENTO DE BRITO
GRACIANA GOMES SILVA
PHILIPPE LEAL FREIRE DOS SANTOS

ALGORITMOS GENÉTICOS APLICADOS AO PROBLEMA DA MOCHILA


BINÁRIA: um estudo comparativo dos métodos de seleção

Monografia apresentada ao Centro Federal de


Educação Tecnológica de Campos como requisito
parcial para conclusão do Curso Superior de
Tecnologia em Desenvolvimento de Software.

Orientador: Prof. Fábio Duncan de Souza

Campos dos Goytacazes/RJ


2007

ii
CLAUDIA NASCIMENTO DE BRITO
GRACIANA GOMES SILVA
PHILIPPE LEAL FREIRE DOS SANTOS

ALGORITMOS GENÉTICOS APLICADOS AO PROBLEMA DA MOCHILA BINÁRIA:


um estudo comparativo dos métodos de seleção

Monografia apresentada ao Centro Federal de


Educação Tecnológica de Campos como requisito
parcial para conclusão do Curso Superior de
Tecnologia em Desenvolvimento de Software.

Aprovada em 27 de abril de 2007

Banca Avaliadora:

.......................................................................................................................................................
Profo Fábio Duncan de Souza (orientador)
Pós-Graduado em Ciências da Computação/UFF
Centro Federal de Educação Tecnológica/Campos

.......................................................................................................................................................
Profo Dalessandro Soares Vianna
Doutor em Informática/PUC-Rio
Centro Federal de Educação Tecnológica/Campos

.......................................................................................................................................................
Profo Breno Fabrício Terra Azevedo
Mestre em Informática/UFES
Centro Federal de Educação Tecnológica/Campos

iii
Dedicamos este trabalho aos nossos familiares.

iv
AGRADECIMENTOS

Gostaríamos de agradecer primeiramente a Deus por ter nos dado capacidade para
concretizarmos este trabalho.
Agradecemos também aos nossos familiares pela compreensão e incentivo.
A Marcos Nascimento de Brito pelo apoio, paciência e amizade.
Ao nosso orientador Fábio Duncan de Souza pela escolha do tema, paciência,
dedicação e amizade.
Ao professor Dalessandro Soares Vianna pelo apoio técnico.
Aos professores do Curso Superior de Tecnologia em Desenvolvimento de Software
pelo aprendizado proporcionado.

v
RESUMO

O Problema da Mochila (Knapsack Problem) é um dos principais problemas estudados nas


áreas de análise de algoritmos, otimização combinatória, pesquisa operacional e inteligência
artificial. O problema da mochila é classificado como NP-completo. Segundo Benfica (2004),
a classe NP-completo envolve os problemas de maior dificuldade entre todos os problemas de
NP. Para resolver problemas pertencentes a esta classe foram criadas metaheurísticas, como
por exemplo: Simulated Annealing, Busca Tabu, Multi-start, GRASP (Greedy Randomized
Adaptive Procedure), Algoritmos Genéticos, Variable Neighborhood Search (VNS) e Colônia
de Formigas (Ant Colonies). Neste trabalho serão apresentadas nove variações de Algoritmos
Genéticos que resolvem o Problema da Mochila Binária com o intuito de comparar as
políticas de seleção Roleta, Torneio, Torneio Estocástico, Seleção Aleatória, Seleção
Determinística, Seleção Estocástica por Resto Sem Reposição, Seleção Estocástica por Resto
Com Reposição, Seleção Estocástica Sem Reposição e Seleção por Ranking, identificando a
que apresenta o melhor resultado para o problema.

Palavras-chave: Algoritmos Genéticos. Problema da Mochila. Problemas NP-completos.


Políticas de Seleção.

vi
LISTA DE FIGURAS

Figura 1 - Fluxograma de um AG simples. .............................................................................. 25


Figura 2 - Distribuição dos indivíduos na Roleta. .................................................................... 27
Figura 3 - Cruzamento em um ponto (1PX). ............................................................................ 31
Figura 4 - Cruzamento em dois pontos (2PX).......................................................................... 31
Figura 5 - Mutação Simples...................................................................................................... 32
Figura 6 – Exemplo de Cruzamento em um ponto (1PX). ....................................................... 37
Figura 7 - Exemplo de Mutação Simples. ................................................................................ 38
Figura 8 - Testes das Políticas de Seleção para a instância de tamanho 50. ............................41
Figura 9 - Testes das Políticas de Seleção para a instância de tamanho 100. .......................... 42
Figura 10 - Testes das Políticas de Seleção para a instância de tamanho 200. ........................ 42
Figura 11 - Testes das Políticas de Seleção para a instância de tamanho 1000. ...................... 43
Figura 12 - Testes das Políticas de Seleção para a instância de tamanho 5000. ...................... 43
Figura 13 - Testes das Políticas de Seleção para a instância de tamanho 10000. .................... 44
Figura 14 - Resultados dos testes ............................................................................................. 44
Figura 15 - Desempenho Médio das Políticas de Seleção........................................................ 46

vii
SUMÁRIO

LISTA DE FIGURAS...................................................................................................................................... vii


I. INTRODUÇÃO............................................................................................................................................ 10
II. O PROBLEMA DA MOCHILA ............................................................................................................... 12
2.1. Complexidade do problema ................................................................................................................. 12
2.2. Características do problema................................................................................................................ 14
2.2.1. O Problema da Mochila inteiro ........................................................................................................ 14
2.2.2. O Problema da Mochila 0-1.............................................................................................................. 14
2.2.3. O Problema da Mochila Restrito ..................................................................................................... 15
2.2.4. O Problema da Soma de Subconjuntos ........................................................................................... 16
2.2.5. O Problema do Troco ........................................................................................................................ 17
2.2.6. O Problema da Mochila Quadrático................................................................................................ 17
2.2.7. O Problema de Múltiplas Mochilas 0-1 ........................................................................................... 18
2.2.8. O Problema de Designação Generalizada ....................................................................................... 19
2.2.9. O Problema Bin-Packing .................................................................................................................. 19
2.2.10. O Problema da Mochila Compartimentada .................................................................................. 20
III. ALGORITMO GENÉTICO .................................................................................................................... 23
3.1. Algoritmo Genético Simples ................................................................................................................ 23
3.1.1. População Inicial ........................................................................................................................... 26
3.1.2. Função Objetivo............................................................................................................................. 26
3.1.3. Seleção ............................................................................................................................................ 27
3.1.3.1. Roleta (Seleção Estocástica com reposição)............................................................................. 27
3.1.3.2. Torneio ..................................................................................................................................... 28
3.1.3.3. Torneio Estocástico .................................................................................................................. 28
3.1.3.4. Seleção Aleatória (Stochastic Universal Sampling - SUS)....................................................... 28
3.1.3.5. Seleção Determinística (Deterministic Sampling - DS)............................................................ 29
3.1.3.6. Seleção Estocástica por Resto Sem Reposição (Stochastic Remainder Sampling) .................. 29
3.1.3.7. Seleção Estocástica por Resto Com Reposição ........................................................................ 29
3.1.3.8. Seleção Estocástica Sem Reposição ......................................................................................... 30
3.1.3.9. Seleção por Ranking ................................................................................................................. 30
3.1.3.10. Positive and Negative Assortative Mating.............................................................................. 30
3.1.4. Cruzamento.................................................................................................................................... 30
3.1.5. Mutação .......................................................................................................................................... 32
3.1.6. Evolução da População ................................................................................................................. 33
3.1.6.1. SGA (Simple Genetic Algorithm) ............................................................................................ 33
3.1.6.2. SSGA (Steady State GA).......................................................................................................... 33
3.1.6.3. Parâmetro Gap da Geração ....................................................................................................... 33
3.1.7. Critério de Parada ......................................................................................................................... 33

viii
IV. IMPLEMENTAÇÃO DO PROBLEMA DA MOCHILA BINÁRIA UTILIZANDO ALGORITMO
GENÉTICO ..................................................................................................................................................... 35
4.1. População Inicial .................................................................................................................................. 35
4.2. Função Objetivo.................................................................................................................................... 36
4.3. Seleção ................................................................................................................................................... 36
4.4. Cruzamento........................................................................................................................................... 37
4.5. Mutação................................................................................................................................................. 37
4.6. Evolução da População ........................................................................................................................ 38
4.7. Critério de Parada................................................................................................................................ 38
V. TESTES COMPUTACIONAIS ................................................................................................................ 40
VI. CONCLUSÃO E TRABALHOS FUTUROS.......................................................................................... 46
VII. REFERÊNCIAS ...................................................................................................................................... 48
ANEXO I: Algoritmo Genético com a Política de Seleção Roleta ............................................................... 50
ANEXO II: Política de Seleção Torneio ........................................................................................................ 64
ANEXO III: Política de Seleção Torneio Estocástico................................................................................... 65
ANEXO IV: Política de Seleção Aleatória..................................................................................................... 67
ANEXO V: Política de Seleção Determinística ............................................................................................. 68
ANEXO VI: Política de Seleção Estocástica por Resto sem Reposição ...................................................... 70
ANEXO VII: Política de Seleção Estocástica por Resto com Reposição .................................................... 72
ANEXO VIII: Política de Seleção Estocástica sem Reposição..................................................................... 75
ANEXO IX: Política de Seleção por Ranking ............................................................................................... 77

ix
I. INTRODUÇÃO

Os problemas NP-completos são aqueles que têm a questão da complexidade ou


tratabilidade não resolvida. De acordo com Benfica (2004), esta classe envolve os problemas
de maior dificuldade entre todos os problemas de NP. Por um lado, sabe-se que se um
problema NP-completo qualquer tiver um algoritmo polinomial que o resolva então todos os
problemas NP-completos também possuirão algoritmos polinomiais para eles. Por outro lado,
nenhum algoritmo polinomial para esses problemas foi desenvolvido até o momento. Esses
dois fatos sugerem que não existam algoritmos polinomiais para problemas NP-completos,
que seriam então intratáveis (TOSCANI, 2005).
Um exemplo clássico de problema NP-completo é o Problema da Mochila (BENFICA,
2004). Suponha que se dispõe de um conjunto de itens, com um peso e um ganho conhecidos,
e de uma mochila com capacidade limitada. Determinar o subconjunto destes itens cujo peso
não exceda aquela capacidade e que maximize o seu ganho total, corresponde a resolver o
problema da mochila. Na literatura pode-se encontrar variações para o problema da mochila,
sendo algumas comentadas no presente trabalho. Porém, a variação que receberá maior
destaque é o problema da mochila binária.
Atualmente, a principal estratégia para solucionar este tipo de problema é fazer uso de
metaheurísticas que têm por objetivo gerar procedimentos de buscas em vizinhanças que
evitem uma parada prematura em ótimos locais, proporcionando soluções satisfatórias
(VIANNA & SOUZA, 2006). Alguns exemplos de metaheurísticas são: Busca Tabu,
Simulated Annealing, GRASP, Algoritmos Genéticos, dentre outras. No entanto, no presente
projeto serão abordados apenas os Algoritmos Genéticos.
Os Algoritmos Genéticos (AGs) pertencem a uma classe de algoritmos de pesquisa
probabilística e de otimização chamada Algoritmos Evolucionários, que simulam os processos
naturais aplicando-os à solução de problemas reais (VIANNA & SOUZA, 2006). Os AGs
possuem uma série de fases (população inicial, função objetivo, seleção, cruzamento, mutação
e critério de parada) e cada fase pode ser modelada de diversas maneiras. O foco deste
trabalho é as políticas de seleção que compõem uma das fases dos Algoritmos Genéticos.
Com base nas informações acima, o presente trabalho tem por objetivo encontrar a
melhor política de seleção para o problema da mochila binária e mostrar os resultados obtidos.
Esse trabalho está organizado em seis capítulos. O Capítulo 1 apresenta a introdução
do trabalho. O Capítulo 2 apresenta o problema da mochila. O Capítulo 3 apresenta a base
conceitual dos Algoritmos Genéticos. O Capítulo 4, por sua vez, descreve a abordagem

10
proposta para solucionar o problema da mochila binária utilizando as políticas de seleção. Já o
Capítulo 5 apresenta os experimentos realizados, bem como os resultados obtidos. Por último,
as conclusões do trabalho são apresentadas no Capítulo 6.

11
II. O PROBLEMA DA MOCHILA

O problema da mochila (também conhecido como Knapsack Problem ou somente KP) é


um dos problemas NP-completos mais estudados nas áreas de Análise de Algoritmos,
Otimização Combinatória, Pesquisa Operacional e Inteligência Artificial. Sua forma clássica
pode ser descrita da seguinte maneira: tendo-se uma mochila de capacidade C e um conjunto
de n objetos diferentes onde a cada objeto (i) está associado um peso (pi) e um ganho (vi),
deve-se encontrar um subconjunto de objetos a transportar de modo que o peso total dos
elementos selecionados não exceda a capacidade da mochila e que o ganho total dos
selecionados seja o maior possível.
Existem problemas que podem ser considerados variações do problema da mochila.
Neste capítulo serão apresentados os seguintes: o problema da mochila inteira (integer
knapsack problem), o problema da mochila binária também conhecida como problema da
mochila 0-1 (binary KP ou zero-one knapsack problem ou 0-1 KP), o problema da mochila
restrito, o problema da soma de subconjuntos, o problema do troco, o problema da mochila
quadrático, o problema de múltiplas mochilas 0-1, o problema de designação generalizada, o
problema do bin-packing e o problema da mochila compartimentada (Compartmentalized
Knapsack Problem).

2.1. Complexidade do problema

Uma vez calculada a complexidade de um algoritmo é possível reconhecer se este é


eficiente ou não. Para isto, uma das alternativas seria a comparação de um algoritmo com
outros que resolvem o mesmo problema. Mas de acordo com Benfica (2004, p.3) “[...] um
algoritmo é eficiente quando a sua complexidade for um polinômio no tamanho da entrada.
[...]”. Sendo assim, algoritmos de complexidade θ(1), θ(n), θ(n2), θ(n3), θ(n5), são
considerados eficientes para problemas de entrada de tamanho n.
Embora logn não seja um polinômio, por não ser pior que um polinomial, é encaixado
entre os polinomiais. Pela mesma razão também se encaixam nesta categoria: θ(logn),
θ(n2logn) entre outros. Os demais algoritmos são genericamente chamados de exponenciais.
Seguindo os mesmos princípios, um problema é considerado tratável ou bem resolvido
quando existir um algoritmo que o resolva em tempo polinomial. Caso contrário, o problema
é considerado intratável. De acordo com Benfica (2004), um problema intratável poderia

12
levar, em certos casos, séculos para computar os dados de entrada e saída de tamanhos
relativamente reduzidos.
Os problemas são classificados em classes. Segundo Toscani (2005), um problema
pertence a classe P quando, numa codificação razoável, pode ser resolvido por algoritmo
determinístico1 em tempo polinomial. Um problema pertence a classe NP quando, numa
codificação razoável, pode ser resolvido por algoritmo não-determinístico2 em tempo
polinomial. Já para identificar um problema como NP-completo será preciso reduzi-lo a um
problema já conhecido como NP-completo (Teorema de Cook).
Com base no Teorema de Cook, um problema Π pertencerá à classe NP-completo se
atender as seguintes condições:
(i) Π ∈ NP
(ii) todo problema de decisão Π’ ∈ NP satisfaz Π’ ∝ Π

A formulação (ii) implica que todo problema da classe NP pode ser transformado
polinomialmente no problema Π NP-completo. Sendo assim, se um problema NP-completo
puder ser resolvido em tempo polinomial, então todos os demais problemas NP também
podem e, conseqüentemente, P=NP. Logo, se Π ∈ NP-completo, e for demonstrado que Π ∈
P, então P=NP. Foi seguindo estes princípios que Benfica demonstrou em seu trabalho que o
Problema da Mochila é NP-Completo.
Uma das alternativas mais utilizadas na literatura para solucionar problemas pertencentes
à classe NP-completo é o uso de metaheurísticas. Segundo (ROMERO & MANTOVANI,
2004, p.1): “As metaheurísticas representam um conjunto de técnicas de otimização adaptadas
para lidar com problemas complexos e que apresentam a característica da explosão
combinatória.[...].”.
Ainda segundo estes autores (ROMERO & MANTOVANI, 2004, p.1): “A idéia
fundamental de uma metaheurística consiste em analisar ou visitar apenas um conjunto
reduzido do espaço de busca, considerando que o espaço de busca é absurdamente
grande.[...]”. Neste sentido, as metaheurísticas não buscam a melhor solução entre todas
possíveis, ou seja, a solução ótima. Elas buscam sim é uma boa solução.
Dentre as principais metaheurísticas podem ser citadas: Simulated Annealing, Busca Tabu,
Multi-start, GRASP (Greedy Randomized Adaptive Procedure), Algoritmos Genéticos,

1
Algoritmos determinísticos resolvem o problema com uma decisão exata a cada passo.
2
Algoritmos não-determinísticos resolvem o problema ao deduzir os melhores passos através de estimativas sob
forma de heurísticas.

13
Variable Neighborhood Search (VNS) e Colônia de Formigas (Ant Colonies). Como poderá
ser visto no capítulo seguinte, neste trabalho daremos enfoque aos Algoritmos Genéticos.

2.2. Características do problema

A partir de agora serão apresentados alguns dos problemas que são considerados
variações para o problema da mochila com suas respectivas modelagens matemáticas:

2.2.1. O Problema da Mochila inteiro

O problema modelado a seguir é chamado na literatura de Problema da Mochila Inteiro


ou simplesmente Problema da Mochila. Não há limitações nas quantidades de itens
selecionados.

Variável de decisão:

- xi: quantidade de itens do tipo i selecionados, i = l,...,n.

Modelagem Matemática:

n
Maximizar Ø = Σ vixi
i=1

n
Sujeito a Σ pixi ≤ C
i=1

xi ≥ 0 e inteiro, i = l,...,n.

2.2.2. O Problema da Mochila 0-1

O Problema da Mochila 0-1 é, talvez, o mais importante Problema da Mochila e um dos


mais estudados problemas de programação discreta, segundo Pisinger(1997). A razão para tal
interesse está, basicamente, ligada a três fatores: a) pode ser visto como o mais simples
problema de programação linear inteira; b) aparece como subproblema em muitos outros
problemas mais complexos; c) pode representar uma gama muito grande de situações práticas.
14
No Problema da Mochila 0-1 temos a situação em que um único exemplar de cada item pode
ser selecionado.

Assim temos as variáveis de decisão:

xi={ 1, se o item i for selecionado;


Modelagem matemática:
0, caso contrário.
i = l,...,n.

Modelagem matemática:

n
Maximizar Ø = Σ vixi
i=1

n
Sujeito a Σ pixi ≤ C
i=1

xi = 0 ou l, i = l,...,n.

Esse problema tem sido estudado por diferentes abordagens, tais como a programação
Dinâmica e a enumeração Implícita.

2.2.3. O Problema da Mochila Restrito

Alguns problemas podem apresentar condições adicionais, como por exemplo, a


limitação da quantidade de itens a serem selecionados. Neste caso, o problema passa a ser
chamado de Problema da Mochila Restrito ou Limitado. Para este problema, considere ainda
os seguintes dados:

- di: quantidade máxima de itens tipo i que pode ser selecionada, i = l,...,n;

- xi: quantidade de itens do tipo i selecionados, i = l,...,n.

15
Modelagem Matemática:

n
Maximizar Ø = Σ vixi
i=1

n
Sujeito a Σ pixi ≤ C
i=1

0 ≤ xi ≤ di e inteiro, i = l,...,n.

2.2.4. O Problema da Soma de Subconjuntos

O Problema da Soma de subconjuntos consiste em selecionar um subconjunto de itens


cuja soma total dos pesos dos itens escolhidos se aproxime ao máximo de C, sem excedê-lo.

Este problema é um caso particular do Problema da Mochila 0-1, onde vi = pi, para
i=l,...,n. Tal problema é conhecido, também, como Problema da Mochila de Valor
Independente e surge em situações onde a quantidade desejada deve ser alcançada, tal que a
diferença entre os valores da capacidade da Mochila (C) e a soma total dos pesos dos itens
selecionados seja minimizado, sem que C seja ultrapassado.

Modelagem Matemática:

n
Maximizar Ø = Σ pixi
i=1

n
Sujeito a Σ pixi ≤ C
i=1

xi = 0 ou l, i = l,...,n.

16
2.2.5. O Problema do Troco

O Problema do Troco geralmente aparece na literatura como um problema de


minimização. O problema consiste em selecionar um número xi (i = l,...,n.) de itens de cada
tipo i tal que o peso total seja C e o número total de itens selecionados seja mínimo.

O Problema é chamado Problema do Troco, pois pode ser interpretado como o problema
de uma caixa (supermercado, banco, etc) que deve devolver uma determinada quantia, C,
usando, para isto, um número mínimos de moedas de valores específicos pi (i=l,...,n). Nesse
caso, para cada valor, um número ilimitado de moedas está disponível. É importante notar que
a condição de igualdade imposta pode fazer com que inexista uma solução para o problema.

Modelagem matemática:

n
Maximizar Ø = Σ xi
i=1

n
Sujeito a Σ pixi = C
i=1

xi ≥ 0 e inteiro, i = l,...,n.

2.2.6. O Problema da Mochila Quadrático

O problema da Mochila Quadrático é um dos mais estudados problemas na área de


problemas da Mochila Não Lineares. Um Problema da Mochila Não linear, em geral, é o
Problema da Mochila com função objetivo não linear ou que envolve restrições não lineares.
Este problema pode ser formulado matematicamente da seguinte forma:

Modelagem
Maximizar Matemática:
Ø = f(x)

n
Sujeito a Σ pixi ≤ C
i=1

xi ≥ 0 e inteiro, i = l,...,n.

17
Onde, f(x) representa uma função quadrática de x da forma xQxT+cxT com x = (x1, x2,...,
xn), c = (c1, c2, ..., cn), e Q = (q1, q2, ..., qn) para algum i com qi ≠ 0, i = l,...,n.

2.2.7. O Problema de Múltiplas Mochilas 0-1

O Problema de Múltiplas Mochilas 0-1 consiste em carregar um conjunto de m mochilas


(m ≤ n) cujas capacidades são dadas por: Cj, j = l,...,m. Este consiste em selecionar
subconjuntos disjuntos de itens tal que o valor de utilidade dos itens selecionados seja
máximo, e cada subconjunto possa ser associado a uma mochila diferente, cuja capacidade
não seja menor que com peso total dos itens no subconjunto.

Variável de decisão:

xij= { 1, se o item i está associado a mochila j;

0, caso contrário.

Modelagem Matemática:

m n
Maximizar Ø = Σ Σ vixij
j=1 i=l
n
Sujeito a Σ pixij ≤ Cj, j = l,...,m.
i=1

m
Σ xij ≤ l, i = l,...,n.
i=1

xij = 0 ou l, i = l,...,n e j = l,...,m.

Quando m = l, o Problema de Múltiplas Mochilas 0-1 se reduz a um Problema da


Mochila 0-1 simples, pois a restrição (terceira linha da modelagem matemática acima) torna-
se redundante.

18
2.2.8. O Problema de Designação Generalizada

O Problema de Designação Generalizada pode ser descrito usando a terminologia


aplicada para os Problemas da Mochila. Este consiste em associar cada item a exatamente
uma mochila, visando maximizar o ganho real total, sem associar a nenhuma mochila um
peso total que ultrapasse sua capacidade. Considere os seguintes dados:

- vij: ganho fornecido pela associação do item i a mochila j, i = l,...,n e j = l,...,m;

- pij: peso do item i se associado à mochila j, i = l, ...,n e j=l,...,m;

Modelagem Matemática:

m n
Maximizar Ø = Σ Σ vijxij
j=1 i=l
n
Sujeito a Σ pijxij ≤ Cj, j = l,...,m.
i=1

m
Σ xij = l, i = l,...,n.
i=1

xij = 0 ou l, i = l,...,n e j = l,...,m.

O problema é, freqüentemente, descrito na literatura como o problema de designação


ótima de n tarefas a m processadores, dados o ganho vij e a quantidade de recursos pij
correspondente à associação da tarefa i ao processador j e a quantidade total de recursos Cj
suportados por cada processador j.

2.2.9. O Problema Bin-Packing

O Problema Bin-Packing pode ser descrito usando a terminologia de Problema da


Mochila, onde:

- pi: peso do item i, i=l,...,n.

- C: capacidade de cada caixa.

19
Associa-se cada item a uma caixa, tal que o peso total dos itens em cada caixa não
exceda C e o número de caixas usadas seja mínimo.

Variáveis de decisão:

yj= { 1, se a caixa j é usada;

0, caso contrário.

ij= {
xModelagem
1, se o item i está associado a caixa j;

0,Matemática:
caso contrário.

Modelagem Matemática:

m
Maximizar Ø = Σ yj
j=1
n
Sujeito a Σ pixij ≤ Cjyj, j = l,...,m.
i=1

m
Σ xij = l, i = l,...,n.
i=1

yj = 0 ou l, xij = 0 ou l, i = l,...,n e j = l,...,m.

2.2.10. O Problema da Mochila Compartimentada

Um alpinista deve carregar sua mochila com n possíveis itens de sua utilidade. A cada
item i, o alpinista atribui um valor de utilidade vi e seu peso pi. O máximo peso que o alpinista
suporta em sua jornada é de L. Até este ponto, o problema coincide com a formulação clássica
do Problema da Mochila. Porém, os itens são de agrupamentos distintos (por exemplo:
agrupamento 1: alimentos, agrupamento 2: utensílios, agrupamento 3: roupas, agrupamento 4:
calçados, etc.) e devem estar em compartimentos separados dentro da mochila (isto é, cada
compartimento contém somente itens de um mesmo agrupamento). Os compartimentos da
mochila são flexíveis, permitindo que o alpinista carregue maior peso em alimentos do que
em roupas, bem como reservar vários compartimentos para alimentos. As capacidades dos

20
compartimentos (incógnitas) são limitadas inferior e superiormente (de acordo com os
agrupamentos), caso estes sejam criados, digamos por: Lkmim e Lkmax (isto é, a soma dos pesos
li dos itens alocados no compartimento deve ser superior ou igual a Lkmim e inferior ou igual a
Lkmax). A cada compartimento é associado um custo ck, caso este seja preenchido com itens do
agrupamento k e, além disso, cada compartimento incluído na mochila produzirá uma perda
da capacidade da mesma, digamos, S (isto é, se, por exemplo, três compartimentos forem
utilizados, então a capacidade disponível na mochila será de L-3S, ao invés de L).
O Problema da Mochila Compartimentada consiste em determinar as capacidades
adequadas de cada compartimento e como estes devem ser carregados de modo que o valor de
utilidade total (soma dos valores de utilidade de todos os itens selecionados) seja máximo,
descontando-se os custos dos compartimentos, os quais dependem dos agrupamentos com que
foram preenchidos (ck).

Dados do problema:

• M = {1,...,m}: conjunto dos tipos de itens;

• li: peso (Kg) do item i (li > 0), i=1,...,m;

• vi: valor de utilidade do item i (vi ≥ 0), i=1,...,m;

• di: limite máximo de itens i na mochila, i=1,...,m;

• K: número total de agrupamentos distintos;

• Ak: agrupamento k, k=1,...,K, (M = A1 ∪ A2 ...∪ AK , Ai ∩ Aj = ∅ , com i ≠ j);

• Nk: número total de possíveis compartimentos para o agrupamento k (por exemplo:


A1={1,2}, então L11 = 2l1+l2 , L21 = l1+2l2 , L31 = 2l1+2l2 , etc., são duas possíveis
capacidades de compartimentos para o agrupamento 1. Ljk referencia o j-ésimo
compartimento associado ao agrupamento k. O número Nk depende essencialmente
dos itens do agrupamento k);

• ck: custo de um compartimento de itens do agrupamento k, onde ck ≥ 0, k=1,...,K;

• L: capacidade (Kg) da mochila;

• Lkmim: capacidade mínima (Kg) de cada compartimento associado ao agrupamento Ak;

21
• Lkmax: capacidade máxima (Kg) de cada compartimento associado ao agrupamento Ak
(Lkmim < Lkmax < L);

• S: perda (Kg) decorrente da inclusão de um novo compartimento na mochila.

Variáveis:

• αijk: número de itens do tipo i, do agrupamento k, no compartimento do tipo j,


i=1,...,m, k=1,...,K e j=1,...,Nk;

• βjk: número de vezes que o compartimento (padrão) do tipo j alocado com o


agrupamento k é repetido na mochila, k=1,...,K e j=1,...,Nk.

Assim, o j-ésimo compartimento com itens do agrupamento k tem:

• A capacidade ocupada dada por:

• OLvalor
jk = Σdepiutilidade dadoepor:
αijk, k= 1,...,k j = 1,...,Nk
iЄA
k

Vjk = Σ viαijk, k= 1,...,k e j = 1,...,Nk


iЄA
k

Um modelo matemático para o problema da mochila compartimentada pode ser escrito


por:
k Nk
Maximizar Σ Σ (Vjk – ck) βjk
k=1 j=1

Sujeito a Vjk = Σ viαijk, k= 1,...,k e j = 1,...,Nk


iЄA
k

Ljk = Σ piαijk, k= 1,...,k e j = 1,...,Nk


iЄA
k

Lkmim ≤ Ljk + S≤ Lkmax, k= 1,...,k e j = 1,...,Nk

Nk
Σ αijkβjk≤ di, i= 1,...,m
j=1

k Nk
Σ Σ (Ljk + S) βjk ≤ L
k=1 j=1

αijk ≥ 0, inteiro, i = 1,...,m, k = 1,...,K e j = 1,...,Nk


βjk ≥ 0, inteiro, k = 1,...,K e j = 1,...,Nk

22
III. ALGORITMO GENÉTICO

Com base na teoria evolutiva de Charles Darwin, onde os indivíduos mais adaptados
teriam maior probabilidade de sobrevivência, foi proposto por John H. Holland em 1975, um
algoritmo matemático para otimização de sistemas complexos, denominado Algoritmo
Genético (AG). Este algoritmo pretendia simular matematicamente todo o mecanismo da
evolução biológica com todas as características e vantagens deste processo.
Segundo Ávila (2002), os AGs são algoritmos de otimização estocásticos que
trabalham de forma “aleatória orientada” de acordo com regras probabilísticas baseadas numa
analogia com os mecanismos da genética natural, sendo utilizados para busca de soluções
ótimas, ou aproximadamente ótimas, em uma grande variedade de problemas. Estes
algoritmos caracterizam-se por, ao término do processo, ter não somente uma solução, mas
uma população que pode representar o comportamento do problema, já que todos os
indivíduos da população são possíveis soluções.
Estes algoritmos diferem dos métodos tradicionais de busca e otimização, sobretudo
em quatro aspectos:
1. Trabalham com uma codificação do conjunto de parâmetros e não com os próprios
parâmetros;
2. Utilizam regras de transição probabilísticas e não determinísticas;
3. Utilizam informações de custo ou recompensa e não derivadas ou outro
conhecimento auxiliar;
4. Trabalham com uma população e não com um único ponto.
As aplicações deste algoritmo vêm crescendo nos últimos anos principalmente nas
áreas científicas, devido a sua versatilidade de seguir de forma mais precisa o comportamento
aleatório da natureza. Podemos citar sua utilização em processamento de imagens,
modelagem e identificação de sistemas, robótica, análise de modelos econômicos e problemas
de engenharia.

3.1. Algoritmo Genético Simples

Os AGs simulam processos naturais de sobrevivência e reprodução das populações,


essenciais em sua evolução. Na natureza, indivíduos de uma mesma população competem
entre si, buscando principalmente a sobrevivência, seja através da busca de recursos como
alimento, ou visando à reprodução. Os indivíduos mais aptos terão um maior número de
descendentes, ao contrário dos indivíduos menos aptos. Desse modo, estes algoritmos tratam
23
as possíveis soluções do problema como indivíduos de uma população, que irão evoluir a cada
iteração ou geração.
A partir dessa idéia, os AGs são utilizados para solucionar problemas de otimização.
Conforme Ávila (2002), em todo problema de otimização existe um objetivo a ser alcançado
(ou vários, no caso de otimizadores multiobjetivos), que é representado por uma função
objetivo. A avaliação desta função permite calcular a aptidão de cada indivíduo. Os AGs
procuram sempre melhorar a população, ou seja, buscam os indivíduos de melhor aptidão.

De acordo com Pozo (2002), os requisitos para a implementação destes algoritmos são:

· Representações das possíveis soluções do problema no formato de um código


genético;
· População inicial que contenha diversidade suficiente para permitir ao algoritmo
combinar características e produzir novas soluções;
· Existência de um método para medir a qualidade de uma solução potencial;
· Um procedimento de combinação de soluções para gerar novos indivíduos na
população;
· Um critério de escolha das soluções que permanecerão na população ou que serão
retirados desta;
· Um procedimento para introduzir periodicamente alterações em algumas soluções da
população, mantendo assim a diversidade da população e a possibilidade de se produzir
soluções inovadoras para serem avaliadas pelo critério de seleção dos mais aptos.
A Figura 1 mostra o fluxograma de um AG simples contendo seu processo evolutivo:

24
INÍCIO

População Inicial

Cálculo Função Objetivo

Seleção

Cruzamento
Operadores
Genéticos
Mutação

NÃO Critério de
Parada?

SIM
FIM

Figura 1 - Fluxograma de um AG simples.

Primeiramente especificam-se os parâmetros iniciais e cria-se aleatoriamente uma


população inicial de indivíduos dentro destes limites. Em seguida verifica-se, através da
função objetivo, a aptidão de cada indivíduo. Aplica-se então um método de seleção que
selecionará os indivíduos sobre os quais serão aplicados os operadores genéticos que
modificam a população no intuito de melhorá-la. Este processo iterativo, correspondente às
sucessivas gerações, prossegue até que se obtenha a convergência baseada em algum critério
pré-estabelecido (critério de parada).
O objetivo dos operadores genéticos é transformar a população através de sucessivas
gerações, buscando melhorar a aptidão dos indivíduos. Eles são necessários para que a
população se diversifique e mantenha as características de adaptação adquiridas pelas

25
gerações anteriores. Na maior parte dos casos, os AGs utilizam dois operadores: cruzamento e
mutação.

3.1.1. População Inicial

Segundo Pozo (2002), a população de um algoritmo genético é o conjunto de indivíduos


que estão sendo cogitados como solução e que serão usados para criar o novo conjunto de
indivíduos para análise. O tamanho da população pode afetar o desempenho global e a
eficiência dos algoritmos genéticos. Populações muito pequenas têm grandes chances de
perder a diversidade necessária para convergir a uma boa solução, pois fornecem uma
pequena cobertura do espaço de busca do problema. Entretanto, se a população tiver muitos
indivíduos, o algoritmo poderá perder grande parte de sua eficiência pela demora em avaliar a
função de aptidão de todo o conjunto a cada iteração, além de ser necessário trabalhar com
maiores recursos computacionais.
Há dois parâmetros para serem decididos: o tamanho da população inicial e o
procedimento para gerar a população. Inicialmente, pensava-se que o tamanho da população
precisava aumentar exponencialmente com o comprimento do cromossomo para gerar boas
soluções. Porém, ele deve cobrir inteiramente o espaço de busca e evitar uma convergência
para um local ótimo, mas não tão grande a ponto de perder tempo de computação.
Geralmente se faz uso de funções aleatórias para gerar os indivíduos, sendo este um
recurso simples, porém fundamental para fornecer maior diversidade da população,
propiciando uma boa abrangência do espaço de pesquisa. Existem várias alternativas ao
método randômico destinadas a suprir deficiências no que diz respeito a dificuldades
existentes quanto à criação aleatória de indivíduos de representação mais complexa. Podemos
citar como exemplo o uso de algoritmos de busca heurística como geradores de populações
iniciais, especialmente em casos que apresentem um alto grau de restrições, onde o AG recebe
uma população que ainda não possui indivíduos ótimos, mas que apresentam pelo menos
algumas das características desejadas.

3.1.2. Função Objetivo

Utilizando a função objetivo, será calculado o valor de aptidão de cada indivíduo da


população. É através desta função que se mede quão próximo um indivíduo está da solução
desejada ou quão boa é esta solução.

26
É essencial que esta função seja muito representativa e diferencie, na proporção correta,
as más soluções das boas. Se houver pouca precisão na avaliação, uma ótima solução pode ser
posta de lado durante a execução do algoritmo, além de gastar mais tempo explorando
soluções pouco promissoras.

3.1.3. Seleção

O processo de seleção é responsável pela escolha dos indivíduos sobre os quais serão
aplicados os operadores genéticos, tendo como nova geração os indivíduos resultantes destas
operações. Assim como ocorre no processo de seleção natural, os indivíduos mais aptos, de
acordo com a função objetivo, têm maiores chances de serem escolhidos, ainda que
indivíduos menos aptos algumas vezes sejam selecionados a fim de manter a variedade da
população. Seguem abaixo algumas formas de seleção, como descritos em Lozano (2006),
Vianna e Souza (2006) e Soares (1997):

3.1.3.1. Roleta (Seleção Estocástica com reposição)

Este método foi proposto por Holland (1975) e seu funcionamento se assemelha à roleta
dos cassinos. Uma vez calculada a função objetivo para os cromossomos da população, cada
indivíduo terá a oportunidade de ser selecionado para cruzamento de acordo com o seu
desempenho relativo ao do grupo, ou seja, cada indivíduo i tem uma probabilidade de seleção
Psel = fi./Σf, onde fi é o valor da sua função objetivo e Σf é o somatório do valor das funções
objetivos de todos os indivíduos da população.

Roleta

28% 31% Cromossomo A


Cromossomo B
Cromossomo C
Cromossomo D
24% 17%

Figura 2 - Distribuição dos indivíduos na Roleta.

27
No exemplo da Figura 2, dados quatro cromossomos A, B, C e D com valores,
respectivamente, 45, 25, 35 e 40 para função objetivo, um gráfico representando a roleta pode
ser observado. De acordo com esta figura, pode-se observar que o setor obtido por um
cromossomo representa uma maior ou menor probabilidade do mesmo ser selecionado após o
giro da roleta. Neste exemplo, o cromossomo A é o que possui a maior probabilidade de ser
selecionado enquanto o cromossomo B é o de menor probabilidade.
A roleta é girada um determinado número de vezes para obter o número requerido de
indivíduos para o cruzamento. Este método apresenta tendência de convergência prematura já
que o crescimento pode ser exponencial.

3.1.3.2. Torneio

Neste método um subconjunto de indivíduos (normalmente um par) é escolhido


aleatoriamente, contudo somente o indivíduo com maior valor da função objetivo é
selecionado. Este processo é repetido até que a quantidade de indivíduos selecionados seja a
necessária para a realização do cruzamento.
Quanto maior for o subconjunto de indivíduos escolhidos, maior será a velocidade com
que os indivíduos mais fortes dominarão a população e conseqüentemente extinguirão os mais
fracos.

3.1.3.3. Torneio Estocástico

É um método similar ao Torneio, porém o método de obtenção do subconjunto de


indivíduos é o da Roleta.

3.1.3.4. Seleção Aleatória (Stochastic Universal Sampling - SUS)

A escolha é feita aleatoriamente entre membros da população. Cada indivíduo i tem


uma probabilidade de seleção Psel = 1/Totpop., onde Totpop é o número total de indivíduos da
população. Neste método todos os indivíduos possuem a mesma probabilidade de serem
selecionados, o que torna muito pequena a probabilidade de causar a evolução da população.

28
3.1.3.5. Seleção Determinística (Deterministic Sampling - DS)

O funcionamento deste método de seleção possui dois estágios. O primeiro é a criação


de uma população temporária e em seguida os indivíduos desta população são selecionados de
forma randômica.
A população temporária é gerada dividindo o valor da função objetivo de um indivíduo
pela média das funções objetivo dos demais indivíduos da população original (fi/fmed). A parte
inteira do resultado determina o número de cópias do indivíduo i que fará parte da população
temporária. Devido à existência de partes fracionárias provenientes dos cálculos, a população
não será totalmente preenchida. Estas vagas ociosas na população serão preenchidas pelos
indivíduos de maior parte fracionária da função objetivo.

3.1.3.6. Seleção Estocástica por Resto Sem Reposição (Stochastic Remainder Sampling)

Método semelhante à Seleção Determinística, porém as vagas restantes na população


temporária serão preenchidas de forma diferente. A parte fracionária, do cálculo da
expectativa de cópias de um indivíduo, será utilizada como valor de probabilidade na seleção
deste.
Por exemplo, um indivíduo que tenha como resultado do cálculo fi/fmed o valor 2.5, terá
2 cópias garantidas na população temporária e 50% de mais uma vaga. O indivíduo a ter sua
possibilidade de seleção avaliada deverá ser escolhido por um critério (o aleatório, por
exemplo) e em seguida um evento deverá ser gerado. Caso este evento esteja dentro dos 50%
de probabilidade, uma cópia do indivíduo será adicionada à população, caso contrário um
outro indivíduo será escolhido aleatoriamente e o processo se repetirá.

3.1.3.7. Seleção Estocástica por Resto Com Reposição

Método semelhante aos dois anteriores, porém as vagas restantes na população


temporária serão preenchidas diferentemente. As partes fracionárias, dos cálculos das
expectativas de cópias dos indivíduos, serão utilizadas como valores para os setores de uma
roleta. A seleção por roleta será executada até que as vagas da população temporária sejam
completadas.

29
3.1.3.8. Seleção Estocástica Sem Reposição

Neste método também é calculado o número de vezes que um indivíduo em potencial


fará parte de cruzamentos para gerar descendentes em uma nova população. Contudo, após
este cálculo, o método da roleta será utilizado e, à medida que os indivíduos forem sendo
selecionados para reprodução, os números de cruzamentos permitidos para estes serão
decrementados até que cheguem a zero e os indivíduos sejam retirados da roleta.

3.1.3.9. Seleção por Ranking

Inicialmente os indivíduos da população são ordenados de acordo com os valores das


suas funções objetivo. Após a ordenação, cada indivíduo terá um valor equivalente a sua
posição no ranking e será utilizado um procedimento similar à seleção pelo método da roleta.
Quanto melhor a posição do indivíduo no ranking, maior será seu setor na roleta e
conseqüentemente maior a sua chance de ser selecionado.

3.1.3.10. Positive and Negative Assortative Mating

Assortative Mating é a ocorrência natural do acoplamento entre indivíduos de estrutura


similar. Acoplamento entre indivíduos com estruturas semelhantes é denominado Positive
Assortative Mating e com estruturas diferentes é chamado de Negative Assortative Mating.
Neste método o primeiro pai é selecionado pelo método da Roleta. Em seguida a
similaridade entre este pai e cada um dos cromossomos é computada (a similaridade entre
dois códigos binários é definida como a distância de Hamming3 entre eles). Se a Assortative
Mating for positivo, o cromossomo mais semelhante com o primeiro pai é escolhido para ser
o segundo pai. Caso contrário (Assortative Mating Negativo), o cromossomo mais diferente é
escolhido para ser o segundo pai.

3.1.4. Cruzamento

O objetivo do cruzamento é a troca de material genético entre os pares de indivíduos


(“pais”) previamente selecionados, o que torna este operador genético o maior responsável
pela criação de novos indivíduos. Após a escolha, os pais são submetidos ao processo de
cruzamento, sendo que este processo pode ou não ocorrer, de acordo com uma dada

3
Distância de Hamming indica a quantidade de bits diferentes do indivíduo. Soares (1997)

30
probabilidade de cruzamento. Por isto, esta probabilidade deve ser alta, geralmente entre 70 e
100% conforme Rahmat-Samii Y. (1999 apud MOGNON, 2004, p. 07). Os AGs são
caracterizados pela alta flexibilidade de implementação e isto vale também para o
cruzamento.
Os principais operadores tradicionais de cruzamento para genomas de comprimento fixo
segundo Goldberg (1989) são:
a) cruzamento em um ponto (1PX): dados dois genomas x e y de comprimento lg,
sorteia-se um número p qualquer tal que 0< p < lg, o primeiro filho f0 receberá todos os genes
x de 1 até p e todos os genes y de p+1 até ly, e o segundo filho o inverso. Um exemplo de
operador de cruzamento em um ponto pode ser visto na figura abaixo:

Ponto de Corte

1 0 0 1 1 0 1 0 0 1
Pais 0 1 0 0 0 1 1 1 0 0

1 0 0 1 1 1 1 1 0 0
Filhos 0 1 0 0 0 0 1 0 0 1

Figura 3 - Cruzamento em um ponto (1PX).

b) cruzamento em dois pontos (2PX): semelhante ao operador de cruzamento por um


ponto, mas neste caso são escolhidos dois pontos de corte, como pode ser visto na Figura 4;

Pontos de Corte

1 0 0 1 1 0 1 0 0 1
Pais
0 1 0 0 0 1 1 1 0 0

1 0 0 0 0 1 1 0 0 1
Filhos 0 1 0 1 1 0 1 1 0 0

Figura 4 - Cruzamento em dois pontos (2PX).

31
c) cruzamento Multi-Ponto (MPX): o cruzamento multi-ponto é uma generalização dos
operadores apresentados anteriormente. Nele são sorteados um número fixo n de pontos de
corte. Como regra geral, uma operação de cruzamento de n pontos pode ser vista como um
caso especial de uma de m > n pontos em que um ou mais (m – n) pontos de corte
selecionados se localizam no final do cromossomo (o ponto de índice i = lg);
d) cruzamento Segmentado (SX): o cruzamento segmentado funciona de maneira
semelhante ao multi-ponto, com a exceção de que sorteia o número de pontos de corte toda
vez que é executado;
e) cruzamento Uniforme (UX): para cada gene a ser preenchido nos cromossomos
filhos, o operador de cruzamento uniforme sorteia de qual dos pais este deve ser gerado;
f) cruzamento por Combinação Parcial (PMX): sorteia dois pontos de corte e faz com
que os indivíduos filhos recebam na íntegra os genes do pai ou da mãe (mãe para um e pai
para outro) situados entre os pontos de corte, depois disso preenche os genes restantes com os
valores considerados mais adequados para cada filho.

3.1.5. Mutação

O objetivo da mutação é simplesmente modificar alguma característica do indivíduo


sobre o qual é aplicada. Esta alteração cria novos valores de características inexistentes ou que
apareciam em pequena quantidade na população em análise. Da mesma forma que o
cruzamento, este operador genético pode ou não ocorrer de acordo com uma dada
probabilidade de mutação que, segundo Rahmat-Samii Y.(1999 apud MOGNON, 2004, p.07),
deve ser bem baixa, algo em torno de 0 a 10% para que a busca pelo indivíduo ótimo não seja
puramente aleatória.
A Figura 5 mostra um exemplo de mutação simples, onde foi invertido o valor de um
gene, criando-se um novo indivíduo.

Indivíduo 1 0 0 1 1 1 1 1 0 0

Novo
1 0 0 1 0 1 1 1 0 0
Indivíduo

Figura 5 - Mutação Simples.

32
3.1.6. Evolução da População

O objetivo da evolução da população é definir a porcentagem de indivíduos substituídos


em cada iteração após o método de cruzamento. Após a realização dos operadores genéticos,
os novos indivíduos são inseridos na população inicial. Conforme Vianna e Souza (2006), esta
inserção pode ser feita utilizando diferentes métodos de evolução da população:

3.1.6.1. SGA (Simple Genetic Algorithm)

Neste modelo, toda a população é substituída por uma nova na geração seguinte.
Utilizando os operadores de seleção, cruzamento e mutação, ocorre a evolução da população,
onde os indivíduos mais adaptados possuem maior chance de serem escolhidos para
cruzamento. Porém, isto pode gerar um regresso na população, pois o indivíduo mais bem
adaptado de uma geração possa ser substituído por outro de uma geração futura.

3.1.6.2. SSGA (Steady State GA)

Neste algoritmo, a cada geração, somente um ou dois indivíduos são gerados e


introduzidos na nova população através da substituição de outros indivíduos. Após o
cruzamento, serão definidos quais indivíduos da população serão substituídos pelos novos
descendentes.

3.1.6.3. Parâmetro Gap da Geração

O parâmetro Gap controla a porcentagem da população a ser substituída em cada


geração. Nos SGAs este parâmetro é igual a 100%, o que significa que todos os indivíduos da
população serão substituídos. Nos SSGAs, este valor é usualmente 1/Totpop, quando apenas
um indivíduo é substituído, onde Totpop é o número total de indivíduos da população.

3.1.7. Critério de Parada

Esta etapa não envolve o uso de nenhum operador genético. Ela simplesmente
verifica, de acordo com um ponto de parada pré-estabelecido, se o AG finalizará ou não o seu
processo de evolução.
Podem ser citados, como critérios de parada, segundo Vianna e Souza (2006):

33
3.1.7.1. Número Máximo de Gerações

Neste tipo de critério, o algoritmo finaliza seu processo de evolução quando atinge um
determinado número de gerações previamente definido. O número ideal de gerações deve ser
definido após a execução de testes para detectar a convergência do algoritmo.

3.1.7.2. Convergência da População

O melhor valor de função objetivo será subtraído da média dos valores das funções
objetivo dos demais indivíduos da população. Se o resultado deste cálculo não ultrapassar um
valor previamente definido, a população convergiu, e o algoritmo finaliza seu processo de
evolução.

No próximo capítulo será apresentada a implementação de nove variações de


Algoritmos Genéticos contemplando suas fases.

34
IV. IMPLEMENTAÇÃO DO PROBLEMA DA MOCHILA BINÁRIA UTILIZANDO
ALGORITMO GENÉTICO

Como pôde ser visto no Capítulo 2, há diversas variações para o Problema da Mochila
sendo todas pertencentes à classe de problemas NP-Completo. Além disso, neste mesmo
capítulo, viu-se que as metaheurísticas são utilizadas para resolver problemas deste tipo. No
presente projeto serão apresentados Algoritmos Genéticos com o intuito de encontrar a
melhor solução para o problema da Mochila Binária. O foco deste trabalho é investigar,
dentre as políticas de seleção Roleta, Torneio, Torneio Estocástico, Seleção Aleatória, Seleção
Determinística, Seleção Estocástica por Resto Sem Reposição, Seleção Estocástica por Resto
Com Reposição, Seleção Estocástica Sem Reposição e Seleção por Ranking, qual apresentará
a melhor solução para o problema.
Amplamente utilizada no meio científico, a Linguagem C foi escolhida para a
implementação devido a sua portabilidade e seu desempenho de linguagem compilada. Os
Algoritmos Genéticos foram implementados a partir do modelo apresentado por Vianna e
Souza (VIANNA & SOUZA, 2006).

4.1. População Inicial

De acordo com Soares (1997), não há consenso em relação ao tamanho da população


inicial. Uma população pequena fornece uma pequena cobertura do espaço de busca do
problema. Já uma grande população fornece uma cobertura maior do espaço de busca e
previne convergências prematuras para soluções locais, porém são necessários maiores
recursos computacionais ou que o algoritmo trabalhe por um período de tempo muito maior
tornando-o inviável. O tamanho da população utilizada neste projeto foi de 100 indivíduos, o
que possibilitou uma boa cobertura do espaço de busca do problema e também se mostrou
eficiente em nossa experiência, pela capacidade computacional disponível.
Os indivíduos (cromossomos) são formados por n alelos, onde n representa a quantidade
de itens possíveis de fazer parte da mochila. Cada alelo pode assumir valores 0 ou 1,
indicando, respectivamente, a ausência ou presença do item na mochila. Estes itens são
compostos por dois valores, ganho e peso, que serão lidos de um arquivo de texto. Cada
indivíduo representa uma solução que será formada por um subconjunto de itens selecionados
para estar na mochila. Para formar indivíduos factíveis para a população inicial, foram
utilizados quatro critérios: maior ganho, menor peso, maior relação ganho por peso
(ganho/peso) e seleção de item entre os seis maiores ganhos.
35
O critério maior ganho foi utilizado para gerar o primeiro indivíduo da população. De
acordo com este, uma busca é feita para se encontrar os itens cujos ganhos sejam os maiores
entre todos. Para formar o segundo indivíduo, foi utilizado o critério menor peso onde uma
varredura é realizada em busca dos itens cujos pesos sejam os menores. O terceiro indivíduo é
formado através do critério maior relação ganho por peso. Assim, para cada item é calculada a
divisão do ganho pelo peso a fim de se encontrar os maiores resultados. A partir do quarto
indivíduo, o critério utilizado foi seleção de item entre os seis maiores ganhos. Desta forma, a
cada varredura, um item será selecionado aleatoriamente entre os seis que representam os
maiores ganhos. O valor seis foi escolhido porque, nos testes com um valor inferior, a
população mostrou-se bastante homogênea.
Após a seleção de um item, em cada critério, seu peso é verificado para saber se este
excede a capacidade da mochila. Se o peso exceder esta capacidade, o item é desconsiderado
e novamente é aplicado o critério para os itens remanescentes, senão, atualiza-se a capacidade
da mochila e nesta inclui-se o item.

4.2. Função Objetivo

Cada indivíduo da população possui um valor de função objetivo. Este valor é calculado
somando-se os ganhos dos itens que compõe o indivíduo. O melhor indivíduo da população
será aquele que possuir o maior valor de função objetivo.

4.3. Seleção

Foco deste trabalho, o processo de seleção é responsável pela escolha de dois indivíduos
sobre os quais serão aplicados os operadores genéticos cruzamento e mutação. Dentre as
políticas descritas no Capítulo 3, serão utilizadas, neste projeto, as implementadas no modelo
de Vianna e Souza (VIANNA & SOUZA, 2006): Roleta, Torneio, Torneio Estocástico,
Seleção Aleatória, Seleção Determinística, Seleção Estocástica por Resto Sem Reposição,
Seleção Estocástica por Resto Com Reposição, Seleção Estocástica Sem Reposição e Seleção
por Ranking.
Cada uma das políticas anteriores irá compor um modelo de Algoritmo Genético onde
as instâncias de teste serão submetidas, visando encontrar as políticas que gerem as melhores
soluções para o problema.

36
4.4. Cruzamento

Neste projeto, o cruzamento realizado com os dois indivíduos selecionados (pais) foi
cruzamento em um ponto (Figura 6), por ser o mais utilizado segundo Vianna (2004). Neste
tipo de cruzamento, definimos como ponto de corte n/2, sendo n o tamanho do indivíduo.
Assim, dois indivíduos (filhos) serão gerados, onde a primeira metade do primeiro pai é
trocada com a primeira metade do segundo pai. A probabilidade de o cruzamento ocorrer será
de 80%. Caso não ocorra, os pais serão mantidos na nova geração e, assim como os filhos,
poderão ou não sofrer mutação.

Ponto de Corte

1ª metade do 1º indivíduo
1 0 0 1 1 0 1 0 0 1
Pais
0 1 0 0 0 1 1 1 0 0
1ª metade do 2º Indivíduo

0 1 0 0 0 0 1 0 0 1

Filhos
1 0 0 1 1 1 1 1 0 0

Figura 6 – Exemplo de Cruzamento em um ponto (1PX).

4.5. Mutação

Da mesma forma que o cruzamento, este operador genético pode ou não ocorrer de
acordo com uma dada probabilidade de mutação que foi de 10% sobre o indivíduo. Na
mutação, os filhos gerados pelo cruzamento, ou os pais que foram mantidos, terão suas
características modificadas da seguinte maneira: dados os n alelos do indivíduo, um é
escolhido randomicamente e seu valor é alterado para 0 se este for 1 e para 1 se este for 0,
como pode ser visto um exemplo na Figura 7.

37
Indivíduo 1 0 0 1 1 1 0 1 0 0

Novo
1 0 0 1 1 1 1 1 0 0
Indivíduo
Figura 7 - Exemplo de Mutação Simples.

4.6. Evolução da População

A evolução da população tem como finalidade a diversificação e a melhoria da


população. O método de evolução da população utilizado neste projeto foi o SGA, onde, com
um tamanho de população fixo, a nova geração substitui a anterior dada às probabilidades de
aplicação dos operadores genéticos (cruzamento e mutação) sobre os dois indivíduos
escolhidos por um determinado método de seleção.
Após a aplicação destes operadores, cada indivíduo terá o somatório de seus pesos
verificado. Se este somatório extrapolar a capacidade da mochila, o item com a menor relação
ganho/peso será descartado até que o somatório dos pesos seja menor ou igual a esta
capacidade. Caso este somatório não alcance a capacidade da mochila, com o objetivo de
melhorar o indivíduo menos evoluído, tenta-se incluir o item com a maior relação ganho/peso
verificando se o seu peso não excede a capacidade da mochila. Se isto ocorrer, tenta-se
incluir o item com o menor peso, sempre respeitando a capacidade da mochila.
Encerrado este processo, para cada indivíduo é calculado o valor de sua função objetivo,
o que indicará se este é melhor do que o atual melhor. Em seguida, os dois indivíduos passam
a compor a nova população.

4.7. Critério de Parada

O critério de parada escolhido neste projeto foi o número de gerações. Neste tipo de
critério, quando o Algoritmo Genético alcança uma determinada geração predefinida, ele é
finalizado, apontando como solução o melhor indivíduo até o momento. De acordo com
Vianna e Souza (2006), o número ideal de gerações deverá ser definido após a execução de
testes para detectar a convergência do algoritmo. Durante os testes, a convergência da melhor
solução para a menor instância foi encontrado em média na geração 20. Já para a maior
instância, percebeu-se que um número maior do que 1000 gerações poderia melhorar o valor

38
da função objetivo, porém inviabilizando o tempo computacional dos testes. Deste modo, o
número de gerações escolhido foi 1000 por não demandar tempo significativo de computação
para instâncias pequenas e não demandar tempo inviável para as maiores instâncias no
equipamento utilizado.

39
V. TESTES COMPUTACIONAIS

Os testes apresentados neste capítulo têm por objetivo avaliar os resultados gerados
pelos Algoritmos Genéticos criados para solucionar o problema da mochila binária. Foram
utilizadas instâncias geradas por um software desenvolvido por Pisinger (Pisinger, 2003,
Pisinger, 1994), que trabalha com parâmetros n, R, S, i, t, onde n representa a quantidade de
itens que podem fazer parte da mochila, R a faixa de coeficientes, S o número de instâncias, i
o índice da instância e t o tipo de critério utilizado. Para a realização destes testes, de acordo
com Martelo e Toth (1990), n assumiu os valores 50, 100, 200, 1000, 5000 e 10000.
Considerou-se também, segundo Pisinger (2003), a faixa de coeficientes igual 1000, o número
de instâncias igual a 1, o índice da instância também igual a 1 e o tipo de critério Weakly
Correlated Instances (Instâncias Fracamente Correlatas), onde o peso (wj) de cada item é
escolhido randomicamente em [1,R] e o ganho (pj) em [wj – R/10, wj + R/10], sendo pj maior
ou igual a 1. Apesar do nome fracamente correlato, as instâncias têm uma correlação muito
alta entre o ganho e o peso de um item, diferindo somente por uma pequena porcentagem.
Este critério foi escolhido por ser o que mais se aproxima do mundo real, segundo Pisinger
(2003). Para cada valor assumido por n, uma instância foi gerada e um valor para a
capacidade da mochila foi calculado a partir da seguinte fórmula:

Onde:
C= capacidade da mochila
i= índice da instância
S= número de instâncias
n= quantidade de itens
j= índice do item
wj= peso do item j

Proposta por De Jong (1975), a medida de desempenho utilizada nos testes foi a off-line.
Esta tem por característica levar em conta apenas o valor da melhor função objetivo
encontrada no final da execução do algoritmo.

40
O computador utilizado para a realização dos testes possuía processador Intel Pentium
IV com 1.70 GHz de freqüência, 512MB de memória principal e sistema operacional
Windows XP. Cada algoritmo foi executado 10 vezes para uma mesma instância. Neste
estudo, considerou-se apenas o maior valor de função objetivo obtido por cada algoritmo
quando submetido a uma dada instância. Dessa forma, serão apresentados a seguir os
resultados obtidos neste processo considerando as seguintes políticas de seleção: Roleta,
Torneio, Torneio Estocástico, Seleção Aleatória, Seleção Determinística, Seleção Estocástica
por Resto Sem Reposição (EstRestoSemRep), Seleção Estocástica por Resto Com Reposição
(EstRestoComRep), Seleção Estocástica sem Reposição (EstSemRep) e Seleção por Ranking.
Considerando a execução dos testes para a instância de tamanho 50, todas as políticas de
seleção geraram valores iguais de função objetivo, como pode ser observado na Figura 8.
Valor da Função Objetivo

20000

15000 13380 13380 13380 13380 13380 13380 13380 13380 13380

10000

5000
ria
o
o
ta

ep

ng
ep
ep
ic
ei

tic
e

ki
R
st

R
rn
ol

ís
ea

an
em
m

m

R

To

in

Se

Co
Al

R
to

tS
Es

to
er

to

Es
es

es
et
o

tR
ei

tR
rn

Es

Es
To

Políticas de Seleção

Figura 8 - Testes das Políticas de Seleção para a instância de tamanho 50.

Assim como ocorreu com o número de itens igual a 50, os valores de função objetivo
para o número de itens igual a 100 foram iguais para todas as políticas, isto pode ser
observado na Figura 9.

41
40000

Valor da Função Objetivo 29128 29128 29128 29128 29128 29128 29128 29128 29128
30000

20000

10000

ia
io
ta

ng
o

ep
ep

ep
ic

r
ne

tic
e

ki
R
st

R
ol

ís
r

ea

an
em
em

m
R


To

in
Al

Co

R
to

tS
S
Es

er

to

to

Es
es
et

es
io

tR

tR
ne

Es

Es
r
To

Políticas de Seleção

Figura 9 - Testes das Políticas de Seleção para a instância de tamanho 100.

Resultados distintos para as políticas de seleção testadas surgiram a partir da instância


de tamanho 200. Pode-se observar na Figura 10 que as políticas de seleção Estocástica por
Resto com Reposição e Estocástica sem Reposição foram as que apresentaram melhores
valores de função objetivo.
Valor da Função Objetivo

54675
54661 54661
54659 54659
54660 54657 54657 54657 54657 54657

54645

54630
ri a
io
ta

ng
o

ep
ep

ep
ti c
ne

tic
e

ki
R
R
ol

R
ás

ís
ea
r

an
em
m

m
R

To

in
c

Se
Al

R
Co
to

tS
Es

er

to

to

Es
es
et

es
o

tR
ei

tR
rn

Es

Es
To

Políticas de Seleção

Figura 10 - Testes das Políticas de Seleção para a instância de tamanho 200.

42
Como pode ser observado na Figura 11, para o número de itens igual a 1000, a política
que apresentou o melhor valor de função objetivo foi seleção Estocástica por Resto com
Reposição.

273570
Valor da Função Objetivo

273560
273560 273556 273556 273556
273554 273554 273554
273549
273550 273547

273540
ia
io
ta

ng
o

ep
ep

ep
tic

r
ne

tic
e

ki
R
R

R
ol

ás

ís
r

ea

an
em
m

m
R

To

in
c

Se
Al

R
Co
to

tS
Es

er

to

to

Es
es
et

es
io

tR

tR
ne

Es

Es
r
To

Políticas de Seleção

Figura 11 - Testes das Políticas de Seleção para a instância de tamanho 1000.

Como pode ser visto na Figura 12, para o número de itens igual a 5000, a política que
apresentou o melhor valor de função objetivo foi seleção Roleta.

1375400
Valor da Função Objetivo

1375324
1375300
1375300
1375223
1375189
1375200
1375145 1375138 1375153
1375137 1375132

1375100
ia
io
ta

ng
o

ep
ep

ep
tic

tic
ne
e

ki
R
R

R
ol

ís
r

ea

an
em
em

m
R


To

in
Al

R
Co
to

tS
S
Es

er

to

to

Es
es
et

es
io

tR

tR
ne

Es

Es
r
To

Políticas de Seleção

Figura 12 - Testes das Políticas de Seleção para a instância de tamanho 5000.

43
Para o número de itens igual a 10000, como pode ser observado na Figura 13, a política
que apresentou o melhor valor de função objetivo foi seleção Aleatória.

2750000
Valor da Função Objetivo

2748151 2748119 2748119 2748119


2748000
2747130
2746735
2746447
2745854
2746000 2745433

2744000
ria
io
ta

g
o

ep
ep

ep

in
tic

tic
ne
e

k
R
ol

R
ás

ís
ea
r

an
em
m

m
R

To

in
c

Se
Al

R
Co
to

tS
Es

er

to

to

Es
es
et

es
io

tR

tR
ne

Es

Es
r
To

Políticas de Seleção

Figura 13 - Testes das Políticas de Seleção para a instância de tamanho 10000.

Com o intuito de identificar a política de seleção que apresentou a melhor solução para
o Problema da Mochila Binária, a seguinte metodologia foi aplicada: para cada instância, um
ranking foi feito com a finalidade de avaliar o comportamento de cada algoritmo. A seguir, foi
calculada, para cada algoritmo, a média aritmética das posições obtidas em cada ranking.
Desse modo, a melhor política de seleção seria aquela que possuísse a menor média.

Política N=50 N=100 N=200 N=1000 N=5000 N=10000 Média Ranking


Roleta 1 1 3 2 1 4 2.0 3
Torneio 1 1 2 2 6 3 2.5 4
Torneio Estocástico 1 1 3 2 7 6 3.3 7
Aleatório 1 1 2 3 2 1 1.7 1
Determinístico 1 1 3 3 4 7 3.2 6
EstRestoSemRep 1 1 3 4 8 2 3.2 6
EstRestoComRep 1 1 1 1 5 2 1.8 2
EstSemRep 1 1 1 5 9 2 3.2 6
Ranking 1 1 3 3 3 5 2.7 5

Figura 14 - Resultados dos testes

44
Analisando os resultados da Figura 14, pôde ser constatado que a política de seleção
Aleatória foi a que alcançou a primeira posição no ranking, ou seja, apresentou a melhor
média nos testes, enquanto que a política de seleção Torneio Estocástico foi a que obteve a
última posição no ranking apresentando o pior média nos testes.

45
VI. CONCLUSÃO E TRABALHOS FUTUROS

Como pôde ser visto, o problema da mochila binária, assim como a família dos
Problemas da Mochila (Knapsack Problem), pertencem a classe de problemas NP-completos.
Como até o momento não foi encontrado nenhum algoritmo de tempo polinomial que resolva
problemas pertencentes a esta classe, uma boa alternativa para resolvê-los é o uso de
metaheurísticas.
Neste trabalho a metaheurística abordada foi Algoritmo Genético. Desse modo, foram
implementadas nove variações de Algoritmos Genéticos que resolvem o problema da mochila
binária com o intuito de comparar as políticas de seleção.
Após comparar as políticas de seleção, foi constatado que estas não geraram resultados
diferentes para a função objetivo, quando aplicadas a instâncias de cromossomos com até 100
alelos. Para as demais instâncias, foram computadas as médias dos desempenhos das políticas
nos testes realizados (Figura 15).

Ranking Política
1º Aleatório
2º EstRestoComRep
3º Roleta
4º Torneio
5º Ranking
6º Determinístico
6º EstRestoSemRep
6º EstSemRep
7º Torneio Estocástico
Figura 15 - Desempenho Médio das Políticas de Seleção.

Como pode ser observado, a política de seleção Aleatória foi a que gerou o melhor
resultado para a função objetivo.
Numa primeira análise, esta política poderia ser considerada uma má escolha devido ao
seu funcionamento não levar em consideração a adaptação do indivíduo. Esta característica
possibilita que indivíduos que representam soluções ruins sejam escolhidos com a mesma
probabilidade dos bons indivíduos. Contudo, a política aleatória gera diversidade na
população, aumentando a cobertura do espaço de busca do problema, saindo mais facilmente
de soluções locais em direção a solução global. Este fato, provavelmente, foi o mais relevante
para o bom desempenho desta política em face das instâncias de testes geradas.

46
Com isto, fica constatado mais uma vez que, a melhor escolha por um parâmetro ou
política de funcionamento do algoritmo genético é na grande maioria das vezes feita através
de testes empíricos.
Neste trabalho a relação entre ganho e peso utilizada na criação das instâncias foi a
Weakly Correlated Instances (Instâncias Fracamente Correlatas) que é uma das quatro
relações propostas por Pisinger. Como trabalho futuro, podem ser criadas novas instâncias
com as diferentes relações a fim de se obter outros resultados que possam possibilitar uma
melhor avaliação das políticas de seleção.
Ainda como trabalho futuro, pode-se variar o tamanho da população de acordo com o
tamanho do indivíduo. Desse modo, dado uma relação entre o tamanho do indivíduo e o
tamanho da população, quanto maior o indivíduo maior seria a população, o que aumentaria a
diversidade da mesma e a cobertura do espaço de busca do problema. Porém, esta relação
teria como limitação os recursos computacionais e o tempo de execução do algoritmo devido
ao excessivo aumento da população, o que poderia torná-lo inviável. Considerando estas
limitações, o tamanho da população, neste estudo, foi constante.
Uma outra proposta para trabalho futuro seria aumentar o número de gerações
juntamente com o tamanho da população e com o tamanho do indivíduo. Este aumento pode
proporcionar uma melhora no valor da função objetivo, pois cresce o número de tentativas de
se obter indivíduos mais bem adaptados.

47
VII. REFERÊNCIAS

ÁVILA, S. L. Algoritmos Genéticos Aplicados na Otimização de Antenas Refletoras.


2002. 98f. Dissertação (Mestrado em Engenharia Elétrica) – Faculdade de Engenharia
Elétrica, Universidade Federal de Santa Catarina, Florianópolis.

BENFICA, A. T. Problema da Mochila aplicado ao Sistema de Memória Virtual. 2004.


15f. Projeto de Pesquisa (Ciência da Computação) – Instituto de Ciências Exatas,
Universidade Federal de Minas Gerais, Belo Horizonte.

DE JONG, K.A. Analysis of the Behavior of a Class of Genetic Adaptive Systems. 1975.
PhD. Thesis - Dep.Computer and Comunication Sciences, Univ. Michigan, Ann Arbor.

GOLDBERG, D. E. Genetic Algorithms in Search, Optimization & Machine Learning.


Addison-Wesley, 1989.

HOLLAND, J. H. Adaptation in Natural and Artificial Systems. The University of


Michigan Press, Ann Arbor, MI, 1975.

LOZANO, M.; MARTÍNEZ, C. G.; MOLINA, D. A Local Genetic Algorithm for Binary-
coded Problems. University of Córdoba, Spain, 2006.

MARTELLO, S.; TOTH, P. Knapsack Problems: Algorithms and Computer


Implementations, Wiley, Chichester, England, 1990.

MOGNON, V. R. Algoritmos Genéticos Aplicados na Otimização de Antenas. 2004. 96f.


Dissertação (Mestrado em Engenharia Elétrica) – Universidade Federal do Paraná, Curitiba.

PISINGER, D. Core Problems in Knapsack Algorithms. Technical Report 94-26, DIKU,


University of Copenhagen, Denmark, 1994.

PISINGER,D.; MARTELLO,S.; TOTH, P. New Trends in Exact Algorithms for the 0-1
Knapsack Problem. Technical Report 97-10, DIKU, University of Copenhagen, Denmark,
1997.

PISINGER,D. Where Are the Hard Knapsack Problems?. Technical Report 03-08, DIKU,
University of Copenhagen, Denmark, 2003.

POZO, A. et. al. Computação Evolutiva. 2002. 61f. Projeto de Pesquisa (Computação
Evolutiva) – Departamento de Informática, Universidade Federal do Paraná, Curitiba.

ROMERO, R.; MANTOVANI, J. R. S. Introdução a Metaheurísticas. Anais do 3o


Congresso Temático de Dinâmica e Controle da SBMAC, Ilha Solteira, 2004.

SOARES, G. L. Algoritmos Genéticos: Estudo, Novas Técnicas e Aplicações. 1997. 145f.


Dissertação (Mestrado em Engenharia Elétrica) – Escola de Engenharia, Universidade Federal
de Minas Gerais, Belo Horizonte.

TOSCANI, L. V.; VELOSO, P. A. S. Complexidade de Algoritmos: análise, projeto e


métodos. Porto Alegre: Sagra Luzzato, 2005.

48
VIANNA, D. S.; SOUZA, F. D. (2006) Um Modelo de Implementação para o
Desenvolvimento de Algoritmos Genéticos. Relatório Técnico. Universidade Candido
Mendes – Campos. Submetido à Revista Produção On Line.

VIANNA, D. S. Heurísticas Híbridas para o Problema da Filogenia. 2004. 187f. Tese


(Doutorado em Informática) – Departamento de Informática, Pontifícia Universidade Católica
do Rio de Janeiro, Rio de Janeiro.

49
ANEXO I: Algoritmo Genético com a Política de Seleção Roleta

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include<math.h>

/* Constante com o maior valor suportado pelo tipo de variável que armazena a função objetivo */
#define INFINITO (float)3.402823466e+38f
/* Macro para retornar o melhor valor entre dois comparados */
/* O sinal de maior da macro abaixo deverá ser alterado caso seu problema seja de minimização */
#define best(A,B) ((A>B) ? (1):(0))
/* Constante que armazena o pior valor de função objetivo (para inicialização de variáveis) */
#define OBJ_VAL_INI (best(0,INFINITO) ? (INFINITO):(0))

/*********************************************************************/
/* Constantes que armazenam parâmetros comumente definidos em AGs */
/* Poderão ser modificadas de acordo com as necessidades do usuário */
/*********************************************************************/
#define SIZE_POP 100 /* Número de indivíduos da população */
#define TOT_SELECT 2 /* Total de indivíduos selecionados para cruzamento */
#define TOT_CHILDREN 2 /* Total de filhos gerados em um cruzamento */
#define MAX_GEN 1000 /* Número máximo de gerações para o algoritmo */
#define PROB_MUTAT 0.1 /* Valor da probabilidade de mutação */
#define PROB_CROSS 0.8 /* Valor da probabilidade de cruzamento */
/********************************************************************/
/* Fim da declaração de parâmetros dos AGs */
/********************************************************************/

/* Constante que indica a quantidade de itens */


#define sizeVector 5000
/* Constante que indica a capacidade da mochila */
#define sizeKnapsack 1254816

/*Estrutura da Mochila*/
typedef struct
{
float earn,weight;
int visited;
}Item;
Item vector[sizeVector];

/* Estrutura do cromossomo */
typedef struct chromossome
{
/* Deverá ser incluída aqui a estrutura de dados do cromossomo
Ex: O cromossomo poderá ser formado por 10 elementos inteiros*/
int *iAlele;
} tpChromossome;

/* Deverá ser definido aqui o tipo de dado que guarda o valor da função objetivo (tpObj) */
/* Tipo padrão: float. */
typedef float tpObj;

/* Estrutura dos indivíduos: formada pelos cromossomos e pelos valores de suas funções objetivo. */
typedef struct individual

50
{
tpChromossome chrom;
tpObj obj;
} tpIndivid;

/******************************************************************/
/* Protótipos das funções */
/******************************************************************/
void initialPopulation( tpIndivid* );
void selection( tpIndivid*, int* );
void crossover( tpIndivid*, int*, tpIndivid* );
void copyChrom( tpChromossome*, tpChromossome* );
void keepFather( tpIndivid*, int*, tpIndivid* );
void mutation( tpChromossome* );
void calcObj ( tpIndivid* );
void updatePop( tpIndivid*, tpIndivid*, int* );
void bestSolut( tpIndivid*, tpIndivid* );
void populationEvolution ( tpIndivid**, tpIndivid*, tpIndivid* );
void stopCriterion ( tpIndivid* , tpIndivid* ,tpIndivid*);
/******************************************************************/
/* Fim da declaração dos protótipos das funções */
/******************************************************************/

/* Função para verificar o peso da mochila */


float verifyWeight(int index, float szKnapsack, tpIndivid *pop, int option)
{
if(vector[index].weight <= szKnapsack)
{
szKnapsack=szKnapsack-vector[index].weight;
pop[option].chrom.iAlele[index]=1;
vector[index].visited=1;
}
else
{
vector[index].visited=1;
}

return szKnapsack;
}
/* Fim da função para verificar o peso da mochila */

/*******************************************************************/
/* Função para gerar a população inicial */
/* Deverá ser implementada pelo usuário */
/*******************************************************************/
void initialPopulation(tpIndivid *pop)
{
int i=0, x, y, z, w, index=-1,
better, larger, vtVisited[sizeVector], option=0, indexLarger=-1, indexVar=-1, vtIndex[6],cabe;
float earnForWeight,szKnapsack,teste;
tpIndivid *pChildren;

szKnapsack=sizeKnapsack;

51
while(option<SIZE_POP)
{
szKnapsack=sizeKnapsack;
i=0;x=0;
for(i=0;i<=(sizeVector-1);i++)
{
pop[option].chrom.iAlele[i]=0;
vector[i].visited=0;
vtVisited[i]=0;
}

if (option==0)
{
while((x<=(sizeVector-1))&&(szKnapsack!=0))
{
better=0;
index=-1;
for(i=0;i<=(sizeVector-1);i++)
{
if((vector[i].visited)!=1)
{
if(vector[i].earn > better)
{
better=vector[i].earn;
index=i;
}
}
}
szKnapsack=verifyWeight(index, szKnapsack, pop, option);
x++;
}
for(i=0;i<=(sizeVector-1);i++)
{
pChildren=pop+option;
}

calcObj(pChildren);
}
if (option==1)
{
while((x<=(sizeVector-1))&&(szKnapsack!=0))
{
better=sizeKnapsack;
index=-1;
for(i=0;i<=(sizeVector-1);i++)
{
if((vector[i].visited)!=1)
{
if(vector[i].weight < better)
{
better=vector[i].weight;
index=i;
}
}
}
szKnapsack=verifyWeight(index, szKnapsack, pop, option);
x++;
}
for(i=0;i<=(sizeVector-1);i++)

52
{
pChildren=pop+option;
}

calcObj(pChildren);
}
if (option==2)
{
while((x<=(sizeVector-1))&&(szKnapsack!=0))
{
better=0;
index=-1;
for(i=0;i<=(sizeVector-1);i++)
{
if((vector[i].visited)!=1)
{

earnForWeight=(vector[i].earn/vector[i].weight);
if(earnForWeight > better)
{
better=earnForWeight;
index=i;
}
}
}
szKnapsack=verifyWeight(index, szKnapsack, pop, option);
x++;
}
for(i=0;i<=(sizeVector-1);i++)
{
pChildren=pop+option;
}

calcObj(pChildren);
}
if(option>=3)
{
while((x<=(sizeVector-1))&&(szKnapsack!=0))
{

for(z=0;z<6;z++)
{
larger=0;
for(i=0;i<=(sizeVector-1);i++)
{
if(vtVisited[i]!=1)
{
if(vector[i].earn > larger)
{
larger=vector[i].earn;
index=i;
}
}
}
vtVisited[index]=1;
vtIndex[z]=index;
}

indexVar=(rand()%6);
indexLarger=vtIndex[indexVar];

53
szKnapsack=verifyWeight(indexLarger, szKnapsack, pop, option);
for(y=0;y<6;y++)
{
w=vtIndex[y];
if(w!=indexLarger)
{
vtVisited[w]=0;
}
}
x++;
}
for(i=0;i<=(sizeVector-1);i++)
{
pChildren=pop+option;
}

calcObj(pChildren);
}
option++;
}
}

/*******************************************************************/
/* Fim da função para gerar a população inicial */
/*******************************************************************/

/***************************************************************************
* Título: SELEÇÃO - ROLETA
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Implementação da política de seleção ROLETA na sua forma
* tradicional.Os valores das funções objetivo dos indivíduos são
* utilizados como setores de uma roleta, em seguida a roleta é
* girada para que os indivíduos sejam selecionados.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* * pSelected - vector que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através de * pSelected
***************************************************************************/
#define NORM 10000 /* Normalizador para geração do fitness - Roleta */
void selection(tpIndivid *pop, int *pSelected)
{
int indexIndiv, /* Identificador do indivíduo da população*/
indexNewFather; /* Índice que referencia os indivíduos
selecionados (novos pais)*/
long int lRandom; /* Armazena o número randômico gerado */
float vtFitness[SIZE_POP], /* vetor para armazenamento do fitness */
fAddFitness = 0, /* Armazena o somatório do fitness dos indivíduos
*/
iTurn = 0; /* Controla o giro da roleta */

54
tpObj betterObj; /* Armazena o melhor valor de função objetivo */

/* Identificação do maior valor entre as funções objetivo para cálculo


do fitness */
betterObj=pop[0].obj;
for(indexIndiv=1; indexIndiv<SIZE_POP; indexIndiv++)
{
if(pop[indexIndiv].obj > betterObj)
{
betterObj=pop[indexIndiv].obj;
}
}

/* Cálculo e somatório do fitness */


for(indexIndiv=0; indexIndiv<SIZE_POP; indexIndiv++)
{
vtFitness[indexIndiv]=(pop[indexIndiv].obj * NORM) / betterObj ;
fAddFitness=fAddFitness+vtFitness[indexIndiv];
}

/* Seleção dos indivíduos de acordo com o número de pais a serem


selecionados */
for(indexNewFather=0; indexNewFather<TOT_SELECT; indexNewFather++)
{
/* Giro da roleta */
indexIndiv=0;
iTurn=vtFitness[indexIndiv];
lRandom=(( rand( )*rand( )) % (long int)fAddFitness);
while(iTurn < lRandom)
{
indexIndiv++;
iTurn=iTurn+vtFitness[indexIndiv];
}/* while */

/* Atribuição da identificação do indivíduo selecinado a estrutura


que será acessada pela função chamadora*/
pSelected[indexNewFather]=indexIndiv;
}/* for */
}
/***************************************************************************
*FIM: ROLETA
***************************************************************************/

/*******************************************************************/
/* Função para gerar o cruzamento */
/* Deverá ser implementada pelo usuário */
/*******************************************************************/
void crossover(tpIndivid *pop, int *selected, tpIndivid *children)
{
int i=0, j, x, cutPoint, vtAux[sizeVector/2], index=1;

cutPoint=sizeVector/2;

for(i=0;i<TOT_CHILDREN;i++)
{
for(j=0;j<sizeVector;j++)

55
{
children[i].chrom.iAlele[j]=pop[selected[i]].chrom.iAlele[j];
}
children[i].obj=pop[selected[i]].obj;
}
i=0;
for(x=0;x<cutPoint;x++)
{
vtAux[x]=children[i].chrom.iAlele[x];
children[i].chrom.iAlele[x]=children[index].chrom.iAlele[x];
children[index].chrom.iAlele[x]=vtAux[x];
}

}
/*******************************************************************/
/* Fim da função para gerar o cruzamento */
/*******************************************************************/

/*******************************************************************/
/* Função para fazer a cópia de cromossomos */
/* Deverá ser implementada pelo usuário */
/*******************************************************************/
void copyChrom(tpChromossome *pDestin, tpChromossome *pOrigin)
{
int indexAlele;

for(indexAlele=0;indexAlele<sizeVector;indexAlele++)
{
(*pDestin).iAlele[indexAlele]=(*pOrigin).iAlele[indexAlele];
}
}
/*******************************************************************/
/* Fim da função para fazer a cópia de cromossomos */
/*******************************************************************/

/*******************************************************************/
/* Função para manter os pais na próxima geração */
/* Não necessita de alteração do usuário */
/*******************************************************************/
void keepFather(tpIndivid *pop, int *selected, tpIndivid *children)
{
int indexChild, /* Identificação do filho na estrutura de filhos gerada pelo cruzamento */
indexFather, /* Identificação do pai na estrutura de pais gerada pela seleção */
indexBetter; /* Identificação do melhor indivíduo em um conjunto */
tpObj betterObj,/* melhor valor de função objetivo dentre um grupo de indivíduos */
prevObj; /* melhor valor de função objetivo computada anteriormente para um grupo
de indivíduos */

prevObj = INFINITO;
/* Loop controlado pelo número de filhos que serão, na verdade, preenchidos pelos melhores pais */
for(indexChild=0;indexChild<TOT_CHILDREN;indexChild++)
{
betterObj = OBJ_VAL_INI;

56
/* Loop controlado pelo número de indivíduos anteriormente selecionados */
for(indexFather=0;indexFather<TOT_SELECT;indexFather++)
{
/* Comparações para encontrar o melhor pai dos ainda não selecionados
(piores do que prevObj)*/
if(best(pop[selected[indexFather]].obj, betterObj))
{
if(best(prevObj, pop[selected[indexFather]].obj)/*== prevObj*/ )
{
betterObj=pop[selected[indexFather]].obj;
indexBetter=selected[indexFather];
}
}
}
prevObj=betterObj;

children[indexChild].obj=betterObj;
/* Loop para copiar o cromossomo da estrutura do pai para o filho */

copyChrom(&children[indexChild].chrom, &pop[indexBetter].chrom);

/* Se o número de filhos for maior do que o de pais o processo reinicia copiando o melhor pai
*/
if(indexChild == indexFather - 1)
{
prevObj=INFINITO;
}
}
}
/*******************************************************************/
/* Fim da função para manter os pais */
/*******************************************************************/

/*******************************************************************/
/* Função para gerar a mutação */
/* Deverá ser implementada pelo usuário */
/*******************************************************************/
void mutation(tpChromossome *chromChild)
{
int indexMutation;
indexMutation=rand( ) % sizeVector;

if((*chromChild).iAlele[indexMutation] == 0)
{
(*chromChild).iAlele[indexMutation]=1;
}
else
{
(*chromChild).iAlele[indexMutation]=0;
}
}
/*******************************************************************/
/* Fim da função de mutação */
/*******************************************************************/

57
/*******************************************************************/
/* Função para calcular a função objetivo */
/* Deverá ser implementada pelo usuário */
/*******************************************************************/
void calcObj(tpIndivid *pChildren)
{
int i, y;
float functionValue=0;
(*pChildren).obj=0;

for(y=0;y<=(sizeVector-1);y++)
{
if((*pChildren).chrom.iAlele[y]==1)
{
functionValue=functionValue+vector[y].earn;
}
}

(*pChildren).obj=functionValue;
}
/*******************************************************************/
/* Fim da função de cálculo da função objetivo */
/*******************************************************************/

/*******************************************************************/
/* Função para atualizar a população */
/* Deverá ser implementada pelo usuário */
/*******************************************************************/
void updatePop(tpIndivid *newPop, tpIndivid *pChildren, int *index)
{
int i;

for(i=0;i<TOT_CHILDREN;i++)
{
newPop[*index]=pChildren[i];
*index=*index+1;
}
}
/*******************************************************************/
/* Fim da função para atualizar a população */
/*******************************************************************/

/*******************************************************************/
/* Função para separar a melhor solução encontrada para o problema */
/* Deverá ser implementada pelo usuário */
/*******************************************************************/
void bestSolut(tpIndivid *pChildren, tpIndivid *bestIndivid)
{
if(best((*pChildren).obj, (*bestIndivid).obj))
{
(*bestIndivid).obj=(*pChildren).obj; /* Copiar o cromossomo da estrutura do filho para a estrutura melhor
cromossomo */
copyChrom(&bestIndivid[0].chrom, &pChildren[0].chrom);
}
}
/*************************************************************************/
/* Fim da função para separar a melhor solução encontrada para o problema */
/*************************************************************************/

58
/* Função para verificar se os filhos cabem na mochila */
void verifyChildren(tpChromossome *pChildren)
{
int x, j, indexSmall, ok=0, indexBig;
float totWeight, smallEFW, earnWeight,bigEFW=0,smallWeight=INFINITO;

totWeight=0;
for(x=0;x<sizeVector;x++)
{
if((*pChildren).iAlele[x] == 1)
{
totWeight=totWeight+vector[x].weight;
}
}

if(totWeight > sizeKnapsack)


{
while(ok==0)
{
totWeight=0;
smallEFW=INFINITO;
for(x=0;x<sizeVector;x++)
{
if((*pChildren).iAlele[x] == 1)
{
totWeight=totWeight+vector[x].weight;
earnWeight=vector[x].earn/vector[x].weight;
if(earnWeight < smallEFW)
{
smallEFW=earnWeight;
indexSmall=x;
}
}
}

if(totWeight > sizeKnapsack)


{
(*pChildren).iAlele[indexSmall]=0;
}
else
{
ok=1;
}
}
}
else
{
while(ok==0)
{
totWeight=0;
bigEFW=0;
for(x=0;x<sizeVector;x++)
{
if((*pChildren).iAlele[x] == 1)
{
totWeight=totWeight+vector[x].weight;
}
}
for(x=0;x<sizeVector;x++)

59
{
if((*pChildren).iAlele[x] == 0)
{
earnWeight=vector[x].earn/vector[x].weight;
if(earnWeight > bigEFW)
{
bigEFW=earnWeight;
indexBig=x;
}
}
}
totWeight=totWeight+vector[indexBig].weight;
if(totWeight <= sizeKnapsack)
{
(*pChildren).iAlele[indexBig]=1;
}
else
{
totWeight=totWeight-vector[indexBig].weight;
while (ok==0)
{
for(x=0;x<sizeVector;x++)
{
if((*pChildren).iAlele[x] == 0)
{
if ( vector[x].weight < smallWeight )
{
smallWeight = vector[x].weight;
indexSmall = x;
}
}
}
totWeight=totWeight+vector[indexSmall].weight;
if (totWeight < sizeKnapsack)
{
(*pChildren).iAlele[indexSmall]=1;
}
else
{
ok=1;
}
}
}
}
}
}
/* Fim da função para verificar se os filhos cabem na mochila */

/*******************************************************************/
/* Função que implementa a evolução da população */
/* Poderão ser usadas outras políticas já implementadas no modelo */
/*******************************************************************/
void populationEvolution(tpIndivid **teste, tpIndivid *bestIndivid, tpIndivid *pChildren)
{
int i, j, x, up, index=0, iCreat, /* Controle do loop de criação de indivíduos */
iProb; /* Número randômico gerado para
checagem das probabilidades*/
int selected[TOT_SELECT]; /* vetor com a identificação dos indivíduos selecionados */

60
tpIndivid *newPop;
tpIndivid *pop;

newPop = (tpIndivid*) malloc (100 * sizeof(tpIndivid));


pop=*teste;

for(iCreat = 0; iCreat < SIZE_POP/2; iCreat++)


{
/* Aloca a estrutura que armazenará os indivíduos selecionados */
selection ( pop, selected );
/* Aloca a estrutura que armazenará os filhos provenientes do cruzamento */
/* Cruzamento e sua probabilidade */
iProb=rand( ) % 100;
if((PROB_CROSS * 100) >= iProb) /*Verifica se o cruzamento deve ser efetuado*/
{
crossover(pop, selected, pChildren);
}
else
{
/* Esta função fará com que os pais sejam mantidos para a próxima geração */
keepFather(pop, selected, pChildren);
}

/* Mutação e sua probabilidade */

for(x=0;x<TOT_CHILDREN;x++)
{
iProb=rand( ) % 100;

if((PROB_MUTAT * 100) >= iProb) /*Verifica se a mutação deve ser efetuada*/


{
mutation(&pChildren[x].chrom);
}
}

for(x=0;x<TOT_CHILDREN;x++)/*Verifica se os filhos cabem na Mochila*/


{
verifyChildren(&pChildren[x].chrom);
calcObj(&pChildren[x]); /*Calcula o valor da função objetivo*/
bestSolut(&pChildren[x], bestIndivid); /*Atualiza a melhor solução*/
}

updatePop(newPop, pChildren, &index); /*Atualiza a população*/

/* Desaloca as estruturas utilizadas*/


}

free(pop);
*teste=newPop;
}
/*******************************************************************/
/* Fim da função de evolução da população */
/*******************************************************************/

61
/*******************************************************************/
/* Função que define o critério de parada do AG */
/* Poderão ser usadas outras políticas já implementadas no modelo */
/*******************************************************************/
void stopCriterion ( tpIndivid *pop, tpIndivid *bestIndivid, tpIndivid *pChildren )
{
int iGenerat, /* Identificador da geração */
iBestObj; /* Identificador da MAIOR Função Objetivo*/
float bestObj; /* MAIOR Função Objetivo*/
int i,j;
iGenerat=0;
iBestObj=0;
bestObj=0;

while(iGenerat < MAX_GEN) /*Controla o número total de gerações*/


{
if (((*bestIndivid).obj) > bestObj)
{
bestObj=(*bestIndivid).obj;
iBestObj=iGenerat;
}
populationEvolution(&pop, bestIndivid, pChildren);
iGenerat++;
}
printf("\n\nMelhor Individuo: %4.3f === Geracao: %d", bestObj, iBestObj );
getch();
}
/*******************************************************************/
/* Fim da função que define o critério de parada do AG */
/*******************************************************************/

/*******************************************************************/
/* Programa Principal */
/* */
/*******************************************************************/
main( )
{
FILE *pa;
char nameFile[20];
tpIndivid bestIndivid;/* melhor indivíduo */
tpIndivid *pop; /* Estrutura que armazena os indivíduos da população */
tpIndivid children[TOT_CHILDREN];
int i,j;
float earn, weight;

bestIndivid.obj = OBJ_VAL_INI;
pop = (tpIndivid*) malloc (100 * sizeof(tpIndivid));
srand(time(NULL)); /* Gerar uma semente aleatória */

bestIndivid.chrom.iAlele = (int *) malloc (sizeVector * sizeof (int));

for ( i=0; i<SIZE_POP; i++ )


{
pop[i].chrom.iAlele = NULL;

pop[i].chrom.iAlele = (int *) malloc (sizeVector * sizeof (int));

62
if (!pop[i].chrom.iAlele)
{
printf ("\nErro na alocação");
}
}

for ( i=0; i<TOT_CHILDREN; i++ )


{
children[i].chrom.iAlele=NULL;
children[i].chrom.iAlele = (int *) malloc (sizeVector * sizeof (int));
if (!children[i].chrom.iAlele)
{
printf ("\nErro na alocação");
}
}

printf("Entre com o nome do arquivo: ");


scanf("%s", nameFile);

if((pa = fopen(nameFile, "r")) == NULL)


{
printf("\nNao foi possivel abrir o arquivo!!!");
getch();
}
else
{
for(i=0;i<sizeVector;i++)
{
fscanf(pa,"%f %f", &earn, &weight);
vector[i].earn=earn;
vector[i].weight=weight;
}
initialPopulation( pop );/* Função que gera a população inicial */
stopCriterion(pop, &bestIndivid, children);
}

fclose(pa);
}
/*******************************************************************/
/* Fim do programa principal */
/*******************************************************************/

63
ANEXO II: Política de Seleção Torneio

/***************************************************************************
* Título: SELEÇÃO - TORNEIO - Variação: ALEATÓRIO
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Nesta função um subconjunto de indivíduos é escolhido de forma
* aleatória, contudo somente o indivíduo com maior valor para
* a função de adequação será selecionado.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através da variável pSelected
***************************************************************************/
void selection( tpIndivid *pop, int* pSelected )
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather, /* Índice que referencia os indivíduos selecionados (novos pais)*/
iCompetitor, /* Índice que referencia os competidores sorteados*/
iBetterIndiv; /* Melhor indivíduo do subconjunto sorteado */
tpObj betterObj; /* Armazena o melhor valor de função objetivo */

/* Seleção dos indivíduos de acordo com o número de pais a serem


selecionados */
for ( idNewFather = 0; idNewFather < TOT_SELECT; idNewFather++ )
{
/* Sorteio de um competidor e definição inicial do mesmo como o melhor */
idIndiv = rand( ) % SIZE_POP;
betterObj = pop[idIndiv].obj;
iBetterIndiv = idIndiv;

/* Sorteio dos demais competidores e execução das comparações (torneio) */


for ( iCompetitor = 1; iCompetitor < TOT_COMPETIT; iCompetitor++ )
{
idIndiv = rand( ) % SIZE_POP;
if ( pop[idIndiv].obj > betterObj )
{
betterObj = pop[idIndiv].obj;
iBetterIndiv = idIndiv;
}
}
/* Atribuição de um novo indivíuo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = iBetterIndiv;
}
}
/***************************************************************************
*Fim: TORNEIO - Variação: ALEATÓRIO
***************************************************************************/

64
ANEXO III: Política de Seleção Torneio Estocástico

/***************************************************************************
* Título: SELEÇÃO - TORNEIO - Variação: ROLETA
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Nesta função um subconjunto de indivíduos é escolhido utilizando
* o método da roleta, contudo somente o indivíduo com maior valor
* para a função de adequação será selecionado.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* * pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através de * pSelected
***************************************************************************/
#define NORM 10000 /* Normalizador para geração do fitness - Roleta */
void roletaTorn( tpIndivid *pop, int iTotCompetit, int* pSelected );
void selection( tpIndivid *pop, int* pSelected )
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather, /* Índice que referencia os indivíduos selecionados (novos pais)*/
iBetterIndiv, /* Melhor indivíduo do subconjunto sorteado */
iCompetitor; /* Índice que referencia os competidores sorteados*/
int* pSelectedRoulette; /* Vetor que armazenará os indivíduos selecionados pela roleta*/
tpObj betterObj; /* Armazena o melhor valor de função objetivo */

/* Estrutura de dados que irá receber os competidores selecionados pela roleta */


pSelectedRoulette = malloc( TOT_COMPETIT * sizeof( int ) );

/* Repetição a ser feita um número de vezes igual a quantidade de indivíduos


a serem selecionados pela função */
for ( idNewFather = 0; idNewFather < TOT_SELECT; idNewFather++ )
{
/* Chamada a função roleta para seleção dos competidores do torneio*/
roletaTorn( pop, TOT_COMPETIT, pSelectedRoulette );

/* Escolha do melhor indivíduo dada sua função objetivo */


idIndiv = pSelectedRoulette[0];
betterObj = pop[idIndiv].obj;
iBetterIndiv = idIndiv;
for ( iCompetitor = 1; iCompetitor < TOT_COMPETIT; iCompetitor++ )
{
idIndiv = pSelectedRoulette[iCompetitor];
if ( pop[idIndiv].obj > betterObj )
{
betterObj = pop[idIndiv].obj;
iBetterIndiv = idIndiv;
} /* if */
}/* for */
/* Atribuição de um novo indivíuo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = iBetterIndiv;
}/* for */

65
free( pSelectedRoulette );
}
/***************************************************************************
* ROLETA chamada pela função TORNEIO - Variação: ROLETA
***************************************************************************/
void roletaTorn( tpIndivid *pop, int iTotCompetit, int* pSelected )
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather; /* Índice que referencia os indivíduos selecionados (novos pais)*/
long int lRandom; /* Armazena o número randômico gerado */
float vtFitness[SIZE_POP], /* Vetor para armazenamento do fitness */
fAddFitness = 0,/* Armazena o somatório do fitness dos indivíduos */
iTurn = 0;/* Controla o giro da roleta */
tpObj betterObj; /* Armazena o melhor valor de função objetivo */

/* Identificação do maior valor entre as funções objetivo para cálculo do


fitness */
betterObj = pop[0].obj;
for ( idIndiv = 1; idIndiv < SIZE_POP; idIndiv++ )
{
if ( pop[idIndiv] .obj> betterObj )
{
betterObj = pop[idIndiv].obj;
}
}

/* Cálculo e somatório do fitness */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
vtFitness[idIndiv] = ( pop[idIndiv].obj * NORM ) / betterObj ;
fAddFitness = fAddFitness + vtFitness[idIndiv];
}

/* Seleção dos indivíduos de acordo com o número de pais a serem


selecionados */
for ( idNewFather = 0; idNewFather < iTotCompetit; idNewFather++ )
{
/* Giro da roleta */
idIndiv = 0;
iTurn = vtFitness[idIndiv];
lRandom = ( ( rand( ) * rand( ) ) % ( long int )fAddFitness );
while ( iTurn < lRandom )
{
idIndiv++;
iTurn = iTurn + vtFitness[idIndiv];
}
/* Atribuição de um novo indivíuo selecionado como pai à estrutura que
será retornada */
pSelected[idNewFather] = idIndiv;
}
}
/***************************************************************************
*Fim: TORNEIO - Variação: ROLETA
***************************************************************************/

66
ANEXO IV: Política de Seleção Aleatória

/***************************************************************************
* Título: SELEÇÃO - ALEATÓRIA
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Nesta função um conjunto de indivíduos é selecionado de forma
* aleatória.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através da variável pSelected
***************************************************************************/
void selection(tpIndivid *pop, int *pSelected)
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather, /* Índice que referencia os indivíduos selecionados (novos pais)*/
vet[SIZE_POP],
i;

/* Seleção dos indivíduos de acordo com o número de pais a serem


selecionados */
for ( i = 0; i < SIZE_POP; i++)
{
vet[i]=i;
}

for ( idNewFather = 0; idNewFather < TOT_SELECT; idNewFather++ )


{
/* Atribuição de um novo indivíduo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = rand( ) % SIZE_POP;
}

}
/***************************************************************************
*Fim: ALEATÓRIA
***************************************************************************/

67
ANEXO V: Política de Seleção Determinística

/***************************************************************************
* Título: SELEÇÃO - DETERMINÍSTICA
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Uma população auxiliar será gerada com o número de cópias que um
* indivíduo tiver direito. Esse número será calculado através da
* divisão do valor da função objetivo do indivíduo pela média das
* funções objetivo dos demais indivíduos (fi/fmed).
* As vagas não preenchidas pelo cálculo anterior, serão preenchidas
* pelos indivíduos que tiverem como resultado da divisão as melhores
* partes fracionárias.
* Uma vez completada a população, uma seleção aleatória será feita
* para encontrar um novo pai que fará parte do próximo cruzamento.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através da variável pSelected
***************************************************************************/
void selection(tpIndivid *pop, int *pSelected)
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather, /* Índice que referencia os indivíduos selecionados (novos pais)*/
iIndivFracBttr, /* Indivíduo de melhor parte fracionária */
iPosition = 0, /* Posição que será ocupada pelo indivíduo na população auxiliar */
iTotCopies = 0, /* Total de cópias que um indivíduo tem direito na população auxiliar */
iCopy; /* Variável para controle de iterações de loops */
int vtPopAux[SIZE_POP]; /* Vetor que armazena a população auxiliar */
float fFracBetter, /* Melhor parte fracionária entre os indivíduos */
fFracCurrent, /* Valor fracionário do indivíduo atual */
fFracPrevious = 0.999999,/* Último valor de parte fracionária já escolhido */
fAddObj = 0, /* Soma de todos os valores das funções objetivo */
fAverageObj; /* Média dos valores das funções objetivo dos indivíduos da população */

/* Cálculo da média dos valores das funções objetivo dos indivíduos */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
fAddObj = fAddObj + pop[idIndiv].obj;
}
fAverageObj = fAddObj / SIZE_POP;

/* Inclusão das cópias dos indivíduos na população auxiliar */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
iTotCopies = ( int )( pop[idIndiv].obj / fAverageObj );
if ( iTotCopies >= 1 )
{
for ( iCopy = 1; iCopy <= iTotCopies; iCopy++ )
{
vtPopAux[iPosition] = idIndiv;

68
iPosition++;
}
}
}
/* Preenchimento das posições ainda vazias da população auxiliar com os
indivíduos de melhor parte fracionária.*/
fFracPrevious = 0.999999;
fFracBetter=0.000000;

for ( iCopy = iPosition; iCopy < SIZE_POP; iCopy++ )


{
for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
fFracCurrent = ( pop[idIndiv].obj/fAverageObj ) - ( int )( pop[idIndiv].obj/fAverageObj );
if ( ( fFracCurrent > fFracBetter ) && ( fFracCurrent < fFracPrevious ) )
{
fFracBetter = fFracCurrent;
iIndivFracBttr = idIndiv;
}
}
/* Indivíduo de melhor valor na parte fracionária é atribuído a
próxima posição vazia da população auxiliar */
vtPopAux[iPosition] = iIndivFracBttr;
iPosition++;
fFracPrevious = fFracBetter;
}

/* Seleção aleatória de um indivíduo da população temporária */


for ( idNewFather = 0; idNewFather < TOT_SELECT; idNewFather++ )
{
/* Atribuição de um novo indivíuo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = vtPopAux[rand( ) % SIZE_POP];
}
}
/***************************************************************************
*Fim: DETERMINÍSTICA
***************************************************************************/

69
ANEXO VI: Política de Seleção Estocástica por Resto sem Reposição

/***************************************************************************
* Título: SELEÇÃO - ESTOCÁSTICA POR RESTO SEM REPOSIÇÃO
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Uma população auxiliar será gerada com o número de cópias que um
* indivíduo tiver direito. Esse número será calculado através da
* divisão do valor da função objetivo do indivíduo pela média das
* funções objetivo dos demais indivíduos (fi/fmed).
* As vagas não preenchidas pelo cálculo anterior, serão preenchidas
* mediante uma escolha aleatória de um indivíduo, que terá sua parte
* fracionária usada como porcentagem de possibilidade para poder
* compor a população auxiliar.
* Uma vez completada a população, uma seleção aleatória será feita
* para encontrar um novo pai que fará parte do próximo cruzamento.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através da variável pSelected
***************************************************************************/
void selection(tpIndivid *pop, int *pSelected)
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather, /* Índice que referencia os indivíduos selecionados (novos pais)*/
iPosition = 0,/* Posição que será ocupada pelo indivíduo na população auxiliar */
iTotCopies = 0,/* Total de cópias que um indivíduo tem direito na população auxiliar */
iCopy, /* Variável para controle de iterações de loops */
iDraw, /* Sorteio aleatório para comparação com a probabilidade de seleção do indivíduo*/
vtPopAux[SIZE_POP]; /* Vetor que armazena a população auxiliar */
float fFracCurrent, /* Valor fracionário do indivíduo atual */
fAddObj = 0,/* Soma de todos os valores das funções objetivo */
fAverageObj; /* Média dos valores das funções objetivo dos indivíduos da população */

/* Cálculo da média dos valores das funções objetivo dos indivíduos */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
fAddObj = fAddObj + pop[idIndiv].obj;
}
fAverageObj = fAddObj / SIZE_POP;

/* Inclusão das cópias dos indivíduos na população auxiliar */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
iTotCopies = ( int )( pop[idIndiv].obj / fAverageObj );
if ( iTotCopies >= 1 )
{
for ( iCopy = 1; iCopy <= iTotCopies; iCopy++ )
{
vtPopAux[iPosition] = idIndiv;
iPosition++;
}

70
}
}

/* Preenchimento das posições ainda vazias da população utilizando a parte


fracionária, da espectativa de cópias de um indivíduo, como percentual
de probabilidadede de seleção para o mesmo. */
for ( iCopy = iPosition; iCopy < SIZE_POP; )
{
idIndiv = rand( ) % SIZE_POP;
fFracCurrent = ( pop[idIndiv].obj/fAverageObj ) - ( int )( pop[idIndiv].obj/fAverageObj );
iDraw = rand( ) % 99;
if ( ( int )( fFracCurrent * 100 ) >= ( iDraw ) )
{
vtPopAux[iPosition] = idIndiv;
iPosition++;
iCopy++;
}
else
{
iCopy--;
}
}

/* Seleção aleatória de um indivíduo da população temporária */


for ( idNewFather = 0; idNewFather < TOT_SELECT; idNewFather++ )
{
/* Atribuição de um novo indivíuo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = vtPopAux[rand( ) % SIZE_POP];
}
}
/***************************************************************************
*Fim: ESTOCÁSTICA POR RESTO SEM REPOSIÇÃO
***************************************************************************/

71
ANEXO VII: Política de Seleção Estocástica por Resto com Reposição

/***************************************************************************
* Título: SELEÇÃO - ESTOCÁSTICA POR RESTO COM REPOSIÇÃO
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Uma população auxiliar será gerada com o número de cópias que um
* indivíduo tiver direito. Esse número será calculado através da
* divisão do valor da função objetivo do indivíduo pela média das
* funções objetivo dos demais indivíduos (fi/fmed).
* As vagas não preenchidas pelo cálculo anterior, serão preenchidas
* utilizando o método da roleta. As partes fracionárias, dos cálculos
* das expectativas de cópias dos indivíduos, serão utilizadas como
* valores para os setores de uma roleta. A seleção por roleta será
* executada até que as vagas da população temporária sejam completadas.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através da variável pSelected
***************************************************************************/
#define NORM 10000 /* Normalizador para geração do fitness - Roleta */
void roletaEprr( tpIndivid *pop, int iTotCompetit, int* pSelected );
void selection ( tpIndivid *pop, int* pSelected )
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather = 0,/* Índice que referencia os indivíduos selecionados (novos pais)*/
iPosition = 0,/* Posição que será ocupada pelo indivíduo na população auxiliar */
iTotCopies = 0,/* Total de cópias que um indivíduo tem direito na população auxiliar */
iCopy, /* Variável para controle de iterações de loops */
iTotSelectRou, /* Total de indivíduos a ser selecionado pelo método da roleta */
vtPopAux[SIZE_POP]; /* Vetor que armazena a população auxiliar */
int* pSelectedRoulette; /* Estrutura de dados que recebe o resultado da seleção pelo método da roleta */
float fPopFrac[SIZE_POP], /* População formada pela parte fracionária da espectativa de cópias */
fAddObj = 0,/* Soma de todos os valores das funções objetivo */
fAverageObj; /* Média dos valores das funções objetivo dos indivíduos da população */

/* Cálculo da média dos valores das funções objetivo dos indivíduos */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
fAddObj = fAddObj + pop[idIndiv].obj;
}
fAverageObj = fAddObj / SIZE_POP;

/* Inclusão das cópias dos indivíduos na população auxiliar */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
iTotCopies = ( int )( pop[idIndiv].obj / fAverageObj );
if ( iTotCopies >= 1 )
{
for ( iCopy = 1; iCopy <= iTotCopies; iCopy++ )
{
vtPopAux[iPosition] = idIndiv;

72
iPosition++;
}
}
fPopFrac[idIndiv] = ( pop[idIndiv].obj/fAverageObj ) - ( int )( pop[idIndiv].obj/fAverageObj );
}

/* Preenchimento das posições ainda vazias da população utilizando a parte


fracionária, da espectativa de cópias de um indivíduo, em um algoritmo do
tipo roleta */
iTotSelectRou = SIZE_POP - iPosition;
pSelectedRoulette = malloc( iTotSelectRou * sizeof( int ) );

roletaEprr( pop, iTotSelectRou, pSelectedRoulette );


/* Inclusão dos indivíduos gerados pelo método da roleta na população
temporária */
for ( iCopy = iPosition; iCopy < SIZE_POP; iCopy++ )
{
vtPopAux[iPosition] = pSelectedRoulette[idNewFather];
iPosition++;
idNewFather++;
}

free( pSelectedRoulette );

/* Seleção aleatória de um indivíduo da população temporária */


for ( idNewFather = 0; idNewFather < TOT_SELECT; idNewFather++ )
{
/* Atribuição de um novo indivíuo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = vtPopAux[rand( ) % SIZE_POP];
}
}
/***************************************************************************
* ROLETA chamada pela função ESTOCÁSTICA POR RESTO COM REPOSIÇÃO
***************************************************************************/
void roletaEprr( tpIndivid *pop, int iTotCompetit, int* pSelected )
{
int idIndiv, /* Identificador do indivíduo da população*/
idNewFather; /* Índice que referencia os indivíduos selecionados (novos pais)*/
long int lRandom; /* Armazena o número randomico gerado */
float vtFitness[SIZE_POP], /* Vetor para armazenamento do fitness */
fAddFitness = 0,/* Armazena o somatório do fitness dos indivíduos */
iTurn = 0;/* Controla o giro da roleta */
tpObj betterObj; /* Armazena o melhor valor de função objetivo */

/* Identificação do maior valor entre as funções objetivo para cálculo do


fitness */
betterObj = pop[0].obj;
for ( idIndiv = 1; idIndiv < SIZE_POP; idIndiv++ )
{
if ( pop[idIndiv].obj > betterObj )
{
betterObj = pop[idIndiv].obj;
}
}

/* Cálculo e somatório do fitness */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )

73
{
vtFitness[idIndiv] = ( pop[idIndiv].obj * NORM ) / betterObj ;
fAddFitness = fAddFitness + vtFitness[idIndiv];
}

/* Seleção dos indivíduos de acordo com o número de pais a serem


selecionados */
for ( idNewFather = 0; idNewFather < iTotCompetit; idNewFather++ )
{
/* Giro da roleta */
idIndiv = 0;
iTurn = vtFitness[idIndiv];
lRandom = ( ( rand( ) * rand( ) ) % ( long int )fAddFitness );
while ( iTurn < lRandom )
{
idIndiv++;
iTurn = iTurn + vtFitness[idIndiv];
}
/* Atribuição de um novo indivíuo selecionado como pai à estrutura que
será retornada */
pSelected[idNewFather] = idIndiv;
}

}
/***************************************************************************
*Fim: ESTOCÁSTICA POR RESTO COM REPOSIÇÃO
***************************************************************************/

74
ANEXO VIII: Política de Seleção Estocástica sem Reposição

/***************************************************************************
* Título: SELEÇÃO - SELEÇÃO ESTOCÁSTICA SEM REPOSIÇÃO
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Uma população auxiliar será gerada com o número de cópias que um
* indivíduo tiver direito. Esse número será calculado através da
* divisão do valor da função objetivo do indivíduo pela média das
* funções objetivo dos demais indivíduos (fi/fmed).
* Após este cálculo, o método da roleta será utilizado e a medida que
* os indivíduos forem sendo selecionados para reprodução os números
* de cruzamentos permitidos para estes serão decrementados até que
* cheguem a zero e os indivíduos sejam retirados da roleta.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através da variável pSelected
***************************************************************************/
#define NORM 10000 /* Normalizador para geração do fitness - Roleta */
void selection( tpIndivid *pop, int* pSelected )
{
int idIndiv, /* Identificador do indivíduo da população */
idNewFather, /* Índice que referencia os indivíduos selecionados (novos pais)*/
vtCopy[SIZE_POP]; /* Vetor com o número de cópias de cada indivíduo */
long int lRandom; /* Armazena o número randômico gerado */
float vtFitness[SIZE_POP], /* Vetor para armazenamento do fitness */
fAddFitness = 0,/* Armazena o somatório do fitness dos indivíduos */
iTurn = 0,/* Controla o giro da roleta */
fAddObj = 0,/* Soma de todos os valores das funções objetivo */
fAverageObj; /* Média dos valores das funções objetivo dos indivíduos da população */
tpObj betterObj; /* Armazena o melhor valor de função objetivo */

/* Identificação do maior valor entre as funções objetivo para cálculo do


fitness */
betterObj = 0.000000;
for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
if ( pop[idIndiv].obj > betterObj )
{
betterObj = pop[idIndiv].obj;
}
}

/* Cálculo e somatório do fitness */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
vtFitness[idIndiv] = ( pop[idIndiv].obj * NORM ) / betterObj ;
fAddFitness = fAddFitness + vtFitness[idIndiv];
}

/* Cálculo da média dos valores das funções objetivo dos indivíduos */

75
for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
fAddObj = fAddObj + pop[idIndiv].obj;
}
fAverageObj = fAddObj / SIZE_POP;

/* Cálculo do número de cópias, de direito, dos indivíduos */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
vtCopy[idIndiv] = ceil( pop[idIndiv].obj / fAverageObj );
}

/* Seleção dos indivíduos de acordo com o número de pais a serem


selecionados */
for ( idNewFather = 0; idNewFather < TOT_SELECT; )
{
idIndiv = 0;
iTurn = vtFitness[idIndiv];
lRandom = ( rand( ) * rand( ) ) % ( long int )fAddFitness;
/* Giro da roleta */
while ( iTurn < lRandom )
{
idIndiv++;
iTurn = iTurn + vtFitness[idIndiv];
}
if ( vtCopy[idIndiv] > 0 )
{
/* Atribuição de um novo indivíuo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = idIndiv;

vtCopy[idIndiv]--;
idNewFather++;
}
}
}

/***************************************************************************
*Fim: SELEÇÃO ESTOCÁSTICA SEM REPOSIÇÃO
***************************************************************************/

76
ANEXO IX: Política de Seleção por Ranking

/***************************************************************************
* Título: SELEÇÃO - RANKING
* Versao: 1.0
* Autor: Fábio Duncan de Souza
* Data: 17/12/2005
* Descrição: Inicialmente os indivíduos da população são ordenados de acordo
* com os valores das suas funções de adaptação. Após a ordenação,
* cada indivíduo terá um valor equivalente a sua posição no ranking
* e, um procedimento similar à seleção pelo método da roleta será
* utilizado. Quanto melhor a posição do indivíduo no ranking, maior
* será seu setor na roleta e conseqüentemente maior a sua chance de
* ser selecionado.
*
* Entrada:
* pop - Estrutura que armazena os cromossomos e funções
* objetivos dos indivíduos da população
*
* pSelected - Vetor que será retornado com a identificação dos
* indivíduos selecionados
*
* Saída: a identificação dos indivíduos selecionados é obtida pela função
* chamadora através da variável pSelected
***************************************************************************/
#define NORM 10000 /* Normalizador para geração do fitness - Roleta */
void roletaRank(int* vetRank, int* pSelected );
void selection( tpIndivid *pop, int* pSelected ) // RANKING
{
int idIndiv, /* Identificador do indivíduo da população */
idIndiv2, /* Indivíduo auxiliar para comparação */
vtRank[SIZE_POP]; /* Vetor de ranks */

/* Inicialização do vetor de rank */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
vtRank[idIndiv] = 1;
}

/* Cadastro dos ranks no vetor */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
for ( idIndiv2 = 0; idIndiv2 < SIZE_POP; idIndiv2++ )
{
if ( pop[idIndiv].obj > pop[idIndiv2].obj )
{
vtRank[idIndiv]++;
}
}
}

roletaRank( vtRank, pSelected );


}
/***************************************************************************
* ROLETA chamada pela função RANKING
***************************************************************************/
void roletaRank( int* vetRank, int* pSelected ) // ROLETA ESPECIAL PARA O RANK
{
int idIndiv, /* Identificador do indivíduo da população*/

77
idNewFather; /* Indice que referencia os indivíduos selecionados (novos pais)*/
long int lAddRank = 0,/* Somatório dos ranks */
lRandom; /* Armazena o número randômico gerado */
float iTurn = 0;/* Controla o giro da roleta */

/* Somatório dos ranks */


for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
lAddRank = lAddRank + vetRank[idIndiv];
}

/* Seleção dos indivíduos de acordo com o número de pais a serem


selecionados */
for ( idNewFather = 0; idNewFather < TOT_SELECT; idNewFather++ )
{
idIndiv = 0;
iTurn = vetRank[idIndiv];
lRandom = ( ( rand( ) * rand( ) ) % lAddRank );

/* Giro da roleta */
while ( iTurn < lRandom )
{
idIndiv++;
iTurn = iTurn + vetRank[idIndiv];
}
/* Atribuição de um novo indivíuo selecionado à estrutura que será
retornada */
pSelected[idNewFather] = idIndiv;
}
}
/**************************************************************************
*Fim: RANKING
***************************************************************************/

78

You might also like