1 #ifndef __SELECTION_ROULETTE_H
2 #define __SELECTION_ROULETTE_H
5 #include <utility> // std::pair
10 #include "chromosome.h"
11 #include "selection.h"
16 // namespace selection {
18 * Selection class Roulette.
19 * Applies Selection on given Generation using Roulette method.
21 template < typename _Chromosome >
22 class Roulette : public Selection<_Chromosome> {
25 * Parent Selection class
27 typedef Selection<_Chromosome> BaseType;
30 * Value type returned by the Fitness function
32 typedef typename BaseType::FitnessValueType FitnessValueType;
35 * Method used for calculating fitness of each Chromosome in
38 * @param generation Generation for which fitness will be calculated
39 * @return vector containing fitness value of each Chromosome in
40 * Generation. Values are set in the same order as they are in
43 vector<FitnessValueType> calculateGenerationFitness(
44 Generation<_Chromosome> generation) {
45 vector<FitnessValueType> generationFitness;
47 for (unsigned int i = 0; i < generation.get().size(); i++) {
48 generationFitness.push_back(this->checkChromosomeFitness(generation.get()[i]));
51 return generationFitness;
55 * Normalizes calculated fitness values of the generation.
57 * @param generationFitness fitness values of the generation
58 * @param chromosomeSize number of Gene's in the Chromosome.
60 * @return multimap containing normalized Fitness as a key and its
61 * Chromosome as the value
63 multimap<FitnessValueType, _Chromosome> normalizeFitness(
64 vector<FitnessValueType> generationFitness,
65 unsigned int chromosomeSize) {
68 FitnessValueType offset;
70 /* we use multimap because it stores multiple values with the
73 multimap<FitnessValueType, _Chromosome> normalizedFitness;
75 min = max = generationFitness[0];
78 for (unsigned int i = 0; i < generationFitness.size(); i++) {
79 if(generationFitness[i] < min) {
80 min = generationFitness[i];
83 if(generationFitness[i] > max) {
84 max = generationFitness[i];
88 offset = (max - min) / (chromosomeSize - 1) - min;
90 for (unsigned int i = 0; i < generationFitness.size(); i++) {
91 normalizedFitness.insert(std::make_pair(generationFitness[i] + offset, this->generation.get()[i]));
94 return normalizedFitness;
100 * @param normalizedFitness multimap containing normalized Fitness
101 * as a key and its Chromosome as the value
102 * @return new Generation of Chromosome's that passed the Selection
104 Generation<_Chromosome> spinRoulette(
105 multimap<FitnessValueType, _Chromosome> normalizedFitness) {
107 typedef typename std::multimap<FitnessValueType, _Chromosome>::iterator FitnessIterator;
109 vector<_Chromosome> selected;
110 multimap<FitnessValueType, _Chromosome> probabilities;
112 unsigned int size = this->generation.size();
113 const unsigned int power2N = 1 << this->generation[0].size();
115 /** Random value used to draw chromosome */
116 FitnessValueType random = 0;
118 /** Position on the roulette wheele */
119 FitnessValueType position = 0;
121 FitnessValueType fitnessSum = 0;
123 // Calculate sum of normalized fitnesses, in order to calculate probabilities
124 for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
125 fitnessSum += it->first;
128 // Calculate probabilities for fitnesses
129 for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
130 position += (it->first / fitnessSum * power2N);
131 probabilities.insert(std::make_pair(position, it->second));
135 * Spin the Roulette until we draw as many chromosomes as in the
136 * original generation.
140 random = (rand() % power2N);
142 for (FitnessIterator it = probabilities.begin(); it != probabilities.end(); it++) {
143 if (random < it->first) {
145 selected.push_back(it->second);
148 // When NaN occur, just get first Chromosome
149 else if (it->first != it->first) {
150 selected.push_back(probabilities.begin()->second);
160 return Generation<_Chromosome>(selected);
164 * Draws new Generation using Roulette method
166 * @return new Generation of Chromosome's that passed the Selection
168 Generation<_Chromosome> do_draw() {
169 multimap<FitnessValueType, _Chromosome> normalizedFitness;
171 normalizedFitness = this->normalizeFitness(
172 this->calculateGenerationFitness(this->generation),
173 this->generation[0].size()
176 return spinRoulette(normalizedFitness);
181 * Class constructor. Initializes class with values.
183 * @param _generation Generation that will be checked against this
185 * @param _fitness Fitness method to calculate fitness of Chromosomes
187 Roulette(Generation<_Chromosome> _generation, genetic::Fitness<_Chromosome>& _fitness) :
188 Selection<_Chromosome>(_generation, _fitness) {
189 this->generation = _generation;
190 this->fitness = _fitness;
196 #endif /* __SELECTION_ROULETTE_H */