ee119d60543490f41bd932f94ba9e2c255c46e45
[genetic.git] / include / selection / linearRankSelection.h
1 #ifndef __SELECTION_LINEAR_RANK_H
2 #define __SELECTION_LINEAR_RANK_H
3
4 #include <map>
5
6 #include "chromosome.h"
7 #include "generation.h"
8 #include "fitness/fitness.h"
9 #include "selection/selection.h"
10
11 using namespace std;
12
13 namespace genetic {
14 //     namespace selection {
15         /**
16          * Linear Rank Selection class.
17          * Based on the 
18          */
19         template < typename _Chromosome >
20         class LinearRankSelection : public Selection<_Chromosome> {
21         public:
22             /**
23              * Type representing Fitness function
24              */
25             typedef Fitness<_Chromosome> GeneticFitness;
26
27             /**
28              * Value type returned by the Fitness function
29              */
30             typedef typename GeneticFitness::ValueType FitnessValueType;
31         protected:
32             /**
33              * Type representing mapped Chromosome by its Rank value
34              */
35             typedef typename std::multimap<FitnessValueType, _Chromosome> ChromosomeMap;
36
37             /** Iterator for ChromosomeMap */
38             typedef typename ChromosomeMap::iterator ChromosomeMapIterator;
39
40             /**
41              * Calculates Ranks for the Chromosomes
42              *
43              * @return multimap containing ranked Chromosomes, where key is the
44              *      rank value.
45              */
46             ChromosomeMap rankChromosomes() {
47                 const unsigned int generationSize = this->generation.size();
48                 FitnessValueType fitness = 0;
49
50                 ChromosomeMap generationFitness;
51
52                 for (unsigned int i = 0; i < generationSize; i++) {
53                     fitness = this->checkChromosomeFitness(this->generation[i]);
54                     generationFitness.insert(std::make_pair(fitness, this->generation[i]));
55                 }
56
57                 // multimap is automatically sorted by key, so we don't need to
58                 // sort it again
59
60                 // p(i) = (rank(i) / N*(N-1)), where rankedGeneration[i] = p(i)
61                 ChromosomeMap rankedGeneration;
62
63                 unsigned int rank = generationSize;
64                 const double denominator = generationSize * (generationSize - 1);
65
66                 for (ChromosomeMapIterator it = generationFitness.begin(); it != generationFitness.end(); it++) {
67                     rankedGeneration.insert(std::make_pair(rank--/denominator, it->second));
68                 }
69
70                 return rankedGeneration;
71             }
72
73             /**
74              * Invokes Selection calculations of the Linear Rank Selection
75              *
76              * @return new Generation of Chromosome's that passed the Selection
77              */
78             virtual Generation<_Chromosome> do_draw() {
79                 ChromosomeMap probabilities = rankChromosomes();
80
81                 unsigned int size = probabilities.size();
82                 const unsigned int denominator = size * (size - 1);
83
84                 std::vector<_Chromosome> selected;
85
86                 /** Random value used to draw chromosome */
87                 FitnessValueType random = 0;
88
89                 while (size > 0) {
90                     bool found = false;
91                     random = (rand() % size) / (float)denominator;
92
93                     for (ChromosomeMapIterator it = probabilities.begin(); it != probabilities.end(); it++) {
94                         if (random < it->first) {
95                             found = true;
96                             selected.push_back(it->second);
97                             break;
98                         }
99                         // When NaN occur, just get first Chromosome
100                         else if (it->first != it->first) {
101                             selected.push_back(probabilities.begin()->second);
102                             found = true;
103                             break;
104                         }
105                     }
106
107                     if (found) {
108                         size--;
109                     }
110                 }
111
112                 return Generation<_Chromosome>(selected);
113             }
114         public:
115             LinearRankSelection(const Generation<_Chromosome>& _generation, GeneticFitness& _fitness) :
116                 Selection<_Chromosome>(_generation, _fitness) {
117             }
118         };
119 //     }
120 }
121
122 #endif /* __SELECTION_LINEAR_RANK_H */