#include "chromosome.h"
#include "generation.h"
#include "fitness/fitness.h"
-#include "generator/generation.h"
+#include "generator/generator.h"
#include "selection/selection.h"
#include "crossover/crossover.h"
#include "mutation/mutation.h"
+#include "condition/condition.h"
+
using namespace std;
namespace genetic {
/**
* Genetic Algorithm itself
*/
- template < typename _Chromosome, typename _Selection, typename _Crossover, typename _Mutation >
+ template < typename _Chromosome, typename _Selection, typename _Crossover, typename _Mutation, typename _Fitness = Fitness<_Chromosome, typename _Selection::FitnessValueType > >
class Algorithm {
public:
+ /**
+ * Type representing Fitness value
+ */
typedef typename _Selection::FitnessValueType FitnessValueType;
protected:
/**
* Generator which draws initial population
*/
- generator::Generation<_Chromosome>& generator;
+ generator::Generator<_Chromosome>& generator;
/**
* Fitness function used in selection
+ *
+ * It is a reference, because Fitness is purely virtual class and we
+ * can't have instance of it. It must be one of derived classes.
*/
- Fitness<_Chromosome, FitnessValueType>& fitness;
+ _Fitness& fitness;
/**
* Crossover function
*/
Generation<_Chromosome> generation;
- const int numberOfGenerations = 100;
+ /**
+ * Method invoked in each iteration of algorithm.
+ *
+ * Applies selection, crossover and mutation on each of the chromosomes
+ * in generation.
+ */
+ void do_search() {
+ _Selection selection(this->generation, fitness);
+ this->generation = selection.draw();
+ this->generation = crossover.cross(this->generation);
+ this->generation = mutation.mutate(this->generation);
+ }
public:
+ /**
+ * Class constructor. Initializes class with values and breeds initial
+ * population using passed generator::Generation.
+ *
+ * @param _generator Generator used to generate initial population
+ * @param _fitness Fitness class used to check fitness of the chromosome
+ * @param crossoverChance probability of crossover (0 = 0%, 1 = 100%)
+ * @param mutationChance probability of fitness (0 = 0%, 1 = 100%)
+ */
Algorithm(
- generator::Generation<_Chromosome>& _generator,
- Fitness<_Chromosome, FitnessValueType>& _fitness,
+ generator::Generator<_Chromosome>& _generator,
+ _Fitness& _fitness,
double crossoverChance,
double mutationChance) :
generator(_generator),
this->generation = this->generator.breed();
}
- void searchForResult() {
- cout << "generation avg best" << endl;
- for(int i = 0; i < this->numberOfGenerations; i++) {
+ /**
+ * Starts Algorithm in search for result.
+ * For each generation but initial, condition is checked, if algorithm
+ * should stop.
+ *
+ * Displays separated by space: generation number, generation average
+ * fitness and best chromosome fitness.
+ *
+ * @param condition Condition used to check after breeding new generation
+ */
+ void searchForResult(Condition<_Chromosome>& condition) {
+ unsigned int i = 0;
+ cout << "generation avg best\n";
+ do {
cout << i;
- _Selection selection(this->generation, fitness);
- this->generation = selection.draw();
- this->generation = crossover.cross(this->generation);
- this->generation = mutation.mutate(this->generation);
+ do_search();
// cout << "New Generation:\n";
// this->showGeneration();
this->showAvgFitness();
this->showBestFitness();
- }
+ } while(condition.check(this->generation) && ++i);
}
+ /**
+ * Displays entire generation.
+ * \attention Method is currently not in use.
+ */
void showGeneration() {
- for (unsigned int i = 0; i < this->generation.get().size(); i++) {
+ unsigned int generationSize = this->generation.size();
+ unsigned int chromosomeSize = this->generation[0].size();
+
+ for (unsigned int i = 0; i < generationSize; i++) {
cout << "# " << i << ") ";
- for (unsigned int j = 0; j < this->generation.get()[i].get().size(); j++) {
- cout << this->generation.get()[i].get()[j].get();
+ for (unsigned int j = 0; j < chromosomeSize; j++) {
+ cout << this->generation[i][j].get();
}
cout << "\n";
}
}
+ /**
+ * Displays average fitness value of the entire generation.
+ */
void showAvgFitness() {
double avg = 0;
- for (unsigned int i = 0; i < this->generation.get().size(); i++) {
- WSTI<_Chromosome, FitnessValueType> fit(this->generation.get()[i], 0.5, 2.5);
+ unsigned int generationSize = this->generation.size();
+
+ for (unsigned int i = 0; i < generationSize; i++) {
+ _Fitness fit(this->generation[i]);
+ fit.parseArguments(fitness.getArguments());
avg += fit.calculate();
}
- cout << " " << avg / this->generation.get().size();
+ cout << " " << avg / generationSize;
}
+ /**
+ * Displays best fitness value of the entire generation.
+ */
void showBestFitness() {
double best = -100000;
- for (unsigned int i = 0; i < this->generation.get().size(); i++) {
- WSTI<_Chromosome, FitnessValueType> fit(this->generation.get()[i], 0.5, 2.5);
+ unsigned int generationSize = this->generation.size();
+
+ for (unsigned int i = 0; i < generationSize; i++) {
+ _Fitness fit(this->generation[i]);
+ fit.parseArguments(fitness.getArguments());
+
double tmp = fit.calculate();
if (tmp > best) {
best = tmp;