int init_chromosome(Chromosome **c) { *c = (Chromosome *)malloc(sizeof(Chromosome)); int i=0, j=0, s=0, complete=0, v=0; unsigned long seed = get_nano_seconds(); srand(seed); s = rand()%SIZE + 1; (*c)->size = s; (*c)->ch = (unsigned int *)malloc(s+1); for (i=1; i<=s; i++) // zero base { complete = 0; while (!complete) { v = rand()%SIZE+1; for (j=1; j<=i; j++) { if ((*c)->ch[j] == v) break; } if (j==i+1) { (*c)->ch[i] = (unsigned int)v; complete = 1; } } } (*c)->p1 = 0; (*c)->p2 = 0; print_chromosome(*c); return 1; }
//--------------------------------------------------------------------------- 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); }
int main(int argc, char *argv[]) { // Need to change to 3. need to remove the logging. if (argc != 4) { printf("Usage: ./maxcut <input data path> <output data path> <log file>\n"); exit(-1); } // Need to remove when submitting. log_file = fopen(argv[3], "w"); fprintf(log_file, "rate, elasped time (s), max val, avg val\n"); start_time = get_seconds(); in = fopen(argv[1], "r"); out = fopen(argv[2], "w"); int i, j, v1, v2, w; // (v1, v2) is the vertex and w is the weight fscanf(in, "%d %d\n", &num_of_vertex, &num_of_edge); int edge[num_of_vertex+1][num_of_vertex+1]; for (i=0; i<=SIZE; i++) for (j=0; j<=SIZE; j++) edge[i][j] = 0; while (fscanf(in, "%d %d %d\n", &v1, &v2, &w) != EOF) { edge[v1][v2] = w; edge[v2][v1] = w; } init_population(); init_offsprings(); init_cost(edge); sort_population(); init_crossover(); int p1, p2; while (!(stop_condition())) { generation++; for (i=1; i<=K; i++) { selection(&p1, &p2); crossover(i, p1, p2); mutation(i); } replacement(edge); sort_population(); } for (i=1; i<=SIZE; i++) { if (population[N]->ch[i] == 1) fprintf(out, "%d ", i); } printf("max: \n"); print_chromosome(population[N]); free_population(); fclose(in); fclose(out); printf("N: %d, K: %d, S_RATE: %lf, M_THRE: %lf, P0: %lf, POINTS: %d, K_FIT: %d, T: %lf\n", N, K, S_RATE, M_THRE, P0, POINTS, K_FIT, T); return 0; }
//--------------------------------------------------------------------------- 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); }