Skip to content
This repository was archived by the owner on Apr 28, 2023. It is now read-only.

Commit 9418e3a

Browse files
Theodoros Theodoridisnicolasvasilache
authored andcommitted
[genetic search] Scale fitness before selection
Using an unscaled fitness value for selection is problematic: -Outstanding individuals take over very quickly, this leads to premature convergence. -When fitness values are close together, very litle selection pressure is applied and selection is almost uniformly random. Having slightly better fitness does not improve an individual's survival chances. -Transposing the fitness function (e.g. adding a constant value) changes the selection probabilities even though the location of the optimum (and the "shape" of the fitness) remain unchanged. Scaling the fitness function helps ameliorate those issues. Sigma scaling is used: fitness' = max(fitness - (mean_fitness - 2 * std_fitness), 0)
1 parent 702d7f5 commit 9418e3a

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

tc/autotuner/genetic_search.cc

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#include "tc/autotuner/genetic_search.h"
1818

19+
#include <algorithm>
20+
#include <numeric>
1921
#include <random>
2022
#include <sstream>
2123

@@ -72,9 +74,35 @@ void mutate(
7274
}
7375
}
7476

75-
void normalizeVector(std::vector<double>& v) {
77+
double mean(std::vector<double>& v) {
78+
if (v.empty()) {
79+
throw std::invalid_argument("Cannot compute the mean of an empty vector.");
80+
}
7681
auto sum = std::accumulate(v.begin(), v.end(), 0.0);
82+
return sum / v.size();
83+
}
84+
85+
double stdv(std::vector<double>& v, double mean) {
86+
std::vector<double> diffs(v.size());
87+
std::transform(v.begin(), v.end(), diffs.begin(), [mean](double val) {
88+
return val - mean;
89+
});
90+
91+
auto squareSum =
92+
std::inner_product(diffs.begin(), diffs.end(), diffs.begin(), 0.0);
93+
return std::sqrt(squareSum / v.size());
94+
}
95+
96+
void sigmaScale(std::vector<double>& v) {
97+
auto m = mean(v);
98+
auto s = stdv(v, m);
99+
std::transform(v.begin(), v.end(), v.begin(), [m, s](double val) {
100+
return std::max(val - (m - 2 * s), 0.0);
101+
});
102+
}
77103

104+
void normalizeVector(std::vector<double>& v) {
105+
auto sum = std::accumulate(v.begin(), v.end(), 0.0);
78106
std::transform(
79107
v.begin(), v.end(), v.begin(), [sum](double v) { return v / sum; });
80108
}
@@ -90,6 +118,7 @@ std::vector<double> computeNormalizedFitness(
90118
[](const std::unique_ptr<CandidateConfiguration>& c) {
91119
return 1.0 / c->runtime.toMicroSeconds();
92120
});
121+
sigmaScale(fitness);
93122
normalizeVector(fitness);
94123
return fitness;
95124
}

0 commit comments

Comments
 (0)