Você está na página 1de 19

Computação Evolucionária

Laboratório I - Algoritmos Genéticos

Lucas Gustavo Dias Martins


2014104349

1 Introdução
Este relatório tem como objetivo apresentar os resultado obtidos na implementação da
solução do problema das N-Rainhas utilizando algoritmos evolucionários, especificamente os
algoritmos genéticos. O problema das N-Rainhas consiste em posicionar N rainhas em um
tabuleiro retangular NxN de maneira que nenhuma das rainhas se coloque em xeque.

Figura 1: Ilustração do problemas das N-Rainhas em um tabuleiro 8x8.

Inicialmente foi definido que as possı́veis soluções seriam representadas genotipicamente


em um vetor de dimensão N. O valor de cada posição da k-ésima coluna (posição do vetor)
representa uma rainha posicionada na i-ésima linha, conforme figura abaixo. Com essa
representação o espaço de busca fica restrito às configurações do tabuleiro onde violações
horizontais (duas rainhas na mesma linha) e verticais (duas rainhas na mesma coluna) não
ocorrem.

1
Figura 2: Ilustração da representação genotı́pica do posicionamento das rainhas no tabuleiro.

A abordagem escolhida para solucionar o problema das N-Rainha foi a implementação de


um algoritmo genético. Nesse tipo de abordagem é criado um espaço inicial com candidatos
aleatórios à solução do problema, chamado a partir de agora de população. Verifica-se a
possibilidade de um indivı́duo dessa população inicial já ser a solução do problema; em
caso afirmativo esse indivı́duo é apresentado como solução e o problema está finalizado.
Entretanto, quando nenhum indivı́duo dessa população é solução do problema partimos para
a segunda etapa, na qual utilizamos um função de aptidão para avaliar a qualidade de cada
indivı́duo, isto é, o quão próximo ele é da solução ótima. No nosso caso a função de aptidão
nos diz quantos conflitos (rainhas em xeque) ocorrem em uma dada configuração (genótipo)
do tabuleiro. A condição ótima ocorre quando a função de aptidão vale 0, indicando que
nessa configuração do tabuleiro nenhuma rainha se coloca em xeque.
O próximo passo é escolher aleatoriamente cinco indivı́duos da população e, dentre eles,
escolher os dois melhores para para sofrerem o processo de combinação (crossover ) entre
si. Isso gera dois novos indivı́duos, filhos, que contém partes de cada pai. Esse processo
gera diversidade (ou variação) na população. Dado que não existe nenhuma solução ótima
na população inicial, o processo de crossover é aplicado com probabilidade 1 (100%). Já o
processo de mutação, que pode ocorrer ou não, é o processo onde são escolhidos ao acaso
duas posições dos genes de cada filho para serem trocados de posição. Esse processo ajuda
no refinamento das soluções e ocorre com uma probabilidade de 80%.
Na sequência os filhos gerados são incluı́dos na população inicial e todos são avaliados
pela função de aptidão e, ocorre a partir daı́, o processo de seleção natural no qual os dois
indivı́duos menos aptos são excluı́dos da população. Caso não seja encontrada a solução
ótima, o processo recomeça com a escolha de novos indivı́duos para a próxima geração a
passarem pelo processo de crossover.
Esse processo ocorre até que a solução ótima seja encontrada ou que o número máximo
de gerações (iterações) seja atingido. O número de rainhas, o tamanho inicial da população
e a quantidade máxima de iterações são parâmetros do problema e devem ser informados no
inı́cio do algoritmo evolutivo.

2
Figura 3: Pseudo código utilizado no algoritmo genético das N-Rainhas.

2 Código MatLab
2.1 Parametrização e criação da população inicial

No código acima o número de rainhas (N), o tamanho da população (M) e número máximo
de gerações são informados. Uma matriz MxN de zeros é gerada e na sequência é preenchida
com soluções aleatórias criadas pela função randperm. Essas soluções são avaliadas e essa
informação é armazenada em uma coluna extra na matriz da população, onde a informação
da N+1 coluna é a qualidade da solução. A partir dessa coluna a população é ordenada em
forma crescente de qualidade, lembrando que tão melhor é uma solução quanto mais próximo
de zero for sua avaliação.

3
2.2 Verificação de solução ótima na população inicial

No trecho acima é feita uma verificação inicial, onde é checada a possibilidade de algum
indivı́duo da população já ser solução do problema, interrompendo o algoritmo é informando
qual a solução inicial que já resolve o problema.

2.3 Seleção dos pais e geração dos filhos

Nessa parte ocorre a seleção aleatória de 5 soluções pertencentes à população inicial,


dentre as quais as duas melhores são escolhidas para formar dois novos indivı́duos – filhos.
A aleatoriedade da seleção dos indivı́duos e garantida pela função randperm (M,5), que
retorna cinco valores distintos entre 1 e M – número de indivı́duos da população. Como a
população inicial já se encontra ordenada em forma crescente de qualidade, os dois melhores
indivı́duos são aqueles que possuem os dois menores valores. Ao ordenar a variável random e
pegar seus dois primeiros valores garantimos que as duas soluções escolhidas são as melhores
entre as cinco.
As duas soluções escolhidas são passadas via parâmetro para a função CutAndCross-
fill Crossover que retorna dois novos indivı́duos, que são formados pela combinação dos
pais. A função CutAndCrossfill Crossover foi disponibilizada pelo professor para facilitar a
resolução do problema e encontra-se em anexo no final do relatório.

2.4 Mutação dos filhos


O processo de mutação pode ser definido como uma pertubação aleatória, que pode
ocorrer ou não, e causa uma pequena varição nos novos indivı́duos gerados – os filhos.

4
Como definido na especificação do problema, a mutação pode ocorrer com uma probabi-
lidade 80%. Para isso é gerado um número aleatório entre 0 e 10. Caso o valor seja maior
do que 2, o processo de mutação ocorre. São gerados dois novos números aleatórios entre 1
e N, que representam as posições dos vetores que sofrerão a troca simples entre si, gerando
uma pertubação ao acaso nos filhos que ajuda no processo de refinamento da solução.

2.5 Avaliação da qualidade de uma possı́vel solução

A avaliação da qualidade de uma determinada solução, seja ela um filho ou indivı́duo


da população inicial, é realizada pela função fitness nq, que também foi disponibilizada pelo
professor. Essa função recebe um indivı́duo da população e retorna o número de colisões
entre rainhas (infrações) que ocorrem nessa solução. Se o valor retornado for 0 isso indica
que o indivı́duo é uma solução ótima para o problema.

2.6 Inserção dos filhos na população inicial

Após serem avaliados, os filhos são inseridos na população inicial e passam a ser encarados
como uma solução comum dentre as outras. É realizado um novo ranqueamento entre todos
os indivı́duos da nova população, que passa a ter M+2 possı́veis soluções. O próximo passo
é excluir do espaço de busca os dois piores indivı́duos, retornando o espaço à M indivı́duos.

5
2.7 Evolução do processo de busca
Esse processo de seleção de cinco indivı́duos aleatoriamente na população e, dentre eles,
a escolha dos dois melhores, realização de Crossover para a geração de duas novas possı́veis
soluções, ocorrência – ou não – de mutação, inserção na população inicial e exclusão dos dois
piores candidatos ocorre até que a solução ótima seja encontrada ou que o número máximo
de gerações permitidas seja alcançado.
No primeiro caso é informada qual a solução ótima e em qual geração ela foi encontrada,
conforme demonstrado pelo código acima. Já o trecho abaixo é responsável por informar
que o algoritmo chegou no limite máximo de gerações permitidas e que não existe solução
entre os indivı́duos da população.

6
3 Resultados
Foram realizados testes com o número de rainhas N = 10, 20 e 50 e com valores do
tamanho da população M = N, 2N, 5N, 10N e 100N e número de máximo de gerações
igual à 500N, afim de observar qual a correlação entre esses parâmetros e o convergência do
algoritmo para a solução ótima.
Os resultados encontram-se nos gráficos abaixo, nos quais estão representados a evolução
do fitness (avaliação) médio da população – representado com uma linha vermelha – e o
melhor fitness (avaliação) – representado com pontos azuis – ao longo das gerações.
A partir desses resultados obtidos, graficamente será possı́vel fazer uma análise a respeito
da relação entre o número de rainhas, o tamanho da população, o número de iterações e a
convergência do algoritmo para a solução ótima.

3.1 Resultados para N = 10

Figura 4: Resultado computacional obtido com N = 10, M = 10.

7
Figura 5: Resultado computacional obtido com N = 10, M = 20.

Figura 6: Resultado computacional obtido com N = 10, M = 50.

8
Figura 7: Resultado computacional obtido com N = 10, M = 100.

Figura 8: Resultado computacional obtido com N = 10, M = 1000.

9
3.2 Resultados para N = 20

Figura 9: Resultado computacional obtido com N = 20, M = 20.

Figura 10: Resultado computacional obtido com N = 20, M = 40.

10
Figura 11: Resultado computacional obtido com N = 20, M = 100.

Figura 12: Resultado computacional obtido com N = 20, M = 200.

11
Figura 13: Resultado computacional obtido com N = 20, M = 2000.

3.3 Resultados para N = 50

Figura 14: Resultado computacional obtido com N = 50, M = 50.

12
Figura 15: Resultado computacional obtido com N = 50, M = 100.

Figura 16: Resultado computacional obtido com N = 50, M = 250.

13
Figura 17: Resultado computacional obtido com N = 50, M = 500.

Figura 18: Resultado computacional obtido com N = 50, M = 5000.

14
4 Discussão dos resultados
Ao analisar os resultados obtidos dos gráficos acima podemos gerar uma tabela compa-
rativa entre o número de gerações necessárias para convergência do algoritmo em função do
número de rainhas – N – e da população inicial – M.
HH
M
H N 2N 5N 10N 100N
N HH
H
10 40 85 260 1000 850
20 810 820 200 2800 ∅
50 3600 18000 8200 ∅ ∅

Tabela 1: Tabela comparativa entre o número de gerações necessárias para convergência do


algoritmo.

Percebe-se que o aumento no número de rainhas dificulta a convergência do algoritmo,


uma vez que para todos os casos em que houve convergência ela ocorreu mais rapidamente
onde o número de rainhas era menor. Em outras palavras, em uma mesma coluna o número
de gerações necessárias para convergência é sempre crescente, independentemente da coluna
escolhida para análise.
Isso demonstra claramente que quanto maior o tamanho do tabuleiro mais difı́cil será a
convergência, sendo necessário um número também maior de iterações do algoritmo. Para
o N = 50 o algoritmo não conseguiu encontrar a solução ótima em duas ocasiões, enquanto
para N = 20 isso só ocorreu uma vez e para N = 10 ele a encontrou em todos os casos.
Também é possı́vel dizer que o aumento da população, mantendo o número de rainhas
constante, tende a dificultar a convergência. Isso é observado ao analisarmos as linhas da
tabela acima, que apresentam um crescimento do número de gerações necessárias paralela-
mente ao aumento do tamanho da população, embora ocorra uma exceção na segunda linha
onde o número de iterações diminuiu com o aumento da população de 2N para 5N.
Esse comportamento, aparentemente contraditório, se deve à aleatoriedade presente no
algoritmo. Nesse tipo de algoritmo não há garantia que, se as mesmas condições iniciais
forem fornecidas, os mesmos resultados serão obtidos, sendo mais provável que os resultados
sejam diferentes.
Os algoritmos genéticos são uma ótima ferramenta para buscar soluções num espaço
amplo de candidatos, sendo uma alternativa ao algoritmos de ”força bruta”que em geral não
são aplicáveis nesses casos. Podemos observar nos gráficos que o algoritmo genético refinou
a qualidade das de todas soluções ao longo do tempo, ainda que não encontrasse, em alguns
casos, a solução ótima, devido ao número limitado de iterações.
Essa limitação pode ser demonstrada no caso obtido para N = 50, M = 5000. Quando
o algoritmo estava limitado a 25.000 iterações ele não encontrou nenhuma solução ótima,
entretanto com o número máximo de iterações aumentado para 2.5000.000 ele foi capaz acha-
lá, sendo necessárias 271.338 gerações (22,04 minutos), demonstrando que quanto maior for o
número máximo de iterações permitidas maiores são as chances de se encontrar uma solução
ótima para o problema quando se aplica um algoritmo genético.

15
Figura 19: Resultado computacional obtido com N = 50, M = 5000, e o número máximo de
gerações de 2.500.000 e dados da execução do algoritmo.

16
Anexos

Figura 20: Códigos das funções fitness nq e CutAndCrossfill Crossover.

17
18
Figura 21: Código desenvolvido para a resolução do problema das N-Rainhas na ı́ntegra.

19

Você também pode gostar