/* create a mutated individual */ individual* mutate_individual( individual* i, int degree ) { individual* mutant; mutant = copy_individual( i ); mutant->correct = -1; mutant->age = 0; mutant->length = 0; int c, mutation_location, new_value; /* there will be degree value changes to the copied individual, but there is no guarantee that there will be degree differences from the original since a single value can be changed multiple times */ for( c = 0; c < degree; c++ ) { mutation_location = randint( mutant->length ); new_value = randint( mutant->length ); while( new_value == mutant->list[mutation_location] ) { new_value = randint( mutant->length ); } mutant->list[mutation_location] = new_value; } return mutant; }
void copy_population(Population * from, Population * to) { for(int i = 0; i < POPULATION_SIZE; ++i) { copy_individual(&from->individuals[i], &to->individuals[i]); } }
void selection_by_tournament(Population * from, Population * to) { int index1, index2; for(int i = 0; i < POPULATION_SIZE; ++i) { index1 = rand() % POPULATION_SIZE; index2 = rand() % POPULATION_SIZE; if(from->individuals[index1].fitness >= from->individuals[index2].fitness) { copy_individual(&from->individuals[index1], &to->individuals[i]); } else { copy_individual(&from->individuals[index2], &to->individuals[i]); } } }
/** * mutate the individual with a new one taken from the population * but just 1 mutation-step away * * @return -1 if no new individual can be found which is 1 gene away */ short mutate_1gene(int *individual, int *population) { int test_mutation[GENOTYPE_LENGTH]; // make a backup copy copy_individual(individual, test_mutation); // breed the possible population int max_mutations = GENOTYPE_LENGTH-1; int mutations[max_mutations][GENOTYPE_LENGTH]; int possible_mutations = 0 ; int i = 0, j; // for every bit of the original individual for ( j = 0 ; j < GENOTYPE_LENGTH ; j++ ) { // mutate a specific gene bitflip1(test_mutation, j); // check if such individual has been // tested already for fitness if ( population[hash(test_mutation)] == 0 ) { // if it's not yet tested put into the pool // of possible mutations copy_individual(test_mutation, mutations[i]); i++; } // get the original individual back copy_individual(individual, test_mutation); } if ( i == 0 ) // no new individual can be found return -1; // select one random "new" individual int new_individual_index = rand() % i; // that's our man copy_individual(mutations[new_individual_index], individual); return 0; }
//--------------------------------------------------------------------------- void start_steady_state(t_parameters ¶ms, t_graph *training_graphs, int num_training_graphs, t_graph *validation_graphs, int num_validation_graphs, int num_variables, int num_procs, int current_proc_id) { int size_to_send = params.code_length * sizeof(t_code3) + params.num_constants * 20 + 20; char *s_source = new char[size_to_send]; char *s_dest = new char[size_to_send]; t_chromosome receive_chromosome; allocate_chromosome(receive_chromosome, params); // a steady state model - // Newly created inviduals replace the worst ones (if the offspring are better) in the same (sub) population. // allocate memory for all sub populations t_chromosome **sub_populations; // an array of sub populations sub_populations = new t_chromosome*[params.num_sub_populations]; for (int p = 0; p < params.num_sub_populations; p++) { sub_populations[p] = new t_chromosome[params.sub_population_size]; for (int i = 0; i < params.sub_population_size; i++) allocate_chromosome(sub_populations[p][i], params); // allocate each individual in the subpopulation } #ifdef USE_THREADS // allocate memory double** vars_values = new double*[params.num_threads]; for (int t = 0; t < params.num_threads; t++) vars_values[t] = new double[num_variables]; // an array of threads. Each sub population is evolved by a thread std::thread **mep_threads = new std::thread*[params.num_threads]; // we create a fixed number of threads and each thread will take and evolve one subpopulation, then it will take another one std::mutex mutex; // we need a mutex to make sure that the same subpopulation will not be evolved twice by different threads #else double* vars_values = new double[num_variables]; #endif t_chromosome best_validation; allocate_chromosome(best_validation, params); double best_validation_fitness = DBL_MAX; // evolve for a fixed number of generations for (int generation = 0; generation < params.num_generations; generation++) { // for each generation #ifdef USE_THREADS int current_subpop_index = 0; for (int t = 0; t < params.num_threads; t++) mep_threads[t] = new std::thread(evolve_one_subpopulation, ¤t_subpop_index, &mutex, sub_populations, generation, ¶ms, training_graphs, num_training_graphs, num_variables, vars_values[t]); for (int t = 0; t < params.num_threads; t++) { mep_threads[t]->join(); delete mep_threads[t]; } #else //for (int p = 0; p < params.num_sub_populations; p++) int p = 0; evolve_one_subpopulation(&p, sub_populations, generation, ¶ms, training_graphs, num_training_graphs, num_variables, vars_values); #endif // find the best individual int best_individual_subpop_index = 0; // the index of the subpopulation containing the best invidual for (int p = 1; p < params.num_sub_populations; p++) if (sub_populations[p][0].fitness < sub_populations[best_individual_subpop_index][0].fitness) best_individual_subpop_index = p; double *partial_values_array = new double[params.code_length]; sub_populations[best_individual_subpop_index][0].simplify(params.code_length); double current_validation_fitness = compute_fitness(sub_populations[best_individual_subpop_index][0], validation_graphs, num_validation_graphs, num_variables, vars_values, partial_values_array); if (!generation || generation && current_validation_fitness < best_validation_fitness) { best_validation_fitness = current_validation_fitness; copy_individual(best_validation, sub_populations[best_individual_subpop_index][0], params); } delete[] partial_values_array; printf("proc_id=%d, generation=%d, best training =%lf best validation =%lf\n", current_proc_id, generation, sub_populations[best_individual_subpop_index][0].fitness, best_validation_fitness); if (current_proc_id == 0) { FILE* f = fopen("tst_log.txt", "a"); fprintf(f, "proc_id=%d, generation=%d, best=%lf\n", current_proc_id, generation, sub_populations[best_individual_subpop_index][0].fitness); fclose(f); } // now copy one individual from one population to the next one. // the copied invidual will replace the worst in the next one (if is better) for (int p = 0; p < params.num_sub_populations; p++) { int k = rand() % params.sub_population_size;// the individual to be copied // replace the worst in the next population (p + 1) - only if is better int index_next_pop = (p + 1) % params.num_sub_populations; // index of the next subpopulation (taken in circular order) if (sub_populations[p][k].fitness < sub_populations[index_next_pop][params.sub_population_size - 1].fitness) { copy_individual(sub_populations[index_next_pop][params.sub_population_size - 1], sub_populations[p][k], params); qsort((void *)sub_populations[index_next_pop], params.sub_population_size, sizeof(sub_populations[0][0]), sort_function); } } #ifdef USE_MPI // here I have to copy few individuals from one process to another process for (int i = 0; i < 1; i++) { int source_sub_population_index = rand() % params.num_sub_populations; int chromosome_index = rand() % params.sub_population_size; int tag = 0; sub_populations[source_sub_population_index][chromosome_index].to_string(s_dest, params.code_length, params.num_constants); MPI_Send((void*)s_dest, size_to_send, MPI_CHAR, (current_proc_id + 1) % num_procs, tag, MPI_COMM_WORLD); MPI_Status status; int flag; MPI_Iprobe(!current_proc_id ? num_procs - 1 : current_proc_id - 1, tag, MPI_COMM_WORLD, &flag, &status); if (flag) { MPI_Recv(s_source, size_to_send, MPI_CHAR, !current_proc_id ? num_procs - 1 : current_proc_id - 1, tag, MPI_COMM_WORLD, &status); receive_chromosome.from_string(s_source, params.code_length, params.num_constants); int dest_sub_population_index = rand() % params.num_sub_populations; if (receive_chromosome.fitness < sub_populations[dest_sub_population_index][params.sub_population_size - 1].fitness) { copy_individual(sub_populations[dest_sub_population_index][params.sub_population_size - 1], receive_chromosome, params); qsort((void *)sub_populations[dest_sub_population_index], params.sub_population_size, sizeof(sub_populations[0][0]), sort_function); } } } #endif } #ifdef USE_THREADS delete[] mep_threads; #endif // print best t_chromosome // any of them can be printed because if we allow enough generations, the populations will become identical print_chromosome(best_validation, params, num_variables); best_validation.to_file_simplified("best.txt", params.code_length, params.num_constants); // free memory for (int p = 0; p < params.num_sub_populations; p++) { for (int i = 0; i < params.sub_population_size; i++) delete_chromosome(sub_populations[p][i]); delete[] sub_populations[p]; } delete[] sub_populations; #ifdef USE_THREADS for (int t = 0; t < params.num_threads; t++) delete[] vars_values[t]; delete[] vars_values; #endif delete[] s_dest; delete[] s_source; delete_chromosome(receive_chromosome); delete_chromosome(best_validation); }
void evolve_one_subpopulation(int *current_subpop_index, t_chromosome ** sub_populations, int generation_index, t_parameters *params, t_graph *training_graphs, int num_training_graphs, int num_variables, double* vars_values) #endif { int pop_index = 0; while (*current_subpop_index < params->num_sub_populations) {// still more subpopulations to evolve? #ifdef USE_THREADS while (!mutex->try_lock()) {}// create a lock so that multiple threads will not evolve the same sub population pop_index = *current_subpop_index; (*current_subpop_index)++; mutex->unlock(); #else pop_index = *current_subpop_index; (*current_subpop_index)++; #endif // pop_index is the index of the subpopulation evolved by the current thread if (pop_index < params->num_sub_populations) { t_chromosome *a_sub_population = sub_populations[pop_index]; t_chromosome offspring1, offspring2; allocate_chromosome(offspring1, *params); allocate_chromosome(offspring2, *params); double *partial_values_array = new double[params->code_length]; if (generation_index == 0) { for (int i = 0; i < params->sub_population_size; i++) { generate_random_chromosome(a_sub_population[i], *params, num_variables); a_sub_population[i].fitness = compute_fitness(a_sub_population[i], training_graphs, num_training_graphs, num_variables, vars_values, partial_values_array); } // sort ascendingly by fitness inside this population qsort((void *)a_sub_population, params->sub_population_size, sizeof(a_sub_population[0]), sort_function); } else // next generations for (int k = 0; k < params->sub_population_size; k += 2) { // we increase by 2 because at each step we create 2 offspring // choose the parents using binary tournament int r1 = tournament_selection(a_sub_population, params->sub_population_size, 2); int r2 = tournament_selection(a_sub_population, params->sub_population_size, 2); // crossover double p_0_1 = rand() / double(RAND_MAX); // a random number between 0 and 1 if (p_0_1 < params->crossover_probability) one_cut_point_crossover(a_sub_population[r1], a_sub_population[r2], *params, offspring1, offspring2); else {// no crossover so the offspring are a copy of the parents copy_individual(offspring1, a_sub_population[r1], *params); copy_individual(offspring2, a_sub_population[r2], *params); } // mutate the result and compute fitness mutation(offspring1, *params, num_variables); offspring1.fitness = compute_fitness(offspring1, training_graphs, num_training_graphs, num_variables, vars_values, partial_values_array); // mutate the other offspring too mutation(offspring2, *params, num_variables); offspring2.fitness = compute_fitness(offspring2, training_graphs, num_training_graphs, num_variables, vars_values, partial_values_array); // replace the worst in the population if (offspring1.fitness < a_sub_population[params->sub_population_size - 1].fitness) { copy_individual(a_sub_population[params->sub_population_size - 1], offspring1, *params); qsort((void *)a_sub_population, params->sub_population_size, sizeof(a_sub_population[0]), sort_function); } if (offspring2.fitness < a_sub_population[params->sub_population_size - 1].fitness) { copy_individual(a_sub_population[params->sub_population_size - 1], offspring2, *params); qsort((void *)a_sub_population, params->sub_population_size, sizeof(a_sub_population[0]), sort_function); } } delete_chromosome(offspring1); delete_chromosome(offspring2); delete[] partial_values_array; } } }
/* Performs variation. */ int variate(int *selected, int *result_ids) { int result, i, k; result = 1; /* copying all individuals from selected */ for(i = 0; i < mu; i++) { result_ids[i] = add_individual(copy_individual(get_individual(selected[i]))); if(result_ids[i] == -1) { log_to_file(log_file, __FILE__, __LINE__, "copying + adding failed"); return (1); } } /* if odd number of individuals, last one is left as is */ if((((double)mu/2) - (int)(mu/2)) != 0) k = mu - 1; else k = mu; /* do recombination */ for(i = 0; i < k; i+= 2) { if (drand(1) <= individual_recombination_probability) { if (variable_swap_probability > 0) { result = uniform_crossover (get_individual(result_ids[i]), get_individual(result_ids[i + 1])); if (result != 0) log_to_file(log_file, __FILE__, __LINE__, "recombination failed!"); } if (variable_recombination_probability > 0) { result = sbx (get_individual(result_ids[i]), get_individual(result_ids[i + 1])); if (result != 0) log_to_file(log_file, __FILE__, __LINE__, "recombination failed!"); } } } /* do mutation */ for(i = 0; i < mu; i++) { if (drand(1) <= individual_mutation_probability) { if (variable_mutation_probability > 0) { result = mutation(get_individual(result_ids[i])); if(result != 0) log_to_file(log_file, __FILE__, __LINE__, "mutation failed!"); } } } /* do evaluation */ for(i = 0; i < mu; i++) { int result; result = eval(get_individual(result_ids[i])); } return (0); }
/********************************************************************** * * sim_ril * * n_chr Number of chromosomes * n_mar Number of markers on each chromosome (vector of length n_chr) * n_ril Number of RILs to simulate * * map Vector of marker locations, of length sum(n_mar) * First marker on each chromosome should be at 0. * * n_str Number of parental strains (either 2, 4, or 8) * * m Interference parameter (0 is no interference) * p For Stahl model, proportion of chiasmata from the NI model * * include_x Whether the last chromosome is the X chromosome * * random_cross Indicates whether the order of the strains in the cross * should be randomized. * * selfing If 1, use selfing; if 0, use sib mating * * cross On output, the cross used for each line * (vector of length n_ril x n_str) * * ril On output, the simulated data * (vector of length sum(n_mar) x n_ril) * * origgeno Like ril, but with no missing data * * error_prob Genotyping error probability (used nly with n_str==2) * * missing_prob Rate of missing genotypes * * errors Error indicators (n_mar x n_ril) * **********************************************************************/ void sim_ril(int n_chr, int *n_mar, int n_ril, double *map, int n_str, int m, double p, int include_x, int random_cross, int selfing, int *cross, int *ril, int *origgeno, double error_prob, double missing_prob, int *errors) { int i, j, k, ngen, tot_mar, curseg; struct individual par1, par2, kid1, kid2; int **Ril, **Cross, **Errors, **OrigGeno; int maxwork, isX, flag, max_xo, *firstmarker; double **Map, maxlen, chrlen, *work; /* count total number of markers */ for(i=0, tot_mar=0; i<n_chr; i++) tot_mar += n_mar[i]; reorg_geno(tot_mar, n_ril, ril, &Ril); reorg_geno(n_str, n_ril, cross, &Cross); reorg_geno(tot_mar, n_ril, errors, &Errors); reorg_geno(tot_mar, n_ril, origgeno, &OrigGeno); /* allocate space */ Map = (double **)R_alloc(n_chr, sizeof(double *)); Map[0] = map; for(i=1; i<n_chr; i++) Map[i] = Map[i-1] + n_mar[i-1]; /* location of first marker */ firstmarker = (int *)R_alloc(n_chr, sizeof(int)); firstmarker[0] = 0; for(i=1; i<n_chr; i++) firstmarker[i] = firstmarker[i-1] + n_mar[i-1]; /* maximum chromosome length (in cM) */ maxlen = Map[0][n_mar[0]-1]; for(i=1; i<n_chr; i++) if(maxlen < Map[i][n_mar[i]-1]) maxlen = Map[i][n_mar[i]-1]; /* allocate space for individuals */ max_xo = (int)qpois(1e-10, maxlen/100.0, 0, 0)*6; if(!selfing) max_xo *= 5; allocate_individual(&par1, max_xo); allocate_individual(&par2, max_xo); allocate_individual(&kid1, max_xo); allocate_individual(&kid2, max_xo); maxwork = (int)qpois(1e-10, (m+1)*maxlen/50.0, 0, 0)*3; work = (double *)R_alloc(maxwork, sizeof(double)); for(i=0; i<n_ril; i++) { /* set up cross */ for(j=0; j<n_str; j++) Cross[i][j] = j+1; if(random_cross) int_permute(Cross[i], n_str); for(j=0; j<n_chr; j++) { isX = include_x && j==n_chr-1; chrlen = Map[j][n_mar[j]-1]; par1.n_xo[0] = par1.n_xo[1] = par2.n_xo[0] = par2.n_xo[1] = 0; /* initial generations */ if(n_str==2) { par1.allele[0][0] = par2.allele[0][0] = 1; par1.allele[1][0] = par2.allele[1][0] = 2; } else if(n_str==4) { par1.allele[0][0] = 1; par1.allele[1][0] = 2; par2.allele[0][0] = 3; par2.allele[1][0] = 4; } else { /* 8 strain case */ par1.allele[0][0] = 1; par1.allele[1][0] = 2; par2.allele[0][0] = 3; par2.allele[1][0] = 4; docross(par1, par2, &kid1, chrlen, m, p, 0, &maxwork, &work); par1.allele[0][0] = 5; par1.allele[1][0] = 6; par2.allele[0][0] = 7; par2.allele[1][0] = 8; docross(par1, par2, &kid2, chrlen, m, p, isX, &maxwork, &work); copy_individual(&kid1, &par1); copy_individual(&kid2, &par2); } /* start inbreeding */ ngen=1; while(1) { R_CheckUserInterrupt(); /* check for ^C */ docross(par1, par2, &kid1, chrlen, m, p, 0, &maxwork, &work); if(!selfing) docross(par1, par2, &kid2, chrlen, m, p, isX, &maxwork, &work); /* are we done? */ flag = 0; if(selfing) { if(kid1.n_xo[0] == kid1.n_xo[1]) { for(k=0; k<kid1.n_xo[0]; k++) { if(kid1.allele[0][k] != kid1.allele[1][k] || fabs(kid1.xoloc[0][k] - kid1.xoloc[1][k]) > 1e-6) { flag = 1; break; } } if(kid1.allele[0][kid1.n_xo[0]] != kid1.allele[1][kid1.n_xo[0]]) flag = 1; } else flag = 1; } else { if(kid1.n_xo[0] == kid1.n_xo[1] && kid1.n_xo[0] == kid2.n_xo[0] && kid1.n_xo[0] == kid2.n_xo[1]) { for(k=0; k<kid1.n_xo[0]; k++) { if(kid1.allele[0][k] != kid1.allele[1][k] || kid1.allele[0][k] != kid2.allele[0][k] || kid1.allele[0][k] != kid2.allele[1][k] || fabs(kid1.xoloc[0][k] - kid1.xoloc[1][k]) > 1e-6 || fabs(kid1.xoloc[0][k] - kid2.xoloc[0][k]) > 1e-6 || fabs(kid1.xoloc[0][k] - kid2.xoloc[1][k]) > 1e-6) { flag = 1; break; } } if(kid1.allele[0][kid1.n_xo[0]] != kid1.allele[1][kid1.n_xo[0]] || kid1.allele[0][kid1.n_xo[0]] != kid2.allele[0][kid1.n_xo[0]] || kid1.allele[0][kid1.n_xo[0]] != kid2.allele[1][kid1.n_xo[0]]) flag = 1; } else flag = 1; } if(!flag) break; /* done inbreeding */ /* go to next generation */ copy_individual(&kid1, &par1); if(selfing) copy_individual(&kid1, &par2); else copy_individual(&kid2, &par2); } /* end with inbreeding of this chromosome */ /* fill in alleles */ curseg = 0; for(k=0; k<n_mar[j]; k++) { /* loop over markers */ while(curseg < kid1.n_xo[0] && Map[j][k] > kid1.xoloc[0][curseg]) curseg++; OrigGeno[i][k+firstmarker[j]] = Ril[i][k+firstmarker[j]] = Cross[i][kid1.allele[0][curseg]-1]; /* simulate missing ? */ if(unif_rand() < missing_prob) { Ril[i][k+firstmarker[j]] = 0; } else if(n_str == 2 && unif_rand() < error_prob) { /* simulate error */ Ril[i][k+firstmarker[j]] = 3 - Ril[i][k+firstmarker[j]]; Errors[i][k+firstmarker[j]] = 1; } } } /* loop over chromosomes */ } /* loop over lines */ }
//--------------------------------------------------------------------------- void start_steady_state_mep(parameters ¶ms, double **training_data, double* target, int num_training_data, int num_variables) // Steady-State { // a steady state approach: // we work with 1 population // newly created individuals will replace the worst existing ones (only if they are better). // allocate memory chromosome *population; population = new chromosome[params.pop_size]; for (int i = 0; i < params.pop_size; i++) allocate_chromosome(population[i], params); chromosome offspring1, offspring2; allocate_chromosome(offspring1, params); allocate_chromosome(offspring2, params); double ** eval_matrix; allocate_partial_expression_values(eval_matrix, num_training_data, params.code_length); // initialize for (int i = 0; i < params.pop_size; i++) { generate_random_chromosome(population[i], params, num_variables); if (params.problem_type == PROBLEM_TYPE_REGRESSION) fitness_regression(population[i], params.code_length, num_variables, num_training_data, training_data, target, eval_matrix); else fitness_classification(population[i], params.code_length, num_variables, params.num_classes, num_training_data, training_data, target, eval_matrix); } // sort ascendingly by fitness qsort((void *)population, params.pop_size, sizeof(population[0]), sort_function); printf("generation %d, best fitness = %lf\n", 0, population[0].fitness); for (int g = 1; g < params.num_generations; g++) {// for each generation for (int k = 0; k < params.pop_size; k += 2) { // choose the parents using binary tournament int r1 = tournament_selection(population, params.pop_size, 2); int r2 = tournament_selection(population, params.pop_size, 2); // crossover double p = rand() / double(RAND_MAX); if (p < params.crossover_probability) one_cut_point_crossover(population[r1], population[r2], params, offspring1, offspring2); else {// no crossover so the offspring are a copy of the parents copy_individual(offspring1, population[r1], params); copy_individual(offspring2, population[r2], params); } // mutate the result and compute fitness mutation(offspring1, params, num_variables); if (params.problem_type == PROBLEM_TYPE_REGRESSION) fitness_regression(offspring1, params.code_length, num_variables, num_training_data, training_data, target, eval_matrix); else fitness_classification(offspring1, params.code_length, num_variables, params.num_classes, num_training_data, training_data, target, eval_matrix); // mutate the other offspring and compute fitness mutation(offspring2, params, num_variables); if (params.problem_type == PROBLEM_TYPE_REGRESSION) fitness_regression(offspring2, params.code_length, num_variables, num_training_data, training_data, target, eval_matrix); else fitness_classification(offspring2, params.code_length, num_variables, params.num_classes, num_training_data, training_data, target, eval_matrix); // replace the worst in the population if (offspring1.fitness < population[params.pop_size - 1].fitness) { copy_individual(population[params.pop_size - 1], offspring1, params); qsort((void *)population, params.pop_size, sizeof(population[0]), sort_function); } if (offspring2.fitness < population[params.pop_size - 1].fitness) { copy_individual(population[params.pop_size - 1], offspring2, params); qsort((void *)population, params.pop_size, sizeof(population[0]), sort_function); } } printf("generation %d, best fitness = %lf\n", g, population[0].fitness); } // print best chromosome print_chromosome(population[0], params, num_variables); // free memory delete_chromosome(offspring1); delete_chromosome(offspring2); for (int i = 0; i < params.pop_size; i++) delete_chromosome(population[i]); delete[] population; delete_data(training_data, target, num_training_data); delete_partial_expression_values(eval_matrix, params.code_length); }
//-------------------------------------------------------------------- void start_steady_state_ga(int pop_size, int num_gens, int num_dims, int num_bits_per_dimension, double pcross, double pm, double min_x, double max_x) // Steady-State genetic algorithm // each step: // pick 2 parents, mate them, // mutate the offspring // and replace the worst in the population // (only if offspring are better) { // allocate memory b_chromosome *population; population = (b_chromosome*)malloc(pop_size * sizeof(b_chromosome)); for (int i = 0; i < pop_size; i++) population[i].x = (char*)malloc(num_dims * num_bits_per_dimension); b_chromosome offspring1, offspring2; offspring1.x = (char*)malloc(num_dims * num_bits_per_dimension); offspring2.x = (char*)malloc(num_dims * num_bits_per_dimension); // initialize for (int i = 0; i < pop_size; i++) { generate_random(population[i], num_dims, num_bits_per_dimension); compute_fitness(&population[i], num_dims, num_bits_per_dimension, min_x, max_x); } qsort((void *)population, pop_size, sizeof(population[0]), sort_function); printf("generation 0\n"); // print the best from generation 0 print_chromosome(&population[0], num_dims, num_bits_per_dimension, min_x, max_x); for (int g = 1; g < num_gens; g++) { for (int k = 0; k < pop_size; k += 2) { // choose the parents using binary tournament int r1 = tournament_selection(2, population, pop_size); int r2 = tournament_selection(2, population, pop_size); // crossover double p = rand() / double(RAND_MAX); if (p < pcross) one_cut_point_crossover(population[r1], population[r2], offspring1, offspring2, num_dims, num_bits_per_dimension); else { copy_individual(&offspring1, population[r1], num_dims, num_bits_per_dimension); copy_individual(&offspring2, population[r2], num_dims, num_bits_per_dimension); } // mutate the result and compute its fitness mutation(offspring1, num_dims, num_bits_per_dimension, pm); compute_fitness(&offspring1, num_dims, num_bits_per_dimension, min_x, max_x); mutation(offspring2, num_dims, num_bits_per_dimension, pm); compute_fitness(&offspring2, num_dims, num_bits_per_dimension, min_x, max_x); // are offspring better than the worst ? if (offspring1.fitness < population[pop_size - 1].fitness) { copy_individual(&population[pop_size - 1], offspring1, num_dims, num_bits_per_dimension); qsort((void *)population, pop_size, sizeof(population[0]), sort_function); } if (offspring2.fitness < population[pop_size - 1].fitness) { copy_individual(&population[pop_size - 1], offspring2, num_dims, num_bits_per_dimension); qsort((void *)population, pop_size, sizeof(population[0]), sort_function); } } printf("generation %d\n", g); print_chromosome(&population[0], num_dims, num_bits_per_dimension, min_x, max_x); } // free memory free(offspring1.x); free(offspring2.x); for (int i = 0; i < pop_size; i++) free(population[i].x); free(population); }
/** * GA with a single fitness function */ int evolve_both(int* first, int* second, int* winner, int* loser, int* population) { int round = 0; float fitness_first, fitness_second; int first_bitflipped[GENOTYPE_LENGTH], second_bitflipped[GENOTYPE_LENGTH]; do { round++; // generate the complementary individuals bitflip(first, first_bitflipped); bitflip(second, second_bitflipped); // mark them as tested in the population population[hash(first)] = 1; population[hash(second)] = 1; // evaluate first and its complementary fitness_first = eval_fit(first, first_bitflipped); // evaluate second fitness_second = eval_fit(second, second_bitflipped); // optimal solution? if ( fitness_first == 0.0 ) { copy_individual(first, winner); copy_individual(second, loser); break; } if ( fitness_second == 0.0 ) { copy_individual(second, winner); copy_individual(first, loser); break; } if ( fitness_first < fitness_second ) { // first wins // mutate loser if ( mutate_1gene(second, population) < 0 ) { // if no more mutations are possible copy_individual(first, winner); copy_individual(second, loser); break; } } else { // second wins // mutate loser if ( mutate_1gene(first, population) < 0 ) { copy_individual(second, winner); copy_individual(first, loser); break; } } } while ( 1 ); return round; }