@@ -162,7 +162,8 @@ void dropInvalidConfigurations(GeneticSearch::Population& population) {
162
162
} // namespace
163
163
164
164
#define VALIDATE () \
165
- CHECK_LT (kNumberElites , kMaxPopulationSize ); \
165
+ CHECK_LT (kMaxPopulationSize , kMatingPoolSize ); \
166
+ CHECK_LT (kMaxPopulationSize , kSelectionPoolSize ); \
166
167
CHECK (kMutationRate >= 0 and kMutationRate <= 100 ) \
167
168
<< " the mutation rate (" << kMutationRate \
168
169
<< " ) should be in the [0,100] interval" ; \
@@ -189,14 +190,15 @@ GeneticSearch::GeneticSearch(
189
190
size_t n,
190
191
uint8_t crossOverRate,
191
192
uint8_t mutationRate,
192
- size_t numberElites)
193
+ size_t matingPoolSize,
194
+ size_t selectionPoolSize)
193
195
: population(),
194
196
lastBestConf (confs[0 ]),
195
197
kMaxPopulationSize(n),
196
- kMatingPoolSize(n * 3 ),
198
+ kMatingPoolSize(matingPoolSize ),
197
199
kCrossOverRate(crossOverRate),
198
200
kMutationRate(mutationRate),
199
- kNumberElites(numberElites ),
201
+ kSelectionPoolSize(selectionPoolSize ),
200
202
rng{std::random_device{}()} {
201
203
restoreRngState (rng);
202
204
VALIDATE ();
@@ -222,14 +224,15 @@ GeneticSearch::GeneticSearch(
222
224
size_t n,
223
225
uint8_t crossOverRate,
224
226
uint8_t mutationRate,
225
- size_t numberElites)
227
+ size_t matingPoolSize,
228
+ size_t selectionPoolSize)
226
229
: population(),
227
230
lastBestConf (conf),
228
231
kMaxPopulationSize(n),
229
- kMatingPoolSize(n * 3 ),
232
+ kMatingPoolSize(matingPoolSize ),
230
233
kCrossOverRate(crossOverRate),
231
234
kMutationRate(mutationRate),
232
- kNumberElites(numberElites ),
235
+ kSelectionPoolSize(selectionPoolSize ),
233
236
rng{std::random_device{}()} {
234
237
restoreRngState (rng);
235
238
VALIDATE ();
@@ -301,13 +304,6 @@ void GeneticSearch::breed() {
301
304
auto matingPool =
302
305
stochasticUniversalSampling (computeAccumulatedFitness (population));
303
306
304
- Population new_population;
305
- new_population.reserve (kMatingPoolSize );
306
- for (size_t c = 0 ; c < kNumberElites ; ++c) {
307
- new_population.push_back (
308
- make_unique<CandidateConfiguration>(population.at (c)->configuration ));
309
- }
310
-
311
307
auto select = [&]() -> TuningConfiguration& {
312
308
auto idx = std::uniform_int_distribution<size_t >{
313
309
size_t (0 ), matingPool.size () - 1 }(rng);
@@ -323,44 +319,20 @@ void GeneticSearch::breed() {
323
319
return dist (rng);
324
320
};
325
321
326
- while (new_population .size () < kMaxPopulationSize ) {
322
+ while (selectionPool .size () < kSelectionPoolSize ) {
327
323
if (shouldCrossOver ()) {
328
324
auto parent1 = select ();
329
325
auto parent2 = select ();
330
326
auto parent3 = select ();
331
- new_population .emplace_back (make_unique<CandidateConfiguration>(
327
+ selectionPool .emplace_back (make_unique<CandidateConfiguration>(
332
328
crossover (parent1, parent2, parent3)));
333
329
} else {
334
- new_population.emplace_back (
335
- make_unique<CandidateConfiguration>(select ()));
330
+ selectionPool.emplace_back (make_unique<CandidateConfiguration>(select ()));
336
331
}
337
332
}
338
- population = std::move (new_population);
339
333
}
340
334
341
- void GeneticSearch::updateParameters () {
342
- dropInvalidConfigurations (population);
343
-
344
- // Sort population before taking any decision
345
- std::sort (
346
- population.begin (),
347
- population.end (),
348
- [](const std::unique_ptr<CandidateConfiguration>& a,
349
- const std::unique_ptr<CandidateConfiguration>& b) {
350
- checkRuntimeRecorded (a->runtime );
351
- checkRuntimeRecorded (b->runtime );
352
- return a->runtime < b->runtime ;
353
- });
354
-
355
- // Update failsafe lastBestConf
356
- lastBestConf =
357
- population.size () > 0 ? population.front ()->configuration : lastBestConf;
358
- if (FLAGS_tuner_print_best) {
359
- MappingOptions options (MappingOptions::makeSingleThreadMappingOptions ());
360
- lastBestConf.applyToMappingOptions (options);
361
- LOG (INFO) << " Best so far:\n " << options;
362
- }
363
-
335
+ void GeneticSearch::resetPopulationIfNotEnoughCandidates () {
364
336
if (population.size () < kMinCandidatesForBreeding ) {
365
337
LOG_IF (ERROR, FLAGS_debug_tuner)
366
338
<< population.size () << " out of " << kMaxPopulationSize
@@ -379,12 +351,69 @@ void GeneticSearch::updateParameters() {
379
351
// Don't lose the first one which was the best from before
380
352
CHECK_LT (0 , population.size ());
381
353
randomizePopulation (population.begin () + 1 , population.end (), rng);
382
- return ;
383
354
}
355
+ }
384
356
357
+ namespace {
358
+ void sortByRuntime (GeneticSearch::Population& population) {
359
+ std::sort (
360
+ population.begin (),
361
+ population.end (),
362
+ [](const std::unique_ptr<CandidateConfiguration>& a,
363
+ const std::unique_ptr<CandidateConfiguration>& b) {
364
+ checkRuntimeRecorded (a->runtime );
365
+ checkRuntimeRecorded (b->runtime );
366
+ return a->runtime < b->runtime ;
367
+ });
368
+ }
369
+ } // namespace
370
+
371
+ void GeneticSearch::updateBestCandidate (const TuningConfiguration& c) {
372
+ lastBestConf = c;
373
+ if (FLAGS_tuner_print_best) {
374
+ MappingOptions options (MappingOptions::makeSingleThreadMappingOptions ());
375
+ lastBestConf.applyToMappingOptions (options);
376
+ LOG (INFO) << " Best so far:\n " << options;
377
+ }
378
+ }
379
+
380
+ void GeneticSearch::generateSelectionPool () {
381
+ dropInvalidConfigurations (population);
382
+ sortByRuntime (population);
383
+ updateBestCandidate (
384
+ population.size () > 0 ? population.front ()->configuration : lastBestConf);
385
+ resetPopulationIfNotEnoughCandidates ();
385
386
breed ();
386
- for (int i = kNumberElites ; i < population.size (); ++i) {
387
- mutate (*population[i], kMutationRate , kMutateIterations , rng);
387
+ selectionPool.clear ();
388
+ selectionPool.emplace_back (make_unique<CandidateConfiguration>(lastBestConf));
389
+ breed ();
390
+ for (size_t i = 1 ; i < selectionPool.size (); ++i) {
391
+ mutate (*selectionPool[i], kMutationRate , kMutateIterations , rng);
392
+ }
393
+ }
394
+
395
+ void GeneticSearch::selectSurvivors () {
396
+ dropInvalidConfigurations (selectionPool);
397
+ sortByRuntime (selectionPool);
398
+ population.clear ();
399
+ std::transform (
400
+ selectionPool.begin (),
401
+ selectionPool.begin () +
402
+ std::min (selectionPool.size (), kMaxPopulationSize ),
403
+ std::back_inserter (population),
404
+ [](const std::unique_ptr<CandidateConfiguration>& c) {
405
+ return make_unique<CandidateConfiguration>(c->configuration );
406
+ });
407
+
408
+ if (selectionPool.size () < kMaxPopulationSize ) {
409
+ auto numberMissing = kMaxPopulationSize - selectionPool.size ();
410
+
411
+ for (size_t i = 0 ; i < numberMissing; ++i) {
412
+ selectionPool.emplace_back (
413
+ make_unique<CandidateConfiguration>(lastBestConf));
414
+ }
415
+ randomizePopulation (
416
+ selectionPool.end () - numberMissing, selectionPool.end (), rng);
388
417
}
389
418
}
390
419
0 commit comments