Reputation: 65
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
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