void Generation::produce_offspring(genetic_parameters const& genetic_param, std::vector<bound> const& param_bounds) { // Initialize random generator std::random_device rd; std::array<unsigned int, std::mt19937::state_size> seed_data; std::generate_n(seed_data.begin(), seed_data.size(), std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::mt19937 engine(seq); // Check if the number of chromosomes is even size_t pairs(0); if (size % 2 == 0) { pairs = size / 2; } else { pairs = (size + 1) / 2; } // Select the pairs of parents and produce an offspring for (size_t i = 0; i < pairs; ++i) { // Select parents via tournament selection Chromosome parent1 = chromosomes[tournament_selection(engine)]; Chromosome parent2 = chromosomes[tournament_selection(engine)]; // Crossover parents crossover_chromosomes(parent1, parent2, genetic_param.prob_crossover, engine); // Mutate parents mutate_chromosome(parent1, genetic_param.prob_mutation, param_bounds, engine); mutate_chromosome(parent2, genetic_param.prob_mutation, param_bounds, engine); // Save new chromosomes offspring.push_back(parent1); if (2 * (i + 1) <= size) { offspring.push_back(parent2); } } // Save new generation chromosomes = offspring; offspring.clear(); }
void perform_crossover_and_mutation(int parent1_index, int parent2_index, int nextpopindex) /* Performs crossover between the given parents, and mutates the offspring */ { int i,j, toggle, max_parent, site; int *crossover_template, *child_1, *child_2; struct element *new_top; #if GA_DEBUG printf("In` perform_crossover_and_mutation with parent index: %d, %d\n", parent1_index, parent2_index); print_a_chromosome(current_pop[parent1_index].chrom); printf("\n"); print_a_chromosome(current_pop[parent2_index].chrom); #endif child_1 = (void *)my_malloc(CHROM_LENGTH * sizeof(int)); child_2 = (void *)my_malloc(CHROM_LENGTH * sizeof(int)); crossover_template = (void *)my_malloc(CHROM_LENGTH * sizeof(int)); /* initialize crossover_template */ for (j = 0; j < CHROM_LENGTH; j++) crossover_template[j] = ZERO; /* First decide whether or not to cross over */ if (knuth_random() < CROSSOVER_RATE) { #if GA_DEBUG printf("Decided to cross over\n"); #endif /* Put ones in the template array where there are crossover sites */ for (j = 0; j < CROSSOVER_SITES; j++) { /* Definitely choose a site at which to cross over */ site = (knuth_random() * (CHROM_LENGTH -1)) + 1; if (crossover_template[site]==ONE) j--; else crossover_template[site] = ONE; } } else { #if GA_DEBUG printf("Decided not to perform crossover\n"); #endif /* Make sure crossover template is all ZEROS */ for (j=0; j < CHROM_LENGTH; j++) if (crossover_template[j] != ZERO) { fprintf(stderr, "Error: Decided not to perform crossover, but crossover template has non-zero\n"); exit(1); } } #if GA_DEBUG printf("Here is the crossover template\n"); for (i=0; i < CHROM_LENGTH; i++) printf("%d", crossover_template[i]); printf("\n"); #endif /* Begin crossing-over. If it was decided not to cross over, then * crossover_template is all zeros. */ toggle = 0; /* this gets switched when we hit a crossover site */ for (j = 0; j < CHROM_LENGTH; j++) { if (crossover_template[j]==ONE) toggle = toggle ? 0 : 1; if (toggle) { child_2[j] = current_pop[parent1_index].chrom[j]; child_1[j] = current_pop[parent2_index].chrom[j]; } else { child_1[j] = current_pop[parent1_index].chrom[j]; child_2[j] = current_pop[parent2_index].chrom[j]; } } #if GA_DEBUG printf("After crossover (or not), here are the two children:\n"); print_a_chromosome(child_1); printf("\n"); print_a_chromosome(child_2); #endif /* Perform mutation operator on the two */ mutate_chromosome(child_1); mutate_chromosome(child_2); #if GA_DEBUG printf("After mutation, here are the two children:\n"); print_a_chromosome(child_1); printf("\n"); print_a_chromosome(child_2); printf("\n We will put them at indices %d and %d\n", nextpopindex, nextpopindex+1); #endif /* We now have two fine children */ /* Put child_1 in next_pop */ for (j = 0; j < CHROM_LENGTH; j++) next_pop[nextpopindex].chrom[j] = child_1[j]; next_pop[nextpopindex].generation = current_generation+1; next_pop[nextpopindex].id = nextpopindex; nextpopindex++; /* Put child_2 in next_pop */ for (j = 0; j < CHROM_LENGTH; j++) next_pop[nextpopindex].chrom[j] = child_2[j]; next_pop[nextpopindex].generation = current_generation+1; next_pop[nextpopindex].id = nextpopindex; #if GA_DEBUG printf("Children have been put in next pop\n"); #endif #if GA_DEBUG printf("About to free pointers\n"); #endif /* Free pointers */ free(child_1); free(child_2); free(crossover_template); }