feat: adds eoForgeScalar and eoParameterFoundry

- Get arithmetic types out of eoOperatorFoundry in eoParameterFoundry.
- Allow for metric space variables management within irace.
This commit is contained in:
Johann Dreo 2021-07-07 21:00:13 +02:00
commit cd7787bbab
4 changed files with 202 additions and 73 deletions

View file

@ -59,9 +59,28 @@ class eoOperatorFoundry : public eoForgeVector< Itf >
size_t index() const { return _index; }
protected:
//! Unique index in the eoAlgoFoundry.
size_t _index;
};
template<class Itf>
class eoParameterFoundry : public eoForgeScalar< Itf >
{
static_assert(std::is_arithmetic<Itf>::value,
"eoParameterFoundry should only be used on arithmetic types (i.e. integer or floating point types)");
public:
eoParameterFoundry(size_t encoding_index, Itf min, Itf max) :
eoForgeScalar<Itf>(min, max),
_index(encoding_index)
{ }
size_t index() const { return _index; }
protected:
//! Unique index in the eoAlgoFoundry.
size_t _index;
};
/** Interface of a Foundry: a class that instantiate an eoAlgo on-the-fly, given a choice of its operators.
*

View file

@ -90,18 +90,18 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry<EOT>
) :
eoAlgoFoundry<EOT>(10),
crossover_rates(0, false),
crossover_rates(0, 0.0, 1.0),
crossover_selectors(1, false),
crossovers(2, false),
aftercross_selectors(3, false),
mutation_rates(4, false),
mutation_rates(4, 0.0, 1.0),
mutation_selectors(5, false),
mutations(6, false),
replacements(7, false),
continuators(8, true), // Always re-instantiate continuators, because they hold a state.
offspring_sizes(9, false),
offspring_sizes(9, 0, std::numeric_limits<size_t>::max()),
_eval(eval),
_init(init),
_max_evals(max_evals),
@ -111,34 +111,31 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry<EOT>
public:
/* Operators containers @{ */
eoOperatorFoundry< double > crossover_rates;
eoParameterFoundry< double > crossover_rates;
eoOperatorFoundry< eoSelectOne<EOT> > crossover_selectors;
eoOperatorFoundry< eoQuadOp<EOT> > crossovers;
eoOperatorFoundry< eoSelectOne<EOT> > aftercross_selectors;
eoOperatorFoundry< double > mutation_rates;
eoParameterFoundry< double > mutation_rates;
eoOperatorFoundry< eoSelectOne<EOT> > mutation_selectors;
eoOperatorFoundry< eoMonOp<EOT> > mutations;
eoOperatorFoundry< eoReplacement<EOT> > replacements;
eoOperatorFoundry< eoContinue<EOT> > continuators;
eoOperatorFoundry< size_t > offspring_sizes;
eoParameterFoundry< size_t > offspring_sizes;
/* @} */
/** instantiate and call the pre-selected algorithm.
*/
void operator()(eoPop<EOT>& pop)
{
assert( crossover_rates.size() > 0); assert(this->at( crossover_rates.index()) < crossover_rates.size());
assert( crossover_selectors.size() > 0); assert(this->at( crossover_selectors.index()) < crossover_selectors.size());
assert( crossovers.size() > 0); assert(this->at( crossovers.index()) < crossovers.size());
assert(aftercross_selectors.size() > 0); assert(this->at(aftercross_selectors.index()) < aftercross_selectors.size());
assert( mutation_rates.size() > 0); assert(this->at( mutation_rates.index()) < mutation_rates.size());
assert( mutation_selectors.size() > 0); assert(this->at( mutation_selectors.index()) < mutation_selectors.size());
assert( mutations.size() > 0); assert(this->at( mutations.index()) < mutations.size());
assert( replacements.size() > 0); assert(this->at( replacements.index()) < replacements.size());
assert( continuators.size() > 0); assert(this->at( continuators.index()) < continuators.size());
assert( offspring_sizes.size() > 0); assert(this->at( offspring_sizes.index()) < offspring_sizes.size());
// Objective function calls counter
eoEvalCounterThrowException<EOT> eval(_eval, _max_evals);
@ -212,7 +209,6 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry<EOT>
double& crossover_rate()
{
assert(this->at(crossover_rates.index()) < crossover_rates.size());
return crossover_rates.instantiate(this->at(crossover_rates.index()));
}
@ -224,7 +220,6 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry<EOT>
double& mutation_rate()
{
assert(this->at(mutation_rates.index()) < mutation_rates.size());
return mutation_rates.instantiate(this->at(mutation_rates.index()));
}
@ -254,7 +249,6 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry<EOT>
size_t& offspring_size()
{
assert(this->at(offspring_sizes.index()) < offspring_sizes.size());
return offspring_sizes.instantiate(this->at(offspring_sizes.index()));
}

View file

@ -215,7 +215,7 @@ class eoForgeOperator<Itf,Op> : public eoForgeInterface<Itf>
*
* @ingroup Foundry
*/
template<class Itf>
template<class Itf, typename Enable = void>
class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
{
public:
@ -238,6 +238,19 @@ class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
_no_cache(always_reinstantiate)
{ }
/** instantiate the operator managed at the given index.
*/
Itf& instantiate(double index)
{
double frac_part, int_part;
frac_part = std::modf(index, &int_part);
if(frac_part != 0) {
eo::log << eo::errors << "there is a fractional part in the given index (" << index << ")" << std::endl;
assert(frac_part != 0);
}
return this->at(static_cast<size_t>(index))->instantiate(_no_cache);
}
/** Add an operator to the list.
*
* @warning When passing a reference (as it is often the case within ParadisEO),
@ -295,13 +308,6 @@ class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
this->at(index) = pfo;
}
/** instantiate the operator managed at the given index.
*/
Itf& instantiate(size_t index)
{
return this->at(index)->instantiate(_no_cache);
}
virtual ~eoForgeVector()
{
for(auto p : *this) {
@ -313,5 +319,66 @@ class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
bool _no_cache;
};
template<class Itf>
class eoForgeScalar
{
public:
using Interface = Itf;
eoForgeScalar(Itf min, Itf max) :
_min(min),
_max(max)
{ }
/** Just return the same value, without managing any instantiation.
*/
Itf& instantiate(double value)
{
this->_value = value;
if(not (_min <= value and value <= _max) ) {
eo::log << eo::errors << "ERROR: the given value is out of range, I'll cap it." << std::endl;
assert(_min <= value and value <= _max);
if(value < _min) {
this->_value = _min;
return this->_value;
}
if(value > _max) {
this->_value = _max;
return this->_value;
}
}
return this->_value;
}
Itf min() const { return _min; }
Itf max() const { return _max; }
void min(Itf min)
{
assert(_min <= _max);
_min = min;
}
void max(Itf max)
{
assert(_max >= _min);
_max = max;
}
void setup(Itf min, Itf max)
{
_min = min;
_max = max;
assert(_min <= _max);
}
// Nothing else, as it would not make sense.
protected:
Itf _value;
Itf _min;
Itf _max;
};
#endif // _eoForge_H_