3 * \remark This file is part of VITA.
5 * \copyright Copyright (C) 2013-2022 EOS di Manlio Morini.
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
10 * You can obtain one at http://mozilla.org/MPL/2.0/
13#if !defined(VITA_EVOLUTION_STRATEGY_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(VITA_EVOLUTION_STRATEGY_TCC)
18#define VITA_EVOLUTION_STRATEGY_TCC
21/// \param[out] env environment
22/// \return a strategy-specific environment
24/// \remark For standard evolution we only need one layer.
27environment std_es<T>::shape(environment env)
34/// \return `true` when evolution must be stopped
36/// We use an accelerated stop condition when:
37/// - after `max_stuck_time` generations the situation doesn't change;
38/// - all the individuals have the same fitness.
41bool std_es<T>::stop_condition() const
43 const auto &env(this->pop_.get_problem().env);
44 Expects(env.max_stuck_time.has_value());
46 const auto &sum(this->sum_);
47 Expects(sum->gen >= sum->last_imp);
49 // Pay attention to `env.max_stuck_time`: it can be a large number and cause
50 // overflow. E.g. `sum->gen > sum->last_imp + *env.max_stuck_time`
52 if (sum->gen - sum->last_imp > *env.max_stuck_time
53 && issmall(sum->az.fit_dist().variance()))
60/// \param[out] env environemnt
61/// \return a strategy-specific environment
63/// \remark ALPS requires more than one layer.
65template<class T, template<class> class CS>
66environment basic_alps_es<T, CS>::shape(environment env)
73/// Increments population's age and checks if it's time to add a new layer.
75template<class T, template<class> class CS>
76void basic_alps_es<T, CS>::after_generation()
78 const auto &sum(this->sum_);
79 auto &pop(this->pop_);
80 const auto &env(pop.get_problem().env);
84 for (auto l(pop.layers() - 1); l; --l)
85 if (almost_equal(sum->az.fit_dist(l - 1).mean(),
86 sum->az.fit_dist( l).mean()))
89 auto layers(pop.layers());
91 for (decltype(layers) l(1); l < layers; ++l)
92 if (issmall(sum->az.fit_dist(l).standard_deviation()))
94 const auto current(pop.individuals(l));
95 pop.set_allowed(l, std::max(env.min_individuals, current / 2));
99 const auto allowed(env.individuals);
100 pop.set_allowed(l, allowed);
103 // Code executed every `age_gap` interval.
104 if (sum->gen && sum->gen % env.alps.age_gap == 0)
106 if (layers < env.layers
107 || sum->az.age_dist(layers - 1).mean() > env.alps.max_age(layers))
111 this->replacement.try_move_up_layer(0);
118/// Saves working / statistical informations about layer status.
120/// \param[in] last_run last run processed
121/// \param[in] current_run current run
123/// Parameters from the environment:
124/// * `env.stat.layers_file` if empty the method will not write any data.
126template<class T, template<class> class CS>
127void basic_alps_es<T, CS>::log_strategy(unsigned last_run,
128 unsigned current_run) const
130 const auto &pop(this->pop_);
131 const auto &env(pop.get_problem().env);
133 if (!env.stat.layers_file.empty())
135 const auto n_lys(env.stat.dir / env.stat.layers_file);
136 std::ofstream f_lys(n_lys, std::ios_base::app);
140 if (last_run != current_run)
143 auto layers(pop.layers());
144 for (decltype(layers) l(0); l < layers; ++l)
146 f_lys << current_run << ' ' << this->sum_->gen << ' ' << l << " <";
148 const auto ma(env.alps.allowed_age(l, layers));
149 if (ma == std::numeric_limits<decltype(ma)>::max())
154 f_lys << ' ' << this->sum_->az.age_dist(l).mean()
155 << ' ' << this->sum_->az.age_dist(l).standard_deviation()
156 << ' ' << static_cast<unsigned>(this->sum_->az.age_dist(l).min())
157 << '-' << static_cast<unsigned>(this->sum_->az.age_dist(l).max())
158 << ' ' << this->sum_->az.fit_dist(l).mean()
159 << ' ' << this->sum_->az.fit_dist(l).standard_deviation()
160 << ' ' << this->sum_->az.fit_dist(l).min()
161 << '-' << this->sum_->az.fit_dist(l).max()
162 << ' ' << pop.individuals(l) << '\n';
166#endif // include guard