30 bool operator()(
const DifferentialEvolution::Candidate& left,
31 const DifferentialEvolution::Candidate& right) {
32 return left.cost < right.cost;
37 void randomize(I begin, I end,
38 const MersenneTwisterUniformRng& rng) {
40 for (
Size i=
n-1; i>0; --i) {
41 std::swap(begin[i], begin[rng.nextInt32() % (i+1)]);
55 "wrong upper bound size in differential evolution configuration");
62 "wrong lower bound size in differential evolution configuration");
70 std::vector<Candidate> population;
73 for (
Size i = 0; i < population.size(); ++i) {
76 "wrong values size in initial population");
80 population = std::vector<Candidate>(
configuration().populationMembers,
85 std::partial_sort(population.begin(), population.begin() + 1, population.end(),
88 Real fxOld = population.front().
cost;
89 Size iteration = 0, stationaryPointIteration = 0;
94 std::partial_sort(population.begin(), population.begin() + 1, population.end(),
98 Real fxNew = population.front().
cost;
110 std::vector<Candidate>& population,
113 std::vector<Candidate> mirrorPopulation;
114 std::vector<Candidate> oldPopulation = population;
119 randomize(population.begin(), population.end(),
rng_);
120 std::vector<Candidate> shuffledPop1 = population;
121 randomize(population.begin(), population.end(),
rng_);
122 std::vector<Candidate> shuffledPop2 = population;
123 randomize(population.begin(), population.end(),
rng_);
124 mirrorPopulation = shuffledPop1;
126 for (
Size popIter = 0; popIter < population.size(); popIter++) {
127 population[popIter].values = population[popIter].values
129 * (shuffledPop1[popIter].values - shuffledPop2[popIter].values);
135 randomize(population.begin(), population.end(),
rng_);
136 std::vector<Candidate> shuffledPop1 = population;
137 randomize(population.begin(), population.end(),
rng_);
138 Array jitter(population[0].values.size(), 0.0);
140 for (
Size popIter = 0; popIter < population.size(); popIter++) {
141 for (
Real& jitterIter : jitter) {
145 + (shuffledPop1[popIter].values - population[popIter].values)
148 mirrorPopulation = std::vector<Candidate>(population.size(),
154 randomize(population.begin(), population.end(),
rng_);
155 std::vector<Candidate> shuffledPop1 = population;
156 randomize(population.begin(), population.end(),
rng_);
158 for (
Size popIter = 0; popIter < population.size(); popIter++) {
159 population[popIter].values = oldPopulation[popIter].values
163 * (population[popIter].values - shuffledPop1[popIter].values);
165 mirrorPopulation = shuffledPop1;
170 randomize(population.begin(), population.end(),
rng_);
171 std::vector<Candidate> shuffledPop1 = population;
172 randomize(population.begin(), population.end(),
rng_);
173 std::vector<Candidate> shuffledPop2 = population;
174 randomize(population.begin(), population.end(),
rng_);
175 mirrorPopulation = shuffledPop1;
176 Array FWeight =
Array(population.front().values.size(), 0.0);
177 for (
Real& fwIter : FWeight)
180 for (
Size popIter = 0; popIter < population.size(); popIter++) {
181 population[popIter].values = population[popIter].values
182 + FWeight * (shuffledPop1[popIter].values - shuffledPop2[popIter].values);
188 randomize(population.begin(), population.end(),
rng_);
189 std::vector<Candidate> shuffledPop1 = population;
190 randomize(population.begin(), population.end(),
rng_);
191 std::vector<Candidate> shuffledPop2 = population;
192 randomize(population.begin(), population.end(),
rng_);
193 mirrorPopulation = shuffledPop1;
196 for (
Size popIter = 0; popIter < population.size(); popIter++) {
197 population[popIter].values = population[popIter].values
198 + FWeight * (shuffledPop1[popIter].values - shuffledPop2[popIter].values);
204 randomize(population.begin(), population.end(),
rng_);
205 std::vector<Candidate> shuffledPop1 = population;
206 randomize(population.begin(), population.end(),
rng_);
207 std::vector<Candidate> shuffledPop2 = population;
208 randomize(population.begin(), population.end(),
rng_);
209 mirrorPopulation = shuffledPop1;
210 Real probFWeight = 0.5;
212 for (
Size popIter = 0; popIter < population.size(); popIter++) {
213 population[popIter].values = oldPopulation[popIter].values
215 * (shuffledPop1[popIter].values - shuffledPop2[popIter].values);
219 for (
Size popIter = 0; popIter < population.size(); popIter++) {
220 population[popIter].values = oldPopulation[popIter].values
222 * (shuffledPop1[popIter].values - shuffledPop2[popIter].values
223 - 2.0 * population[popIter].values);
230 randomize(population.begin(), population.end(),
rng_);
231 std::vector<Candidate> shuffledPop1 = population;
232 randomize(population.begin(), population.end(),
rng_);
233 std::vector<Candidate> shuffledPop2 = population;
234 randomize(population.begin(), population.end(),
rng_);
235 mirrorPopulation = shuffledPop1;
239 for (
Size popIter = 0; popIter < population.size(); popIter++) {
245 * (shuffledPop1[popIter].values - shuffledPop2[popIter].values);
256 crossover(oldPopulation, population, population, mirrorPopulation, p);
260 const std::vector<Candidate>& oldPopulation,
261 std::vector<Candidate>& population,
262 const std::vector<Candidate>& mutantPopulation,
263 const std::vector<Candidate>& mirrorPopulation,
272 std::vector<Array> crossoverMask(population.size(),
273 Array(population.front().values.size(), 1.0));
274 std::vector<Array> invCrossoverMask = crossoverMask;
278 for (
Size popIter = 0; popIter < population.size(); popIter++) {
279 population[popIter].values = oldPopulation[popIter].values * invCrossoverMask[popIter]
280 + mutantPopulation[popIter].values * crossoverMask[popIter];
283 for (
Size memIter = 0; memIter < population[popIter].values.size(); memIter++) {
284 if (population[popIter].values[memIter] >
upperBound_[memIter])
285 population[popIter].values[memIter] =
upperBound_[memIter]
287 * (mirrorPopulation[popIter].values[memIter]
289 if (population[popIter].values[memIter] <
lowerBound_[memIter])
290 population[popIter].values[memIter] =
lowerBound_[memIter]
292 * (mirrorPopulation[popIter].values[memIter]
298 population[popIter].cost = p.
value(population[popIter].values);
302 if (!std::isfinite(population[popIter].cost))
309 std::vector<Array> & crossoverMask,
310 std::vector<Array> & invCrossoverMask,
311 const Array & mutationProbabilities)
const {
312 for (
Size cmIter = 0; cmIter < crossoverMask.size(); cmIter++) {
313 for (
Size memIter = 0; memIter < crossoverMask[cmIter].size(); memIter++) {
315 invCrossoverMask[cmIter][memIter] = 0.0;
317 crossoverMask[cmIter][memIter] = 0.0;
324 const std::vector<Candidate> & population)
const {
331 * (1.0 - 1.0 / population.front().values.size())
332 + 1.0 / population.
front().values.size();
336 mutationProbabilities[coIter] =
338 (
int) population.
front().values.size()))
339 / (population.front().values.size()
344 QL_FAIL(
"Unknown crossover type ("
348 return mutationProbabilities;
360 Real sizeWeightLowerBound = 0.1, sizeWeightUpperBound = 0.9;
363 Real sizeWeightChangeProb = 0.1;
366 currGenSizeWeight = sizeWeightLowerBound +
rng_.
nextReal() * sizeWeightUpperBound;
371 Real crossoverChangeProb = 0.1;
379 std::vector<Candidate> & population,
386 for (
Size j = 1; j < population.size(); ++j) {
392 if (!std::isfinite(population[j].cost))
1-D array used in linear algebra.
const_iterator end() const
Size size() const
dimension of the array
const_iterator begin() const
Array lowerBound(const Array ¶ms) const
Array upperBound(const Array ¶ms) const
virtual Real value(const Array &x) const
method to overload to compute the cost function value in x
std::vector< Array > initialPopulation
void fillInitialPopulation(std::vector< Candidate > &population, const Problem &p) const
Candidate bestMemberEver_
const Configuration & configuration() const
void adaptCrossover() const
void getCrossoverMask(std::vector< Array > &crossoverMask, std::vector< Array > &invCrossoverMask, const Array &mutationProbabilities) const
MersenneTwisterUniformRng rng_
void calculateNextGeneration(std::vector< Candidate > &population, Problem &costFunction) const
void crossover(const std::vector< Candidate > &oldPopulation, std::vector< Candidate > &population, const std::vector< Candidate > &mutantPopulation, const std::vector< Candidate > &mirrorPopulation, Problem &costFunction) const
Array currGenSizeWeights_
Array getMutationProbabilities(const std::vector< Candidate > &population) const
EndCriteria::Type minimize(Problem &p, const EndCriteria &endCriteria) override
minimize the optimization problem P
@ Rand1DiffWithPerVectorDither
@ EitherOrWithOptimalRecombination
@ Rand1SelfadaptiveWithRotation
Array rotateArray(Array inputArray) const
void adaptSizeWeights() const
Criteria to end optimization process:
bool checkStationaryFunctionValue(Real fxOld, Real fxNew, Size &statStateIterations, EndCriteria::Type &ecType) const
bool checkMaxIterations(Size iteration, EndCriteria::Type &ecType) const
Constrained optimization problem.
const Array & currentValue() const
current value of the local minimum
Constraint & constraint() const
Constraint.
Real value(const Array &x)
call cost function computation and increment evaluation counter
void setFunctionValue(Real functionValue)
CostFunction & costFunction() const
Cost function.
void setCurrentValue(const Array ¤tValue)
Differential Evolution optimization method.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_FAIL(message)
throw an error (possibly with file and line information)
QL_INTEGER Integer
integer number
std::size_t Size
size of a container