Added LinearRankSelection.
authorRafał Długołęcki <rafal@dlugolecki.net.pl>
Mon, 6 Apr 2015 14:37:52 +0000 (16:37 +0200)
committerRafał Długołęcki <rafal@dlugolecki.net.pl>
Mon, 6 Apr 2015 14:37:52 +0000 (16:37 +0200)
src/main.cpp
src/selection/linearRankSelection.h [new file with mode: 0644]

index 3e73d5873484fecac2db1777c809fb957caae326..36dd6028c472b0b983d04aaeab8652eb0d04e1c5 100644 (file)
@@ -9,6 +9,7 @@
 #include "generator/bit.h"
 
 #include "selection/roulette.h"
+#include "selection/linearRankSelection.h"
 #include "crossover/crossover.h"
 #include "mutation/mutation.h"
 #include "fitness/wsti.h"
@@ -25,7 +26,7 @@ int main() {
     typedef Chromosome<_Gene> _Chromosome;
 
     typedef WSTI<_Chromosome> _Fitness;
-    typedef Roulette<_Chromosome> _Selection;
+    typedef LinearRankSelection<_Chromosome> _Selection;
     typedef Crossover<_Chromosome> _Crossover;
     typedef Mutation<_Chromosome> _Mutation;
 
diff --git a/src/selection/linearRankSelection.h b/src/selection/linearRankSelection.h
new file mode 100644 (file)
index 0000000..8a09046
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef __SELECTION_LINEAR_RANK_H
+#define __SELECTION_LINEAR_RANK_H
+
+#include <map>
+
+#include "chromosome.h"
+#include "generation.h"
+#include "fitness/fitness.h"
+#include "selection/selection.h"
+
+using namespace std;
+
+namespace genetic {
+//     namespace selection {
+        /**
+         * Linear Rank Selection class.
+         * Based on the 
+         */
+        template < typename _Chromosome >
+        class LinearRankSelection : public Selection<_Chromosome> {
+        public:
+            /**
+             * Type representing Fitness function
+             */
+            typedef Fitness<_Chromosome> GeneticFitness;
+
+            /**
+             * Value type returned by the Fitness function
+             */
+            typedef typename GeneticFitness::ValueType FitnessValueType;
+        protected:
+            typedef typename std::multimap<FitnessValueType, _Chromosome> ChromosomeMap;
+            typedef typename ChromosomeMap::iterator ChromosomeMapIterator;
+
+            /**
+             * Calculates Ranks for the Chromosomes
+             *
+             * @return multimap containing ranked Chromosomes, where key is the
+             *      rank value.
+             */
+            ChromosomeMap rankChromosomes() {
+                const unsigned int generationSize = this->generation.size();
+                FitnessValueType fitness = 0;
+
+                ChromosomeMap generationFitness;
+
+                for (unsigned int i = 0; i < generationSize; i++) {
+                    fitness = this->checkChromosomeFitness(this->generation[i]);
+                    generationFitness.insert(std::make_pair(fitness, this->generation[i]));
+                }
+
+                // multimap is automatically sorted by key, so we don't need to
+                // sort it again
+
+                // p(i) = (rank(i) / N*(N-1)), where rankedGeneration[i] = p(i)
+                ChromosomeMap rankedGeneration;
+
+                unsigned int rank = generationSize;
+                double denominator = generationSize * (generationSize - 1);
+
+                for (ChromosomeMapIterator it = generationFitness.begin(); it != generationFitness.end(); it++) {
+//                     cout << "rank: " << rank << " denominator: " << denominator << " res: " << (rank-1)/denominator << "\n";
+                    rankedGeneration.insert(std::make_pair(rank--/denominator, it->second));
+                }
+
+                return rankedGeneration;
+            }
+
+            /**
+             * Selection calculations should be done here.
+             *
+             * @return new Generation of Chromosome's that passed the Selection
+             */
+            virtual Generation<_Chromosome> do_draw() {
+                ChromosomeMap probabilities = rankChromosomes();
+
+                unsigned int size = probabilities.size();
+                unsigned int denominator = size * (size - 1);
+
+                std::vector<_Chromosome> selected;
+
+                /** Random value used to draw chromosome */
+                FitnessValueType random = 0;
+
+                while (size > 0) {
+                    bool found = false;
+                    random = (rand() % size) / (double)denominator;
+
+                    for (ChromosomeMapIterator it = probabilities.begin(); it != probabilities.end(); it++) {
+//                     cout << "Random: " << random << " First: " << it->first << "\n";
+                        if (random < it->first) {
+                            found = true;
+                            selected.push_back(it->second);
+                            break;
+                        }
+                        // When NaN occur, just get first Chromosome
+                        else if (it->first != it->first) {
+                            selected.push_back(probabilities.begin()->second);
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    if (found) {
+                        size--;
+                    }
+                }
+
+                return Generation<_Chromosome>(selected);
+            }
+        public:
+            LinearRankSelection(Generation<_Chromosome> _generation, GeneticFitness& _fitness) :
+                Selection<_Chromosome>(_generation, _fitness) {
+            }
+        };
+//     }
+}
+
+#endif /* __SELECTION_LINEAR_RANK_H */