13#if !defined(ULTRA_EVOLUTION_REPLACEMENT_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(ULTRA_EVOLUTION_REPLACEMENT_TCC)
18#define ULTRA_EVOLUTION_REPLACEMENT_TCC
25strategy<E>::strategy(E &eva,
const parameters ¶ms)
26 : eva_(eva), params_(params)
42 status_t &status)
const
44 static_assert(std::is_same_v<individual_t, typename P::value_type>);
46 Expects(!this->params_.needs_init());
48 const auto rounds(this->params_.evolution.tournament_size);
52 auto worst_coord(random::coord(pop));
53 auto worst_fitness(this->eva_(pop[worst_coord]));
55 for (std::size_t i(1); i < rounds; ++i)
57 const auto new_coord(random::coord(pop));
58 const auto new_fitness(this->eva_(pop[new_coord]));
60 if (new_fitness < worst_fitness)
62 worst_fitness = new_fitness;
63 worst_coord = new_coord;
69 const auto elitism(this->params_.evolution.elitism);
70 assert(in_0_1(elitism));
72 const bool replace(offspring.fit > worst_fitness || !
random::boolean(elitism));
74 pop[worst_coord] = offspring.ind;
87template<PopulationWithMutex P>
90 for (
const auto &prg : from)
91 try_add_to_layer(to, prg);
124template<PopulationWithMutex P,
class S>
126 const S &incoming_source)
const
127 requires (std::same_as<S, individual_t> || std::same_as<S, scored_t>)
129 static_assert(std::is_same_v<individual_t, typename P::value_type>);
131 const individual_t &incoming([&] ->
const individual_t &
133 if constexpr (std::same_as<S, scored_t>)
134 return incoming_source.ind;
136 return incoming_source;
139 Expects(incoming.is_valid());
141 auto &pop(pops.primary());
147 if (std::lock_guard lock(pop.mutex()); pop.size() < pop.allowed())
149 pop.push_back(incoming);
154 individual_t displaced;
155 assert(displaced.empty());
160 typename P::coord coord {};
164 const std::size_t ts(this->params_.evolution.tournament_size);
166 Expects(ts <= parameters::evolution_parameters::max_tournament_size);
168 std::vector<snapshot_t> candidates;
169 candidates.reserve(ts);
171 const auto max_age([&]
173 std::shared_lock lock(pop.mutex());
176 for (std::size_t i(0); i < ts; ++i)
178 const auto c(random::coord(pop));
180 candidates.push_back({c, pop[c]});
183 return pop.max_age();
187 std::size_t worst_idx(0);
188 auto worst_fit(this->eva_(candidates[0].ind));
189 auto worst_age(candidates[0].ind.age());
191 for (std::size_t i(1); i < ts; ++i)
193 const auto trial_fit(this->eva_(candidates[i].ind));
194 const auto trial_age(candidates[i].ind.age());
196 if (trial_age > std::max(worst_age, max_age)
197 || (std::max(worst_age, trial_age) <= max_age
198 && trial_fit < worst_fit))
201 worst_fit = trial_fit;
202 worst_age = trial_age;
206 bool replace_worst(
false);
208 if (
const auto incoming_age(incoming.age());
209 incoming_age <= max_age && worst_age > max_age)
212 replace_worst =
true;
214 else if (incoming_age > max_age && worst_age <= max_age)
217 replace_worst =
false;
221 const auto incoming_fit([&]
223 if constexpr (std::same_as<S, scored_t>)
224 return incoming_source.fit;
226 return this->eva_(incoming);
229 replace_worst = incoming_fit >= worst_fit;
235 const auto coord(candidates[worst_idx].coord);
237 std::lock_guard lock(pop.mutex());
241 if (
const bool changed(pop[coord] != candidates[worst_idx].ind); changed)
248 if (pops.has_secondary())
250 ultraERROR(
"ALPS snapshot/commit mismatch in non-final layer{}",
257 displaced = pop[coord];
258 pop[coord] = incoming;
261 const bool replaced(!displaced.empty());
263 if (pops.has_secondary() && replaced)
266 scored_t(std::move(displaced), std::move(worst_fit)));
272template<PopulationWithMutex P,
class S>
274 requires (std::same_as<S, individual_t> || std::same_as<S, scored_t>)
276 return try_add_to_layer(alps_layer_pair(layer), incoming);
292template<PopulationWithMutex P>
294 status_t &status)
const
296 static_assert(std::is_same_v<individual_t, typename P::value_type>);
297 Expects(!this->params_.needs_init());
299 const bool inserted(try_add_to_layer(pops, offspring));
300 const bool new_best(status.update_if_better(offspring));
302 if (inserted || !new_best || !pops.has_secondary())
308 const auto elitism(this->params_.evolution.elitism);
309 assert(in_0_1(elitism));
311 auto retries(
static_cast<unsigned>(std::ceil(elitism * 3.0)));
314 if (try_add_to_layer(pops.secondary(), offspring))
320 status_t &status)
const
322 Expects(!this->params_.needs_init());
324 const auto off_fit(this->eva_(offspring));
325 status.update_if_better(scored_individual(offspring, off_fit));
330 const auto elitism(this->params_.evolution.elitism);
331 assert(in_0_1(elitism));
333 if (
const auto target_fit(this->eva_(target));
334 off_fit >= target_fit || !random::boolean(elitism))
bool update_if_better(const scored_individual< I, F > &)
Definition evolution_status.h:35
void try_promote_individuals(const P &, P &) const
Definition evolution_replacement.h:89
bool operator()(P &, const scored_t &, status_t &) const
Definition evolution_replacement.h:42
bool boolean(double p)
Definition random.h:154
static constexpr std::size_t max_tournament_size
Definition parameters.h:180