# fitness.h

    00001 /*
    00002     This library is free software; you can redistribute it and/or modify
    00003     it under the terms of the GNU General Public License as published by
    00004     the Free Software Foundation; either version 2 of the License, or
    00005     (at your option) any later version.
    00006
    00007     This library is distributed in the hope that it will be useful,
    00008     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00009     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00010     Lesser General Public License for more details.
    00011
    00012     You should have received a copy of the GNU General Public License
    00013     along with this library; if not, write to the Free Software
    00014     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00015
    00016     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
    00017              jeggermo@liacs.nl
    00018 */
    00019
    00020 #ifndef _FITNESS_FUNCTION_H
    00021 #define _FITNESS_FUNCTION_H
    00022
    00023 #include <gp/eoParseTree.h>
    00024 #include <eo>
    00025
    00026 #include <cmath>
    00027 #include "parameters.h"
    00028 #include "node.h"
    00029
    00030 using namespace gp_parse_tree;
    00031 using namespace std;
    00032
    00033
    00034
    00035 // the first fitness is the normal goal fitness
    00036 // the second fitness is the tree size (we prefer smaller trees)
    00037 // lets use names to define the different fitnesses
    00038 #define NORMAL 0      // Stepwise Adaptation of Weights Fitness
    00039 #define SMALLESTSIZE 1  // The size of the tree, we want to minimize this one -- statistics will tell us the smallest tree size
    00040
    00041
    00042 // Look: overloading the maximization without overhead (thing can be inlined)
    00043 class MinimizingFitnessTraits : public eoParetoFitnessTraits
    00044 {
    00045   public :
    00046   static bool maximizing(int which) { return false;} // we want to minimize both fitnesses
    00047   static unsigned nObjectives()          { return 2;} // the number of fitnesses }
    00048 };
    00049
    00050 // Lets define our MultiObjective FitnessType
    00051 typedef eoParetoFitness<MinimizingFitnessTraits> FitnessType;
    00052
    00053
    00054 // John Koza's sextic polynomial (our example problem)
    00055
    00056 double sextic_polynomial(double x)
    00057 {
    00058         double result=0;
    00059         result = pow(x,6) - (2*pow(x,4)) + pow(x,2);
    00060         return result;
    00061 };
    00062
    00063 // we use the following functions for the basic math functions
    00064
    00065 double _plus(double arg1, double arg2)
    00066 {
    00067         return arg1 + arg2;
    00068 }
    00069
    00070 double _minus(double arg1, double arg2)
    00071 {
    00072         return arg1 - arg2;
    00073 }
    00074
    00075 double _multiplies(double arg1, double arg2)
    00076 {
    00077         return arg1 * arg2;
    00078 }
    00079
    00080 // the function for a protected divide looks a little bit different
    00081 double _divides(double arg1, double arg2)
    00082 {
    00083         if (arg2 ==0)
    00084                 return 0;
    00085         else
    00086                 return arg1 / arg2;
    00087 }
    00088
    00089 double _negate(double arg1)
    00090 {
    00091         return -arg1;
    00092 }
    00093
    00094
    00095
    00096 // now let's define our tree nodes
    00097
    00098 void init(vector<Node> &initSequence)
    00099 {
    00100
    00101                 // we have only one variable (X)
    00102                 Operation varX( (unsigned int) 0, string("X") );
    00103
    00104
    00105                 // the main binary operators
    00106                 Operation OpPLUS ( _plus, string("+"));
    00107                 Operation OpMINUS( _minus,string("-"));
    00108                 Operation OpMULTIPLIES(_multiplies,string("*"));
    00109                 // We can use a protected divide function.
    00110                 Operation OpDIVIDE( _divides, string("/") );
    00111
    00112
    00113                 // Now the functions as binary functions
    00114                 Operation PLUS( string("plus"), _plus);
    00115                 Operation MINUS( string("minus"), _minus);
    00116                 Operation MULTIPLIES( string("multiply"), _multiplies);
    00117                 Operation DIVIDE( string("divide"), _divides);
    00118
    00119
    00120                 // and some unary  functions
    00121                 Operation NEGATE( _negate,string("-"));
    00122                 Operation SIN ( sin, string("sin"));
    00123                 Operation COS ( cos, string("cos"));
    00124
    00125                 // Now we are ready to add the possible nodes to our initSequence (which is used by the eoDepthInitializer)
    00126
    00127                 // so lets start with our variable
    00128                 initSequence.push_back(varX);
    00129
    00130                 // followed by the constants 2, 4, 6
    00131                 for(unsigned int i=2; i <= 6; i+=2)
    00132                 {
    00133                         char text[255];
    00134                         sprintf(text, "%i", i);
    00135                         Operation op(i*1.0, text);
    00136                         initSequence.push_back( op );
    00137                         // and we add the variable again (so we have get lots of variables);
    00138                         initSequence.push_back( varX );
    00139                 }
    00140
    00141                 // next we add the unary functions
    00142
    00143                 initSequence.push_back( NEGATE );
    00144                 initSequence.push_back( SIN );
    00145                 initSequence.push_back( COS );
    00146
    00147                 // and the binary functions
    00148                 initSequence.push_back( PLUS);
    00149                 initSequence.push_back( MINUS );
    00150                 initSequence.push_back( MULTIPLIES );
    00151                 initSequence.push_back( DIVIDE );
    00152
    00153                 // and the binary operators
    00154                 initSequence.push_back( OpPLUS);
    00155                 initSequence.push_back( OpMINUS );
    00156
    00157                 initSequence.push_back( OpMULTIPLIES );
    00158                 initSequence.push_back( OpDIVIDE );
    00159
    00160
    00161 };
    00162
    00163
    00164
    00165 class RegFitness: public eoEvalFunc< eoParseTree<FitnessType, Node> >
    00166 {
    00167         public:
    00168
    00169                 typedef eoParseTree<FitnessType, Node> EoType;
    00170
    00171                 void operator()(EoType &_eo)
    00172                 {
    00173
    00174                                 vector< double > input(1); // the input variable(s)
    00175                                 double output(0.);
    00176                                 double target;
    00177                                 FitnessType fitness;
    00178
    00179
    00180                                 float x=0;
    00181                                 double fit=0;
    00182                                 for(x=-1; x <= 1; x+=0.1)
    00183                                 {
    00184                                         input[0] = x;
    00185                                         target = sextic_polynomial(x);
    00186                                         _eo.apply(output,input);
    00187
    00188                                         fit += pow(target - output, 2);
    00189                                 }
    00190
    00191                                 fitness[NORMAL] = fit;
    00192
    00193                                 fitness[SMALLESTSIZE] =  _eo.size() / (1.0*parameter.MaxSize);
    00194                                 _eo.fitness(fitness);
    00195
    00196                                 if (fitness[NORMAL] < best[NORMAL])
    00197                                 {
    00198                                         best[NORMAL] = fitness[NORMAL];
    00199                                         tree="";
    00200                                         _eo.apply(tree);
    00201                                 }
    00202
    00203                 }
    00204
    00205
    00206
    00207                 RegFitness(eoValueParam<unsigned> &_generationCounter, vector< Node > &initSequence, Parameters &_parameter) : eoEvalFunc<EoType>(), generationCounter(_generationCounter), parameter(_parameter)
    00208                 {
    00209                         init(initSequence);
    00210                         best[NORMAL] = 1000;
    00211                         tree= "not found";
    00212                 };
    00213
    00214                 ~RegFitness()
    00215                 {
    00216                         cerr << "Best Fitness= " << best[NORMAL] << endl;
    00217                         cerr << tree << endl;
    00218                 };
    00219
    00220         private:
    00221                 eoValueParam<unsigned> &generationCounter; // so we know the current generation
    00222                 Parameters &parameter; // the parameters
    00223                 FitnessType best;       // the best found fitness
    00224                 string tree;
    00225 };
    00226
    00227 #endif
    00228