33 const std::vector<T>& parent1,
const std::vector<T>& parent2,
size_t point) {
34 if (parent1.size() != parent2.size()) {
35 throw std::invalid_argument(
"OnePointCrossoverAtPoint: parent sizes must match");
37 if (point > parent1.size()) {
38 throw std::invalid_argument(
"OnePointCrossoverAtPoint: point must be <= parent size");
40 std::vector<T> child1(parent1.begin(), parent1.begin() +
static_cast<std::ptrdiff_t
>(point));
41 child1.insert(child1.end(), parent2.begin() +
static_cast<std::ptrdiff_t
>(point), parent2.end());
42 std::vector<T> child2(parent2.begin(), parent2.begin() +
static_cast<std::ptrdiff_t
>(point));
43 child2.insert(child2.end(), parent1.begin() +
static_cast<std::ptrdiff_t
>(point), parent1.end());
44 return {child1, child2};
52template <
typename T,
typename RNG>
54 const std::vector<T>& parent2,
56 if (parent1.size() != parent2.size()) {
57 throw std::invalid_argument(
"OnePointCrossover: parent sizes must match");
59 if (parent1.size() < 2) {
60 throw std::invalid_argument(
"OnePointCrossover: parent size must be >= 2");
62 std::uniform_int_distribution<size_t> dist(1, parent1.size() - 1);
75 const std::vector<T>& parent1,
const std::vector<T>& parent2,
size_t point1,
size_t point2) {
76 if (parent1.size() != parent2.size()) {
77 throw std::invalid_argument(
"TwoPointCrossoverAtPoints: parent sizes must match");
79 if (point1 > point2 || point2 > parent1.size()) {
80 throw std::invalid_argument(
81 "TwoPointCrossoverAtPoints: require point1 <= point2 <= parent size");
83 std::vector<T> child1 = parent1;
84 std::vector<T> child2 = parent2;
85 for (
size_t i = point1; i < point2; ++i) {
86 std::swap(child1[i], child2[i]);
88 return {child1, child2};
95template <
typename T,
typename RNG>
97 const std::vector<T>& parent2,
99 if (parent1.size() != parent2.size()) {
100 throw std::invalid_argument(
"TwoPointCrossover: parent sizes must match");
102 if (parent1.size() < 2) {
103 throw std::invalid_argument(
"TwoPointCrossover: parent size must be >= 2");
105 std::uniform_int_distribution<size_t> dist(0, parent1.size());
106 size_t a = dist(rng);
107 size_t b = dist(rng);
122 const std::vector<T>& parent1,
const std::vector<T>& parent2,
123 const std::vector<bool>& swap_mask) {
124 if (parent1.size() != parent2.size() || parent1.size() != swap_mask.size()) {
125 throw std::invalid_argument(
"UniformCrossoverByMask: sizes must all match");
127 std::vector<T> child1 = parent1;
128 std::vector<T> child2 = parent2;
129 for (
size_t i = 0; i < swap_mask.size(); ++i) {
131 std::swap(child1[i], child2[i]);
134 return {child1, child2};
143template <
typename T,
typename RNG>
145 const std::vector<T>& parent2,
146 double swap_probability, RNG& rng) {
147 if (parent1.size() != parent2.size()) {
148 throw std::invalid_argument(
"UniformCrossover: parent sizes must match");
150 if (swap_probability < 0.0 || swap_probability > 1.0) {
151 throw std::invalid_argument(
"UniformCrossover: swap_probability must be in [0, 1]");
153 std::bernoulli_distribution dist(swap_probability);
154 std::vector<bool> mask(parent1.size());
155 for (
size_t i = 0; i < mask.size(); ++i) {
172 const std::vector<double>& parent1,
const std::vector<double>& parent2,
173 const std::vector<double>& gamma) {
174 if (parent1.size() != parent2.size() || parent1.size() != gamma.size()) {
175 throw std::invalid_argument(
"BlendCrossoverByGamma: sizes must all match");
177 std::vector<double> child1(parent1.size());
178 std::vector<double> child2(parent1.size());
179 for (
size_t i = 0; i < parent1.size(); ++i) {
180 child1[i] = (1.0 - gamma[i]) * parent1[i] + gamma[i] * parent2[i];
181 child2[i] = gamma[i] * parent1[i] + (1.0 - gamma[i]) * parent2[i];
183 return {child1, child2};
191template <
typename RNG>
193 const std::vector<double>& parent1,
const std::vector<double>& parent2,
double alpha,
195 if (parent1.size() != parent2.size()) {
196 throw std::invalid_argument(
"BlendCrossover: parent sizes must match");
199 throw std::invalid_argument(
"BlendCrossover: alpha must be non-negative");
201 std::uniform_real_distribution<double> dist(0.0, 1.0);
202 std::vector<double> gamma(parent1.size());
203 for (
size_t i = 0; i < gamma.size(); ++i) {
204 gamma[i] = (1.0 + 2.0 * alpha) * dist(rng) - alpha;
223 const std::vector<double>& parent1,
const std::vector<double>& parent2,
double eta,
224 const std::vector<double>& draws) {
225 if (parent1.size() != parent2.size() || parent1.size() != draws.size()) {
226 throw std::invalid_argument(
"SimulatedBinaryCrossoverByDraw: sizes must all match");
229 throw std::invalid_argument(
"SimulatedBinaryCrossoverByDraw: eta must be non-negative");
231 for (
double u : draws) {
232 if (u < 0.0 || u >= 1.0) {
233 throw std::invalid_argument(
234 "SimulatedBinaryCrossoverByDraw: every draw must be in [0, 1)");
238 std::vector<double> child1(parent1.size());
239 std::vector<double> child2(parent1.size());
240 const double exponent = 1.0 / (eta + 1.0);
241 for (
size_t i = 0; i < parent1.size(); ++i) {
243 double beta_q = (u <= 0.5) ? std::pow(2.0 * u, exponent)
244 : std::pow(1.0 / (2.0 * (1.0 - u)), exponent);
245 child1[i] = 0.5 * ((1.0 + beta_q) * parent1[i] + (1.0 - beta_q) * parent2[i]);
246 child2[i] = 0.5 * ((1.0 - beta_q) * parent1[i] + (1.0 + beta_q) * parent2[i]);
248 return {child1, child2};
256template <
typename RNG>
258 const std::vector<double>& parent1,
const std::vector<double>& parent2,
double eta,
260 if (parent1.size() != parent2.size()) {
261 throw std::invalid_argument(
"SimulatedBinaryCrossover: parent sizes must match");
263 std::uniform_real_distribution<double> dist(0.0, 1.0);
264 std::vector<double> draws(parent1.size());
265 for (
size_t i = 0; i < draws.size(); ++i) {
266 draws[i] = dist(rng);
Definition acquisition_functions.hpp:16
std::pair< std::vector< T >, std::vector< T > > TwoPointCrossover(const std::vector< T > &parent1, const std::vector< T > &parent2, RNG &rng)
RNG-driven wrapper: draws two points in [0, size], sorted ascending.
Definition crossover.hpp:96
std::pair< std::vector< T >, std::vector< T > > UniformCrossover(const std::vector< T > &parent1, const std::vector< T > &parent2, double swap_probability, RNG &rng)
RNG-driven wrapper: each gene swaps independently with probability swap_probability.
Definition crossover.hpp:144
std::pair< std::vector< double >, std::vector< double > > SimulatedBinaryCrossoverByDraw(const std::vector< double > &parent1, const std::vector< double > &parent2, double eta, const std::vector< double > &draws)
Simulated binary crossover (Deb & Agrawal 1995; DEAP's cxSimulatedBinary), given an explicit per-gene...
Definition crossover.hpp:222
std::pair< std::vector< T >, std::vector< T > > OnePointCrossoverAtPoint(const std::vector< T > &parent1, const std::vector< T > &parent2, size_t point)
Splits both parents at point and swaps tails.
Definition crossover.hpp:32
std::pair< std::vector< T >, std::vector< T > > OnePointCrossover(const std::vector< T > &parent1, const std::vector< T > &parent2, RNG &rng)
RNG-driven wrapper: draws an interior point in [1, size-1] uniformly.
Definition crossover.hpp:53
std::pair< std::vector< T >, std::vector< T > > UniformCrossoverByMask(const std::vector< T > &parent1, const std::vector< T > &parent2, const std::vector< bool > &swap_mask)
Swaps each gene independently wherever swap_mask is true.
Definition crossover.hpp:121
std::pair< std::vector< double >, std::vector< double > > BlendCrossover(const std::vector< double > &parent1, const std::vector< double > &parent2, double alpha, RNG &rng)
RNG-driven wrapper (DEAP's cxBlend): draws gamma_i = (1+2*alpha)*u_i - alpha per gene,...
Definition crossover.hpp:192
std::pair< std::vector< double >, std::vector< double > > SimulatedBinaryCrossover(const std::vector< double > &parent1, const std::vector< double > &parent2, double eta, RNG &rng)
RNG-driven wrapper: draws u_i ~ Uniform(0, 1) per gene (std::uniform_real_distribution is documented ...
Definition crossover.hpp:257
std::pair< std::vector< double >, std::vector< double > > BlendCrossoverByGamma(const std::vector< double > &parent1, const std::vector< double > &parent2, const std::vector< double > &gamma)
Blends each gene pair via an explicit per-gene gamma: child1_i = (1-gamma_i)*x1_i + gamma_i*x2_i,...
Definition crossover.hpp:171
std::pair< std::vector< T >, std::vector< T > > TwoPointCrossoverAtPoints(const std::vector< T > &parent1, const std::vector< T > &parent2, size_t point1, size_t point2)
Swaps the [point1, point2) segment between both parents.
Definition crossover.hpp:74