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