@@ -162,7 +162,8 @@ void dropInvalidConfigurations(GeneticSearch::Population& population) {
162162} // namespace
163163
164164#define VALIDATE () \
165- CHECK_LT (kNumberElites , kMaxPopulationSize ); \
165+ CHECK_LT (kMaxPopulationSize , kMatingPoolSize ); \
166+ CHECK_LT (kMaxPopulationSize , kSelectionPoolSize ); \
166167 CHECK (kMutationRate >= 0 and kMutationRate <= 100 ) \
167168 << " the mutation rate (" << kMutationRate \
168169 << " ) should be in the [0,100] interval" ; \
@@ -189,14 +190,15 @@ GeneticSearch::GeneticSearch(
189190 size_t n,
190191 uint8_t crossOverRate,
191192 uint8_t mutationRate,
192- size_t numberElites)
193+ size_t matingPoolSize,
194+ size_t selectionPoolSize)
193195 : population(),
194196 lastBestConf (confs[0 ]),
195197 kMaxPopulationSize(n),
196- kMatingPoolSize(n * 3 ),
198+ kMatingPoolSize(matingPoolSize ),
197199 kCrossOverRate(crossOverRate),
198200 kMutationRate(mutationRate),
199- kNumberElites(numberElites ),
201+ kSelectionPoolSize(selectionPoolSize ),
200202 rng{std::random_device{}()} {
201203 restoreRngState (rng);
202204 VALIDATE ();
@@ -222,14 +224,15 @@ GeneticSearch::GeneticSearch(
222224 size_t n,
223225 uint8_t crossOverRate,
224226 uint8_t mutationRate,
225- size_t numberElites)
227+ size_t matingPoolSize,
228+ size_t selectionPoolSize)
226229 : population(),
227230 lastBestConf (conf),
228231 kMaxPopulationSize(n),
229- kMatingPoolSize(n * 3 ),
232+ kMatingPoolSize(matingPoolSize ),
230233 kCrossOverRate(crossOverRate),
231234 kMutationRate(mutationRate),
232- kNumberElites(numberElites ),
235+ kSelectionPoolSize(selectionPoolSize ),
233236 rng{std::random_device{}()} {
234237 restoreRngState (rng);
235238 VALIDATE ();
@@ -301,13 +304,6 @@ void GeneticSearch::breed() {
301304 auto matingPool =
302305 stochasticUniversalSampling (computeAccumulatedFitness (population));
303306
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-
311307 auto select = [&]() -> TuningConfiguration& {
312308 auto idx = std::uniform_int_distribution<size_t >{
313309 size_t (0 ), matingPool.size () - 1 }(rng);
@@ -323,44 +319,20 @@ void GeneticSearch::breed() {
323319 return dist (rng);
324320 };
325321
326- while (new_population .size () < kMaxPopulationSize ) {
322+ while (selectionPool .size () < kSelectionPoolSize ) {
327323 if (shouldCrossOver ()) {
328324 auto parent1 = select ();
329325 auto parent2 = select ();
330326 auto parent3 = select ();
331- new_population .emplace_back (make_unique<CandidateConfiguration>(
327+ selectionPool .emplace_back (make_unique<CandidateConfiguration>(
332328 crossover (parent1, parent2, parent3)));
333329 } else {
334- new_population.emplace_back (
335- make_unique<CandidateConfiguration>(select ()));
330+ selectionPool.emplace_back (make_unique<CandidateConfiguration>(select ()));
336331 }
337332 }
338- population = std::move (new_population);
339333}
340334
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 () {
364336 if (population.size () < kMinCandidatesForBreeding ) {
365337 LOG_IF (ERROR, FLAGS_debug_tuner)
366338 << population.size () << " out of " << kMaxPopulationSize
@@ -379,12 +351,69 @@ void GeneticSearch::updateParameters() {
379351 // Don't lose the first one which was the best from before
380352 CHECK_LT (0 , population.size ());
381353 randomizePopulation (population.begin () + 1 , population.end (), rng);
382- return ;
383354 }
355+ }
384356
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 ();
385386 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);
388417 }
389418}
390419
0 commit comments