63 const std::vector<Objectives>& objectives) {
64 const size_t n = objectives.size();
65 std::vector<size_t> domination_count(n, 0);
66 std::vector<std::vector<size_t>> dominates_set(n);
67 std::vector<std::vector<size_t>> fronts;
68 std::vector<size_t> current_front;
70 for (
size_t p = 0; p < n; ++p) {
71 for (
size_t q = 0; q < n; ++q) {
75 if (
Dominates(objectives[p], objectives[q])) {
76 dominates_set[p].push_back(q);
77 }
else if (
Dominates(objectives[q], objectives[p])) {
78 domination_count[p]++;
81 if (domination_count[p] == 0) {
82 current_front.push_back(p);
86 while (!current_front.empty()) {
87 fronts.push_back(current_front);
88 std::vector<size_t> next_front;
89 for (
size_t p : current_front) {
90 for (
size_t q : dominates_set[p]) {
91 if (--domination_count[q] == 0) {
92 next_front.push_back(q);
96 current_front = std::move(next_front);
116inline std::vector<double>
CrowdingDistance(
const std::vector<Objectives>& front_objectives) {
117 const size_t n = front_objectives.size();
118 std::vector<double> distances(n, 0.0);
122 const size_t num_objectives = front_objectives[0].size();
123 for (
const auto& obj : front_objectives) {
124 if (obj.size() != num_objectives) {
125 throw std::invalid_argument(
126 "CrowdingDistance: every objective vector in a front must have equal size");
130 std::fill(distances.begin(), distances.end(), std::numeric_limits<double>::infinity());
134 for (
size_t m = 0; m < num_objectives; ++m) {
135 std::vector<size_t> order(n);
136 std::iota(order.begin(), order.end(),
size_t{0});
137 std::stable_sort(order.begin(), order.end(), [&](
size_t a,
size_t b) {
138 return front_objectives[a][m] < front_objectives[b][m];
141 const double min_val = front_objectives[order.front()][m];
142 const double max_val = front_objectives[order.back()][m];
143 const double range = max_val - min_val;
145 distances[order.front()] = std::numeric_limits<double>::infinity();
146 distances[order.back()] = std::numeric_limits<double>::infinity();
151 for (
size_t i = 1; i + 1 < n; ++i) {
152 if (distances[order[i]] == std::numeric_limits<double>::infinity()) {
155 distances[order[i]] +=
156 (front_objectives[order[i + 1]][m] - front_objectives[order[i - 1]][m]) / range;
176 if (population.size() + offspring.size() < mu) {
177 throw std::invalid_argument(
178 "NSGA2Replacement: population.size() + offspring.size() must be >= mu");
181 std::vector<Individual<Genotype, Objectives>> combined = population;
182 combined.insert(combined.end(), std::make_move_iterator(offspring.begin()),
183 std::make_move_iterator(offspring.end()));
185 std::vector<Objectives> objectives;
186 objectives.reserve(combined.size());
187 for (
const auto& ind : combined) {
188 objectives.push_back(ind.fitness);
192 std::vector<Individual<Genotype, Objectives>> next_generation;
193 next_generation.reserve(mu);
194 for (
const auto& front : fronts) {
195 if (next_generation.size() + front.size() <= mu) {
196 for (
size_t idx : front) {
197 next_generation.push_back(combined[idx]);
199 if (next_generation.size() == mu) {
203 std::vector<Objectives> front_objectives;
204 front_objectives.reserve(front.size());
205 for (
size_t idx : front) {
206 front_objectives.push_back(combined[idx].fitness);
210 std::vector<size_t> order(front.size());
211 std::iota(order.begin(), order.end(),
size_t{0});
212 std::stable_sort(order.begin(), order.end(),
213 [&](
size_t a,
size_t b) { return distances[a] > distances[b]; });
215 const size_t remaining = mu - next_generation.size();
216 for (
size_t i = 0; i < remaining; ++i) {
217 next_generation.push_back(combined[front[order[i]]]);
222 return next_generation;
std::vector< Individual< Genotype, Objectives > > NSGA2Replacement(const std::vector< Individual< Genotype, Objectives > > &population, std::vector< Individual< Genotype, Objectives > > offspring, size_t mu)
NSGA-II survivor selection: combines population and offspring, fast-non-dominated- sorts the pool,...
Definition nsga2.hpp:173
bool Dominates(const Objectives &a, const Objectives &b)
Pareto dominance (maximization convention): a dominates b iff a[i] >= b[i] for every objective i,...
Definition nsga2.hpp:39
std::vector< std::vector< size_t > > FastNonDominatedSort(const std::vector< Objectives > &objectives)
Fast non-dominated sort (Deb et al. 2002, Algorithm: fast-non-dominated-sort): partitions [0,...
Definition nsga2.hpp:62