AUTOMAKE_OPTIONS = gnu subdir-objects
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
+AM_CXXFLAGS=-std=c++11
EXTRA_DIST = \
config.rpath
: genes(chromosome.get()) {
}
- Chromosome& operator=(const Chromosome&){
+ Chromosome& operator=(const Chromosome& chromosome){
+ this->genes = chromosome.get();
return *this;
}
--- /dev/null
+#ifndef __FITNESS_FITNESS_H
+#define __FITNESS_FITNESS_H
+
+#include "../chromosome.h"
+
+namespace genetic {
+ /**
+ * Base Fitness template class. It should be a base class for any custom
+ * fitness functions.
+ */
+ template < typename _Chromosome, typename _Value = double >
+ class Fitness {
+ template<typename> friend class Selection ;
+ public:
+ typedef typename _Chromosome::GeneType GeneType;
+ typedef _Value ValueType;
+ protected:
+ _Chromosome chromosome;
+
+ /*
+ * Some calculations here...
+ */
+ virtual _Value do_calculate() = 0;
+
+ public:
+ Fitness() {}
+
+ Fitness(_Chromosome& _chromosome)
+ : chromosome(_chromosome.get()) {
+ }
+
+ _Value calculate() {
+ return this->do_calculate();
+ }
+ };
+}
+
+#endif /* __FITNESS_FITNESS_H */
#include "../gene.h"
+#include "fitness.h"
+
using namespace std;
namespace genetic {
/**
* Just an example Fitness function based on WSTI version.
*/
- template < typename _Chromosome >
- class WSTI {
+ template <typename _Chromosome, typename _Value = double>
+ class WSTI : public Fitness<_Chromosome, _Value> {
protected:
- _Chromosome chromosome;
-
float span_start;
float span_end;
- double fenotype() {
+ _Value fenotype() {
int _fenotype = 0;
int ratio = 1;
- for (unsigned int i = 0; i < chromosome.get().size(); i++) {
- _fenotype = _fenotype + chromosome.get()[i].get() * ratio;
+ for (unsigned int i = 0; i < this->chromosome.get().size(); i++) {
+ _fenotype = _fenotype + this->chromosome.get()[i].get() * ratio;
ratio = ratio * 2;
}
return _fenotype;
}
- double calculateFenotype() {
+ _Value calculateFenotype() {
const unsigned int power2N = 1 << this->chromosome.get().size();
return span_start + (span_end - span_start) * this->fenotype() / power2N;
}
- public:
- WSTI(_Chromosome& _chromosome, float start, float end)
- : chromosome(_chromosome.get()), span_start(start), span_end(end) {
- }
- double calculate() {
- double fenotype = this->calculateFenotype();
+ _Value do_calculate() {
+ _Value fenotype = this->calculateFenotype();
return (exp(fenotype) * sin(3.1415 * fenotype) + 1) / fenotype;
}
+ public:
+ WSTI(float start, float end)
+ : span_start(start), span_end(end) {
+ }
+ WSTI(_Chromosome& _chromosome, float start, float end)
+ : Fitness<_Chromosome>(_chromosome), span_start(start), span_end(end) {
+ }
};
}
vector<_Chromosome> get() const {
return this->chromosomes;
}
+
+ Generation& operator=(const Generation& generation){
+ this->chromosomes = generation.get();
+ return *this;
+ }
};
}
public:
/**
- * Constructor. Initializes required variables and constans
+ * Constructor. Initializes required variables and constants
*
* @param generationSize Indicates size of the generation
* @param generationSize Indicates size of the chromosome
#include "generation.h"
#include "generator/generation.h"
+#include "selection/roulette.h"
+
#include "fitness/wsti.h"
using namespace std;
const int chromosomeSize = 11;
const int generationSize = 20;
+ WSTI<_Chromosome> fitness(0.5, 2.5);
generator::Generation<_Chromosome> generationGenerator(generationSize, chromosomeSize);
Generation<_Chromosome> generation = generationGenerator.breed();
- for (unsigned int i = 0; i < generationSize; i++) {
- WSTI<_Chromosome> fitness(generation.get()[i], 0.5, 2.5);
+ cout << "Generation:\n";
+ for (unsigned int i = 0; i < generation.get().size(); i++) {
+ cout << "# ";
+ for (unsigned int j = 0; j < generation.get()[i].get().size(); j++) {
+ cout << generation.get()[i].get()[j].get();
+ }
+ cout << "\n";
+ }
+
+ Roulette<_Chromosome> roulette(generation, fitness);
+ Generation<_Chromosome> newGeneration = roulette.draw();
- cout << "Fitness is equal to: " << fitness.calculate() << "\n";
+ cout << "New Generation:\n";
+ for (unsigned int i = 0; i < newGeneration.get().size(); i++) {
+ cout << "# ";
+ for (unsigned int j = 0; j < newGeneration.get()[i].get().size(); j++) {
+ cout << newGeneration.get()[i].get()[j].get();
+ }
+ cout << "\n";
}
return 0;
--- /dev/null
+#ifndef __SELECTION_ROULETTE_H
+#define __SELECTION_ROULETTE_H
+
+#include <vector>
+#include <utility> // std::pair
+#include <algorithm> // std::sort
+#include <map>
+#include <cstdlib>
+#include <iostream>
+
+#include "chromosome.h"
+#include "selection.h"
+
+using namespace std;
+
+namespace genetic {
+// namespace selection {
+ template < typename _Chromosome >
+ class Roulette : public Selection<_Chromosome> {
+ public:
+ typedef Selection<_Chromosome> BaseType;
+ typedef typename BaseType::FitnessValueType FitnessValueType;
+ protected:
+ vector<FitnessValueType> calculateGenerationFitness(
+ Generation<_Chromosome> generation) {
+ vector<FitnessValueType> generationFitness;
+
+ for (unsigned int i = 0; i < generation.get().size(); i++) {
+ generationFitness.push_back(this->checkChromosomeFitness(generation.get()[i]));
+ }
+
+ return generationFitness;
+ }
+ map<FitnessValueType, _Chromosome> normalizeFitness(
+ vector<FitnessValueType> generationFitness) {
+ FitnessValueType min;
+ FitnessValueType max;
+ FitnessValueType offset;
+ map<FitnessValueType, _Chromosome> normalizedFitness;
+
+ min = max = generationFitness[0];
+
+ for (unsigned int i = 0; i < generationFitness.size(); i++) {
+ if(generationFitness[i] < min) {
+ min = generationFitness[i];
+ }
+
+ if(generationFitness[i] > max) {
+ max = generationFitness[i];
+ }
+ }
+
+ offset = (max - min) / (generationFitness.size() - 1) - min;
+
+ for (unsigned int i = 0; i < generationFitness.size(); i++) {
+ normalizedFitness[generationFitness[i] + offset] = this->generation.get()[i];
+ }
+
+ return normalizedFitness;
+ }
+
+ /**
+ * Spins the Roulette
+ */
+ Generation<_Chromosome> spinRoulette(
+ map<FitnessValueType, _Chromosome> normalizedFitness) {
+
+ typedef typename std::map<FitnessValueType, _Chromosome>::iterator FitnessIterator;
+
+ vector<_Chromosome> selected;
+ map<FitnessValueType, _Chromosome> probabilities;
+
+ unsigned int size = this->generation.get().size();
+ double random = 0;
+
+ FitnessValueType fitnessSum = 0;
+
+ // Calculate sum of normalized fitnesses, in order to calculate probabilities
+ for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
+ fitnessSum += it->first;
+ }
+
+ // Calculate probabilities for fitnesses
+ for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
+ probabilities[it->first / fitnessSum] = it->second;
+ }
+
+ /*
+ * Spin the Roulette until we draw as many chromosomes as in the
+ * original generation.
+ */
+ while (size) {
+ bool found = false;
+ random = (rand() % 10000) / 100000.0;
+
+ for (FitnessIterator it = probabilities.begin(); it != probabilities.end(); it++) {
+ if (it->first > random) {
+ found = true;
+ selected.push_back(it->second);
+ break;
+ }
+ }
+ if (found) {
+ size--;
+ }
+ }
+ return Generation<_Chromosome>(selected);
+ }
+
+ /**
+ * Draws random
+ */
+ Generation<_Chromosome> do_draw() {
+ map<FitnessValueType, _Chromosome> normalizedFitness;
+
+ normalizedFitness = this->normalizeFitness(
+ this->calculateGenerationFitness(this->generation)
+ );
+
+ return spinRoulette(normalizedFitness);
+ }
+
+ public:
+ Roulette(Generation<_Chromosome> _generation, genetic::Fitness<_Chromosome>& _fitness) :
+ Selection<_Chromosome>(_generation, _fitness) {
+ this->generation = _generation;
+ this->fitness = _fitness;
+
+ time_t t;
+ srand((unsigned)time(&t));
+ }
+ };
+// }
+}
+
+#endif /* __SELECTION_ROULETTE_H */
--- /dev/null
+#ifndef __SELECTION_SELECTION_H
+#define __SELECTION_SELECTION_H
+
+#include "chromosome.h"
+#include "generation.h"
+#include "../fitness/fitness.h"
+
+using namespace std;
+
+namespace genetic {
+// namespace selection {
+ template < typename _Chromosome >
+ class Selection {
+ public:
+ typedef Fitness<_Chromosome> GeneticFitness;
+ typedef typename GeneticFitness::ValueType FitnessValueType;
+ protected:
+ Generation<_Chromosome> generation;
+ GeneticFitness& fitness;
+
+ FitnessValueType checkChromosomeFitness(_Chromosome chromosome) {
+ this->fitness.chromosome = chromosome;
+ return fitness.calculate();
+ }
+
+ virtual Generation<_Chromosome> do_draw() = 0;
+
+ public:
+ Selection(Generation<_Chromosome> _generation, GeneticFitness& _fitness) :
+ generation(_generation), fitness(_fitness) {
+ }
+
+ Generation<_Chromosome> draw() {
+ return this->do_draw();
+ }
+ };
+// }
+}
+
+#endif /* __SELECTION_SELECTION_H */