45 template <
typename ITER,
46 typename BREEDING_FUNC,
49 typename URNG = std::default_random_engine>
50 std::multimap<double, typename std::iterator_traits<ITER>::value_type>
Genetic(ITER b, ITER e,
55 URNG &&rng = std::default_random_engine{size_t(std::chrono::system_clock::now().time_since_epoch().count())})
57 using GENOTYPE =
typename std::iterator_traits<ITER>::value_type;
60 auto population = std::multimap<double, GENOTYPE>{};
62 population.emplace(evaluate(*b), *b);
63 if (population.size() < 2)
64 throw ExceptionLogic(
"Parthenogenesis is not allowed, at least two individuals are needed.");
67 while (!stop(population))
69 auto newpopulation = std::multimap<double, GENOTYPE>{};
72 auto ranpos = std::vector<size_t>(population.size());
73 std::iota(ranpos.begin(), ranpos.end(), 0);
74 std::shuffle(ranpos.begin(), ranpos.end(), rng);
76 for (
size_t tmp = 0; tmp < population.size(); )
78 if (tmp + 1 >= ranpos.size())
81 auto it1 = std::next(population.begin(), ranpos[tmp++]);
82 auto it2 = std::next(population.begin(), ranpos[tmp++]);
83 auto children = std::pair<GENOTYPE, GENOTYPE>{};
84 if (tmp >= ranpos.size())
86 children = breed(it1->second, it2->second, rng);
90 auto it3 = std::next(population.begin(), ranpos[tmp]);
92 if (it1->first < it2->first)
94 if (it2->first < it3->first)
96 children = breed(it1->second, it2->second, rng);
101 children = breed(it1->second, it3->second, rng);
102 ranpos[tmp] = ranpos[tmp - 1];
107 if (it1->first < it3->first)
109 children = breed(it1->second, it2->second, rng);
114 children = breed(it2->second, it3->second, rng);
115 ranpos[tmp] = ranpos[tmp - 2];
121 auto fitness = evaluate(children.first);
122 newpopulation.emplace(fitness, std::move(children.first));
123 fitness = evaluate(children.second);
124 newpopulation.emplace(fitness, std::move(children.second));
129 newpopulation.insert(*population.begin());
130 newpopulation.erase(--newpopulation.end());
131 population.swap(newpopulation);
135 const auto s = population.size();
136 std::move(newpopulation.begin(), newpopulation.end(), std::inserter(population, population.end()));
137 population.erase(std::next(population.begin(), s), population.end());
161 template<
typename T,
typename URNG>
inline std::pair<std::vector<T>, std::vector<T>>
operator()(
const std::vector<T> &idv1,
const std::vector<T> &idv2, URNG &rng)
const
163 if (idv1.size() != idv2.size())
165 const auto s = idv1.size();
169 auto ran = std::uniform_int_distribution<size_t>(0, s - 1);
170 const auto cut = ran(rng);
171 auto child1 = std::vector<T>(s);
172 auto child2 = std::vector<T>(s);
173 for (
auto tmp =
size_t(0); tmp < cut; ++tmp)
175 child1[tmp] = idv1[tmp];
176 child2[tmp] = idv2[tmp];
178 for (
auto tmp = cut; tmp < s; ++tmp)
180 child1[tmp] = idv2[tmp];
181 child2[tmp] = idv1[tmp];
183 return std::make_pair(std::move(child1), std::move(child2));
197 {
return --generation == 0; }
207 template<
typename T>
inline bool operator()(
const std::multimap<double, T> &population)
const
208 {
return population.begin()->first < threshold; }
Stops when the best individual has a fitness lower than a threshold.
bool operator()(const std::multimap< double, T > &population) const
constexpr GenerationCounter(size_t cnt)
Simple counter to stop an genetic algorithm.
bool operator()(const T &)
constexpr FitnessThreshold(double thresh)
std::pair< std::vector< T >, std::vector< T > > operator()(const std::vector< T > &idv1, const std::vector< T > &idv2, URNG &rng) const
std::multimap< double, typename std::iterator_traits< ITER >::value_type > Genetic(ITER b, ITER e, BREEDING_FUNC breed, EVAL_FUNC evaluate, STOP_FUNC stop, GenerationStrategy keep_parents=GenerationStrategy::KEEP_BEST_PARENT, URNG &&rng=std::default_random_engine{size_t(std::chrono::system_clock::now().time_since_epoch().count())})
Invalid argument error (e.g.: nullptr pointer)