t-eoPareto.cpp

00001 
00002 #include <eo>
00003 
00004 //#include <utils/eoMOFitnessStat.h>
00005 #include <eoNDSorting.h>
00006 #include <eoParetoFitness.h>
00007 
00008 using namespace std;
00009 
00010 // Look: overloading the maximization without overhead (thing can be inlined)
00011 class MinimizingFitnessTraits : public eoParetoFitnessTraits
00012 {
00013   public :
00014   static bool maximizing(int) { return false; }
00015 };
00016 
00017 typedef eoParetoFitness<MinimizingFitnessTraits> fitness_type;
00018 
00019 const unsigned chromsize=3;
00020 const double minval = -5;
00021 const double maxval = 5;
00022 
00023 struct eoDouble : public EO<fitness_type>
00024 {
00025   double value[chromsize];
00026 };
00027 
00028 class Mutate : public eoMonOp<eoDouble>
00029 {
00030   bool operator()(eoDouble& _eo)
00031   {
00032     for (unsigned i = 0; i < chromsize; ++i)
00033     {
00034       if (rng.flip(1./chromsize))
00035         _eo.value[i] += rng.normal() * 0.1 * _eo.value[i];
00036 
00037       if (_eo.value[i] < minval)
00038         _eo.value[i] = minval;
00039       else if (_eo.value[i] > maxval)
00040         _eo.value[i] = maxval;
00041     }
00042 
00043     return true;
00044   }
00045 };
00046 
00047 class Eval : public eoEvalFunc<eoDouble>
00048 {
00049   void operator()(eoDouble& _eo)
00050   {
00051     vector<double> x(_eo.value, _eo.value + chromsize);
00052     fitness_type f;
00053 
00054     for (unsigned i = 0; i < chromsize; ++i)
00055     {
00056       if (i < chromsize-1)
00057       {
00058         f[0] += -10.0 * exp(-0.2 * sqrt(x[i]*x[i] + x[i+1]*x[i+1]));
00059       }
00060 
00061       f[1] += pow(fabs(x[i]), 0.8) + 5 * pow(sin(x[i]),3.);
00062     }
00063 
00064     _eo.fitness(f);
00065   }
00066 };
00067 
00068 class Init : public eoInit<eoDouble>
00069 {
00070   void operator()(eoDouble& _eo)
00071   {
00072     _eo.value[0] = rng.uniform();
00073 
00074     double range = maxval - minval;
00075 
00076     for (unsigned i = 1; i < chromsize; ++i)
00077       _eo.value[i] = rng.uniform() * range + minval;
00078     _eo.invalidate();
00079   }
00080 };
00081 
00086 template <class EOT, class WorthT = double>
00087 class eoNDPlusReplacement : public eoReplacement<EOT>
00088 {
00089 public:
00090 
00091     // using eoNDPlusReplacement< EOT, WorthT >::first;
00092 
00093     eoNDPlusReplacement(eoPerf2Worth<EOT, WorthT>& _perf2worth)
00094         : perf2worth(_perf2worth)
00095         {}
00096 
00097     struct WorthPair : public pair<WorthT, const EOT*>
00098     {
00099         bool operator<(const WorthPair& other) const
00100             { return other.first < this->first; }
00101     };
00102 
00103 
00104   void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
00105   {
00106     unsigned sz = _parents.size();
00107     _parents.reserve(_parents.size() + _offspring.size());
00108     std::copy(_offspring.begin(), _offspring.end(), back_inserter(_parents));
00109 
00110     // calculate worths
00111     perf2worth(_parents);
00112     perf2worth.sort_pop(_parents);
00113     perf2worth.resize(_parents, sz);
00114 
00115     _offspring.clear();
00116   }
00117 
00118 private :
00119     eoPerf2Worth<EOT, WorthT>& perf2worth;
00120 };
00121 
00122 template <class EOT>
00123 eoPerf2Worth<EOT, double>& make_perf2worth(eoParser& parser, eoState& state)
00124 {
00125 
00126   unsigned what = parser.createParam(unsigned(1), "perf2worth", "worth mapping indicator : \n\t \
00127                   0: non_dominated sorting \n\t\
00128                   1: non_dominated sorting 2 \n\t\
00129                   2: simple ranking \n\t", 'w').value();
00130 
00131   switch (what)
00132   {
00133     case 1 : return state.storeFunctor(new eoNDSorting_II<EOT>());
00134     case 2 :
00135     {
00136       eoDominanceMap<eoDouble>&  dominance = state.storeFunctor(new eoDominanceMap<EOT>);
00137       return state.storeFunctor(new eoParetoRanking<EOT>(dominance));
00138     }
00139   }
00140   //default
00141 
00142   if (what > 2)
00143   {
00144     std::cout << "Warning, need an integer < 3 for perf2worth" << std::endl;
00145     // should actually set parser flag, but I don't care
00146   }
00147 
00148   return state.storeFunctor(new eoNDSorting_I<EOT>(0.5));
00149 }
00150 
00151 template <class EOT>
00152 eoSelectOne<EOT>& make_selector(eoParser& parser, eoState& state, eoPerf2Worth<EOT, double>& perf2worth)
00153 {
00154   unsigned tournamentsize = parser.createParam(unsigned(2), "tournament_size", "Tournament Size", 't').value();
00155   double stochtour = parser.createParam(unsigned(0.95), "tournament_prob", "Probability in stochastic tournament").value();
00156 
00157   switch (parser.createParam(unsigned(0), "selector", "Which selector (too lazy to explain: use the source)", 's').value())
00158   {
00159     case 1 : return state.storeFunctor(new eoStochTournamentWorthSelect<eoDouble>(perf2worth, stochtour));
00160     case 2 : return state.storeFunctor(new eoRouletteWorthSelect<eoDouble>(perf2worth));
00161     case 3 : return state.storeFunctor(new eoRandomSelect<EOT>);
00162   }
00163   // default
00164 
00165   return state.storeFunctor(new eoDetTournamentWorthSelect<eoDouble>(perf2worth, tournamentsize));
00166 }
00167 
00168 // Test pareto dominance and perf2worth, and while you're at it, test the eoGnuPlot monitor as well
00169 void the_main(int argc, char* argv[])
00170 {
00171   Init init;
00172   Eval eval;
00173   Mutate mutate;
00174 
00175   eoParser parser(argc, argv);
00176   eoState state;
00177 
00178   unsigned num_gen  = parser.createParam(unsigned(50), "num_gen", "number of generations to run", 'g').value();
00179   unsigned pop_size = parser.createParam(unsigned(100), "pop_size", "population size", 'p').value();
00180   eoPop<eoDouble> pop(pop_size, init);
00181 
00182   // Look, a factory function
00183   eoPerf2Worth<eoDouble, double>& perf2worth = make_perf2worth<eoDouble>(parser, state);
00184 
00185   // Look: another factory function, now for selection
00186   eoSelectOne<eoDouble>& select = make_selector<eoDouble>(parser, state, perf2worth);
00187 
00188   // One general operator
00189   eoProportionalOp<eoDouble> opsel;
00190   opsel.add(mutate, 1.0);
00191 
00192   // the breeder
00193   eoGeneralBreeder<eoDouble> breeder(select, opsel);
00194 
00195   // replacement
00196   eoNDPlusReplacement<eoDouble> replace(perf2worth);
00197 
00198   unsigned long generation = 0;
00199   eoGenContinue<eoDouble> gen(num_gen, generation);
00200   eoCheckPoint<eoDouble> cp(gen);
00201 
00202   eoMOFitnessStat<eoDouble> fitness0(0, "FirstObjective");
00203   eoMOFitnessStat<eoDouble> fitness1(1, "SecondObjective");
00204 
00205   cp.add(fitness0);
00206   cp.add(fitness1);
00207 
00208   eoGnuplot1DSnapshot snapshot("pareto");
00209   //snapshot.with(eoGnuplot::Points(3));
00210 
00211   cp.add(snapshot);
00212 
00213   snapshot.add(fitness0);
00214   snapshot.add(fitness1);
00215 
00216   // the algo
00217   eoEasyEA<eoDouble> ea(cp, eval, breeder, replace);
00218 
00219   if (parser.userNeedsHelp())
00220   {
00221     parser.printHelp(std::cout);
00222     return;
00223   }
00224 
00225   apply<eoDouble>(eval, pop);
00226   ea(pop);
00227 }
00228 
00229 
00230 int main(int argc, char* argv[])
00231 {
00232   try
00233   {
00234     the_main(argc, argv);
00235   }
00236   catch (std::exception& e)
00237   {
00238     std::cout << "Exception thrown: " << e.what() << std::endl;
00239     throw e; // make sure it does not pass the test
00240   }
00241 }
00242 
00243 
00244 
00245 // Local Variables:
00246 // mode: C++
00247 // c-file-style: "Stroustrup"
00248 // End:

Generated on Thu Oct 19 05:06:43 2006 for EO by  doxygen 1.3.9.1