std::vector<population::individual_type> hv_greedy_s_policy::select(population &pop) const { // Fall back to best_s_policy when facing a single-objective problem. if (pop.problem().get_f_dimension() == 1) { return best_s_policy(m_rate, m_type).select(pop); } 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; // Indices of fronts. std::vector< std::vector< population::size_type> > fronts_i = pop.compute_pareto_fronts(); // Fitness vectors of individuals according to the indices above. std::vector< std::vector< fitness_vector> > fronts_f (fronts_i.size()); // Nadir point is established manually later, first point is as a first "safe" candidate. fitness_vector refpoint(pop.get_individual(0).cur_f); for (unsigned int f_idx = 0 ; f_idx < fronts_i.size() ; ++f_idx) { fronts_f[f_idx].resize(fronts_i[f_idx].size()); for (unsigned int p_idx = 0 ; p_idx < fronts_i[f_idx].size() ; ++p_idx) { fronts_f[f_idx][p_idx] = fitness_vector(pop.get_individual(fronts_i[f_idx][p_idx]).cur_f); // Update the nadir point manually for efficiency. for (unsigned int d_idx = 0 ; d_idx < fronts_f[f_idx][p_idx].size() ; ++d_idx) { refpoint[d_idx] = std::max(refpoint[d_idx], fronts_f[f_idx][p_idx][d_idx]); } } } // Epsilon is added to nadir point for (unsigned int d_idx = 0 ; d_idx < refpoint.size() ; ++d_idx) { refpoint[d_idx] += m_nadir_eps; } // Store which front we process (start with front 0) and the number of processed individuals. unsigned int front_idx = 0; unsigned int processed_individuals = 0; // Vector for maintaining the original indices of points std::vector<unsigned int> orig_indices; while (processed_individuals < migration_rate) { // If we need to pull every point from given front anyway, just push back the individuals right away if (fronts_f[front_idx].size() <= (migration_rate - processed_individuals)) { for(unsigned int i = 0 ; i < fronts_i[front_idx].size() ; ++i) { result.push_back(pop.get_individual(fronts_i[front_idx][i])); } processed_individuals += fronts_f[front_idx].size(); ++front_idx; } else { // Prepare the vector for the original indices if (orig_indices.size() == 0) { orig_indices.resize(fronts_i[front_idx].size()); iota(orig_indices.begin(), orig_indices.end(), 0); } // Compute the greatest contributor hypervolume hv(fronts_f[front_idx], false); hv.set_copy_points(false); unsigned int gc_idx = hv.greatest_contributor(refpoint); result.push_back(pop.get_individual(fronts_i[front_idx][orig_indices[gc_idx]])); // Remove it from the front along with its index orig_indices.erase(orig_indices.begin() + gc_idx); fronts_f[front_idx].erase(fronts_f[front_idx].begin() + gc_idx); ++processed_individuals; } } return result; }