// This function uses two fixed points for two-point crossover. For better performance these two points may be made random and/or adjusted over time // For example, in higher generations they could be moved further to the back public void twoFixedPointCrossover() { int selectionSize = Convert.ToInt32(0.4 * populationSize); Genome parent1 = new Genome(); Genome parent2 = new Genome(); Genome child1 = new Genome(); Genome child2 = new Genome(); int r; int fixpoint1 = 4; int fixpoint2 = 15; 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; for (int j = 0; j < 20; j++) { // Case 1: fixpoint 1 to fixpoint 2, fixpoints exclusive if (j > fixpoint1 && j < fixpoint2) { // Iterates over the eight-bit-blocks and adds all bits to the respective parent 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)); } } // Case 2: Before fixpoint 1 and after fixpoint 2, fixpoints inclusive else { // Iterates over the eight-bit-blocks and adds all bits to the respective parent 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); } } }
// This function uses single-bit Uniform Crossover. public void singleBitCrossover() { // 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(); Genome mask = new Genome(); 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. This function sucks. mask = new Genome(true); // Generates children for (int j = 0; j < 160; j++) { if (mask.Genome1.Get(j)) { // If mask(i) is 1 then child1 gets the value at that point from parent1, child2 from parent2 child1.Genome1.Set(j, parent1.Genome1.Get(j)); child2.Genome1.Set(j, parent2.Genome1.Get(j)); } else { // If mask(i) is 0 then child1 gets the value at that point from parent2, child2 from parent1 child1.Genome1.Set(j, parent2.Genome1.Get(j)); child2.Genome1.Set(j, parent1.Genome1.Get(j)); } } // Adds the genome and its corresponding path to the population at position i. Also sets Selected to false. 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); } } }
private void button_genomeToPath_Click(object sender, EventArgs e) { Genome genome = new Genome(); char[] text = this.textBox1.Text.ToCharArray(); for (int i = 0; i < 160; i++) { if (text[i] == '1') { genome.Genome1.Set(i, true); } } Genome.genomeToPath(genome); this.glControl1.Refresh(); }
// 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); } } }