Bigger values for testing results.
[genetic.git] / src / algorithm.h
index 162fdd02afa761dc7a27e52c43944defd5c0af32..9386607347fa9039a999ebf6b9dbd222ce6499f7 100644 (file)
@@ -6,31 +6,39 @@
 #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
@@ -47,11 +55,31 @@ namespace genetic {
          */
         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),
@@ -62,45 +90,73 @@ namespace genetic {
             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;