Ultra 0.9.4
Loading...
Searching...
No Matches
evolution_strategy.tcc
Go to the documentation of this file.
1
12
13#if !defined(ULTRA_EVOLUTION_STRATEGY_H)
14# error "Don't include this file directly, include the specific .h instead"
15#endif
16
17#if !defined(ULTRA_EVOLUTION_STRATEGY_TCC)
18#define ULTRA_EVOLUTION_STRATEGY_TCC
19
34template<Evaluator E>
35evolution_strategy<E>::evolution_strategy(const problem &prob, E &eva)
36 : eva_(eva), prob_(prob)
37{
38}
39
40template<Evaluator E>
41template<LayeredPopulation P>
42bool evolution_strategy<E>::valid_layer(P &pop, typename P::layer_iter iter)
43{
44 return pop.layers() && iterator_of(iter, pop.range_of_layers());
45}
46
64template<Evaluator E>
65template<Population P>
67{
68 return &pop;
69}
70
82template<Evaluator E>
83template<Population P>
84std::size_t evolution_strategy<E>::max_parallelism(const P &pop) const noexcept
85{
86 if constexpr (LayeredPopulation<P>)
87 return pop.layers();
88
89 return 1;
90}
91
116template<Evaluator E>
117template<Population P>
119 P &pop, const summary<individual_t, fitness_t> &sum)
120{
121 pop.inc_age();
122
123 if constexpr (LayeredPopulation<P>)
124 {
125 assert(&pop.problem() == &this->get_problem());
126 const auto &params(pop.problem().params);
127 assert(params.evolution.max_stuck_gen);
128
129 for (const auto layers(pop.range_of_layers()); auto &layer : layers)
130 if (sum.stagnation() > params.evolution.max_stuck_gen
131 && issmall(sum.az.fit_dist(layer).variance()))
132 {
133 layer.reset(pop.problem());
134 ultraINFO("Resetting layer {}", layer.uid());
135 }
136 }
137}
138
150template<Evaluator E>
151alps_es<E>::alps_es(const problem &prob, E &eva)
152 : evolution_strategy<E>(prob, eva),
153 select_(this->eva_, prob.params),
154 recombine_(this->eva_, prob),
155 replace_(this->eva_, prob.params)
156{
157}
158
180template<Evaluator E>
181template<LayeredPopulation P>
183 P &pop, typename P::layer_iter iter,
184 const evolution_status<individual_t, fitness_t> &starting_status) const
185{
186 Expects(this->valid_layer(pop, iter));
187
188 return
189 [this,
190 sel_pop = alps::selection_layers(pop, iter),
191 rep_pop = alps::replacement_layers(pop, iter),
192 status = starting_status] mutable
193 {
194 Ensures(sel_pop.size());
195 Ensures(rep_pop.size());
196 Ensures(&sel_pop.primary() == &rep_pop.primary());
197
198 const auto parents(this->select_(sel_pop));
199 const auto offspring(this->recombine_(parents));
200 this->replace_(rep_pop, offspring, status);
201 };
202}
203
212template<Evaluator E>
213template<LayeredPopulation P>
214void alps_es<E>::init(P &pop) const
215{
216 alps::set_age(pop);
217}
218
231template<Evaluator E>
232template<LayeredPopulation P>
233auto *alps_es<E>::refinement_subgroup(P &pop) const noexcept
234{
235 return pop.layers() < 3 ? nullptr : &pop.back();
236}
237
248template<Evaluator E>
249template<LayeredPopulation P>
250std::size_t alps_es<E>::max_parallelism(const P &) const noexcept
251{
252 return hardware_threads();
253}
254
271template<Evaluator E>
272template<LayeredPopulation P>
275{
276 Expects(&pop.problem() == &this->get_problem());
277
278 const auto &params(pop.problem().params);
279 Expects(params.alps.max_layers > 1);
280
281 pop.inc_age();
282
283 const auto layers(pop.range_of_layers());
284 bool layer_structure_changed(false);
285
286 if (pop.layers() > 1)
287 {
288 auto layer(std::next(layers.begin()));
289
290 while (layer != layers.end())
291 {
292 if (almost_equal(sum.az.fit_dist(*std::prev(layer)).mean(),
293 sum.az.fit_dist(*layer).mean()))
294 {
295 ultraDEBUG("ALPS: erasing layer UID={}", layer->uid());
296 layer = pop.erase(layer);
297 layer_structure_changed = true;
298 }
299 else
300 {
301 const auto sd(sum.az.fit_dist(*layer).standard_deviation());
302 const bool converged(issmall(sd));
303
304 if (converged)
305 {
306 const auto prev_allowed(layer->allowed());
307 const auto new_allowed(std::max(params.population.min_individuals,
308 layer->size() / 2));
309
310 if (new_allowed < prev_allowed)
311 {
312 ultraDEBUG("ALPS: decreasing allowed individuals of layer "
313 "UID={} to {}", layer->uid(), new_allowed);
314
315 layer->allowed(new_allowed);
316 }
317 }
318 else if (layer->allowed() < params.population.individuals)
319 {
320 ultraDEBUG("ALPS: restoring allowed individuals of layer UID={} "
321 "to {}", layer->uid(), params.population.individuals);
322
323 layer->allowed(params.population.individuals);
324 }
325
326 ++layer;
327 }
328 }
329 }
330
331 // Code executed every `age_gap` interval.
332 if (sum.generation && sum.generation % params.alps.age_gap == 0)
333 {
334 if (pop.layers() < params.alps.max_layers)
335 {
336 ultraDEBUG("ALPS: adding layer");
337 pop.add_layer();
338 layer_structure_changed = true;
339 }
340 else
341 {
342 ultraDEBUG("ALPS: try moving up first layer");
343 this->replace_.try_promote_individuals(pop.front(), pop.layer(1));
344 pop.init(pop.front());
345 }
346 }
347
348 if (layer_structure_changed)
349 alps::set_age(pop);
350}
351
364template<Evaluator E>
366{
367 params.alps.age_gap = 20;
368 params.alps.max_layers =
369 std::max<unsigned>(2, std::thread::hardware_concurrency());
370 params.alps.p_main_layer = 0.75;
371
372 return params;
373}
374
375template<Evaluator E>
376std_es<E>::std_es(const problem &prob, E &eva)
377 : evolution_strategy<E>(prob, eva),
378 select_(this->eva_, prob.params),
379 recombine_(this->eva_, prob),
380 replace_(this->eva_, prob.params)
381{
382}
383
398template<Evaluator E>
399template<SizedRandomAccessPopulation P>
401 P &pop,
402 const evolution_status<individual_t, fitness_t> &starting_status) const
403{
404 return
405 [this, &p = pop, status = starting_status]() mutable
406 {
407 Ensures(!p.empty());
408
409 const auto parents(this->select_(p));
410 const auto offspring(this->recombine_(parents));
411 this->replace_(p, offspring, status);
412 };
413}
414
429template<Evaluator E>
430template<LayeredPopulation P>
432 [[maybe_unused]] P &pop, typename P::layer_iter iter,
433 const evolution_status<individual_t, fitness_t> &starting_status) const
434{
435 Expects(this->valid_layer(pop, iter));
436
437 return operations(*iter, starting_status);
438}
439
440template<Evaluator E>
441de_es<E>::de_es(const problem &prob, E &eva)
442 : evolution_strategy<E>(prob, eva),
443 recombine_(prob),
444 replace_(this->eva_, prob.params)
445{
446}
447
462template<Evaluator E>
463template<SizedRandomAccessPopulation P>
465 [[maybe_unused]] P &pop,
466 const evolution_status<individual_t, fitness_t> &starting_status) const
467{
468 return
469 [this, &p = pop, status = starting_status]() mutable
470 {
471 Ensures(!p.empty());
472
473 const auto selected(this->select_(p));
474 const auto offspring(this->recombine_(selected));
475 this->replace_(selected.target, offspring, status);
476 };
477}
478
493template<Evaluator E>
494template<LayeredPopulation P>
496 [[maybe_unused]] P &pop, typename P::layer_iter iter,
497 const evolution_status<individual_t, fitness_t> &starting_status) const
498{
499 Expects(this->valid_layer(pop, iter));
500
501 return operations(*iter, starting_status);
502}
503
504#endif // include guard
alps_layer_pair< typename P::layer_t > replacement_layers(P &pop, typename P::layer_iter l)
Definition alps.h:220
alps_layer_pair< const typename P::layer_t > selection_layers(const P &pop, typename P::layer_const_iter l)
Definition alps.h:257
alps_es(const problem &, E &)
Definition evolution_strategy.h:152
void after_generation(P &, const summary< individual_t, fitness_t > &)
Definition evolution_strategy.h:274
void init(P &) const
Definition evolution_strategy.h:215
auto * refinement_subgroup(P &) const noexcept
Definition evolution_strategy.h:234
auto operations(P &, typename P::layer_iter, const evolution_status< individual_t, fitness_t > &) const
Definition evolution_strategy.h:183
std::size_t max_parallelism(const P &) const noexcept
Definition evolution_strategy.h:251
static parameters shape(parameters)
Definition evolution_strategy.h:366
auto operations(P &, const evolution_status< individual_t, fitness_t > &) const
Definition evolution_strategy.h:465
Definition evolution_status.h:36
Definition evolution_strategy.h:66
std::size_t max_parallelism(const P &) const noexcept
Definition evolution_strategy.h:85
P * refinement_subgroup(P &) const noexcept
Definition evolution_strategy.h:67
void after_generation(P &, const summary< individual_t, fitness_t > &)
Definition evolution_strategy.h:119
auto operations(P &, const evolution_status< individual_t, fitness_t > &) const
Definition evolution_strategy.h:401
Definition evolution_summary.h:33
Definition population.h:42
double p_main_layer
Definition alps.h:178
std::size_t max_layers
Maximum number of layers an ALPS layered population can grow to.
Definition alps.h:172
unsigned age_gap
Definition alps.h:169
Definition parameters.h:26
Definition problem.h:26