--- /dev/null
+#ifndef __ALGORITHM_H
+#define __ALGORITHM_H
+
+#include <iostream>
+
+#include "chromosome.h"
+#include "generation.h"
+#include "fitness/fitness.h"
+#include "generator/generation.h"
+#include "selection/selection.h"
+#include "crossover/crossover.h"
+#include "mutation/mutation.h"
+
+using namespace std;
+
+namespace genetic {
+ /**
+ * Genetic Algorithm itself
+ */
+ template < typename _Chromosome, typename _Selection, typename _Crossover, typename _Mutation >
+ class Algorithm {
+ public:
+ typedef typename _Selection::FitnessValueType FitnessValueType;
+ protected:
+ /**
+ * Generator which draws initial population
+ */
+ generator::Generation<_Chromosome>& generator;
+
+ /**
+ * Fitness function used in selection
+ */
+ Fitness<_Chromosome, FitnessValueType>& fitness;
+
+ /**
+ * Crossover function
+ */
+ _Crossover crossover;
+
+ /**
+ * Mutation function
+ */
+ _Mutation mutation;
+
+ /**
+ * Current population
+ */
+ Generation<_Chromosome> generation;
+
+ const int numberOfGenerations = 100;
+ public:
+ Algorithm(
+ generator::Generation<_Chromosome>& _generator,
+ Fitness<_Chromosome, FitnessValueType>& _fitness,
+ double crossoverChance,
+ double mutationChance) :
+ generator(_generator),
+ fitness(_fitness),
+ crossover(crossoverChance),
+ mutation(mutationChance) {
+
+ this->generation = this->generator.breed();
+ }
+
+ void searchForResult() {
+ cout << "generation avg best" << endl;
+ for(int i = 0; i < this->numberOfGenerations; i++) {
+ cout << i;
+ _Selection selection(this->generation, fitness);
+// cout << "[+] Algorithm::Selection.draw()\n";
+ this->generation = selection.draw();
+// cout << "[+] Crossover\n";
+ this->generation = crossover.cross(this->generation);
+// cout << "[+] Mutate\n";
+ this->generation = mutation.mutate(this->generation);
+
+// cout << "New Generation:\n";
+// this->showGeneration();
+ this->showAvgFitness();
+ this->showBestFitness();
+ }
+ }
+
+ void showGeneration() {
+ for (unsigned int i = 0; i < this->generation.get().size(); i++) {
+ cout << "# " << i << ") ";
+ for (unsigned int j = 0; j < this->generation.get()[i].get().size(); j++) {
+ cout << this->generation.get()[i].get()[j].get();
+ }
+ cout << "\n";
+ }
+ }
+
+ void showAvgFitness() {
+ double avg = 0;
+// cout << "Fitness:\n";
+ for (unsigned int i = 0; i < this->generation.get().size(); i++) {
+// cout << "# " << i << ") ";
+ WSTI<_Chromosome, FitnessValueType> fit(this->generation.get()[i], 0.5, 2.5);
+// cout << fit.calculate() << "\n";
+ avg += fit.calculate();
+ }
+ cout << " " << avg / this->generation.get().size();
+ }
+
+ void showBestFitness() {
+ double best = -100000;
+ for (unsigned int i = 0; i < this->generation.get().size(); i++) {
+// cout << "# " << i << ") ";
+ WSTI<_Chromosome, FitnessValueType> fit(this->generation.get()[i], 0.5, 2.5);
+// cout << fit.calculate() << "\n";
+ double tmp = fit.calculate();
+ if (tmp > best) {
+ best = tmp;
+ }
+ }
+ cout << " " << best << endl;
+ }
+ };
+}
+
+#endif /* __ALGORITHM_H */
--- /dev/null
+#ifndef __CROSSOVER_CROSSOVER_H
+#define __CROSSOVER_CROSSOVER_H
+
+#include "chromosome.h"
+#include "generation.h"
+
+using namespace std;
+
+namespace genetic {
+// namespace crossover {
+ template < typename _Chromosome >
+ class Crossover {
+ public:
+ typedef double CrossoverChanceType;
+ typedef typename _Chromosome::GeneType GeneType;
+ protected:
+ CrossoverChanceType chance;
+
+ _Chromosome do_cross(_Chromosome first, _Chromosome second, unsigned int splitPlace) {
+ const unsigned int chromosomeSize = first.get().size();
+
+// cout << " ";
+// for (unsigned int i = 0; i < chromosomeSize; i++) {
+// cout << first.get()[i].get();
+// }
+// cout << "\n x ";
+// for (unsigned int i = 0; i < chromosomeSize; i++) {
+// cout << second.get()[i].get();
+// }
+// cout << "\n--------";
+// for (unsigned int i = 0; i < chromosomeSize; i++) {
+// if (i == splitPlace) {
+// cout << "^";
+// }
+// else {
+// cout << "-";
+// }
+// }
+
+ vector<GeneType> crossedChromosome;
+ for (unsigned int i = 0; i < chromosomeSize; i++) {
+ if (i < splitPlace) {
+ crossedChromosome.push_back(first.get()[i].get());
+ }
+ else {
+ crossedChromosome.push_back(second.get()[i].get());
+ }
+ }
+
+// cout << "\n ";
+// for (unsigned int i = 0; i < chromosomeSize; i++) {
+// cout << crossedChromosome[i].get();
+// }
+// cout << "\n";
+
+ return _Chromosome(crossedChromosome);
+ }
+
+ public:
+ Crossover(CrossoverChanceType chance) :
+ chance(chance) {
+ }
+
+ Generation<_Chromosome> cross(Generation<_Chromosome> _generation) {
+ const unsigned int generationSize = _generation.get().size();
+ vector<_Chromosome> newGeneration;
+
+ for (unsigned int i = 0; i < generationSize; i++) {
+ CrossoverChanceType random = (rand() + 1 % 10000) / 10000.0;
+ _Chromosome chromosome = _generation.get()[i];
+ if (random < this->chance) {
+ const unsigned int chromosomeSize = chromosome.get().size();
+ const unsigned int splitPlace = rand() % chromosomeSize;
+ unsigned int pairedChromosome = 0;
+
+ /**
+ * Search for different Chromosome, and crossover them together
+ */
+ do {
+ pairedChromosome = rand() % generationSize;
+ } while(pairedChromosome == i);
+
+ chromosome = do_cross(chromosome, _generation.get()[pairedChromosome], splitPlace);
+ }
+ newGeneration.push_back(chromosome);
+ }
+
+ return Generation<_Chromosome>(newGeneration);
+ }
+ };
+// }
+}
+
+#endif /* __CROSSOVER_CROSSOVER_H */
_fenotype = _fenotype + this->chromosome.get()[i].get() * ratio;
ratio = ratio * 2;
}
+// cout << "Fenotyp: " << _fenotype << "\n";
return _fenotype;
}
#include "generator/generation.h"
#include "selection/roulette.h"
-
+#include "crossover/crossover.h"
+#include "mutation/mutation.h"
#include "fitness/wsti.h"
+#include "algorithm.h"
+
using namespace std;
using namespace genetic;
typedef Gene<int> _Gene;
typedef Chromosome<_Gene> _Chromosome;
+ typedef WSTI<_Chromosome> _Fitness;
+ typedef Roulette<_Chromosome> _Selection;
+ typedef Crossover<_Chromosome> _Crossover;
+ typedef Mutation<_Chromosome> _Mutation;
+
+ typedef generator::Generation<_Chromosome> _Generator;
+ typedef Algorithm<_Chromosome, _Selection, _Crossover, _Mutation> _Algorithm;
+
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();
-
- 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 << "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";
- }
+ const int generationSize = 30;
+ const double crossoverChance = 0.75;
+ const double mutationChance = 0.01;
+// const int numberOfGenerations = 100;
+
+ _Fitness fitness(0.5, 2.5);
+ _Generator generationGenerator(generationSize, chromosomeSize);
+
+ _Algorithm algorithm(generationGenerator, fitness, crossoverChance, mutationChance);
+
+ algorithm.searchForResult();
return 0;
}
--- /dev/null
+#ifndef __MUTATION_MUTATION_H
+#define __MUTATION_MUTATION_H
+
+#include <iostream>
+
+#include "chromosome.h"
+#include "generation.h"
+
+using namespace std;
+
+namespace genetic {
+// namespace crossover {
+ template < typename _Chromosome>
+ class Mutation {
+ public:
+ typedef double MutationChanceType;
+ protected:
+ MutationChanceType chance;
+
+ public:
+ Mutation(MutationChanceType chance) :
+ chance(chance) {
+ }
+
+ Generation<_Chromosome> mutate(Generation<_Chromosome> _generation) {
+ const unsigned int generationSize = _generation.get().size();
+ const unsigned int chromosomeSize = _generation.get()[0].get().size();
+ vector<_Chromosome> newGeneration;
+
+ for (unsigned int i = 0; i < generationSize; i++) {
+ MutationChanceType random = (rand() % 10000) / 10000.0;
+// cout << " Mutation chance: " << chance << ", random: " << random << "\n";
+ newGeneration.push_back(_generation.get()[i]);
+
+ if (random < this->chance) {
+// cout << " > Mutated!\n";
+ unsigned int which = (rand() % chromosomeSize);
+ newGeneration[i].get()[which] = !newGeneration[i].get()[which].get();
+ }
+ }
+ return Generation<_Chromosome>(newGeneration);
+ }
+ };
+// }
+}
+
+#endif /* __MUTATION_MUTATION_H */
return generationFitness;
}
- map<FitnessValueType, _Chromosome> normalizeFitness(
- vector<FitnessValueType> generationFitness) {
+ multimap<FitnessValueType, _Chromosome> normalizeFitness(
+ vector<FitnessValueType> generationFitness,
+ unsigned int chromosomeSize) {
FitnessValueType min;
FitnessValueType max;
FitnessValueType offset;
- map<FitnessValueType, _Chromosome> normalizedFitness;
+ multimap<FitnessValueType, _Chromosome> normalizedFitness;
min = max = generationFitness[0];
+ offset = 0;
for (unsigned int i = 0; i < generationFitness.size(); i++) {
if(generationFitness[i] < min) {
}
}
- offset = (max - min) / (generationFitness.size() - 1) - min;
+ offset = (max - min) / (chromosomeSize - 1) - min;
for (unsigned int i = 0; i < generationFitness.size(); i++) {
- normalizedFitness[generationFitness[i] + offset] = this->generation.get()[i];
+ normalizedFitness.insert(std::make_pair(generationFitness[i] + offset, this->generation.get()[i]));
}
return normalizedFitness;
* Spins the Roulette
*/
Generation<_Chromosome> spinRoulette(
- map<FitnessValueType, _Chromosome> normalizedFitness) {
+ multimap<FitnessValueType, _Chromosome> normalizedFitness) {
- typedef typename std::map<FitnessValueType, _Chromosome>::iterator FitnessIterator;
+ typedef typename std::multimap<FitnessValueType, _Chromosome>::iterator FitnessIterator;
vector<_Chromosome> selected;
- map<FitnessValueType, _Chromosome> probabilities;
+ multimap<FitnessValueType, _Chromosome> probabilities;
unsigned int size = this->generation.get().size();
- double random = 0;
+ const unsigned int power2N = 1 << this->generation.get()[0].get().size();
+
+ /** Random value used to draw chromosome */
+ FitnessValueType random = 0;
+
+ /** Position on the roulette wheele */
+ FitnessValueType position = 0;
FitnessValueType fitnessSum = 0;
// Calculate probabilities for fitnesses
for (FitnessIterator it = normalizedFitness.begin(); it != normalizedFitness.end(); it++) {
- probabilities[it->first / fitnessSum] = it->second;
+ position += (it->first / fitnessSum * power2N);
+ probabilities.insert(std::make_pair(position, it->second));
}
/*
* Spin the Roulette until we draw as many chromosomes as in the
* original generation.
*/
- while (size) {
+ while (size > 0) {
bool found = false;
- random = (rand() % 10000) / 100000.0;
+ random = (rand() % power2N);
for (FitnessIterator it = probabilities.begin(); it != probabilities.end(); it++) {
- if (it->first > random) {
+ if (random < it->first) {
found = true;
selected.push_back(it->second);
break;
}
+ // When NaN occur:
+ else if (it->first != it->first) {
+ selected.push_back(probabilities.begin()->second);
+ found = true;
+ break;
+ }
}
+
if (found) {
size--;
}
* Draws random
*/
Generation<_Chromosome> do_draw() {
- map<FitnessValueType, _Chromosome> normalizedFitness;
+ multimap<FitnessValueType, _Chromosome> normalizedFitness;
normalizedFitness = this->normalizeFitness(
- this->calculateGenerationFitness(this->generation)
+ this->calculateGenerationFitness(this->generation),
+ this->generation.get()[0].get().size()
);
return spinRoulette(normalizedFitness);
Selection<_Chromosome>(_generation, _fitness) {
this->generation = _generation;
this->fitness = _fitness;
-
- time_t t;
- srand((unsigned)time(&t));
}
};
// }