Made Algorithm functions more generic.
authorRafał Długołęcki <rafal@dlugolecki.net.pl>
Sun, 5 Apr 2015 08:25:39 +0000 (10:25 +0200)
committerRafał Długołęcki <rafal@dlugolecki.net.pl>
Sun, 5 Apr 2015 08:25:39 +0000 (10:25 +0200)
src/algorithm.h
src/fitness/fitness.h
src/fitness/wsti.h
src/main.cpp

index 894f4880019034d0e2004bca4e45cfff4d49ecfd..9b2e3bea75b3bca8717c2ee6c72b22b830975708 100644 (file)
@@ -19,7 +19,7 @@ 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:
         /**
@@ -38,7 +38,7 @@ namespace genetic {
          * 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
@@ -79,7 +79,7 @@ namespace genetic {
          */
         Algorithm(
             generator::Generation<_Chromosome>& _generator,
-            Fitness<_Chromosome, FitnessValueType>& _fitness,
+           _Fitness& _fitness,
             double crossoverChance,
             double mutationChance) :
                 generator(_generator),
@@ -130,12 +130,12 @@ namespace genetic {
 
         /**
          * Displays average fitness value of the entire generation.
-         * @todo make it more generic
          */
         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);
+                _Fitness fit(this->generation.get()[i]);
+                fit.parseArguments(fitness.getArguments());
                 avg += fit.calculate();
             }
             cout << " " << avg / this->generation.get().size();
@@ -143,13 +143,13 @@ namespace genetic {
 
         /**
          * Displays best fitness value of the entire generation.
-         * @todo make it more generic, currently has hardcoded WSTI Fitness
-         *      class, due its additional arguments
          */
         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);
+                _Fitness fit(this->generation.get()[i]);
+                fit.parseArguments(fitness.getArguments());
+
                 double tmp = fit.calculate();
                 if (tmp > best) {
                     best = tmp;
index 66263f1bbc82363adfea48830cbccb148c607bfe..093490d367e1fa7add12bb9164cb62f9c1d0ee39 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __FITNESS_FITNESS_H
 #define __FITNESS_FITNESS_H
 
+#include <map>
+#include <string>
+
 #include "chromosome.h"
 
 namespace genetic {
@@ -55,6 +58,22 @@ namespace genetic {
         _Value calculate() {
             return this->do_calculate();
         }
+
+        /**
+         * Method used to pass additional arguments needed by the function to
+         * run correctly.
+         */
+        virtual void parseArguments(std::map<string, string>) { }
+
+        /**
+         * Method used to get additional arguments needed by the function to
+         * run correctly
+         *
+         * @return map containing additional arguments, empty if do not use any
+         */
+        virtual std::map<string, string> getArguments() {
+            return std::map<string, string>();
+        }
     };
 }
 
index d99dd18b8e6d58673a5f750d6e7ca8634fe7d55b..3743a9ca00077143a90fb126aba02e718d3a2c46 100644 (file)
@@ -57,7 +57,16 @@ namespace genetic {
         }
     public:
         /**
-         * Class constructor. Initializes class with requied values.
+         * Class constructor. Initializes class with required values.
+         *
+         * @param _chromosome Chromosome, for which value will be calculated
+         */
+        WSTI(_Chromosome& _chromosome)
+            : Fitness<_Chromosome>(_chromosome) {
+        }
+
+        /**
+         * Class constructor. Initializes class with required values.
          *
          * @param start begining of the Fitness function domain
          * @param end end of the Fitness function domain
@@ -67,7 +76,7 @@ namespace genetic {
         }
 
         /**
-         * Class constructor. Initializes class with requied values.
+         * Class constructor. Initializes class with required values.
          *
          * @param _chromosome Chromosome, for which value will be calculated
          * @param start begining of the Fitness function domain
@@ -76,6 +85,43 @@ namespace genetic {
         WSTI(_Chromosome& _chromosome, float start, float end)
             : Fitness<_Chromosome>(_chromosome), span_start(start), span_end(end) {
         }
+
+        /**
+         * Method used to pass additional arguments needed by the function to
+         * run correctly.
+         * Required map keys are:
+         *  - _span_start_ - with value equal to begining of the Fitness function domain
+         *  - _span_end_ - with value equal to end of the Fitness function domain
+         * Their values should be floats.
+         * 
+         * @param args map containing span_start and span_end as a keys and
+         *      their values (_double_) passed as strings
+         */
+        virtual void parseArguments(std::map<string, string> args) {
+            std::map<string, string>::iterator it;
+            for (it = args.begin(); it != args.end(); it++) {
+                if (it->first == "span_start") {
+                    this->span_start = std::stod(it->second);
+                }
+                else if (it->first == "span_end") {
+                    this->span_end = std::stod(it->second);
+                }
+            }
+        }
+
+        /**
+         * Method used to get additional arguments needed by the function to
+         * run correctly.
+         *
+         * @return map containing span_start and span_end as a map keys, with
+         *      their values passed as string
+         */
+        std::map<string, string> getArguments() {
+            std::map<string, string> fit_args;
+            fit_args.insert(std::pair<string, string>("span_start", std::to_string(span_start)));
+            fit_args.insert(std::pair<string, string>("span_end", std::to_string(span_end)));
+            return fit_args;
+        }
     };
 }
 
index 3816b435095ef27255cb76f50ab4192231da97c0..f2aec1380acfd130482c57cc364305fdb6da4876 100644 (file)
@@ -1,5 +1,7 @@
 #include <iostream>
 #include <vector>
+#include <map>
+#include <string>
 
 #include "gene.h"
 #include "chromosome.h"
@@ -27,7 +29,7 @@ int main() {
     typedef Mutation<_Chromosome> _Mutation;
 
     typedef generator::Generation<_Chromosome> _Generator;
-    typedef Algorithm<_Chromosome, _Selection, _Crossover, _Mutation> _Algorithm;
+    typedef Algorithm<_Chromosome, _Selection, _Crossover, _Mutation, _Fitness> _Algorithm;
     typedef Condition<_Chromosome> _Condition;
 
     const int chromosomeSize = 10;