Genetic Algorithm is too smart

Hello all- The genetic algorithm I have been working on seems to be too smart. The genome settles out after 10-12 generations, despite a 70% chance for genomes to mutate. The genetic algorithm models a version of the arcade game "lunar lander" that I made. The code is decently organized, but I can clarify if need be. Note: This is not the same issue as the previous question I asked about this algorithm, as I fixed that problem that I had. However, the symptoms are the same. Thanks.

//genome has to be as long as lifespan in ticks, since it parses an instruction every tick
//String gen1 = "30003003003002002002001000100333333333333322222222222222000000000000000000000000000000000000000000000000000000000000000000000000000000111111111110000000000000000000";
float size = 20;
float groundLevel = 500;
float crashTolerance = 2.5;
float xTolerance = 1.5;
final int genSize = 50;
int gen_num = 1;
float gcorX;
float gcorY; 
float gsize = 50;
int life_time = 300;
ArrayList<DumbLander> landers = new ArrayList();
int timeIter = 300; 

String[] genome_a;
String[] genome_b;
float[] scores;
float [] fitnessScores= new float[genSize];
float fitness;
float bscore;
String weightedIndexList = "";
int p1, p2;
String p1Genome;
String p2Genome;
float percentChanceForMutation = 0.8;
int countDone;

void setup() {

  size(1000, 800);
  //frameRate(10);
  groundLevel = height-100;
  rectMode(CENTER);
  bscore = dist(0, 0, width, height);

  gcorX = random(width);
  gcorY= random(height);

  genome_a = new String[genSize];
  genome_b = new String[genSize];
  scores = new float[genSize];

  for (int j = 0; j<genSize; j++) {
    genome_a[j] = starterString();
    scores[j] = 0;
  }

  countDone = 0;

  for (int j = 0; j<genSize; j++) {
    genome_a[j] = randomGenome();
    scores[j] = 0;
  }
  for ( int i=0; i < genSize; i++ ) landers.add( new DumbLander( i, genome_a[i] ) );
}

String starterString() {
  // String mut = "" + char( '0' + int( random(4) ) ); //  + " 01020302010300" ;
  String mut = "" +  int( random(4) );
  //print(mut);
  return( mut );
}

String randomGenome() {
  String first = "";
  for (int t = 0; t<life_time; t++) {
    first +=int(random(4));
  }
  // print(first + " |GEN| ");
  return first;
}

void draw() {
  gcorX = 500;
  gcorY = 750;
  background(20);

  point(gcorX, gcorY);
  text("goal", gcorX, gcorY);
  for (int j = 0; j<genSize; j++) {
    landers.get(j).move();
  }

  if (countDone == genSize) {
    //  print("DONE\n");
    // arrayCopy( genome_a, genome_b );

    fitnessScores=  getFitness(); // check this

    weightedIndexList =   createWeightedList(); //review this
    //   println(weightedIndexList);

    chooseParents(); //especially review this
    // println("PARENTS:" + p1 +"|" + p2);

    //for (int k = 0; k<genSize; k++) println(landers.get(k).toString());

    landers.clear();

    for (int k = 0; k<genSize; k++) {
      genome_a[k] = newGenomeFromMating(); // check this

      if (random(1) < percentChanceForMutation) mutate();
      //      addInst(k);
      landers.add(new DumbLander(k, genome_a[k]));
      // noLoop();
    }

    //   for (int j = 0; j<genSize; j++) {
    //genome_a[j] = randomGenome(); // replace this with the "new genomes" function
    //scores[j] = 0;
    //  landers.add(new DumbLander(j, genome_a[j]));
    // }

    countDone = 0;
    gen_num ++;

    // printArray(fitnessScores);


    print(" { " + gen_num + " } ");
    // life_time ++;
  }

  pushMatrix();

  fill(0, 255, 0, 100);
  rect(gcorX, gcorY, gsize, gsize);
  fill(255);
  rect(width/2, height, width, 100);

  popMatrix();
}

public float[] getFitness() {
  float[] fitnesses = new float[genSize];

  for (int i = 0; i<genSize; i++) {
    landers.get(i).calcScores(i);    //trouble
  }
  fitnesses = scores;

  return fitnesses;
}

public String createWeightedList() {
  String ret = ""; 
  int plholder = 0;
  char letholder; // prev char
  for (int i = 0; i<genSize; i++) {
    plholder = int(fitnessScores[i] + 0.5);
    letholder = char( i + 65); // '0' + i
    for (int j = 0; j<plholder; j++) {
      ret += letholder;
    }
  }

  println("RET: {{" + ret +"}}");
  return ret;
}

public void chooseParents() {

  //int pos=-1;
  //int pos2 = -1;
  //float max=Integer.MIN_VALUE; //lowest possible value of an int.
  //for (int i=0; i<fitnessScores.length; i++)
  //{
  //  if (fitnessScores[i]>max)
  //  {
  //    pos=i;
  //    max=fitnessScores[i];
  //  }
  //} 

  p1 = int(weightedIndexList.charAt(int(random(0, weightedIndexList.length())))-65); // p1 = weightedIndexList.charAt(int(weightedIndexList.charAt(int(random(0, weightedIndexList.length())))));
  println("P1 *" + p1 + "**");
  p2 = int(weightedIndexList.charAt(int(random(0, weightedIndexList.length())))-65);
  println("P2 *" + p2 + "**");
  // p2 = int(random(0, weightedIndexList.length()));
  if (p2 == p1) p2 = int(weightedIndexList.charAt(int(random(0, weightedIndexList.length())))-65);
  //if (p1 >= 50) p1 -=0;
  // if (p2 >= 50) p2 -=0;
  p1Genome = landers.get(p1).genome;
  println("P1 GENOME: " + p1Genome);
  p2Genome = landers.get(p2).genome;
  println("P2 GENOME: " +p2Genome);
}

public String newGenomeFromMating() {
  String ret = "";
  int midpoint = int(random(50, p1Genome.length() - 50));

  if (random(1) <.5) {
    String parent1Part1 = p1Genome.substring(0, midpoint);
    String parent2Part2 = p2Genome.substring(midpoint, p1Genome.length());
    ret  = parent1Part1 + parent2Part2;
  } else {
    String parent1Part2 = p1Genome.substring(midpoint, p1Genome.length());
    String parent2Part1 = p2Genome.substring(0, midpoint);
    ret = parent2Part1 + parent1Part2;
  }
  return ret;
}


public void mutate() {
  int which = int(random(0, genSize));

  int randomIndex =  int(random(5, p1Genome.length() - 5));
  String part1 = genome_a[which].substring(0, randomIndex);
  String part2 = genome_a[which].substring(randomIndex + 1, p1Genome.length());
  int insert =  int(random(0, 4));



  String mutatedGenome = part1 + insert + part2;

  genome_a[which] = mutatedGenome;
}

public void addInst(int which1) {
  int which2 = which1;

  int randomIndex =  int(random(1, p1Genome.length() - 1));
  String part1 = genome_a[which2].substring(0, randomIndex);
  String part2 = genome_a[which2].substring(randomIndex, p1Genome.length());
  int insert =  int(random(0, 4));
  String changedGenome = part1 + insert + part2;

  genome_a[which2] = changedGenome;
}





public void mousePressed() {
  noLoop();
}
public void mouseReleased() {
  loop();
}


class DumbLander {

  String genome = "";
  color desig;
  int desigNum;

  float gA = .1;
  float Vx, Vy;
  float xpos = width/2;
  float ypos = 50;

  float fitness;

  int counter = 0;

  int current_inst;
  int[] instructions; 
  boolean inst_a, inst_b, inst_c; 
  boolean didLand;
  boolean hitGoal = false;
  boolean dis = false; //disable 
  boolean done = false;

  boolean Lred = false;
  boolean Rred = false;
  boolean Dred = false;

  DumbLander(int num, String Genome) {
    desigNum = num;
    inst_a = inst_b = inst_c = false;  
    desig=color(random(40, 255), random(40, 255), random(40, 255), 200);
    // life_time = millis() + timeIter;
    current_inst = 0;
    checkString( Genome );
    //life_time = timeIter;
    dis = false; //not disabled

    genome = Genome;
  }


  void checkString(String in) {
    instructions = new int[in.length()];
    for ( int j = 0; j < in.length(); j++ ) {
      instructions[j] = int( in.charAt(j)- '0');
    }
    // printArray(instructions);
  }

  void calcScores(int landerNum) {

    scores[landerNum] = 10000/dist(xpos, ypos, gcorX, gcorY);
    if (dis == true) {
      if (didLand == true) scores[landerNum] += 20;
      else if (didLand == false) scores[landerNum] *= .5;
      if (hitGoal == true) scores[landerNum] += 100;
      if (hitGoal == true && didLand == true) scores[landerNum ] += 300;
    }

    //printArray(scores);
  }

  public String toString() {
    String ret = "";
    //  print(desigNum + " | " + genome);

    ret += "< CheckNumber: |#|" + desigNum + "|#| Genome: |*|" + genome + "|*|>" ;
    return ret;
  }

  void move() {

    if (dis == false) { // if (counter<= life_time && dis == false) {
      gA = 0.1;
      Vy += gA;

      if ( current_inst < instructions.length ) { //for every instruction in the instruction array 
        int i = instructions[current_inst++]; //i is used to represent the value of the instruction at the current instruction value
        switch( i ) { //switches between actions for instruction. For example, if the value "i" is 2, it would enact instruction case 2. it reads and enacts on the instructions based on their value and reads them in sequence based on their position in the array
        case 0:
          // Do nothing.
          break;
        case 1:
          Vy -= .3;
          Dred = true;
          //  Vy -= 1.5;
          break;
        case 2:
          Vx -= .2;
          Lred = true;
          //Vx -= 1.2;
          break;
        case 3:
          Vx += .2;
          Rred = true;
          // Vx += 1.2;
          break;
        default:
          //println( "Bum instruction: " + i )//instruction does not exist
          break;
        }
        ypos += Vy;
        xpos += Vx;
      }



      //for (int i = 0; i< genome.length(); i++) {

      //  if (genome.charAt(i) == 'n') {
      //  } else if (genome.charAt(i) == 'w') {
      //     Vy -= .3;
      //  } else if (genome.charAt(i) == 'a') {
      //    Vx -= .2;
      //  } else if (genome.charAt(i) == 'd') {
      //    Vx += .2;
      //  } else ;
      //}

      //if (keyPressed && key == 'w') {
      //  Vy -= .3;
      //}
      //if (keyPressed && key == 'a') {
      //  Vx -= .2;
      //}
      //if (keyPressed && key == 'd') {
      //  Vx += .2;
      //}

      if (ypos>=730) {
        if (Vy>= crashTolerance || abs(Vx) > xTolerance ) {

          print("Crash");
          didLand = false;
        } else {

          print("************************************land************************************");

          didLand = true;
        }
        if (xpos <= gcorX + (gsize+10) && gcorX >= gcorX - (gsize  +10)) {
          hitGoal = true;
          //  print("hitGoal");
        }
        dis = true;
      }



      update();
      counter++;
      if (counter> life_time) dis = true;
    } else if (dis == true && done == false) {
      dis = true;
      Vy = 0;
      Vx = 0;
      gA = 0;
      counter = 0; 
      update();
      countDone++;
      print(countDone);
      done = true;
    }  
    update();
  }

  void update() {

    pushMatrix();
    // translate(xpos, ypos);
    fill(desig);
    //rect(width/2, 0, 20, 20);
    rect(xpos, ypos, 20, 20);
    fill(255, 0, 0, 200);
    if (Lred == true) triangle(xpos, ypos-size/2, xpos, ypos+size/2, xpos-size, ypos );
    if (Rred == true)triangle(xpos, ypos-size/2, xpos, ypos+size/2, xpos + size, ypos );
    if (Dred == true) triangle(xpos-(-size/2), ypos, xpos-(size/2), ypos, xpos-0, ypos+size );

    pushMatrix();
    fill(255);
    //text(desigNum + " xpos ypos here", xpos, ypos);
    //text( "X velocity: " + Vx, xpos-50, ypos-25);
    //text( "Y velocity: " + Vy, xpos-50, ypos-40);
    text( desigNum, xpos -5, ypos +4);
    popMatrix();

    popMatrix();

    Lred = Dred = Rred = false;
  }
}
Sign In or Register to comment.