2

I am having trouble creating a Genetic Algorithm in java. I am competing in an online GA contest. I am trying to save the best result each time back into index 0, but it just becomes a reference to the original index. Meaning when I evolve the rest of the indexes, if it evolves the best members original index I lose it.

I have tried shimming it with a getClone method that converts the objects data to and int array and creates a new object from it.

Individual class:

class Individual {
 public int[] angle;
 public int[] thrust;
 public double fitness;
 public Individual(){
 angle = new int[2];
 thrust = new int[2];
 for (int i = 0; i < 2; i++) { 
 this.angle[i] = ThreadLocalRandom.current().nextInt(0, 37) - 18;
 this.thrust[i] = ThreadLocalRandom.current().nextInt(0, 202);
 this.thrust[i] = ( (this.thrust[i] == 201) ? 650 : this.thrust[i] );
 }
 this.fitness = Double.MIN_VALUE;
 }
 public Individual(int[][] genes, double f){
 this.fitness = f;
 angle = new int[2];
 thrust = new int[2];
 this.angle[0] = genes[0][0];
 this.angle[1] = genes[0][1];
 this.thrust[0] = genes[1][0];
 this.thrust[1] = genes[1][1]; 
 }
 public Individual getClone() {
 int[][] genes = new int[2][2];
 genes[0][0] = (int)this.angle[0];
 genes[0][1] = (int)this.angle[1];
 genes[1][0] = (int)this.thrust[0];
 genes[1][1] = (int)this.thrust[1];
 return ( new Individual(genes, this.fitness) );
 }
 public Individual crossover(Individual other) {
 int[][] genes = new int[2][2];
 genes[0][0] = (int)( (this.angle[0] + other.angle[0])/2 );
 genes[0][1] = (int)( (this.angle[1] + other.angle[1])/2 );
 genes[1][0] = ( (this.thrust[0] == 650 || other.thrust[0] == 650) ? 650: (int)( (this.thrust[0] + other.thrust[0])/2 ) );
 genes[1][1] = ( (this.thrust[1] == 650 || other.thrust[1] == 650) ? 650: (int)( (this.thrust[1] + other.thrust[1])/2 ) );
 return ( new Individual(genes, Double.MIN_VALUE) );
 }
 public void mutate() {
 for (int i = 0; i < 2; i++) {
 if(ThreadLocalRandom.current().nextInt(0, 2)==1) { 
 this.angle[i] = ThreadLocalRandom.current().nextInt(0, 37) - 18;
 }
 if(ThreadLocalRandom.current().nextInt(0, 2)==1) {
 this.thrust[i] = ThreadLocalRandom.current().nextInt(0, 202);
 this.thrust[i] = ( (this.thrust[i] == 201) ? 650 : this.thrust[i] );
 }
 }
 }

Population class:

class Population {
 public Individual[] individuals;
 public Population(int populationSize) {
 individuals = new Individual[populationSize];
 for (int i = 0; i < populationSize; i ++) {
 individuals[i] = new Individual();
 }
 }
 public void resetFitness() {
 for (int i = 0; i < individuals.length; i++) {
 individuals[i].fitness = Double.MIN_VALUE;
 }
 }
 public void setIndividual(int i, Individual indiv) {
 individuals[i] = indiv.getClone();
 }
 public Individual getIndividual(int i) {
 return individuals[i].getClone();
 }
 public int size() { 
 return this.individuals.length; 
 }
 public Individual getFittest() {
 int fittest = 0;
 // Loop through individuals to find fittest
 for (int i = 0; i < individuals.length; i++) {
 if (individuals[i].fitness > individuals[fittest].fitness) {
 fittest = i;
 }
 }
 return individuals[fittest].getClone();
 }
}

The necessaries from the sim class:

class simGA {
 private Population pop; 
 private final static int TSIZE = 5; //tournement size
 public simGA (int poolsize) { 
 this.pop = new Population(poolsize);
 }
 public Individual search(int generations, int totalMoves) {
 //this.pop.resetFitness();
 for (int g = 0; g < generations; g++) {
 for (int i = 0; i < this.pop.individuals.length; i++) {
 this.pop.individuals[i].fitness = sim(this.pop.individuals[i],totalMoves);
 }
 System.err.print("Generation " + g + " ");
 this.pop = evolvePopulation(this.pop);
 }
 return pop.getFittest();
 }
 private Population evolvePopulation(Population p) {
 //save fittest
 Population tempPop = new Population(p.individuals.length);
 tempPop.setIndividual(0, p.getFittest().getClone() );
 System.err.print("Best move: " + tempPop.individuals[0].fitness);
 System.err.println();
 for (int i = 1; i < p.individuals.length; i++) {
 Individual indiv1 = tournamentSelection(p);
 Individual indiv2 = tournamentSelection(p);
 Individual newIndiv = indiv1.crossover(indiv2);
 newIndiv.mutate();
 tempPop.setIndividual(i, newIndiv.getClone() );
 }
 return tempPop;
 }
 // Select individuals for crossover
 private Individual tournamentSelection(Population pop) {
 // Create a tournament population
 Population tournament = new Population(TSIZE);
 // For each place in the tournament get a random individual
 for (int i = 0; i < TSIZE; i++) {
 int randomId = ThreadLocalRandom.current().nextInt(1, this.pop.individuals.length);
 tournament.setIndividual(i, pop.getIndividual(randomId).getClone() );
 }
 // Get the fittest
 return tournament.getFittest().getClone();
 }
 private double sim(Individual s, int moves) {
 return score; //score of simmed moves
 }

How can I make sure that the best individual is getting saved, not as a reference? When I error print the best score, sometimes it is lost and a worse scoring move is chosen. I don't think it is necessarily a object cloning issue, I can clone the game objects that are simulated just fine, resetting them each run.

As I said, this is for a contest, so I cannot use any libraries on the site, and also is the reason I am not posting the full code, the intricacies of the simulator it self that scores the moves are not to be just given away. But suffice it to say the scores come back as expected for the move when worked out on paper.

I response to NWS, I thought my getClone method was doing a deep copy.

Reference used beside wiki and other knowledge on Genetic Algorithms: http://www.theprojectspot.com/tutorial-post/creating-a-genetic-algorithm-for-beginners/3

I have fixed it by not resimming the individual at index 0. However this means there are other issue with my code not related to the question.

asked Dec 27, 2016 at 7:08
2
  • Isnt this a deep copy vs shallow copy issue ? Commented Dec 27, 2016 at 7:46
  • to save it, you've to create a new Object, and store into all the attribute values. In some cas, i prefer to store a Collection of this new Object. Commented Dec 27, 2016 at 21:48

2 Answers 2

1
Individual newIndiv = indiv1.crossover(indiv2);

Above line is resetting the fitness to Double.MIN_VALUE. So, whenever evolvePopulation is called, only individual at index 0 is fittest.

answered Dec 27, 2016 at 7:52
Sign up to request clarification or add additional context in comments.

2 Comments

That is correct, but I keep losing the individual at index 0 when i want to keep it.
This line resets all indexes: this.pop.individuals[i].fitness = sim(this.pop.individuals[i],totalMoves);
1

I have fixed it by not resimming the individual at index 0. However this means there are other issue with my code not related to the question, since resimming the same individual from the same point in time as before should not change it's fitness.

answered Dec 28, 2016 at 0:12

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.