3 * \remark This file is part of VITA.
5 * \copyright Copyright (C) 2013-2023 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_RECOMBINATION_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(VITA_EVOLUTION_RECOMBINATION_TCC)
18#define VITA_EVOLUTION_RECOMBINATION_TCC
21/// \param[in] pop the current population
22/// \param[in] eva the current evaluator
23/// \param[out] stats pointer to the current set of statistics
26strategy<T>::strategy(const population<T> &pop, evaluator<T> &eva,
28 : pop_(pop), eva_(eva), stats_(stats)
34/// This is a quite standard crossover + mutation operator.
36/// \param[in] parent a vector of ordered parents
37/// \return the offspring
40typename strategy<T>::offspring_t base<T>::run(
41 const typename strategy<T>::parents_t &parent)
43 const auto &pop(this->pop_);
44 const auto &prob(pop.get_problem());
46 const auto p_cross(prob.env.p_cross);
47 const auto p_mutation(prob.env.p_mutation);
48 const auto brood_recombination(prob.env.brood_recombination);
50 Expects(0.0 <= p_cross && p_cross <= 1.0);
51 Expects(0.0 <= p_mutation && p_mutation <= 1.0);
52 Expects(brood_recombination);
53 Expects(parent.size() >= 2);
55 const auto r1(parent[0]), r2(parent[1]);
57 if (random::boolean(p_cross))
59 auto cross_and_mutate(
60 [&](const T &p1, const T &p2)
62 T ret(crossover(p1, p2));
63 ++this->stats_->crossovers;
67 // This could be an original contribution of Vita but it's hard to be
69 // It remembers of the hereditary repulsion constraint (I guess you
70 // could call it signature repulsion) and seems to:
71 // * maintain diversity during the exploration phase;
72 // * optimize the exploitation phase.
73 while (p1.signature() == ret.signature()
74 || p2.signature() == ret.signature())
75 this->stats_->mutations += ret.mutation(p_mutation, prob);
81 T off(cross_and_mutate(pop[r1], pop[r2]));
83 if (brood_recombination > 1)
85 fitness_t fit_off(this->eva_.fast(off));
87 for (unsigned i(1); i < brood_recombination; ++i)
89 T tmp(cross_and_mutate(pop[r1], pop[r2]));
91 const auto fit_tmp(this->eva_.fast(tmp));
92 if (fit_tmp > fit_off)
104 T off(pop[random::boolean() ? r1 : r2]);
105 this->stats_->mutations += off.mutation(p_mutation, prob);
111/// This is strictly based on the DE crossover operator.
113/// \param[in] parent a vector of ordered parents
114/// \return the offspring
117typename strategy<T>::offspring_t de<T>::run(
118 const typename strategy<T>::parents_t &parent)
120 Expects(parent.size() >= 2);
122 const auto &pop(this->pop_);
123 const auto &env(pop.get_problem().env);
125 assert(0.0 < env.p_cross);
126 assert(env.p_cross <= 1.0);
128 const auto a(pickup(pop, parent[0]));
129 const auto b(pickup(pop, parent[0]));
131 return {pop[parent[0]].crossover(env.p_cross, env.de.weight,
132 pop[parent[1]], pop[a], pop[b])};
134#endif // include guard