We are about to switch to a new forum software. Until then we have removed the registration on this forum.
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;
}
}