1 #ifndef __SELECTION_ROULETTE_H
2 #define __SELECTION_ROULETTE_H
5 #include <utility> // std::pair
6 #include <algorithm> // std::sort
11 #include "chromosome.h"
12 #include "selection.h"
17 // namespace selection {
18 template < typename _Chromosome >
19 class Roulette : public Selection<_Chromosome> {
21 typedef Selection<_Chromosome> BaseType;
22 typedef typename BaseType::FitnessValueType FitnessValueType;
24 vector<FitnessValueType> calculateGenerationFitness(
25 Generation<_Chromosome> generation) {
26 vector<FitnessValueType> generationFitness;
28 for (unsigned int i = 0; i < generation.get().size(); i++) {
29 generationFitness.push_back(this->checkChromosomeFitness(generation.get()[i]));
32 return generationFitness;
34 multimap<FitnessValueType, _Chromosome> normalizeFitness(
35 vector<FitnessValueType> generationFitness,
36 unsigned int chromosomeSize) {
39 FitnessValueType offset;
40 multimap<FitnessValueType, _Chromosome> normalizedFitness;
42 min = max = generationFitness[0];
45 for (unsigned int i = 0; i < generationFitness.size(); i++) {
46 if(generationFitness[i] < min) {
47 min = generationFitness[i];
50 if(generationFitness[i] > max) {
51 max = generationFitness[i];
55 offset = (max - min) / (chromosomeSize - 1) - min;
57 for (unsigned int i = 0; i < generationFitness.size(); i++) {
58 normalizedFitness.insert(std::make_pair(generationFitness[i] + offset, this->generation.get()[i]));
61 return normalizedFitness;
67 Generation<_Chromosome> spinRoulette(
68 multimap<FitnessValueType, _Chromosome> normalizedFitness) {
70 typedef typename std::multimap<FitnessValueType, _Chromosome>::iterator FitnessIterator;
72 vector<_Chromosome> selected;
73 multimap<FitnessValueType, _Chromosome> probabilities;
75 unsigned int size = this->generation.get().size();
76 const unsigned int power2N = 1 << this->generation.get()[0].get().size();
78 /** Random value used to draw chromosome */
79 FitnessValueType random = 0;
81 /** Position on the roulette wheele */
82 FitnessValueType position = 0;
84 FitnessValueType fitnessSum = 0;
86 // Calculate sum of normalized fitnesses, in order to calculate probabilities
87 for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
88 fitnessSum += it->first;
91 // Calculate probabilities for fitnesses
92 for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
93 position += (it->first / fitnessSum * power2N);
94 probabilities.insert(std::make_pair(position, it->second));
98 * Spin the Roulette until we draw as many chromosomes as in the
99 * original generation.
103 random = (rand() % power2N);
105 for (FitnessIterator it = probabilities.begin(); it != probabilities.end(); it++) {
106 if (random < it->first) {
108 selected.push_back(it->second);
111 // When NaN occur, just get first Chromosome
112 else if (it->first != it->first) {
113 selected.push_back(probabilities.begin()->second);
123 return Generation<_Chromosome>(selected);
129 Generation<_Chromosome> do_draw() {
130 multimap<FitnessValueType, _Chromosome> normalizedFitness;
132 normalizedFitness = this->normalizeFitness(
133 this->calculateGenerationFitness(this->generation),
134 this->generation.get()[0].get().size()
137 return spinRoulette(normalizedFitness);
141 Roulette(Generation<_Chromosome> _generation, genetic::Fitness<_Chromosome>& _fitness) :
142 Selection<_Chromosome>(_generation, _fitness) {
143 this->generation = _generation;
144 this->fitness = _fitness;
150 #endif /* __SELECTION_ROULETTE_H */