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> {
24 typedef Selection<_Chromosome> BaseType;
25 typedef typename BaseType::FitnessValueType FitnessValueType;
28 * Method used for calculating fitness of each Chromosome in
31 * @param generation Generation for which fitness will be calculated
32 * @return vector containing fitness value of each Chromosome in
33 * Generation. Values are set in the same order as they are in
36 vector<FitnessValueType> calculateGenerationFitness(
37 Generation<_Chromosome> generation) {
38 vector<FitnessValueType> generationFitness;
40 for (unsigned int i = 0; i < generation.get().size(); i++) {
41 generationFitness.push_back(this->checkChromosomeFitness(generation.get()[i]));
44 return generationFitness;
48 * Normalizes calculated fitness values of the generation.
50 * @param generationFitness fitness values of the generation
51 * @param chromosomeSize number of Gene's in the Chromosome.
53 * @return multimap containing normalized Fitness as a key and its
54 * Chromosome as the value
56 multimap<FitnessValueType, _Chromosome> normalizeFitness(
57 vector<FitnessValueType> generationFitness,
58 unsigned int chromosomeSize) {
61 FitnessValueType offset;
63 /* we use multimap because it stores multiple values with the
66 multimap<FitnessValueType, _Chromosome> normalizedFitness;
68 min = max = generationFitness[0];
71 for (unsigned int i = 0; i < generationFitness.size(); i++) {
72 if(generationFitness[i] < min) {
73 min = generationFitness[i];
76 if(generationFitness[i] > max) {
77 max = generationFitness[i];
81 offset = (max - min) / (chromosomeSize - 1) - min;
83 for (unsigned int i = 0; i < generationFitness.size(); i++) {
84 normalizedFitness.insert(std::make_pair(generationFitness[i] + offset, this->generation.get()[i]));
87 return normalizedFitness;
93 * @param normalizedFitness multimap containing normalized Fitness
94 * as a key and its Chromosome as the value
95 * @return new Generation of Chromosome's that passed the selection
97 Generation<_Chromosome> spinRoulette(
98 multimap<FitnessValueType, _Chromosome> normalizedFitness) {
100 typedef typename std::multimap<FitnessValueType, _Chromosome>::iterator FitnessIterator;
102 vector<_Chromosome> selected;
103 multimap<FitnessValueType, _Chromosome> probabilities;
105 unsigned int size = this->generation.get().size();
106 const unsigned int power2N = 1 << this->generation.get()[0].get().size();
108 /** Random value used to draw chromosome */
109 FitnessValueType random = 0;
111 /** Position on the roulette wheele */
112 FitnessValueType position = 0;
114 FitnessValueType fitnessSum = 0;
116 // Calculate sum of normalized fitnesses, in order to calculate probabilities
117 for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
118 fitnessSum += it->first;
121 // Calculate probabilities for fitnesses
122 for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
123 position += (it->first / fitnessSum * power2N);
124 probabilities.insert(std::make_pair(position, it->second));
128 * Spin the Roulette until we draw as many chromosomes as in the
129 * original generation.
133 random = (rand() % power2N);
135 for (FitnessIterator it = probabilities.begin(); it != probabilities.end(); it++) {
136 if (random < it->first) {
138 selected.push_back(it->second);
141 // When NaN occur, just get first Chromosome
142 else if (it->first != it->first) {
143 selected.push_back(probabilities.begin()->second);
153 return Generation<_Chromosome>(selected);
157 * Draws new Generation using Roulette method
159 Generation<_Chromosome> do_draw() {
160 multimap<FitnessValueType, _Chromosome> normalizedFitness;
162 normalizedFitness = this->normalizeFitness(
163 this->calculateGenerationFitness(this->generation),
164 this->generation.get()[0].get().size()
167 return spinRoulette(normalizedFitness);
172 * Class constructor. Initializes class with values.
174 * @param _generation Generation that will be checked against this
176 * @param _fitness Fitness method to calculate fitness of Chromosomes
178 Roulette(Generation<_Chromosome> _generation, genetic::Fitness<_Chromosome>& _fitness) :
179 Selection<_Chromosome>(_generation, _fitness) {
180 this->generation = _generation;
181 this->fitness = _fitness;
187 #endif /* __SELECTION_ROULETTE_H */