//--------------------------------------------------------------------------- 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 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; } } }
//-------------------------------------------------------------------- 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); }