monsterbasher
monsterbasher

Reputation: 65

Fitness for a genetic algorithm refuses to budge

I'm making a genetic algorithm to evolve chars into "Hello World",but when I execute the program it crosses over once and stays the same for the remainder of the run. I know for certain my crossOver and mutate method works, but is there something wrong in my chooseParents method?

    public class Algorithm{
       private static int newPopLength = 5;
       private static final double MUTATE_RATE = .015;
       private static final double CROSSOVER_RATE = .6;

       public static Population evolvePopulation(Population pop){
          Population newPopulation = new Population(pop.size());
       //crossover
          for(int  x = 0; x<pop.size(); x++){
          //chooses two parents for crossover
             Chromosome chrom1 = chooseParents(pop);
             Chromosome chrom2 = chooseParents(pop);
             Chromosome newChild = crossOver(chrom1, chrom2);
             newPopulation.setChromosome(x, newChild);
          }
       //mutate
          for(int x = 0; x < pop.size(); x++){
             mutate(newPopulation.getChromosome(x));
          }
          return newPopulation;
       } 

       //crossover method
       public static Chromosome crossOver(Chromosome chrom1, Chromosome chrom2){
          Chromosome childChrom = new Chromosome();
          childChrom.generateChromosome();
       //Creates and generates childChromosome

          char []arr1 = chrom1.getChromosome();
          char []arr2 = chrom2.getChromosome();
          char []childArr = new char[arr1.length];

       //crosses over by 1/2 of each array
          for(int x = 0; x<arr2.length; x++){
             if(x <= Math.round(arr1.length / 2)){
                childArr[x] = arr1[x];
             }
             else{
                childArr[x] = arr2[x];
             }
          }
          for(int x = 0; x<childArr.length; x++){
             childChrom.setGene(childArr[x], x);
          }
          return childChrom;
       }
       //mutates chromosome by selecting a random point and replacing it with a random char
       public static void mutate(Chromosome chrom){
          if(Math.random() <= MUTATE_RATE){
             int rand = Math.round((int)(Math.random() * chrom.size()));
             chrom.setGene((char)((Math.random()*25) + 97), rand);
          }
       }
       private static Chromosome chooseParents(Population pop){
          Population newPopulation = new Population(newPopLength);

          Chromosome fittest = new Chromosome();
          for(int x = 0; x<newPopulation.size(); x++){
          //randomlu chooses 5 chromosomes
             Chromosome newChrom = pop.getChromosome((int)(Math.random()*pop.size()));
             newPopulation.setChromosome(x, newChrom);

          }
          return newPopulation.getFittest();

       }
    }
public class FitnessCalc{
   private static char solution[] = new char[Chromosome.getDefaultLength()];
   public static void setSolution(String word){
      solution = word.toCharArray();
   }

   public static char[] getSolution(){
      return solution;
   }
   public static int getFitness(Chromosome chrom){
      int fitness = 0;
      String chromWord = String.valueOf(chrom);
      char []chromArray = chromWord.toCharArray(); 

      for(int x = 0; x< solution.length;x++){
         //return 
fitness += Math.abs((int)(chrom.getGene(x)) - (int)(solution[x]));
      }
      return fitness;
   }


   public static int maxFitness(){
      int maxFitness =10241024;
      return maxFitness;
   }
}


   public Chromosome getFittest(){
      Chromosome fittest = new Chromosome();
      fittest.generateChromosome();
      for(int x = 0; x<size(); x++){
   if(FitnessCalc.getFitness(getChromosome(x))<= FitnessCalc.getFitness(fittest)){
         //if(FitnessCalc.getFitness(getChromosome(x)) >= FitnessCalc.getFitness(fittest)){
            fittest =  getChromosome(x);
         }
      }

      return fittest;
   }

Output:

Generation  992 Fittest Hello2aorld Fitness 28
Generation  993 Fittest Hello2aorld Fitness 28
Generation  994 Fittest Hello2aorld Fitness 28
Generation  995 Fittest Hello2aorld Fitness 28
Generation  996 Fittest Hello2aorld Fitness 28
Generation  997 Fittest Hello2aorld Fitness 28
Generation  998 Fittest Hello2aorld Fitness 28
Generation  999 Fittest Hello2aorld Fitness 28
Generation 1000 Fittest Hello2aorld Fitness 28


Generation 998 Fittest 2ello'aorld Fitness 39
Generation 999 Fittest 2ello'aorld Fitness 39
Generation 1000 Fittest 2ello'aorld Fitness 39

Generation 998 Fittest Sello,Porld Fitness 30
Generation 999 Fittest Sello,Porld Fitness 30
Generation 1000 Fittest Sello,Porld Fitness 30

Upvotes: 0

Views: 156

Answers (1)

Alexander Weber
Alexander Weber

Reputation: 799

Let's have a closer look at the snippet of your static getFitness(Chromosome chrom) function:

for(int x = 0; x< solution.length;x++){
  return fitness += Math.abs((int)(chrom.getGene(x)) - (int)(solution[x]));
}
return fitness;

Are you trying to accumulate fitness here? If so, it does not work, as you are returning fitness right after you added the absolute difference while x = 0. You are not looping over all genes there, so you should probably get rid of the first return.

The other thing which I was confused by is your getFittest() function. Here you say that the fittest chromosome has the highest fitness value:

if(FitnessCalc.getFitness(getChromosome(x)) >= FitnessCalc.getFitness(fittest)){
  fittest =  getChromosome(x);
}

But is that really true? Remember, you are subtracting character genotypes (their Int representation), so the fittest would be the one with a smaller difference, because it is closer to the actual character. As a rule of thumb one could say that most optimization problems are about finding the minimum, so you should always double check for that.

Try to fix those both things and let us know if you are still experiencing problems with the evolutionary process.

Upvotes: 3

Related Questions