00001 #ifdef _MSC_VER
00002 #pragma warning(disable:4786)
00003 #endif
00004
00005 #include <gp/eoParseTree.h>
00006 #include <eo>
00007
00008 using namespace gp_parse_tree;
00009 using namespace std;
00010
00011
00012
00013 class SymregNode
00014 {
00015 public :
00016
00017 enum Operator {X = 'x', Plus = '+', Min = '-', Mult = '*', PDiv = '/'};
00018
00019 SymregNode(void) { init(); }
00020 SymregNode(Operator _op) { op = _op; }
00021 virtual ~SymregNode(void) {}
00022
00023
00024 int arity(void) const { return op == X? 0 : 2; }
00025
00026 void randomize(void) {}
00027
00028
00029 template <class Children>
00030 void operator()(double& result, Children args, double var) const
00031 {
00032 double r1, r2;
00033
00034 if (arity() == 2)
00035 {
00036 args[0].apply(r1, var);
00037 args[1].apply(r2, var);
00038 }
00039
00040 switch (op)
00041 {
00042 case Plus : result = r1 + r2; break;
00043 case Min : result = r1 - r2; break;
00044 case Mult : result = r1 * r2; break;
00045 case PDiv :
00046 {
00047 if (r2 == 0.0)
00048 result = 1.0;
00049 else
00050 result = r1 / r2;
00051 break;
00052 }
00053
00054 case X : result = var; break;
00055 }
00056
00057 }
00058
00060 template <class Children>
00061 void operator()(string& result, Children args) const
00062 {
00063 static const string lb = "(";
00064 static const string rb = ")";
00065 char opStr[4] = " ";
00066 opStr[1] = op;
00067
00068 if (arity() == 0)
00069 {
00070 result = "x";
00071 return;
00072 }
00073
00074 string r1;
00075 args[0].apply(r1);
00076 result = lb + r1;
00077 result += opStr;
00078 args[1].apply(r1);
00079 result += r1 + rb;
00080 }
00081
00082 Operator getOp(void) const { return op; }
00083
00084 protected :
00085
00086 void init(void) { op = X; }
00087
00088 private :
00089
00090 Operator op;
00091 };
00092
00094 static SymregNode init_sequence[5] = {SymregNode::X, SymregNode::Plus, SymregNode::Min, SymregNode::Mult, SymregNode::PDiv};
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 std::ostream& operator<<(std::ostream& os, const SymregNode& eot)
00113 {
00114 os << static_cast<char>(eot.getOp());
00115 return os;
00116 }
00117
00118 std::istream& operator>>(std::istream& is, SymregNode& eot)
00119 {
00120 char type;
00121 type = (char) is.get();
00122 eot = SymregNode(static_cast<SymregNode::Operator>(type));
00123 return is;
00124 }
00125
00126
00127
00130 double targetFunction(double x)
00131 {
00132 return x * x * x * x - x * x * x + x * x * x - x * x + x - 10;
00133 }
00134
00135
00136 const double xbegin = -10.0f;
00137 const double xend = 10.0f;
00138 const double xstep = 1.3f;
00139
00140 template <class FType, class Node> struct RMS: public eoEvalFunc< eoParseTree<FType, Node> >
00141 {
00142 public :
00143
00144 typedef eoParseTree<FType, Node> EoType;
00145
00146 typedef eoParseTree<FType, Node> argument_type;
00147 typedef double fitness_type;
00148
00149 RMS(void) : eoEvalFunc<EoType>()
00150 {
00151 int n = int( (xend - xbegin) / xstep);
00152
00153 inputs.resize(n);
00154 target.resize(n);
00155
00156 int i = 0;
00157
00158 for (double x = xbegin; x < xend && i < n; ++i, x+=xstep)
00159 {
00160 target[i] = targetFunction(x);
00161 inputs[i] = x;
00162 }
00163 }
00164
00165 ~RMS() {}
00166
00167 void operator()( EoType & _eo )
00168 {
00169 vector<double> outputs;
00170 outputs.resize(inputs.size());
00171
00172 double fitness = 0.0;
00173
00174 for (unsigned i = 0; i < inputs.size(); ++i)
00175 {
00176 _eo.apply(outputs[i], inputs[i]);
00177 fitness += (outputs[i] - target[i]) * (outputs[i] - target[i]);
00178 }
00179
00180 fitness /= (double) target.size();
00181 fitness = sqrt(fitness);
00182
00183 if (fitness > 1e+20)
00184 fitness = 1e+20;
00185
00186 _eo.fitness(fitness);
00187 }
00188
00189 private :
00190 vector<double> inputs;
00191 vector<double> target;
00192 };
00193
00194 template <class EOT, class FitnessType>
00195 void print_best(eoPop<EOT>& pop)
00196 {
00197 std::cout << std::endl;
00198 FitnessType best = pop[0].fitness();
00199 int index = 0;
00200
00201 for (unsigned i = 1; i < pop.size(); ++i)
00202 {
00203 if (best < pop[i].fitness())
00204 {
00205 best = pop[i].fitness();
00206 index = i;
00207 }
00208 }
00209
00210 std::cout << "\t";
00211
00212 string str;
00213 pop[index].apply(str);
00214
00215 std::cout << str.c_str();
00216 std::cout << std::endl << "RMS Error = " << pop[index].fitness() << std::endl;
00217 }
00218
00219 int main()
00220 {
00221 typedef eoMinimizingFitness FitnessType;
00222 typedef SymregNode GpNode;
00223
00224 typedef eoParseTree<FitnessType, GpNode> EoType;
00225 typedef eoPop<EoType> Pop;
00226
00227 const int MaxSize = 100;
00228 const int nGenerations = 10;
00229
00230
00231 vector<GpNode> init(init_sequence, init_sequence + 5);
00232
00233
00234 eoGpDepthInitializer<FitnessType, GpNode> initializer(10, init);
00235
00236
00237 RMS<FitnessType, GpNode> eval;
00238
00239 Pop pop(50, initializer);
00240
00241 apply<EoType>(eval, pop);
00242
00243 eoSubtreeXOver<FitnessType, GpNode> xover(MaxSize);
00244 eoBranchMutation<FitnessType, GpNode> mutation(initializer, MaxSize);
00245
00246
00247
00248 eoSGATransform<EoType> transform(xover, 0.75, mutation, 0.25);
00249
00250
00251 eoDetTournamentSelect<EoType> selectOne(2);
00252
00253 eoSelectMany<EoType> select(selectOne,2, eo_is_an_integer);
00254
00255
00256 eoSSGAWorseReplacement<EoType> replace;
00257
00258
00259 eoGenContinue<EoType> term(nGenerations);
00260
00261 eoCheckPoint<EoType> checkPoint(term);
00262
00263 eoAverageStat<EoType> avg;
00264 eoBestFitnessStat<EoType> best;
00265 eoStdoutMonitor monitor;
00266
00267 checkPoint.add(monitor);
00268 checkPoint.add(avg);
00269 checkPoint.add(best);
00270
00271 monitor.add(avg);
00272 monitor.add(best);
00273
00274
00275 eoEasyEA<EoType> gp(checkPoint, eval, select, transform, replace);
00276
00277 std::cout << "Initialization done" << std::endl;
00278
00279 print_best<EoType, FitnessType>(pop);
00280
00281 try
00282 {
00283 gp(pop);
00284 }
00285 catch (std::exception& e)
00286 {
00287 std::cout << "exception: " << e.what() << std::endl;;
00288 exit(EXIT_FAILURE);
00289 }
00290
00291 print_best<EoType, FitnessType>(pop);
00292
00293 }
00294
00295