Professional Documents
Culture Documents
Algoritmos Genéticos Aplicados Ao Problema Da Mochila Binária
Algoritmos Genéticos Aplicados Ao Problema Da Mochila Binária
SOFTWARE
ii
CLAUDIA NASCIMENTO DE BRITO
GRACIANA GOMES SILVA
PHILIPPE LEAL FREIRE DOS SANTOS
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
vi
LISTA DE FIGURAS
vii
SUMÁRIO
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
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
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.
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:
Variável de decisão:
Modelagem Matemática:
n
Maximizar Ø = Σ vixi
i=1
n
Sujeito a Σ pixi ≤ C
i=1
xi ≥ 0 e inteiro, 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.
- di: quantidade máxima de itens tipo i que pode ser selecionada, 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.
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 é 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.
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.
Variável de decisão:
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
18
2.2.8. O Problema de Designação Generalizada
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
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:
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
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:
21
• Lkmax: capacidade máxima (Kg) de cada compartimento associado ao agrupamento Ak
(Lkmim < Lkmax < L);
Variáveis:
• OLvalor
jk = Σdepiutilidade dadoepor:
αijk, k= 1,...,k j = 1,...,Nk
iЄA
k
Nk
Σ αijkβjk≤ di, i= 1,...,m
j=1
k Nk
Σ Σ (Ljk + S) βjk ≤ L
k=1 j=1
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.
De acordo com Pozo (2002), os requisitos para a implementação destes algoritmos são:
24
INÍCIO
População Inicial
Seleção
Cruzamento
Operadores
Genéticos
Mutação
NÃO Critério de
Parada?
SIM
FIM
25
gerações anteriores. Na maior parte dos casos, os AGs utilizam dois operadores: cruzamento e
mutaçã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):
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
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
28
3.1.3.5. Seleção Determinística (Deterministic Sampling - DS)
3.1.3.6. Seleção Estocástica por Resto Sem Reposição (Stochastic Remainder Sampling)
29
3.1.3.8. Seleção Estocástica Sem Reposição
3.1.4. Cruzamento
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
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
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
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
32
3.1.6. Evolução da População
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.
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.
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.
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).
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
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.
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
tó
ki
R
st
R
rn
ol
ís
ea
an
em
m
m
cá
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
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
tó
ki
R
st
R
ol
ís
r
ea
an
em
em
m
R
cá
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
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
tó
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
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
tó
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
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
tó
ki
R
R
R
ol
ís
r
ea
an
em
em
m
R
cá
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
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
2744000
ria
io
ta
g
o
ep
ep
ep
in
tic
tic
ne
e
tó
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
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.
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
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.
LOZANO, M.; MARTÍNEZ, C. G.; MOLINA, D. A Local Genetic Algorithm for Binary-
coded Problems. University of Córdoba, Spain, 2006.
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.
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.
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 */
/********************************************************************/
/*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 */
/******************************************************************/
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 */
/*******************************************************************/
/* 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;
}
}
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;
for(x=0;x<TOT_CHILDREN;x++)
{
iProb=rand( ) % 100;
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;
/*******************************************************************/
/* 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 */
62
if (!pop[i].chrom.iAlele)
{
printf ("\nErro na alocação");
}
}
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 */
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 */
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 */
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;
}
/***************************************************************************
*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 */
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;
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 */
70
}
}
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 */
72
iPosition++;
}
}
fPopFrac[idIndiv] = ( pop[idIndiv].obj/fAverageObj ) - ( int )( pop[idIndiv].obj/fAverageObj );
}
free( pSelectedRoulette );
73
{
vtFitness[idIndiv] = ( pop[idIndiv].obj * NORM ) / betterObj ;
fAddFitness = fAddFitness + vtFitness[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 */
75
for ( idIndiv = 0; idIndiv < SIZE_POP; idIndiv++ )
{
fAddObj = fAddObj + pop[idIndiv].obj;
}
fAverageObj = fAddObj / SIZE_POP;
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 */
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 */
/* 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