3 #include <geneial/core/operations/crossover/MultiValueChromosomeNPointCrossover.h>
4 #include <geneial/utility/Random.h>
10 geneial_private_namespace(geneial)
12 geneial_private_namespace(operation)
14 geneial_private_namespace(crossover)
16 using ::geneial::population::Population;
17 using ::geneial::population::chromosome::MultiValueChromosome;
18 using ::geneial::operation::coupling::BaseCouplingOperation;
19 using ::geneial::utility::Random;
21 geneial_export_namespace
25 template<
typename VALUE_TYPE,
typename FITNESS_TYPE>
26 typename BaseCrossoverOperation<FITNESS_TYPE>::crossover_result_set MultiValueChromosomeNPointCrossover<VALUE_TYPE,
27 FITNESS_TYPE>::doMultiValueCrossover(
28 const typename MultiValueChromosome<VALUE_TYPE, FITNESS_TYPE>::const_ptr &mommy,
29 const typename MultiValueChromosome<VALUE_TYPE, FITNESS_TYPE>::const_ptr &daddy)
const
32 typename BaseCouplingOperation<FITNESS_TYPE>::offspring_result_set resultset;
35 const unsigned int crossoverPoints = this->getCrossoverSettings().getCrossOverPoints();
36 const unsigned int totalWidth = this->getBuilderFactory().getSettings().getNum();
40 std::vector<unsigned int> crossoverPositions;
41 crossoverPositions.reserve(crossoverPoints);
45 if (this->getCrossoverSettings().getWidthSetting()
46 == MultiValueChromosomeNPointCrossoverSettings::EQUIDISTANT_WIDTH)
48 const unsigned int equidistantwidth = totalWidth / (crossoverPoints + 1);
50 for (
unsigned int i = 0; i < crossoverPoints; i++)
52 crossoverPositions.emplace_back(i * equidistantwidth);
56 else if (this->getCrossoverSettings().getWidthSetting()
57 == MultiValueChromosomeNPointCrossoverSettings::RANDOM_WIDTH
58 || this->getCrossoverSettings().getWidthSetting()
59 == MultiValueChromosomeNPointCrossoverSettings::RANDOM_MIN_WIDTH)
62 unsigned int minWidth;
63 if (this->getCrossoverSettings().getWidthSetting()
64 == MultiValueChromosomeNPointCrossoverSettings::RANDOM_WIDTH)
70 minWidth = this->getCrossoverSettings().getMinWidth();
75 const auto max = this->getBuilderFactory().getSettings().getNum();
76 while (crossoverPositions.size() < crossoverPoints)
78 const unsigned int rnd_pos = Random::generate<int>(0, max);
81 valid &= rnd_pos >= minWidth;
87 valid &= rnd_pos <= totalWidth - minWidth;
93 const auto pos = std::find(crossoverPositions.begin(), crossoverPositions.end(), rnd_pos);
94 valid &= pos == crossoverPositions.end();
100 const auto itlow = std::lower_bound(crossoverPositions.begin(), crossoverPositions.end(), rnd_pos);
101 const auto itup = std::upper_bound(crossoverPositions.begin(), crossoverPositions.end(), rnd_pos);
104 valid &= itlow == crossoverPositions.end()
105 || (itlow != crossoverPositions.end() && rnd_pos - *itlow >= minWidth);
111 valid &= itup == crossoverPositions.end()
112 || (itup != crossoverPositions.end() && *itup - rnd_pos >= minWidth);
117 crossoverPositions.emplace_back(rnd_pos);
120 std::sort(crossoverPositions.begin(),crossoverPositions.end());
124 assert(crossoverPositions.size() == crossoverPoints);
126 auto child_candidate = this->createChildCandidate();
128 const auto &daddy_container = daddy->getContainer();
129 const auto &mommy_container = mommy->getContainer();
130 auto &child_container = child_candidate->getContainer();
132 assert(daddy_container.size() == mommy_container.size());
137 crossoverPositions.push_back(daddy_container.size());
139 auto widthIterator = crossoverPositions.cbegin();
143 for (; widthIterator != crossoverPositions.end(); ++widthIterator)
147 std::copy(mommy_container.begin() + i, mommy_container.begin() + *widthIterator, child_container.begin()+i);
151 std::copy(daddy_container.begin() + i, daddy_container.begin() + *widthIterator, child_container.begin()+i);
156 assert(child_container.size() == mommy_container.size());
158 resultset.emplace_back(std::move(child_candidate));
160 return std::move(resultset);