#include //#include #include #include using namespace std; // Look: overloading the maximization without overhead (thing can be inlined) class MinimizingFitnessTraits : public eoParetoFitnessTraits { public : static bool maximizing(int) { return false; } }; typedef eoParetoFitness fitness_type; const unsigned chromsize=3; const double minval = -5; const double maxval = 5; struct eoDouble : public EO { double value[chromsize]; }; class Mutate : public eoMonOp { bool operator()(eoDouble& _eo) { for (unsigned i = 0; i < chromsize; ++i) { if (rng.flip(1./chromsize)) _eo.value[i] += rng.normal() * 0.1 * _eo.value[i]; if (_eo.value[i] < minval) _eo.value[i] = minval; else if (_eo.value[i] > maxval) _eo.value[i] = maxval; } return true; } }; class Eval : public eoEvalFunc { void operator()(eoDouble& _eo) { vector x(_eo.value, _eo.value + chromsize); fitness_type f; for (unsigned i = 0; i < chromsize; ++i) { if (i < chromsize-1) { f[0] += -10.0 * exp(-0.2 * sqrt(x[i]*x[i] + x[i+1]*x[i+1])); } f[1] += pow(fabs(x[i]), 0.8) + 5 * pow(sin(x[i]),3.); } _eo.fitness(f); } }; class Init : public eoInit { void operator()(eoDouble& _eo) { _eo.value[0] = rng.uniform(); double range = maxval - minval; for (unsigned i = 1; i < chromsize; ++i) _eo.value[i] = rng.uniform() * range + minval; _eo.invalidate(); } }; // Trying out an elitist non-dominated sorted replacement scheme template class eoNDPlusReplacement : public eoReplacement { public: eoNDPlusReplacement(eoPerf2Worth& _perf2worth) : perf2worth(_perf2worth) {} struct WorthPair : public pair { bool operator<(const WorthPair& other) const { return other.first < first; } }; void operator()(eoPop& _parents, eoPop& _offspring) { unsigned sz = _parents.size(); _parents.reserve(_parents.size() + _offspring.size()); copy(_offspring.begin(), _offspring.end(), back_inserter(_parents)); // calculate worths perf2worth(_parents); perf2worth.sort_pop(_parents); perf2worth.resize(_parents, sz); _offspring.clear(); } private : eoPerf2Worth& perf2worth; }; template eoPerf2Worth& make_perf2worth(eoParser& parser, eoState& state) { unsigned what = parser.createParam(unsigned(1), "perf2worth", "worth mapping indicator : \n\t \ 0: non_dominated sorting \n\t\ 1: non_dominated sorting 2 \n\t\ 2: simple ranking \n\t", 'w').value(); switch (what) { case 1 : return state.storeFunctor(new eoNDSorting_II()); case 2 : { eoDominanceMap& dominance = state.storeFunctor(new eoDominanceMap); return state.storeFunctor(new eoParetoRanking(dominance)); } } //default if (what > 2) { cout << "Warning, need an integer < 3 for perf2worth" << endl; // should actually set parser flag, but I don't care } return state.storeFunctor(new eoNDSorting_I(0.5)); } template eoSelectOne& make_selector(eoParser& parser, eoState& state, eoPerf2Worth& perf2worth) { unsigned tournamentsize = parser.createParam(unsigned(2), "tournament_size", "Tournament Size", 't').value(); double stochtour = parser.createParam(unsigned(0.95), "tournament_prob", "Probability in stochastic tournament").value(); switch (parser.createParam(unsigned(0), "selector", "Which selector (too lazy to explain: use the source)", 's').value()) { case 1 : return state.storeFunctor(new eoStochTournamentWorthSelect(perf2worth, stochtour)); case 2 : return state.storeFunctor(new eoRouletteWorthSelect(perf2worth)); case 3 : return state.storeFunctor(new eoRandomSelect); } // default return state.storeFunctor(new eoDetTournamentWorthSelect(perf2worth, tournamentsize)); } // Test pareto dominance and perf2worth, and while you're at it, test the eoGnuPlot monitor as well void the_main(int argc, char* argv[]) { Init init; Eval eval; Mutate mutate; eoParser parser(argc, argv); eoState state; unsigned num_gen = parser.createParam(unsigned(10), "num_gen", "number of generations to run", 'g').value(); unsigned pop_size = parser.createParam(unsigned(100), "pop_size", "population size", 'p').value(); eoPop pop(pop_size, init); // Look, a factory function eoPerf2Worth& perf2worth = make_perf2worth(parser, state); // Look: another factory function, now for selection eoSelectOne& select = make_selector(parser, state, perf2worth); // One general operator eoProportionalOp opsel; opsel.add(mutate, 1.0); // the breeder eoGeneralBreeder breeder(select, opsel); // replacement eoNDPlusReplacement replace(perf2worth); unsigned long generation = 0; eoGenContinue gen(num_gen, generation); eoCheckPoint cp(gen); eoMOFitnessStat fitness0(0, "FirstObjective"); eoMOFitnessStat fitness1(1, "SecondObjective"); cp.add(fitness0); cp.add(fitness1); #if !defined(NO_GNUPLOT) eoGnuplot1DSnapshot snapshot("pareto"); snapshot.pointSize =3; cp.add(snapshot); snapshot.add(fitness0); snapshot.add(fitness1); #endif // the algo eoEasyEA ea(cp, eval, breeder, replace); if (parser.userNeedsHelp()) { parser.printHelp(cout); return; } apply(eval, pop); ea(pop); } int main(int argc, char* argv[]) { try { the_main(argc, argv); } catch (exception& e) { cout << "Exception thrown: " << e.what() << endl; throw e; // make sure it does not pass the test } }