paradiseo/eo/src/moo/eoEpsMOEA.h

136 lines
3.7 KiB
C++

#ifndef eoEpsMOEA_h
#define eoEpsMOEA_h
#include <eoAlgo.h>
#include <moo/eoEpsilonArchive.h>
#include <utils/eoStat.h>
template <class EOT>
class eoEpsMOEA : public eoAlgo<EOT> {
public:
eoEpsMOEA(
eoContinue<EOT>& _continuator,
eoEvalFunc<EOT>& _eval,
eoGenOp<EOT>& _op,
const std::vector<double>& eps,
unsigned max_archive_size = std::numeric_limits<unsigned>::max()
) : continuator(_continuator),
eval (_eval),
loopEval(_eval),
popEval(loopEval),
op(_op),
archive(eps, max_archive_size)
{
}
void operator()(eoPop<EOT>& pop) {
eoPop<EOT> offspring;
popEval(offspring, pop);
for (unsigned i = 0; i < pop.size(); ++i) pop[i].fitnessReference().setWorth(1.0);
do {
unsigned nProcessed = 0;
while (nProcessed < pop.size()) {
offspring.clear();
epsPopulator populator(archive, pop, offspring);
op(populator);
nProcessed += offspring.size();
popEval(pop, offspring);
for (unsigned i = 0; i < offspring.size(); ++i) {
offspring[i].fitnessReference().setWorth(1.0);
archive(offspring[i]);
update_pop(pop, offspring[i]);
}
}
// quite expensive to copy the entire archive time and time again, but this will make it work more seamlessly with the rest of EO
offspring.clear();
archive.appendTo(offspring);
} while (continuator(offspring)); // check archive
// return archive
pop.clear();
archive.appendTo(pop);
}
private :
void update_pop(eoPop<EOT>& pop, const EOT& offspring) {
std::vector<unsigned> dominated;
for (unsigned i = 0; i < pop.size(); ++i) {
int dom = offspring.fitness().check_dominance(pop[i].fitness());
switch (dom) {
case 1 : // indy dominates this
dominated.push_back(i);
break;
case -1 : // is dominated, do not insert
return;
case 0: // incomparable
break;
}
}
if (dominated.size()) {
pop[ dominated[ rng.random(dominated.size()) ] ] = offspring;
}
// non-dominated everywhere, overwrite random one
pop[ rng.random(pop.size()) ] = offspring;
}
class epsPopulator : public eoPopulator<EOT> {
using eoPopulator< EOT >::src;
eoEpsilonArchive<EOT>& archive;
bool fromArchive;
public:
epsPopulator(eoEpsilonArchive<EOT>& arch, const eoPop<EOT>& pop, eoPop<EOT>& res) : eoPopulator<EOT>(pop, res), archive(arch), fromArchive(true) {}
const EOT& select() {
fromArchive = !fromArchive;
using std::cout;
using std::endl;
if (fromArchive && !archive.empty()) {
return archive.selectRandom();
}
// tournament selection on population
const EOT& eo1 = rng.choice(src);
const EOT& eo2 = rng.choice(src);
if (eo1.fitness().dominates(eo2.fitness())) return eo1;
return eo2; // they are drawn at random, so no need to do an extra randomization step
}
};
eoContinue<EOT>& continuator;
eoEvalFunc <EOT> & eval ;
eoPopLoopEval<EOT> loopEval;
eoPopEvalFunc<EOT>& popEval;
eoGenOp<EOT>& op;
eoEpsilonArchive<EOT> archive;
};
#endif