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

Commit 446b19b

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 de3eea1 commit 446b19b

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

@@ -74,9 +76,35 @@ void mutate(
7476
}
7577
}
7678

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

106+
void normalizeVector(std::vector<double>& v) {
107+
auto sum = std::accumulate(v.begin(), v.end(), 0.0);
80108
std::transform(
81109
v.begin(), v.end(), v.begin(), [sum](double v) { return v / sum; });
82110
}
@@ -92,6 +120,7 @@ std::vector<double> computeNormalizedFitness(
92120
[](const std::unique_ptr<CandidateConfiguration>& c) {
93121
return 1.0 / c->runtime.toMicroSeconds();
94122
});
123+
sigmaScale(fitness);
95124
normalizeVector(fitness);
96125
return fitness;
97126
}

0 commit comments

Comments
 (0)