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();
}
Esempio n. 2
0
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);

}