public static void genomeToPath(Genome pathGenome) { // Initialize Path List //LinkedList<EZPathFollowing.PathPart> output = new LinkedList<EZPathFollowing.PathPart>(); // Resets the global path Variables.resetPath(); // Resets the gloabl genome Variables.resetGenome(); // Initialize Variables double length; // Length is a number n from 0 to 7. 0.5 + n * 0.5 is the length of a Pathpart double angle; // Angle a is a number from 0 to 7, 10 + a * 5 is the angle in DEGREE bool driveRight; double direction = (360 - Variables.configuration_start.Theta[0]) * Math.PI / 180; EZPathFollowing.Point2D start = Variables.start; // Iterate over all 20 GenomeParts for (int i = 0; i < 20; i++) { // Length is saved in Bits 1,2 and 3 and is required for both PathParts length = GenomePart.getDouble(pathGenome.genome.Get(i * 8 + 1), pathGenome.genome.Get(i * 8 + 2), pathGenome.genome.Get(i * 8 + 3)); length = 0.5 + length * 0.5; // Bit 0 says whether its a curve or line if (pathGenome.genome.Get(i * 8) == false) { // The first Pathpart needs a start and direction if (i == 0) { Variables.path.AddLast(EZPathFollowing.PathPrimitives.line(length, direction, start)); } else { Variables.path.AddLast(EZPathFollowing.PathPrimitives.line(length)); } } else { // Angle and driveRight are only necessary for curves (Bit 0 = true) angle = GenomePart.getDouble(pathGenome.genome.Get(i * 8 + 4), pathGenome.genome.Get(i * 8 + 5), pathGenome.genome.Get(i * 8 + 6)); angle = (10 + angle * 5) * Math.PI / 180; driveRight = pathGenome.genome.Get(i * 8 + 7); // Again, first PathPart needs a start and direction if (i == 0) { Variables.path.AddLast(EZPathFollowing.PathPrimitives.curve(length, direction, angle, driveRight, start)); } else { Variables.path.AddLast(EZPathFollowing.PathPrimitives.curve(length, angle, driveRight)); } } } }
public void add(GenomePart value) { // Paths have a maximum lengths of 20 if (this.length < 20) { // Get the BitArray from the GenomePart BitArray array = value.getBitArray(); // Temporary array of bools since BitArrays don't have the needed functions bool[] temp = new bool[8]; // Copy the BitArray from GenomePart to the array of bool array.CopyTo(temp, 0); // Copy the values to the Genome, offset by length * 8 for (int i = 0; i < 8; i++) { genome.Set(length * 8 + i, temp[i]); } // Increment the length this.length++; } }
// This function uses genomePart Uniform Crossover. It works like a crossover function but uses a significantly shorter mask genome // because it always chooses an entire 8bit block public void eightBitCrossover() { // Size of current new generation is 40% of old generation (before crossover) int selectionSize = Convert.ToInt32(0.4 * populationSize); int r; Genome parent1 = new Genome(); Genome parent2 = new Genome(); bool[] mask; Genome child1 = new Genome(); Genome child2 = new Genome(); // Iterates from selection Size (current maximum of the new population) to population size, the wanted maximum. That means 60% come from crossover for (int i = selectionSize; i < populationSize; i++) { // Randomly selects first parent r = Variables.getRandomInt(0, selectionSize); parent1 = oldPopulation[r].Genome; // Randomly selects second parent r = Variables.getRandomInt(0, selectionSize); parent2 = oldPopulation[r].Genome; // Crates a random mask genome in form of a char[]. char[] is much faster than bool[], genome or bitarray and for our purpose the format doesn't matter mask = GenomePart.getRandomGenome(); for (int j = 0; j < 20; j++) { // Checks the mask if (mask[j]) { // If mask == 1 then the i'th 8bit block will be selected from parent1 for child1 and from parent2 for child2 // k = j*8 since every position in the mask genome covers 8 positions in the actual genome for (int k = j * 8; k < j * 8 + 8; k++) { child1.Genome1.Set(k, parent1.Genome1.Get(k)); child2.Genome1.Set(k, parent2.Genome1.Get(k)); } } else { // If mask == 0 then the i'th 8bit block will be selected from parent1 for child2 and from parent2 for child1 // k = j*8 since every position in the mask genome covers 8 positions in the actual genome for (int k = j * 8; k < j * 8 + 8; k++) { child1.Genome1.Set(k, parent2.Genome1.Get(k)); child2.Genome1.Set(k, parent1.Genome1.Get(k)); } } } Genome.genomeToPath(child1); population[i] = new Population(Variables.path, child1, 0, false, false); // Counts up since we are adding 2 children per iteration, not just one i++; // If we are not yet at maximum (which could happen due to double->int conversion) we add the second child too if (i < populationSize) { Genome.genomeToPath(child2); population[i] = new Population(Variables.path, child2, 0, false, false); } } }
public void add(GenomePart value) { // Paths have a maximum lengths of 20 if (this.length < 20) { // Get the BitArray from the GenomePart BitArray array = value.getBitArray(); // Temporary array of bools since BitArrays don't have the needed functions bool[] temp = new bool[8]; // Copy the BitArray from GenomePart to the array of bool array.CopyTo(temp,0); // Copy the values to the Genome, offset by length * 8 for (int i = 0; i < 8; i++) { genome.Set(length * 8 + i, temp[i]); } // Increment the length this.length++; } }