population random_breeder::breed(const population &generation, const std::vector<double> &fitnesses) const { using namespace std; population ret; tree_crossover_reproducer repr; node_crossover_reproducer mrepr; builder random_builder; experimental_parameters e = exp_params(); const uint32_t growth_tree_min = e["growth_tree_min"]; const uint32_t growth_tree_max = e["growth_tree_max"]; while(ret.size() < generation.size()) { const agent &mother = generation[rand() % generation.size()]; const agent &father = generation[rand() % generation.size()]; agent mutant = random_builder.grow(program_types_set, growth_tree_min, growth_tree_max); const vector<agent> children = repr.reproduce(vector<agent> { mother, father }); if(children.size() > 0) { agent res0 = mrepr.reproduce(vector<agent> { children[0], mutant })[0]; ret.push_back(res0); } if(children.size() > 1) { agent res1 = mrepr.reproduce(vector<agent> { children[1], mutant })[0]; ret.push_back(res1); } } return ret; }
void report(population& p) { switch(cfg.report_every) { case config::report::none: break; case config::report::avg: { float avg = 0.0; for(auto i = p.begin(); i != p.end(); ++i) avg += i->eval; avg /= static_cast<float>(p.size()); std::cout << iter << ' ' << avg << '\n'; } break; case config::report::best: std::cout << iter << ' ' << p[0].eval << '\n'; break; } if(cfg.report_var) { std::cout << iter << ' ' << statistics::variance(p) << '\n'; } }
void increase_tree_depth(generation_table& gtable, population& pop, int& from_depth, combo::arity_t& needed_arg_count, int fill_from_arg, const reduct::rule& reduction_rule) { for (population::iterator it = pop.begin(); it != pop.end(); ++it) { int number_of_combinations = 1; bool can_have_leaves = false; std::vector<generation_table::iterator> assignment; std::vector<combo::combo_tree::leaf_iterator> leaves; for (combo::combo_tree::leaf_iterator lit = it->begin_leaf(); lit != it->end_leaf(); ++lit) { if (combo::is_argument(*lit)) if (combo::get_argument(*lit).abs_idx() <= needed_arg_count) continue; for (std::vector<generation_node>::iterator it2 = gtable.begin(); it2 != gtable.end(); it2++) if (combo::equal_type_tree(it2->node, combo::infer_vertex_type(*it, lit))) { if (it2->glist.size() != 0) can_have_leaves = true; assignment.push_back(it2); number_of_combinations *= it2->glist.size(); break; } } if (!can_have_leaves) number_of_combinations = 0; for (int i = 0; i < number_of_combinations; i++) { combo::combo_tree temp_tree(*it); int ongoing_count = 1; leaves.clear(); for (combo::combo_tree::leaf_iterator lit = temp_tree.begin_leaf(); lit != temp_tree.end_leaf(); ++lit) leaves.push_back(lit); std::vector<generation_table::iterator>::iterator it2 = assignment.begin(); for (std::vector<combo::combo_tree::leaf_iterator>::iterator lit = leaves.begin(); lit != leaves.end(); ++lit) { if (combo::is_argument(**lit)) if (combo::get_argument(**lit).abs_idx() <= needed_arg_count) continue; if ((*it2)->glist.size() != 0) { node_list::iterator it3 = (*it2)->glist.begin(); for (int n = 0; n < (int)(i/(number_of_combinations/(ongoing_count * (*it2)->glist.size())) % (*it2)->glist.size()); n++) it3++; temp_tree.replace(*lit, *it3); ongoing_count *= (*it2)->glist.size(); } it2++; } bool erased = true; for (combo::combo_tree::leaf_iterator lit = temp_tree.begin_leaf(); lit != temp_tree.end_leaf(); ++lit) { if (combo::get_arity(*lit) != 0 && !combo::is_argument(*lit)) { erased = false; break; } } if (combo::does_contain_all_arg_up_to(temp_tree, needed_arg_count)) { erased = false; } if (!erased) { //Uses less memory but is very slow /*fill_leaves_single(temp_tree, fill_from_arg); reduced_insertion(new_pop, temp_tree, reduction_rule);*/ pop.push_front(temp_tree); } } } }
family_vector rnd_selector::select(const population&p,const int fcount) { family_vector result(fcount); for(int i=0;i<fcount;i++) result[i]=std::make_pair(m_random.uniform(0,p.size()-1), m_random.uniform(0,p.size()-1)); return result; }
void adapt_population(population& p) { float F_min = min_element(p.begin(),p.end(),eval_comp)->eval; for(unsigned int i=0; i<p.size(); i++) { float sum = 0.0; for(unsigned int j=0; j<p.size(); j++) sum += p[j].eval - F_min; p[i].adapt = (p[i].eval - F_min)/sum; } }
std::vector<population::individual_type> best_s_policy::select(const population &pop) const { const population::size_type migration_rate = get_n_individuals(pop); // Create a temporary array of individuals. std::vector<population::individual_type> result(pop.begin(),pop.end()); // Sort the individuals (best go first). std::sort(result.begin(),result.end(),dom_comp(pop)); // Leave only desired number of elements in the result. result.erase(result.begin() + migration_rate,result.end()); return result; }
void fill_leaves(population& pop, int& from_arg) { for (population::iterator it = pop.begin(); it != pop.end(); ++it) { int local_from_arg = from_arg; for (combo::combo_tree::leaf_iterator lit = it->begin_leaf(); lit != it->end_leaf(); ++lit) { if (!combo::is_argument(*lit)) { combo::arity_t number_of_leaves = combo::get_arity(*lit); if (number_of_leaves < 0) number_of_leaves = -1 * number_of_leaves + 1; for (combo::arity_t count = 0; count < number_of_leaves; count++) { (*it).append_child(lit, combo::argument(++local_from_arg)); } } } } }
void ms::evolve(population &pop) const { // Let's store some useful variables. const population::size_type NP = pop.size(); // Get out if there is nothing to do. if (m_starts == 0 || NP == 0) { return; } // Local population used in the algorithm iterations. population working_pop(pop); //ms main loop for (int i=0; i< m_starts; ++i) { working_pop.reinit(); m_algorithm->evolve(working_pop); if (working_pop.problem().compare_fc(working_pop.get_individual(working_pop.get_best_idx()).cur_f,working_pop.get_individual(working_pop.get_best_idx()).cur_c, pop.get_individual(pop.get_worst_idx()).cur_f,pop.get_individual(pop.get_worst_idx()).cur_c ) ) { //update best population replacing its worst individual with the good one just produced. pop.set_x(pop.get_worst_idx(),working_pop.get_individual(working_pop.get_best_idx()).cur_x); pop.set_v(pop.get_worst_idx(),working_pop.get_individual(working_pop.get_best_idx()).cur_v); } if (m_screen_output) { std::cout << i << ". " << "\tCurrent iteration best: " << working_pop.get_individual(working_pop.get_best_idx()).cur_f << "\tOverall champion: " << pop.champion().f << std::endl; } } }
void mutation_function(population& p) { for(auto i = p.begin(); i != p.end(); ++i) { float prob = 1 - i->adapt; // probability of mutation float r = uniform_random(); // random float between <0,1) if(r < prob) { mutation::random_transposition(i->perm); i->eval = evaluation(i->perm); // after mutation is done we have to evaluate this specimen again } } }
void replacement(population& p) { std::sort(p.begin(), p.end(), eval_cmp()); p.resize(population_size); if( p[0].eval < best_specimen.eval ) { best_specimen = p[0]; deviate_count = 0; } else { deviate_count++; } }
void allocate_pop(population &pop,size_t NumDims,int stra_num,int num_obj) { size_t pop_size=pop.size(); size_t i; for ( i=0;i<pop_size;i++ ) allocate_ind(pop[i],NumDims,stra_num,num_obj); }
void reallocate_stra(population &pop,int stra_idx,int size,double val) { int pop_size=pop.size(); int i; for ( i=0;i<pop_size;i++ ) pop[i].stra[stra_idx].assign(size,val); }
std::vector<std::pair<population::size_type,std::vector<population::individual_type>::size_type> > random_r_policy::select(const std::vector<population::individual_type> &immigrants, const population &dest) const { const population::size_type rate_limit = std::min<population::size_type>(get_n_individuals(dest),boost::numeric_cast<population::size_type>(immigrants.size())); // Temporary vectors to store sorted indices of the populations. std::vector<population::size_type> immigrants_idx(boost::numeric_cast<std::vector<population::size_type>::size_type>(immigrants.size())); std::vector<population::size_type> dest_idx(boost::numeric_cast<std::vector<population::size_type>::size_type>(dest.size())); // Fill in the arrays of indices. iota(immigrants_idx.begin(),immigrants_idx.end(),population::size_type(0)); iota(dest_idx.begin(),dest_idx.end(),population::size_type(0)); // Permute the indices (immigrants). for (population::size_type i = 0; i < rate_limit; ++i) { population::size_type next_idx = i + (m_urng() % (rate_limit - i)); if (next_idx != i) { std::swap(immigrants_idx[i], immigrants_idx[next_idx]); } } // Permute the indices (destination). for (population::size_type i = 0; i < rate_limit; ++i) { population::size_type next_idx = i + (m_urng() % (dest.size() - i)); if (next_idx != i) { std::swap(dest_idx[i], dest_idx[next_idx]); } } // Return value. std::vector<std::pair<population::size_type,std::vector<population::individual_type>::size_type> > retval; for (population::size_type i = 0; i < rate_limit; ++i) { retval.push_back(std::make_pair(dest_idx[i],immigrants_idx[i])); } return retval; }
/** * @param[in] pop input population. * * @return the number of individuals to be migrated from/to the population according to the current migration rate and type. */ population::size_type base::get_n_individuals(const population &pop) const { population::size_type retval = 0; switch (m_type) { case absolute: retval = boost::numeric_cast<population::size_type>(m_rate); if (retval > pop.size()) { pagmo_throw(value_error,"absolute migration rate is higher than population size"); } break; case fractional: retval = boost::numeric_cast<population::size_type>(double_to_int::convert(m_rate * pop.size())); pagmo_assert(retval <= pop.size()); } return retval; }
void report_end(population& p) { if(cfg.report_every == config::report::none) { if(cfg.report_population) { if(cfg.debug) { std::cout << "Reporting population\n"; std::cout << "Evaluation = [ permutation ]\n"; } std::sort(p.begin(), p.end(), eval_cmp()); for(auto i = p.begin(); i != p.end(); ++i) std::cout << i->eval << " = " << i->perm << std::endl; } if(cfg.report_best) { if(cfg.debug) { std::cout << "Reporting best speciman\n"; std::cout << "Evaluation = [ permutation ]\n"; } std::cout << best_specimen.eval << " = " << best_specimen.perm << std::endl; } if(cfg.optimum > -1) { if(cfg.debug) { std::cout << "Reporting number of iterations needed to compute best specimen with given optimum value or --max-iter if optimum is not reached\n"; } std::cout << iter << "\n"; } if(cfg.compare_operators) { std::cout << "ox = " << ox_count << "\n"; std::cout << "cx = " << cx_count << "\n"; std::cout << "pmx = " << pmx_count << "\n"; std::cout << "crossovers = " << x_count << "\n"; } } }
void init_prev_population() { for(int i = 0; i < population_size; ++i) { specimen s; s.perm = permutation(N); s.eval = s.adapt = 0.0; prev_population.push_back(s); } }
std::vector<population::individual_type> best_kill_s_policy::select(population &pop) const { pagmo_assert(get_n_individuals(pop) <= pop.size()); // Gets the number of individuals to select const population::size_type migration_rate = get_n_individuals(pop); // Create a temporary array of individuals. std::vector<population::individual_type> result; // Gets the indexes of the best individuals std::vector<population::size_type> best_idx = pop.get_best_idx(migration_rate); // Puts the best individuals in results for (population::size_type i =0; i< migration_rate; ++i) { result.push_back(pop.get_individual(best_idx[i])); } // Remove them from the original population // (note: the champion will still carry information on the best guy ...) for (population::size_type i=0 ; i<migration_rate; ++i) { pop.reinit(best_idx[i]); } return result; }
void reallocate_stra(population &pop,population &trial_pop,int stra_idx,int size,double val) { int pop_size=pop.size(); int tri_pop_size=trial_pop.size(); if ( pop_size!=tri_pop_size ) { stringstream ss_err; ss_err<<"\n" <<"Error in reallocate_stra:" <<"pop and trial_pop's size mismatch." <<"\n"; throw logic_error(ss_err.str()); } int i; for ( i=0;i<pop_size;i++ ) { pop[i].stra[stra_idx].assign(size,val); trial_pop[i].stra[stra_idx].assign(size,val); } }
/// Evolve method. void monte_carlo::evolve(population &pop) const { // Let's store some useful variables. const problem::base &prob = pop.problem(); const problem::base::size_type prob_dimension = prob.get_dimension(), prob_i_dimension = prob.get_i_dimension(); const decision_vector &lb = prob.get_lb(), &ub = prob.get_ub(); const population::size_type pop_size = pop.size(); // Get out if there is nothing to do. if (pop_size == 0 || m_max_eval == 0) { return; } // Initialise temporary decision vector, fitness vector and decision vector. decision_vector tmp_x(prob_dimension); fitness_vector tmp_f(prob.get_f_dimension()); constraint_vector tmp_c(prob.get_c_dimension()); // Main loop. for (std::size_t i = 0; i < m_max_eval; ++i) { // Generate a random decision vector. for (problem::base::size_type j = 0; j < prob_dimension - prob_i_dimension; ++j) { tmp_x[j] = boost::uniform_real<double>(lb[j],ub[j])(m_drng); } for (problem::base::size_type j = prob_dimension - prob_i_dimension; j < prob_dimension; ++j) { tmp_x[j] = boost::uniform_int<int>(lb[j],ub[j])(m_urng); } // Compute fitness and constraints. prob.objfun(tmp_f,tmp_x); prob.compute_constraints(tmp_c,tmp_x); // Locate the worst individual. const population::size_type worst_idx = pop.get_worst_idx(); if (prob.compare_fc(tmp_f,tmp_c,pop.get_individual(worst_idx).cur_f,pop.get_individual(worst_idx).cur_c)) { pop.set_x(worst_idx,tmp_x); } } }
// perform (\lambda+\mu) -> (\lambda) selection void dgea_alg::select(population& pop, population& child_pop) { int pop_size=pop.size(); int num_dims=m_ppara->get_dim(); int i; population pop_merged(pop_size); vector<vector<double> > prev_x(pop_size); for ( i=0;i<pop_size;i++ ) { prev_x[i].resize(num_dims); pop_merged[i]=pop[i]; // record previous x prev_x[i]=pop[i].x; }// for every individual // push child population at the tail of merged population copy( child_pop.begin(),child_pop.end(),back_inserter(pop_merged) ); nth_element(pop_merged.begin(), pop_merged.begin()+pop_size, pop_merged.end()); //// heap sorting //make_heap(pop_merged.begin(),pop_merged.end()); //for ( i=0;i<pop_size;i++ ) //{ // // record delta x for stat purpose // pop_heap(pop_merged.begin(),pop_merged.end()); // pop_merged.pop_back(); // const individual& new_ind=pop_merged.front(); // pop[i]=new_ind; // m_alg_stat.delta_x[i]=pop[i].x-prev_x[i];// pop_merged:{parents,offsprings} //} for ( i=0;i<pop_size;i++ ) { pop[i]=pop_merged[i]; // record delta x m_alg_stat.delta_x[i] = (pop[i].x-prev_x[i]); }// for every individual }// end function select
/** * Updates the constraints scaling vector with the given population. * @param[in] population pop. */ void cstrs_self_adaptive::update_c_scaling(const population &pop) { if(*m_original_problem != pop.problem()) { pagmo_throw(value_error,"The problem linked to the population is not the same as the problem given in argument."); } // Let's store some useful variables. const population::size_type pop_size = pop.size(); // get the constraints dimension //constraint_vector c(m_original_problem->get_c_dimension(), 0.); problem::base::c_size_type prob_c_dimension = m_original_problem->get_c_dimension(); problem::base::c_size_type number_of_eq_constraints = m_original_problem->get_c_dimension() - m_original_problem->get_ic_dimension(); const std::vector<double> &c_tol = m_original_problem->get_c_tol(); m_c_scaling.resize(m_original_problem->get_c_dimension()); std::fill(m_c_scaling.begin(),m_c_scaling.end(),0.); // evaluates the scaling factor for(population::size_type i=0; i<pop_size; i++) { // updates the current constraint vector const population::individual_type ¤t_individual = pop.get_individual(i); const constraint_vector &c = current_individual.cur_c; // computes scaling with the right definition of the constraints (can be in base problem? currently used // by con2mo as well) for(problem::base::c_size_type j=0; j<number_of_eq_constraints; j++) { m_c_scaling[j] = std::max(m_c_scaling[j], std::max(0., (std::abs(c.at(j)) - c_tol.at(j))) ); } for(problem::base::c_size_type j=number_of_eq_constraints; j<prob_c_dimension; j++) { m_c_scaling[j] = std::max(m_c_scaling[j], std::max(0., c.at(j) - c_tol.at(j)) ); } } }
void enumerate_program_trees(generation_table& gtable, int depth, combo::type_tree& ttree, population& pop, const reduct::rule& reduction_rule) { pop.clear(); // For each generation node with the right return-type, add it to the pop for (std::vector<generation_node>::iterator it = gtable.begin(); it != gtable.end(); ++it) { if (combo::equal_type_tree(it->node, combo::get_signature_output(ttree))) { for (node_list::iterator it2 = it->glist.begin(); it2 != it->glist.end(); it2++) pop.push_back(combo::combo_tree(*it2)); break; } } // add the right number of arguments int from_arg = combo::get_signature_inputs(ttree).size(); combo::arity_t needed_arg_count = combo::type_tree_arity(ttree); std::cout << ttree << " " << needed_arg_count << std::endl; for (int i = 1; i < depth; i++) { fill_leaves(pop, from_arg); reduce(pop, reduction_rule); increase_tree_depth(gtable, pop, i, needed_arg_count, from_arg, reduction_rule); } for (population::iterator it = pop.begin(); it != pop.end();) { bool erased = false; for (combo::combo_tree::leaf_iterator lit = it->begin_leaf(); lit != it->end_leaf(); ++lit) { if (get_arity(*lit) != 0 && !combo::is_argument(*lit)) { erased = true; break; } } if (!combo::does_contain_all_arg_up_to(*it, needed_arg_count)) { erased = true; } if (erased) it = pop.erase(it); else ++it; } }
// tournament selection without replacement // the individuals that survive reproduction are placed in the mating pool void tselect_without_replacement( population &pop ) { int *shuffle = new int [pop.popsize()]; int pick; int s = parameter::tournament_size; pre_tselect_without_replacement( shuffle, pick, pop.popsize() );//take pick to zero & shuffle the shuffle array (permutation) pop.MatingPool[0]=pop.best(); for( int i=1; i< pop.popsize(); i++ ) { if( pick+s > pop.popsize() ) pre_tselect_without_replacement( shuffle, pick, pop.popsize() ); pop.MatingPool[i] = pop.tournament_winner( shuffle, pick, s ); } delete [] shuffle; }
family_vector niche_ga::select(const population&p,int count) { dna_cmeans::u_vector data=fill_data_vector(p); int cluster_count=static_cast<int>(p.size()*0.10); dna_cmeans::result r; if(call_nums>=10){ call_nums=0; cm.m_center_sequence.erase(cm.m_center_sequence.begin(),cm.m_center_sequence.end()); } if(cm.m_center_sequence.size()==0){ r=cm.cluster(dna_distance,cluster_count,data.begin(),data.end(),data.size(),1.0); } else{ r=cm.cluster(dna_distance,data.begin(),data.end(),data.size()); } call_nums++; clusters cls=dna_cmeans::u2clsuters(r.u); Random rnd; family_vector result(count); int c=0; // сколько мы уже отобрали для скрещивания while(c!=count){ int father_cluster=rnd.uniform(0,cls.size()-1); if(cls[father_cluster].size()<2) continue; int father_index=rnd.uniform(0,cls[father_cluster].size()-1); int mather_cluster=father_cluster; int mather_index=rnd.uniform(0,cls[mather_cluster].size()-1); result[c]=std::make_pair(cls[father_cluster][father_index].first, cls[mather_cluster][mather_index].first); c++; } return result; }
bool simpleLSM_job::eval_population_fitness(population &pop) { char pwd[FILENAME_MAX]; getcwd(pwd, sizeof(pwd)); log.debug("Current working directory", pwd); float cputime=0; float walltime=0; for (sample &s : pop) { prepare_work_dir_for_sample(s); boost::timer::cpu_timer timer; eval_sample_fitness(s); boost::timer::cpu_times elapsed = timer.elapsed(); log.debug(" CPU TIME: ", (elapsed.user + elapsed.system) / 1e9, " seconds", ", WALLCLOCK TIME: ", elapsed.wall / 1e9, " seconds"); cputime+=((elapsed.user + elapsed.system) / 1e9); walltime+=(elapsed.wall / 1e9); } log.debug("total CPU TIME:", cputime, "total WALLCLOCK TIME:", walltime); log.debug("avergae CPU TIME:", cputime/pop.size(), "avergae WALLCLOCK TIME:", walltime/pop.size()); return true; }
/** * Constructor using initial constrained problem * * Note: This problem is not inteded to be used by itself. Instead use the * self-adaptive algorithm if you want to solve constrained problems. * * @param[in] problem base::problem to be modified to use a self-adaptive * as constraints handling technique. * @param[in] pop population to be used to set up the penalty coefficients. * */ cstrs_self_adaptive::cstrs_self_adaptive(const base &problem, const population &pop): base_meta( problem, problem.get_dimension(), problem.get_i_dimension(), problem.get_f_dimension(), 0, 0, std::vector<double>()), m_apply_penalty_1(false), m_scaling_factor(0.0), m_c_scaling(problem.get_c_dimension(),0.0), m_f_hat_down(problem.get_f_dimension(),0.0), m_f_hat_up(problem.get_f_dimension(),0.0), m_f_hat_round(problem.get_f_dimension(),0.0), m_i_hat_down(0.0), m_i_hat_up(0.0), m_i_hat_round(0.0), m_map_fitness(), m_map_constraint(), m_decision_vector_hash() { if(m_original_problem->get_c_dimension() <= 0){ pagmo_throw(value_error,"The original problem has no constraints."); } // check that the dimension of the problem is 1 if (m_original_problem->get_f_dimension() != 1) { pagmo_throw(value_error,"The original fitness dimension of the problem must be one, multi objective problems can't be handled with self adaptive meta problem."); } if(problem != pop.problem()) { pagmo_throw(value_error,"The problem linked to the population is not the same as the problem given in argument."); } update_penalty_coeff(pop); }
void erase_duplicate(population& pop) { pop.sort(opencog::size_tree_order<combo::vertex>()); pop.unique(); }
population choosiness_breeder::breed(const population &generation, const std::vector<double> &fitnesses) const { using namespace std; population ret; tree_crossover_reproducer repr; node_crossover_reproducer mrepr; builder random_builder; deque<const agent *> mut_gen; for(const auto &a : generation) mut_gen.push_back(&a); experimental_parameters e = exp_params(); const uint32_t growth_tree_min = e["growth_tree_min"]; const uint32_t growth_tree_max = e["growth_tree_max"]; const double max_dist = sqrt(_maze.rows() * _maze.rows() + _maze.columns() * _maze.columns()); _phenotypes.clear(); for(const auto &a : mut_gen) _phenotypes.at(a->final_state().row, a->final_state().col).push_back(a); map<const agent *, vector<const agent *> > matches; for(auto ait = mut_gen.begin(); ait != mut_gen.end();) { const agent *const a = *ait; const vector<vector<const agent *> > plausible_mates = _phenotypes.find_in_range(a->final_state().row, a->final_state().col, a->chromosomes()[0]); vector<const agent *> flattened_mates; for(const auto &v : plausible_mates) flattened_mates.insert(flattened_mates.end(), v.begin(), v.end()); for(auto it = flattened_mates.begin(); it != flattened_mates.end();) { if(distance((*it)->final_state().col, (*it)->final_state().row, a->final_state().col, a->final_state().row) > (*it)->chromosomes()[0]) { it = flattened_mates.erase(it); continue; } ++it; } if(flattened_mates.empty()) { ait = mut_gen.erase(ait); continue; } matches[a] = flattened_mates; ++ait; } const population::size_type new_size = generation.size(); random_shuffle(mut_gen.begin(), mut_gen.end()); while(ret.size() < new_size) { for(const auto &mother : mut_gen) { if(ret.size() >= new_size) break; const vector<const agent *> &fathers = matches[mother]; if(fathers.empty()) continue; const agent &father = *fathers[rand() % fathers.size()]; agent mutant = random_builder.grow(program_types_set, growth_tree_min, growth_tree_max); mutant.set_chromosomes(vector<double> { rand_normal() * max_dist }); vector<agent> children = repr.reproduce(vector<agent> { *mother, father }); if(children.empty()) continue; agent &child = children[0]; child.set_chromosomes(vector<double> { (mother->chromosomes()[0] + father.chromosomes()[0]) / 2.0 }); agent res = mrepr.reproduce(vector<agent> { child, mutant })[0]; res.set_chromosomes(vector<double> { (child.chromosomes()[0] + mutant.chromosomes()[0]) / 2.0 }); ret.push_back(res); } } return ret; }
/** * Run the co-evolution algorithm * * @param[in,out] pop input/output pagmo::population to be evolved. */ void cstrs_co_evolution::evolve(population &pop) const { // Let's store some useful variables. const problem::base &prob = pop.problem(); const population::size_type pop_size = pop.size(); const problem::base::size_type prob_dimension = prob.get_dimension(); // get the constraints dimension problem::base::c_size_type prob_c_dimension = prob.get_c_dimension(); //We perform some checks to determine wether the problem/population are suitable for co-evolution if(prob_c_dimension < 1) { pagmo_throw(value_error,"The problem is not constrained and co-evolution is not suitable to solve it"); } if(prob.get_f_dimension() != 1) { pagmo_throw(value_error,"The problem is multiobjective and co-evolution is not suitable to solve it"); } // Get out if there is nothing to do. if(pop_size == 0) { return; } //get the dimension of the chromosome of P2 unsigned int pop_2_dim = 0; switch(m_method) { case algorithm::cstrs_co_evolution::SIMPLE: { pop_2_dim = 2; break; } case algorithm::cstrs_co_evolution::SPLIT_NEQ_EQ: { pop_2_dim = 4; break; } case algorithm::cstrs_co_evolution::SPLIT_CONSTRAINTS: pop_2_dim = 2*prob.get_c_dimension(); break; default: pagmo_throw(value_error,"The constraints co-evolutionary method is not valid."); break; } // split the population into two populations // the population P1 associated to the modified problem with penalized fitness // and population P2 encoding the penalty weights // Populations size population::size_type pop_1_size = pop_size; population::size_type pop_2_size = m_pop_penalties_size; //Creates problem associated to P2 problem::cstrs_co_evolution_penalty prob_2(prob,pop_2_dim,pop_2_size); prob_2.set_bounds(m_pen_lower_bound,m_pen_upper_bound); //random initialization of the P2 chromosome (needed for the fist generation) std::vector<decision_vector> pop_2_x(pop_2_size); std::vector<fitness_vector> pop_2_f(pop_2_size); for(population::size_type j=0; j<pop_2_size; j++) { pop_2_x[j] = decision_vector(pop_2_dim,0.); // choose random coefficients between lower bound and upper bound for(population::size_type i=0; i<pop_2_dim;i++) { pop_2_x[j][i] = boost::uniform_real<double>(m_pen_lower_bound,m_pen_upper_bound)(m_drng); } } //vector of the population P1. Initialized with clones of the original population std::vector<population> pop_1_vector; for(population::size_type i=0; i<pop_2_size; i++){ pop_1_vector.push_back(population(pop)); } // Main Co-Evolution loop for(int k=0; k<m_gen; k++) { // for each individuals of pop 2, evolve the current population, // and store the position of the feasible idx for(population::size_type j=0; j<pop_2_size; j++) { problem::cstrs_co_evolution prob_1(prob, pop_1_vector.at(j), m_method); // modify the problem by setting decision vector encoding penalty // coefficients w1 and w2 in prob 1 prob_1.set_penalty_coeff(pop_2_x.at(j)); // creating the POPULATION 1 instance based on the // updated prob 1 // prob_1 is a BASE_META???? THE CLONE OF prob_1 IN POP_1 IS AT THE LEVEL OF // THE BASE CLASS AND NOT AT THE LEVEL OF THE BASE_META, NO?!? population pop_1(prob_1,0); // initialize P1 chromosomes. The fitnesses related to problem 1 are computed for(population::size_type i=0; i<pop_1_size; i++) { pop_1.push_back(pop_1_vector.at(j).get_individual(i).cur_x); } // evolve the P1 instance m_original_algo->evolve(pop_1); //updating the original problem population (computation of fitness and constraints) pop_1_vector.at(j).clear(); for(population::size_type i=0; i<pop_1_size; i++){ pop_1_vector.at(j).push_back(pop_1.get_individual(i).cur_x); } // set up penalization variables needs for the population 2 // the constraints has not been evaluated yet. prob_2.update_penalty_coeff(j,pop_2_x.at(j),pop_1_vector.at(j)); } // creating the POPULATION 2 instance based on the // updated prob 2 population pop_2(prob_2,0); // compute the fitness values of the second population for(population::size_type i=0; i<pop_2_size; i++) { pop_2.push_back(pop_2_x[i]); } m_original_algo_penalties->evolve(pop_2); // store the new chromosomes for(population::size_type i=0; i<pop_2_size; i++) { pop_2_x[i] = pop_2.get_individual(i).cur_x; pop_2_f[i] = pop_2.get_individual(i).cur_f; } // Check the exit conditions (every 40 generations, just as DE) if(k % 40 == 0) { // finds the best population population::size_type best_idx = 0; for(population::size_type j=1; j<pop_2_size; j++) { if(pop_2_f[j][0] < pop_2_f[best_idx][0]) { best_idx = j; } } const population ¤t_population = pop_1_vector.at(best_idx); decision_vector tmp(prob_dimension); double dx = 0; for(decision_vector::size_type i=0; i<prob_dimension; i++) { tmp[i] = current_population.get_individual(current_population.get_worst_idx()).best_x[i] - current_population.get_individual(current_population.get_best_idx()).best_x[i]; dx += std::fabs(tmp[i]); } if(dx < m_xtol ) { if (m_screen_output) { std::cout << "Exit condition -- xtol < " << m_xtol << std::endl; } break; } double mah = std::fabs(current_population.get_individual(current_population.get_worst_idx()).best_f[0] - current_population.get_individual(current_population.get_best_idx()).best_f[0]); if(mah < m_ftol) { if(m_screen_output) { std::cout << "Exit condition -- ftol < " << m_ftol << std::endl; } break; } // outputs current values if(m_screen_output) { std::cout << "Generation " << k << " ***" << std::endl; std::cout << " Best global fitness: " << current_population.champion().f << std::endl; std::cout << " xtol: " << dx << ", ftol: " << mah << std::endl; std::cout << " xtol: " << dx << ", ftol: " << mah << std::endl; } } } // find the best fitness population in the final pop population::size_type best_idx = 0; for(population::size_type j=1; j<pop_2_size; j++) { if(pop_2_f[j][0] < pop_2_f[best_idx][0]) { best_idx = j; } } // store the final population in the main population // can't avoid to recompute the vectors here, otherwise we // clone the problem stored in the population with the // pop = operator! pop.clear(); for(population::size_type i=0; i<pop_1_size; i++) { pop.push_back(pop_1_vector.at(best_idx).get_individual(i).cur_x); } }
/** * Updates the penalty coefficients with the given population. * @param[in] population pop. */ void cstrs_self_adaptive::update_penalty_coeff(const population &pop) { if(*m_original_problem != pop.problem()) { pagmo_throw(value_error,"The problem linked to the population is not the same as the problem given in argument."); } // Let's store some useful variables. const population::size_type pop_size = pop.size(); // Get out if there is nothing to do. if (pop_size == 0) { return; } m_map_fitness.clear(); m_map_constraint.clear(); // store f and c in maps depending on the the x hash for(population::size_type i=0; i<pop_size; i++) { const population::individual_type ¤t_individual = pop.get_individual(i); // m_map_fitness.insert(std::pair<std::size_t, fitness_vector>(m_decision_vector_hash(current_individual.cur_x),current_individual.cur_f)); m_map_fitness[m_decision_vector_hash(current_individual.cur_x)]=current_individual.cur_f; m_map_constraint[m_decision_vector_hash(current_individual.cur_x)]=current_individual.cur_c; } std::vector<population::size_type> feasible_idx(0); std::vector<population::size_type> infeasible_idx(0); // store indexes of feasible and non feasible individuals for(population::size_type i=0; i<pop_size; i++) { const population::individual_type ¤t_individual = pop.get_individual(i); if(m_original_problem->feasibility_c(current_individual.cur_c)) { feasible_idx.push_back(i); } else { infeasible_idx.push_back(i); } } // if the population is only feasible, then nothing is done if(infeasible_idx.size() == 0) { update_c_scaling(pop); m_apply_penalty_1 = false; m_scaling_factor = 0.; return; } m_apply_penalty_1 = false; m_scaling_factor = 0.; // updates the c_scaling, needed for solution infeasibility computation update_c_scaling(pop); // evaluate solutions infeasibility //compute_pop_solution_infeasibility(solution_infeasibility, pop); std::vector<double> solution_infeasibility(pop_size); std::fill(solution_infeasibility.begin(),solution_infeasibility.end(),0.); // evaluate solutions infeasibility solution_infeasibility.resize(pop_size); std::fill(solution_infeasibility.begin(),solution_infeasibility.end(),0.); for(population::size_type i=0; i<pop_size; i++) { const population::individual_type ¤t_individual = pop.get_individual(i); // compute the infeasibility of the constraint solution_infeasibility[i] = compute_solution_infeasibility(current_individual.cur_c); } // search position of x_hat_down, x_hat_up and x_hat_round population::size_type hat_down_idx = -1; population::size_type hat_up_idx = -1; population::size_type hat_round_idx = -1; // first case, the population contains at least one feasible solution if(feasible_idx.size() > 0) { // initialize hat_down_idx hat_down_idx = feasible_idx.at(0); // x_hat_down = feasible individual with lowest objective value in p for(population::size_type i=0; i<feasible_idx.size(); i++) { const population::size_type current_idx = feasible_idx.at(i); const population::individual_type ¤t_individual = pop.get_individual(current_idx); if(m_original_problem->compare_fitness(current_individual.cur_f, pop.get_individual(hat_down_idx).cur_f)) { hat_down_idx = current_idx; } } // hat down is now available fitness_vector f_hat_down = pop.get_individual(hat_down_idx).cur_f; // x_hat_up value depends if the population contains infeasible individual with objective // function better than f_hat_down bool pop_contains_infeasible_f_better_x_hat_down = false; for(population::size_type i=0; i<infeasible_idx.size(); i++) { const population::size_type current_idx = infeasible_idx.at(i); const population::individual_type ¤t_individual = pop.get_individual(current_idx); if(m_original_problem->compare_fitness(current_individual.cur_f, f_hat_down)) { pop_contains_infeasible_f_better_x_hat_down = true; // initialize hat_up_idx hat_up_idx = current_idx; break; } } if(pop_contains_infeasible_f_better_x_hat_down) { // hat_up_idx is already initizalized // gets the individual with maximum infeasibility and objfun lower than f_hat_down for(population::size_type i=0; i<infeasible_idx.size(); i++) { const population::size_type current_idx = infeasible_idx.at(i); const population::individual_type ¤t_individual = pop.get_individual(current_idx); if(m_original_problem->compare_fitness(current_individual.cur_f, f_hat_down) && (solution_infeasibility.at(current_idx) >= solution_infeasibility.at(hat_up_idx)) ) { if(solution_infeasibility.at(current_idx) == solution_infeasibility.at(hat_up_idx)) { if(m_original_problem->compare_fitness(current_individual.cur_f, pop.get_individual(hat_up_idx).cur_f)) { hat_up_idx = current_idx; } } else { hat_up_idx = current_idx; } } } // apply penalty 1 m_apply_penalty_1 = true; } else { // all the infeasible soutions have an objective function value greater than f_hat_down // the worst is the one that has the maximum infeasibility // initialize hat_up_idx hat_up_idx = infeasible_idx.at(0); for(population::size_type i=0; i<infeasible_idx.size(); i++) { const population::size_type current_idx = infeasible_idx.at(i); const population::individual_type ¤t_individual = pop.get_individual(current_idx); if(solution_infeasibility.at(current_idx) >= solution_infeasibility.at(hat_up_idx)) { if(solution_infeasibility.at(current_idx) == solution_infeasibility.at(hat_up_idx)) { if(m_original_problem->compare_fitness(pop.get_individual(hat_up_idx).cur_f, current_individual.cur_f)) { hat_up_idx = current_idx; } } else { hat_up_idx = current_idx; } } } // do not apply penalty 1 m_apply_penalty_1 = false; } } else { // case where there is no feasible solution in the population // best is the individual with the lowest infeasibility hat_down_idx = 0; hat_up_idx = 0; for(population::size_type i=0; i<pop_size; i++) { const population::individual_type ¤t_individual = pop.get_individual(i); if(solution_infeasibility.at(i) <= solution_infeasibility.at(hat_down_idx)) { if(solution_infeasibility.at(i) == solution_infeasibility.at(hat_down_idx)) { if(m_original_problem->compare_fitness(current_individual.cur_f, pop.get_individual(hat_down_idx).cur_f)) { hat_down_idx = i; } } else { hat_down_idx = i; } } } // worst individual for(population::size_type i=0; i<pop_size; i++) { const population::individual_type ¤t_individual = pop.get_individual(i); if(solution_infeasibility.at(i) >= solution_infeasibility.at(hat_up_idx)) { if(solution_infeasibility.at(i) == solution_infeasibility.at(hat_up_idx)) { if(m_original_problem->compare_fitness(pop.get_individual(hat_up_idx).cur_f, current_individual.cur_f)) { hat_up_idx = i; } } else { hat_up_idx = i; } } } // apply penalty 1 to the population m_apply_penalty_1 = true; } // stores the hat round idx, i.e. the solution with highest objective // function value in the population hat_round_idx = 0; for(population::size_type i=0; i<pop_size; i++) { const population::individual_type ¤t_individual = pop.get_individual(i); if(m_original_problem->compare_fitness(pop.get_individual(hat_round_idx).cur_f, current_individual.cur_f)) { hat_round_idx = i; } } // get the objective function values of the three individuals m_f_hat_round = pop.get_individual(hat_round_idx).cur_f; m_f_hat_down = pop.get_individual(hat_down_idx).cur_f; m_f_hat_up = pop.get_individual(hat_up_idx).cur_f; // get the solution infeasibility values of the three individuals m_i_hat_round = solution_infeasibility.at(hat_round_idx); m_i_hat_down = solution_infeasibility.at(hat_down_idx); m_i_hat_up = solution_infeasibility.at(hat_up_idx); // computes the scaling factor m_scaling_factor = 0.; // evaluates scaling factor if(m_original_problem->compare_fitness(m_f_hat_down, m_f_hat_up)) { m_scaling_factor = (m_f_hat_round[0] - m_f_hat_up[0]) / m_f_hat_up[0]; } else { m_scaling_factor = (m_f_hat_round[0] - m_f_hat_down[0]) / m_f_hat_down[0]; } if(m_f_hat_up[0] == m_f_hat_round[0]) { m_scaling_factor = 0.; } }