package org.myrobotlab.genetic; import java.util.ArrayList; import java.util.Random; /** * Genetic Algorithms implementation * * This implementation of the Genetic algorithms describe on this site http://www.ai-junkie.com/ga/intro/gat1.html * * The principle is simple, you have a bank of chromosomes that contains a serie of bits that can be decoded by your application * Each chromosomes are then check to see how they can solve what you try to intend, and get a score (fitness) to express how good they solves it. * Chromosomes are then picks at random from the pool, with chromosomes weighted by their fitness, then recombine (swap part of their bits serie) * and mutate (changing random bits in their serie) and put into a new pool of chromosome (generation). The algorithm run a number of generation * and try to improve his best fitting chromosome. * * Usage: * implements Genetic interface in the class you want to use the algorithm for the decode (how you convert the serie of bits to your data) * and the calcFitness (give a score to your chromosome) methods * Instanciate GeneticAlgorithm with it's config parameters * populationSize: number of chromosome in the pool * genomeSize: the number of gene in your chromosome (the number of data you want to use) * geneSize: the number of byte you use for each gene (data) * recombinationRate: Is the chance that two chromosomes get mixed together, 0.7 is usually a good start * mutationRate: Is the chance that a giving bit get modified, 0.001 is usually a good start * call doGeneration(number of generation) to get the best fitting chromosome * * The parameters are very empiric. They will influence how quick and precise the chromosome will evolve toward your best solution. * * @author Christian/Calamity * */ public class GeneticAlgorithm { double recombinationRate = 0.7; double mutationRate = 0.001; int populationPoolSize = 100; ArrayList<Chromosome> chromosomes = new ArrayList<Chromosome>(); int geneSize = 8; private Genetic geneticClass; public GeneticAlgorithm(Genetic geneticClass, int populationSize, int genomeSize, int geneSize, double recombinationRate, double mutationRate) { // TODO Auto-generated constructor stub populationPoolSize = populationSize; this.recombinationRate = recombinationRate; this.mutationRate = mutationRate; this.geneSize = geneSize; this.geneticClass = geneticClass; for (int i = 0; i < populationSize; i++) { Chromosome chromo = new Chromosome(genomeSize * geneSize); chromosomes.add(chromo); } } public Chromosome doGeneration(int generation) { //decode the genes //calculate the fitness of the pool Chromosome bestFit=chromosomes.get(0); for (int i = 0; i < generation; i++) { geneticClass.decode(chromosomes); geneticClass.calcFitness(chromosomes); Double totalFitness=0.0; for (Chromosome chromosome : chromosomes) { totalFitness += chromosome.fitness; if (bestFit != null && chromosome.fitness > bestFit.fitness) { bestFit = chromosome; } } if (i != generation-1){ //last iteration, no need to mutate ArrayList<Chromosome> newPool = new ArrayList<Chromosome>(); newPool.add(bestFit); while (newPool.size() < populationPoolSize) { Chromosome c1 = new Chromosome(RandomWheel(chromosomes, totalFitness)); Chromosome c2 = new Chromosome(RandomWheel(chromosomes, totalFitness)); newPool.add(c1.recombine(c2, recombinationRate).mutate(mutationRate)); newPool.add(c2.recombine(c1, recombinationRate).mutate(mutationRate)); } chromosomes = newPool; } } return bestFit; } private Chromosome RandomWheel(ArrayList<Chromosome> chromosomes, Double totalFitness) { // TODO Auto-generated method stub Random rand = new Random(); double randomNumber = rand.nextInt(totalFitness.intValue()); Double fitnessCount = 0.0; for (Chromosome chromosome : chromosomes) { fitnessCount += chromosome.fitness; if (randomNumber < fitnessCount) { return chromosome; } } return null; } public void setGeneticClass(Genetic geneticClass) { // TODO Auto-generated method stub this.geneticClass = geneticClass; } }