fix eoForge*
- fix memory allocation in forges. - fix empty variadic tuples when handling constructors without arg. - remove eoForgeMap.
This commit is contained in:
parent
1fdd977408
commit
2183ee688b
5 changed files with 276 additions and 65 deletions
|
|
@ -70,15 +70,22 @@ class eoForgeOperator : public eoForgeInterface<Itf>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoForgeOperator(Args&&... args) :
|
eoForgeOperator(Args&&... args) :
|
||||||
_args(std::forward<Args>(args)...)
|
_args(std::forward<Args>(args)...),
|
||||||
|
_instanciated(nullptr)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Itf& instanciate()
|
Itf& instanciate()
|
||||||
{
|
{
|
||||||
return *(constructor(_args));
|
if(not _instanciated) {
|
||||||
|
_instanciated = constructor(_args);
|
||||||
|
}
|
||||||
|
return *_instanciated;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~eoForgeOperator() {}
|
virtual ~eoForgeOperator()
|
||||||
|
{
|
||||||
|
delete _instanciated;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::tuple<Args...> _args;
|
std::tuple<Args...> _args;
|
||||||
|
|
@ -97,6 +104,7 @@ class eoForgeOperator : public eoForgeInterface<Itf>
|
||||||
Op* constructor(std::tuple<Ts...>& args, index<Idx...>)
|
Op* constructor(std::tuple<Ts...>& args, index<Idx...>)
|
||||||
{
|
{
|
||||||
Op* p_op = new Op(std::get<Idx>(args)...);
|
Op* p_op = new Op(std::get<Idx>(args)...);
|
||||||
|
_instanciated = p_op;
|
||||||
return p_op;
|
return p_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,50 +114,33 @@ class eoForgeOperator : public eoForgeInterface<Itf>
|
||||||
return constructor(args, gen_seq<sizeof...(Ts)>{});
|
return constructor(args, gen_seq<sizeof...(Ts)>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Itf* _instanciated;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A map holding an operator with deferred instanciation at a given key.
|
template<class Itf, class Op>
|
||||||
*
|
class eoForgeOperator<Itf,Op> : public eoForgeInterface<Itf>
|
||||||
* @note You can actually store several instances of the same class,
|
|
||||||
* with different parametrization (or not).
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
eoForgeMap<eoSelect<EOT>> named_factories;
|
|
||||||
|
|
||||||
// Capture constructor's parameters and defer instanciation.
|
|
||||||
named_factories.add<eoRankMuSelect<EOT>>("RMS", 1);
|
|
||||||
named_factories.setup<eoRankMuSelect<EOT>>("RMS", 5); // Edit
|
|
||||||
|
|
||||||
// Actually instanciate.
|
|
||||||
eoSelect<EOT>& op = named_factories.instanciate("RMS");
|
|
||||||
|
|
||||||
// Call.
|
|
||||||
op();
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @ingroup Forge
|
|
||||||
*/
|
|
||||||
template<class Itf>
|
|
||||||
class eoForgeMap : public std::map<std::string, std::shared_ptr<eoForgeInterface<Itf>> >
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<class Op, typename... Args>
|
eoForgeOperator() :
|
||||||
void setup(std::string key, Args&&... args)
|
_instanciated(nullptr)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Itf& instanciate()
|
||||||
{
|
{
|
||||||
auto opf = std::make_shared< eoForgeOperator<Itf,Op,Args...> >(std::forward<Args>(args)...);
|
if(not _instanciated) {
|
||||||
(*this)[key] = opf;
|
_instanciated = new Op;
|
||||||
|
}
|
||||||
|
return *_instanciated;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Op, typename... Args>
|
virtual ~eoForgeOperator()
|
||||||
void add(std::string key, Args&&... args)
|
|
||||||
{
|
{
|
||||||
setup<Op>(key, std::forward<Args>(args)...);
|
delete _instanciated;
|
||||||
}
|
}
|
||||||
|
|
||||||
Itf& instanciate(std::string key)
|
protected:
|
||||||
{
|
Itf* _instanciated;
|
||||||
return this->at(key)->instanciate();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A vector holding an operator with deferred instanciation at a given index.
|
/** A vector holding an operator with deferred instanciation at a given index.
|
||||||
|
|
@ -174,27 +165,44 @@ class eoForgeMap : public std::map<std::string, std::shared_ptr<eoForgeInterface
|
||||||
* @ingroup Forge
|
* @ingroup Forge
|
||||||
*/
|
*/
|
||||||
template<class Itf>
|
template<class Itf>
|
||||||
class eoForgeVector : public std::vector<std::shared_ptr<eoForgeInterface<Itf>> >
|
class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<class Op, typename... Args>
|
template<class Op, typename... Args>
|
||||||
void add(Args&&... args)
|
void add(Args&&... args)
|
||||||
{
|
{
|
||||||
auto opf = std::make_shared< eoForgeOperator<Itf,Op,Args...> >(std::forward<Args>(args)...);
|
auto pfo = new eoForgeOperator<Itf,Op,Args...>(std::forward<Args>(args)...);
|
||||||
this->push_back(opf);
|
this->push_back(pfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Op>
|
||||||
|
void add()
|
||||||
|
{
|
||||||
|
eoForgeInterface<Itf>* pfo = new eoForgeOperator<Itf,Op>;
|
||||||
|
this->push_back(pfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Op, typename... Args>
|
template<class Op, typename... Args>
|
||||||
void setup(size_t index, Args&&... args)
|
void setup(size_t index, Args&&... args)
|
||||||
{
|
{
|
||||||
auto opf = std::make_shared< eoForgeOperator<Itf,Op,Args...> >(std::forward<Args>(args)...);
|
assert(this->at(index) != nullptr);
|
||||||
this->at(index) = opf;
|
delete this->at(index);
|
||||||
|
auto pfo = new eoForgeOperator<Itf,Op,Args...>(std::forward<Args>(args)...);
|
||||||
|
this->at(index) = pfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
Itf& instanciate(size_t index)
|
Itf& instanciate(size_t index)
|
||||||
{
|
{
|
||||||
return this->at(index)->instanciate();
|
return this->at(index)->instanciate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~eoForgeVector()
|
||||||
|
{
|
||||||
|
for(auto p : *this) {
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _eoForge_H_
|
#endif // _eoForge_H_
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ set (TEST_LIST
|
||||||
t-eoEvalCmd
|
t-eoEvalCmd
|
||||||
t-operator-forge
|
t-operator-forge
|
||||||
t-forge-algo
|
t-forge-algo
|
||||||
|
t-algo-forged
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
218
eo/test/t-algo-forged.cpp
Normal file
218
eo/test/t-algo-forged.cpp
Normal file
|
|
@ -0,0 +1,218 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <eo>
|
||||||
|
#include <ga.h>
|
||||||
|
#include "../../problems/eval/oneMaxEval.h"
|
||||||
|
|
||||||
|
template<class EOT>
|
||||||
|
class eoFoundryEA : public eoAlgo<EOT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const size_t dim = 5;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::array<size_t, dim> _encoding;
|
||||||
|
|
||||||
|
struct Indices
|
||||||
|
{
|
||||||
|
static const size_t continuators = 0;
|
||||||
|
static const size_t crossovers = 1;
|
||||||
|
static const size_t mutations = 2;
|
||||||
|
static const size_t selectors = 3;
|
||||||
|
static const size_t replacements = 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
const Indices index_of;
|
||||||
|
|
||||||
|
eoFoundryEA( eoEvalFunc<EOT>& eval ) :
|
||||||
|
index_of(),
|
||||||
|
_eval(eval)
|
||||||
|
{
|
||||||
|
_encoding = { 0 }; // dim * 0
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t& at(size_t i)
|
||||||
|
{
|
||||||
|
return _encoding.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=( std::array<size_t,dim> a)
|
||||||
|
{
|
||||||
|
_encoding = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
eoForgeVector< eoContinue<EOT> > continuators;
|
||||||
|
eoForgeVector< eoQuadOp<EOT> > crossovers;
|
||||||
|
eoForgeVector< eoMonOp<EOT> > mutations;
|
||||||
|
eoForgeVector< eoSelectOne<EOT> > selectors;
|
||||||
|
eoForgeVector< eoReplacement<EOT> > replacements;
|
||||||
|
|
||||||
|
void operator()(eoPop<EOT>& pop)
|
||||||
|
{
|
||||||
|
assert(continuators.size() > 0); assert(_encoding.at(index_of.continuators) < continuators.size());
|
||||||
|
assert( crossovers.size() > 0); assert(_encoding.at(index_of.crossovers) < crossovers.size());
|
||||||
|
assert( mutations.size() > 0); assert(_encoding.at(index_of.mutations) < mutations.size());
|
||||||
|
assert( selectors.size() > 0); assert(_encoding.at(index_of.selectors) < selectors.size());
|
||||||
|
assert(replacements.size() > 0); assert(_encoding.at(index_of.replacements) < replacements.size());
|
||||||
|
|
||||||
|
eoSequentialOp<EOT> variator;
|
||||||
|
variator.add(this->crossover(), 1.0);
|
||||||
|
variator.add(this->mutation(), 1.0);
|
||||||
|
|
||||||
|
eoGeneralBreeder<EOT> breeder(this->selector(), variator, 1.0);
|
||||||
|
|
||||||
|
eoGenContinue<EOT> common_cont(100);
|
||||||
|
eoCombinedContinue<EOT> gen_cont(common_cont);
|
||||||
|
gen_cont.add(this->continuator());
|
||||||
|
|
||||||
|
eoEasyEA<EOT> algo = eoEasyEA<EOT>(gen_cont, _eval, breeder, this->replacement());
|
||||||
|
|
||||||
|
algo(pop);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name()
|
||||||
|
{
|
||||||
|
std::ostringstream name;
|
||||||
|
name << _encoding.at(index_of.continuators) << " (" << this->continuator().className() << ") + ";
|
||||||
|
name << _encoding.at(index_of.crossovers) << " (" << this->crossover().className() << ") + ";
|
||||||
|
name << _encoding.at(index_of.mutations) << " (" << this->mutation().className() << ") + ";
|
||||||
|
name << _encoding.at(index_of.selectors) << " (" << this->selector().className() << ") + ";
|
||||||
|
name << _encoding.at(index_of.replacements) << " (" << this->replacement().className() << ")";
|
||||||
|
return name.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
eoEvalFunc<EOT>& _eval;
|
||||||
|
|
||||||
|
eoContinue<EOT>& continuator()
|
||||||
|
{
|
||||||
|
assert(_encoding.at(index_of.continuators) < continuators.size());
|
||||||
|
return continuators.instanciate(_encoding.at(index_of.continuators));
|
||||||
|
}
|
||||||
|
|
||||||
|
eoQuadOp<EOT>& crossover()
|
||||||
|
{
|
||||||
|
assert(_encoding.at(index_of.crossovers) < crossovers.size());
|
||||||
|
return crossovers.instanciate(_encoding.at(index_of.crossovers));
|
||||||
|
}
|
||||||
|
|
||||||
|
eoMonOp<EOT>& mutation()
|
||||||
|
{
|
||||||
|
assert(_encoding.at(index_of.mutations) < mutations.size());
|
||||||
|
return mutations.instanciate(_encoding.at(index_of.mutations));
|
||||||
|
}
|
||||||
|
|
||||||
|
eoSelectOne<EOT>& selector()
|
||||||
|
{
|
||||||
|
assert(_encoding.at(index_of.selectors) < selectors.size());
|
||||||
|
return selectors.instanciate(_encoding.at(index_of.selectors));
|
||||||
|
}
|
||||||
|
|
||||||
|
eoReplacement<EOT>& replacement()
|
||||||
|
{
|
||||||
|
assert(_encoding.at(index_of.replacements) < replacements.size());
|
||||||
|
return replacements.instanciate(_encoding.at(index_of.replacements));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int /*argc*/, char** /*argv*/)
|
||||||
|
{
|
||||||
|
size_t dim = 500;
|
||||||
|
size_t pop_size = 10;
|
||||||
|
|
||||||
|
eo::log << eo::setlevel(eo::warnings);
|
||||||
|
|
||||||
|
using EOT = eoBit<double>;
|
||||||
|
|
||||||
|
oneMaxEval<EOT> eval;
|
||||||
|
|
||||||
|
eoBooleanGenerator gen(0.5);
|
||||||
|
eoInitFixedLength<EOT> init(dim, gen);
|
||||||
|
|
||||||
|
eoFoundryEA<EOT> foundry(eval);
|
||||||
|
|
||||||
|
/***** Continuators ****/
|
||||||
|
for(size_t i=10; i < 30; i+=10 ) {
|
||||||
|
foundry.continuators.add< eoSteadyFitContinue<EOT> >(10,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Crossovers ****/
|
||||||
|
foundry.crossovers.add< eo1PtBitXover<EOT> >();
|
||||||
|
foundry.crossovers.add< eoUBitXover<EOT> >(0.5); // preference over 1
|
||||||
|
|
||||||
|
for(size_t i=1; i < 11; i+=4) {
|
||||||
|
foundry.crossovers.add< eoNPtsBitXover<EOT> >(i); // nb of points
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Mutations ****/
|
||||||
|
foundry.mutations.add< eoBitMutation<EOT> >(0.01); // proba of flipping one bit
|
||||||
|
for(size_t i=1; i < 11; i+=4) {
|
||||||
|
foundry.mutations.add< eoDetBitFlip<EOT> >(i); // mutate k bits
|
||||||
|
}
|
||||||
|
|
||||||
|
foundry.selectors.add< eoStochTournamentSelect<EOT> >(0.5);
|
||||||
|
foundry.selectors.add< eoSequentialSelect<EOT> >();
|
||||||
|
foundry.selectors.add< eoProportionalSelect<EOT> >();
|
||||||
|
for(size_t i=2; i < 10; i+=4) {
|
||||||
|
foundry.selectors.add< eoDetTournamentSelect<EOT> >(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Replacements ****/
|
||||||
|
foundry.replacements.add< eoCommaReplacement<EOT> >();
|
||||||
|
foundry.replacements.add< eoPlusReplacement<EOT> >();
|
||||||
|
foundry.replacements.add< eoSSGAWorseReplacement<EOT> >();
|
||||||
|
for(size_t i=2; i < 10; i+=4) {
|
||||||
|
foundry.replacements.add< eoSSGADetTournamentReplacement<EOT> >(i);
|
||||||
|
}
|
||||||
|
foundry.replacements.add< eoSSGAStochTournamentReplacement<EOT> >(0.51);
|
||||||
|
|
||||||
|
|
||||||
|
size_t n = foundry.continuators.size() * foundry.crossovers.size() * foundry.mutations.size() * foundry.selectors.size() * foundry.replacements.size();
|
||||||
|
std::clog << n << " possible algorithms instances." << std::endl;
|
||||||
|
|
||||||
|
EOT best_sol;
|
||||||
|
std::string best_algo = "";
|
||||||
|
|
||||||
|
size_t i=0;
|
||||||
|
for(size_t i_cont = 0; i_cont < foundry.continuators.size(); ++i_cont ) {
|
||||||
|
for(size_t i_cross = 0; i_cross < foundry.crossovers.size(); ++i_cross ) {
|
||||||
|
for(size_t i_mut = 0; i_mut < foundry.mutations.size(); ++i_mut ) {
|
||||||
|
for(size_t i_sel = 0; i_sel < foundry.selectors.size(); ++i_sel ) {
|
||||||
|
for(size_t i_rep = 0; i_rep < foundry.replacements.size(); ++i_rep ) {
|
||||||
|
std::clog << "\r" << i++ << "/" << n-1; std::clog.flush();
|
||||||
|
|
||||||
|
eoPop<EOT> pop;
|
||||||
|
pop.append(pop_size, init);
|
||||||
|
apply(eval,pop);
|
||||||
|
|
||||||
|
foundry.at(foundry.index_of.continuators) = i_cont;
|
||||||
|
foundry.at(foundry.index_of.crossovers) = i_cross;
|
||||||
|
foundry.at(foundry.index_of.mutations) = i_mut;
|
||||||
|
foundry.at(foundry.index_of.selectors) = i_sel;
|
||||||
|
foundry.at(foundry.index_of.replacements) = i_rep;
|
||||||
|
|
||||||
|
// Or, if you know the order.
|
||||||
|
foundry = {i_cont, i_cross, i_mut, i_sel, i_rep};
|
||||||
|
|
||||||
|
// Actually perform a search
|
||||||
|
foundry(pop);
|
||||||
|
|
||||||
|
if(best_sol.invalid()) {
|
||||||
|
best_sol = pop.best_element();
|
||||||
|
best_algo = foundry.name();
|
||||||
|
} else if(pop.best_element().fitness() > best_sol.fitness()) {
|
||||||
|
best_sol = pop.best_element();
|
||||||
|
best_algo = foundry.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl << "Best algo: " << best_algo << ", with " << best_sol << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,8 @@ int main(int /*argc*/, char** /*argv*/)
|
||||||
eoBooleanGenerator gen(0.5);
|
eoBooleanGenerator gen(0.5);
|
||||||
eoInitFixedLength<EOT> init(dim, gen);
|
eoInitFixedLength<EOT> init(dim, gen);
|
||||||
|
|
||||||
|
eoGenContinue<EOT> common_cont(100);
|
||||||
|
|
||||||
eoForgeVector< eoContinue<EOT> > continuators;
|
eoForgeVector< eoContinue<EOT> > continuators;
|
||||||
continuators.add< eoSteadyFitContinue<EOT> >(10,10);
|
continuators.add< eoSteadyFitContinue<EOT> >(10,10);
|
||||||
continuators.add< eoGenContinue<EOT> >(100);
|
continuators.add< eoGenContinue<EOT> >(100);
|
||||||
|
|
@ -46,7 +48,7 @@ int main(int /*argc*/, char** /*argv*/)
|
||||||
replacors.add< eoSSGAStochTournamentReplacement<EOT> >(0.51);
|
replacors.add< eoSSGAStochTournamentReplacement<EOT> >(0.51);
|
||||||
|
|
||||||
std::clog << continuators.size() * crossovers.size() * mutations.size() * selectors.size() * replacors.size()
|
std::clog << continuators.size() * crossovers.size() * mutations.size() * selectors.size() * replacors.size()
|
||||||
<< " algorithm instances to test." << std::endl;
|
<< " possible algorithms instances." << std::endl;
|
||||||
|
|
||||||
EOT best_sol;
|
EOT best_sol;
|
||||||
std::string best_algo = "";
|
std::string best_algo = "";
|
||||||
|
|
@ -82,7 +84,10 @@ int main(int /*argc*/, char** /*argv*/)
|
||||||
|
|
||||||
eoGeneralBreeder<EOT> breeder(selector, variator, 1.0);
|
eoGeneralBreeder<EOT> breeder(selector, variator, 1.0);
|
||||||
|
|
||||||
eoEasyEA<EOT> algo(continuator, eval, breeder, replacor);
|
eoCombinedContinue<EOT> gen_cont(common_cont);
|
||||||
|
gen_cont.add(continuator);
|
||||||
|
|
||||||
|
eoEasyEA<EOT> algo(gen_cont, eval, breeder, replacor);
|
||||||
|
|
||||||
eoPop<EOT> pop;
|
eoPop<EOT> pop;
|
||||||
pop.append(pop_size, init);
|
pop.append(pop_size, init);
|
||||||
|
|
|
||||||
|
|
@ -24,27 +24,6 @@ struct OpB : public OpInterface
|
||||||
|
|
||||||
int main(int /*argc*/, char** /*argv*/)
|
int main(int /*argc*/, char** /*argv*/)
|
||||||
{
|
{
|
||||||
// Forge container using names.
|
|
||||||
eoForgeMap<OpInterface> named_factories;
|
|
||||||
|
|
||||||
// Capture constructor's parameters and defer instanciation.
|
|
||||||
named_factories.add<OpA>("OpA", "I'm A");
|
|
||||||
named_factories.setup<OpA>("OpA", "I'm actually A"); // Edit
|
|
||||||
named_factories.add<OpB>("OpB1", "I'm B", " prime");
|
|
||||||
named_factories.add<OpB>("OpB2", "I'm a B", " junior");
|
|
||||||
|
|
||||||
// Actually instanciante.
|
|
||||||
OpInterface& opa = named_factories.instanciate("OpA");
|
|
||||||
OpInterface& opb1 = named_factories.instanciate("OpB1");
|
|
||||||
|
|
||||||
// Call.
|
|
||||||
opa();
|
|
||||||
opb1();
|
|
||||||
|
|
||||||
// Instanciate and call.
|
|
||||||
named_factories.instanciate("OpB2")();
|
|
||||||
|
|
||||||
|
|
||||||
// Forge container using indices.
|
// Forge container using indices.
|
||||||
eoForgeVector<OpInterface> indexed_factories;
|
eoForgeVector<OpInterface> indexed_factories;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue