#include "generator/bit.h"
#include "selection/roulette.h"
+#include "selection/linearRankSelection.h"
#include "crossover/crossover.h"
#include "mutation/mutation.h"
#include "fitness/wsti.h"
typedef Chromosome<_Gene> _Chromosome;
typedef WSTI<_Chromosome> _Fitness;
- typedef Roulette<_Chromosome> _Selection;
+ typedef LinearRankSelection<_Chromosome> _Selection;
typedef Crossover<_Chromosome> _Crossover;
typedef Mutation<_Chromosome> _Mutation;
--- /dev/null
+#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 */