Algoritmos Genéticos

Eu fiquei principalmente interessado nessa técnica de Algoritmos Genéticos que é inspirada na biologia evolutiva e usa hereditariedade, mutação, seleção natural e recombinação (crossing over) para achar soluções aproximadas de problemas de otimização e busca. Isso funciona da seguinte forma: os algoritmos genéticos são implementados como uma simulação de computador em que uma população de representações abstratas de solução é selecionada em busca de soluções melhores (fazendo um paralelo com o papel de um indivíduo biológico, ou seja, uma tentativa de solução de problemas de sobrevivência no mundo real). A evolução geralmente se inicia a partir de um conjunto de soluções criado aleatoriamente e é realizada através de gerações. A cada geração, a adaptação de cada solução na população é avaliada, alguns indivíduos são selecionados para a próxima geração de acordo com sua aptidão em resolver o problema proposto, e recombinados ou mutados para formar uma nova população. A nova população então é utilizada como entrada para a próxima iteração do algoritmo. Em outras palavras, um algoritmo genético atua na resolução de um problema da mesma forma que a evolução atua, isto é, através de populações de indivíduos que geram descendentes através de várias gerações e são selecionados naturalmente de acordo com suas características. Explico melhor com um exemplo a seguir.


A solução do problema usando algoritmos genéticos é extremamente elegante, fácil e não nos custa esforço nenhum. Simplesmente nós, os programadores, não resolvemos o problema, mas deixamos a solução evoluir sozinha. Elegante, não? Para esse problema das antenas, fazemos o seguinte. Digamos que queremos alocar 100 freqüências em 500 antenas.


Já dá pra perceber algumas semelhanças com a evolução biológica. Temos uma população com centenas ou milhares de indivíduos, cada um destes com características diferentes. Os genes são as partes do código genético de cada indivíduo. Então, no nosso exemplo, cada indivíduo possui 500 genes, cada um dos quais sendo um par antena-freqüência, por exemplo, um indivíduo pode possuir um gene que seja 324-12, ou seja, ele pode ter na sua antena de número 324 a freqüência 12. A mutação é uma mudança aleatória em um gene, então digamos, se um indivíduo possui um gene dizendo que sua antena de número 324 possui a freqüência 12, o seu filho pode herdar esse gene e, caso ele sofra uma mutação, pode mudar para a freqüência 57, formando o gene 324-57. O cruzamento acontece quando dois indivíduos cruzam entre si para gerar filhos. No nosso caso, pegamos dois indivíduos (dois conjuntos de antenas com freqüências) e geramos um filho (novo conjunto de antenas com freqüências). No caso esse filho recebe metade dos genes do seu pai e metade dos genes da sua mãe. Essa doação de genes á aleatória, contanto que tenha 50% do pai e 50% da mãe.

E a seleção natural? Bem, a partir das regras que o professor deu para calcularmos a interferência entre as antenas dependendo das distâncias entre elas, podemos calcular a aptidão de cada indivíduo. Cada um possui características que o tornam mais apto ou menos apto para sobreviver, se reproduzir e passar seus genes para seus descendentes. No nosso caso a aptidão é a interferência total de um indivíduo. Tendo as regras para calcular a interferência de cada antena, podemos chegar em resultados que mostrem as aptidões dos indivíduos. No nosso exemplo, temos uma população de 3 mil indivíduos, cada um deles tendo um valor de interferência que é causado pelas suas antenas de acordo com as freqüências de cada uma e suas respectivas distâncias com as demais antenas. Lembro-me que a aptidão inicial média da população era um valor muito alto de interferência, ou seja, quando inicializamos as antenas com freqüências aleatórias, fica tudo muito confuso e existe uma interferência altíssima. Percebamos que nesse caso, um valor menor para interferência significa um indivíduo mais apto, ou seja, que possui os melhores genes para sobreviver.
Depois de gerarmos a população inicial (onde cada indivíduo é uma possível solução do problema), começamos a rodar o programa. A cada geração, calculamos a aptidão de cada indivíduo e permitimos que se reproduzam com uma probabilidade maior para aqueles que tiverem uma aptidão melhor. Dessa prole, depois do cruzamento, pegamos um pequeníssimo percentual dos indivíduos e nestes causamos mutações em um pequeníssimo percentual dos seus genes. Daí pegamos a prole inteira, tanto aqueles que sofreram mutações (uns poucos) como aqueles que não sofreram (quase todos) e calculamos a aptidão de cada um deles. Selecionamos um percentual maior daqueles que tem uma melhor aptidão e um pequeno percentual de quem tem aptidão ruim.


Lembro-me que no início a interferência média da população era algo em torno de 2500. Mas ao longo da simulação, víamos um gráfico dessa interferência em cada geração sendo construído e ia decrescendo. Depois de algumas dezenas de milhares de gerações (que bom que os computadores são rápidos), lembro que o melhor resultado que conseguimos foi de interferência 11. Impressionante! Aqueles indivíduos que tinham sido inicializados aleatoriamente, foram sendo cruzados de acordo com suas aptidões e esses cruzamentos seguiram as leis da probabilidade onde aqueles com melhor aptidão tinham mais chances de sobreviver e cruzar. Essa tendência estatística convergiu cada vez mais para uma população com a aptidão melhorada.
E algoritmos genéticos tem sido usados muito para resolver muitos problemas computacionais. Esse tipo de algoritmo é usado por empresas de telecomunicações para determinar a posição ótima de uma rede de torres de telefones celulares, também é usado para melhorar a área de cobertura de satélites, para descobrir novos algoritmos de ordenação, melhores rotas de transporte, etc. É uma infinidade de usos. Já li sobre um satélite da NASA onde os engenheiros não projetaram o satélite, mas ele evoluiu. Eles simplesmente pegaram vários projetos de satélite e jogaram dentro de um algoritmo genético. Daí, o programa pegava os vários projetos, ia misturando eles, cruzando, gerando automaticamente novos projetos que eram uma mistura dos vários projetos iniciais, eles sofriam mutações e depois de muitas gerações de cruzamento, mutação e seleção, surgiram novos projetos inéditos muito melhores. O poder da seleção natural é fantástico.
A ordenação de conjuntos é um problema rotineiro da computação e existem muitos algoritmos famosos para resolver esse problema. Mas com o uso de algoritmos genéticos, são obtidos novos algoritmos de ordenação que os próprios programadores não fazem a menor idéia de como eles funcionam, só sabem que conseguem ordenar conjuntos e de forma excelente. Nada como um mecânismo simples de seleção gradual e cumulativa direcionando as soluções por caminhos cada vez mais adaptados de acordo com as situações locais. O poder da seleção cumulativa é bem explicado no livro "O Relojoeiro Cego" do biólogo Richard Dawkins e ele dedica todo um capítulo para esclarecer esta questão. Ele prova que um macaco batendo aleatoriamente numa máquina de escrever nunca poderia produzir todas as obras de Shakespeare. Mas se for usado o mecânismo da seleção cumulativa e gradual, em um tempo razoável, o tal macaco datilógrafo poderia tornar-se um grande escritor.
0 Comments:
Postar um comentário
<< Home