fix(eoStandardBitMutation):
- Fix all operators in eoStandardBitMutation.h - Bitflip componennt was not bound, use explicit assignement of rates. - Fix normal and fast operators algorithms. Co-authored-by: Potalas <potalas@free.fr>
This commit is contained in:
parent
9cb60e4b10
commit
ff744aea7c
2 changed files with 114 additions and 70 deletions
|
|
@ -7,6 +7,8 @@
|
||||||
/** Standard bit mutation with mutation rate p:
|
/** Standard bit mutation with mutation rate p:
|
||||||
* choose k from the binomial distribution Bin(n,p) and apply flip_k(x).
|
* choose k from the binomial distribution Bin(n,p) and apply flip_k(x).
|
||||||
*
|
*
|
||||||
|
* If rate is null (the default), use 1/chrom.size().
|
||||||
|
*
|
||||||
* @ingroup Bitstrings
|
* @ingroup Bitstrings
|
||||||
* @ingroup Variators
|
* @ingroup Variators
|
||||||
*/
|
*/
|
||||||
|
|
@ -14,7 +16,11 @@ template<class EOT>
|
||||||
class eoStandardBitMutation : public eoMonOp<EOT>
|
class eoStandardBitMutation : public eoMonOp<EOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoStandardBitMutation(double rate = 0.5) :
|
/** Constructor.
|
||||||
|
*
|
||||||
|
* @param rate mutation rate, 1/chrom.size() if ignored or zero (the default)
|
||||||
|
*/
|
||||||
|
eoStandardBitMutation(double rate = 0) :
|
||||||
_rate(rate),
|
_rate(rate),
|
||||||
_nb(1),
|
_nb(1),
|
||||||
_bitflip(_nb)
|
_bitflip(_nb)
|
||||||
|
|
@ -22,9 +28,12 @@ class eoStandardBitMutation : public eoMonOp<EOT>
|
||||||
|
|
||||||
virtual bool operator()(EOT& chrom)
|
virtual bool operator()(EOT& chrom)
|
||||||
{
|
{
|
||||||
|
assert(chrom.size()>0);
|
||||||
|
if(_rate == 0) {
|
||||||
|
_rate = (double) 1/chrom.size();
|
||||||
|
}
|
||||||
_nb = eo::rng.binomial(chrom.size(),_rate);
|
_nb = eo::rng.binomial(chrom.size(),_rate);
|
||||||
// BitFlip operator is bound to the _nb reference,
|
_bitflip.number_bits(_nb);
|
||||||
// thus one don't need to re-instantiate.
|
|
||||||
return _bitflip(chrom);
|
return _bitflip(chrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,8 +55,7 @@ template<class EOT>
|
||||||
class eoUniformBitMutation : public eoMonOp<EOT>
|
class eoUniformBitMutation : public eoMonOp<EOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoUniformBitMutation(double rate = 0.5) :
|
eoUniformBitMutation() :
|
||||||
_rate(rate),
|
|
||||||
_nb(1),
|
_nb(1),
|
||||||
_bitflip(_nb)
|
_bitflip(_nb)
|
||||||
{}
|
{}
|
||||||
|
|
@ -55,15 +63,13 @@ class eoUniformBitMutation : public eoMonOp<EOT>
|
||||||
virtual bool operator()(EOT& chrom)
|
virtual bool operator()(EOT& chrom)
|
||||||
{
|
{
|
||||||
_nb = eo::rng.random(chrom.size());
|
_nb = eo::rng.random(chrom.size());
|
||||||
// BitFlip operator is bound to the _nb reference,
|
_bitflip.number_bits(_nb);
|
||||||
// thus one don't need to re-instantiate.
|
|
||||||
return _bitflip(chrom);
|
return _bitflip(chrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string className() const {return "eoUniformBitMutation";}
|
virtual std::string className() const {return "eoUniformBitMutation";}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
double _rate;
|
|
||||||
unsigned _nb;
|
unsigned _nb;
|
||||||
eoDetSingleBitFlip<EOT> _bitflip;
|
eoDetSingleBitFlip<EOT> _bitflip;
|
||||||
};
|
};
|
||||||
|
|
@ -84,17 +90,21 @@ template<class EOT>
|
||||||
class eoConditionalBitMutation : public eoStandardBitMutation<EOT>
|
class eoConditionalBitMutation : public eoStandardBitMutation<EOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoConditionalBitMutation(double rate = 0.5) :
|
eoConditionalBitMutation(double rate = 0) :
|
||||||
eoStandardBitMutation<EOT>(rate)
|
eoStandardBitMutation<EOT>(rate)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual bool operator()(EOT& chrom)
|
virtual bool operator()(EOT& chrom)
|
||||||
{
|
{
|
||||||
assert(chrom.size()>0);
|
assert(chrom.size()>0);
|
||||||
this->_nb = eo::rng.binomial(chrom.size()-1,this->_rate);
|
if(this->_rate == 0) {
|
||||||
this->_nb++;
|
this->_rate = (double) 1/chrom.size();
|
||||||
// BitFlip operator is bound to the _nb reference,
|
}
|
||||||
// thus one don't need to re-instantiate.
|
this->_nb = 0;
|
||||||
|
while(this->_nb < 1) {
|
||||||
|
this->_nb = eo::rng.binomial(chrom.size(),this->_rate);
|
||||||
|
}
|
||||||
|
this->_bitflip.number_bits(this->_nb);
|
||||||
return this->_bitflip(chrom);
|
return this->_bitflip(chrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,12 +133,14 @@ class eoShiftedBitMutation : public eoStandardBitMutation<EOT>
|
||||||
virtual bool operator()(EOT& chrom)
|
virtual bool operator()(EOT& chrom)
|
||||||
{
|
{
|
||||||
assert(chrom.size()>0);
|
assert(chrom.size()>0);
|
||||||
this->_nb = eo::rng.binomial(chrom.size()-1,this->_rate);
|
if(this->_rate == 0) {
|
||||||
|
this->_rate = (double) 1/chrom.size();
|
||||||
|
}
|
||||||
|
this->_nb = eo::rng.binomial(chrom.size(),this->_rate);
|
||||||
if(this->_nb == 0) {
|
if(this->_nb == 0) {
|
||||||
this->_nb = 1;
|
this->_nb = 1;
|
||||||
}
|
}
|
||||||
// BitFlip operator is bound to the _nb reference,
|
this->_bitflip.number_bits(this->_nb);
|
||||||
// thus one don't need to re-instantiate.
|
|
||||||
return this->_bitflip(chrom);
|
return this->_bitflip(chrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,7 +154,7 @@ class eoShiftedBitMutation : public eoStandardBitMutation<EOT>
|
||||||
*
|
*
|
||||||
* From:
|
* From:
|
||||||
* Furong Ye, Carola Doerr, and Thomas Back.
|
* Furong Ye, Carola Doerr, and Thomas Back.
|
||||||
* Interpolating local and global search by controllingthe variance of standard bit mutation.
|
* Interpolating local and global search by controlling the variance of standard bit mutation.
|
||||||
* In 2019 IEEE Congress on Evolutionary Computation(CEC), pages 2292–2299.
|
* In 2019 IEEE Congress on Evolutionary Computation(CEC), pages 2292–2299.
|
||||||
*
|
*
|
||||||
* In contrast to standard bit mutation, this operators allows to scale
|
* In contrast to standard bit mutation, this operators allows to scale
|
||||||
|
|
@ -152,29 +164,40 @@ class eoShiftedBitMutation : public eoStandardBitMutation<EOT>
|
||||||
* @ingroup Variators
|
* @ingroup Variators
|
||||||
*/
|
*/
|
||||||
template<class EOT>
|
template<class EOT>
|
||||||
class eoNormalBitMutation : public eoStandardBitMutation<EOT>
|
class eoNormalBitMutation : public eoMonOp<EOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoNormalBitMutation(double rate = 0.5, double variance = 1) :
|
eoNormalBitMutation(double mean = 0, double variance = 0) :
|
||||||
eoStandardBitMutation<EOT>(rate),
|
_mean(mean),
|
||||||
_variance(variance)
|
_variance(variance),
|
||||||
|
_nb(1),
|
||||||
|
_bitflip(_nb)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual bool operator()(EOT& chrom)
|
virtual bool operator()(EOT& chrom)
|
||||||
{
|
{
|
||||||
this->_nb = eo::rng.normal(this->_rate * chrom.size(), _variance);
|
assert(chrom.size() > 0);
|
||||||
if(this->_nb >= chrom.size()) {
|
if(_mean == 0) {
|
||||||
this->_nb = eo::rng.random(chrom.size());
|
_mean = (double) 1/chrom.size();
|
||||||
}
|
}
|
||||||
// BitFlip operator is bound to the _nb reference,
|
if(_variance == 0) {
|
||||||
// thus one don't need to re-instantiate.
|
_variance = std::log(chrom.size());
|
||||||
return this->_bitflip(chrom);
|
}
|
||||||
|
_nb = eo::rng.normal(_mean, _variance);
|
||||||
|
if(_nb >= chrom.size()) {
|
||||||
|
_nb = eo::rng.random(chrom.size());
|
||||||
|
}
|
||||||
|
_bitflip.number_bits(_nb);
|
||||||
|
return _bitflip(chrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string className() const {return "eoNormalBitMutation";}
|
virtual std::string className() const {return "eoNormalBitMutation";}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
double _mean;
|
||||||
double _variance;
|
double _variance;
|
||||||
|
unsigned _nb;
|
||||||
|
eoDetSingleBitFlip<EOT> _bitflip;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Fast mutation which size is sampled from an adaptive power law.
|
/** Fast mutation which size is sampled from an adaptive power law.
|
||||||
|
|
@ -188,11 +211,10 @@ class eoNormalBitMutation : public eoStandardBitMutation<EOT>
|
||||||
* @ingroup Variators
|
* @ingroup Variators
|
||||||
*/
|
*/
|
||||||
template<class EOT>
|
template<class EOT>
|
||||||
class eoFastBitMutation : public eoStandardBitMutation<EOT>
|
class eoFastBitMutation : public eoMonOp<EOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoFastBitMutation(double rate = 0.5, double beta = 1.5) :
|
eoFastBitMutation(double beta = 1.5) :
|
||||||
eoStandardBitMutation<EOT>(rate),
|
|
||||||
_beta(beta)
|
_beta(beta)
|
||||||
{
|
{
|
||||||
assert(beta > 1);
|
assert(beta > 1);
|
||||||
|
|
@ -200,74 +222,96 @@ class eoFastBitMutation : public eoStandardBitMutation<EOT>
|
||||||
|
|
||||||
virtual bool operator()(EOT& chrom)
|
virtual bool operator()(EOT& chrom)
|
||||||
{
|
{
|
||||||
this->_nb = powerlaw(chrom.size(),_beta);
|
_nb = powerlaw(chrom.size(),_beta);
|
||||||
// BitFlip operator is bound to the _nb reference,
|
_bitflip.number_bits(_nb);
|
||||||
// thus one don't need to re-instantiate.
|
return _bitflip(chrom);
|
||||||
return this->_bitflip(chrom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string className() const {return "eoFastBitMutation";}
|
virtual std::string className() const {return "eoFastBitMutation";}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
double powerlaw(unsigned int n, double beta)
|
||||||
double powerlaw(unsigned n, double beta)
|
|
||||||
{
|
{
|
||||||
double cnb = 0;
|
double cnb = 0;
|
||||||
for(unsigned i=1; i<n; ++i) {
|
for(unsigned int i=1; i<=n/2; ++i) {
|
||||||
cnb += std::pow(i,-beta);
|
cnb += std::pow(i,-beta);
|
||||||
}
|
}
|
||||||
return eo::rng.powerlaw(0,n,beta) / cnb;
|
double trigger = eo::rng.uniform(0,1);
|
||||||
|
double cursor = 0;
|
||||||
|
double rate = 1;
|
||||||
|
for(unsigned int i=1; i<=n/2; ++i) {
|
||||||
|
cursor += std::pow(i,-beta) / cnb;
|
||||||
|
if(cursor >= trigger) {
|
||||||
|
rate = static_cast<double>(i) / static_cast<double>(n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eo::rng.binomial(n,rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// double powerlaw(unsigned n, double beta)
|
||||||
|
// {
|
||||||
|
// double cnb = 0;
|
||||||
|
// for(unsigned i=1; i<n; ++i) {
|
||||||
|
// cnb += std::pow(i,-beta);
|
||||||
|
// }
|
||||||
|
// return eo::rng.powerlaw(0,n,beta) / cnb;
|
||||||
|
// }
|
||||||
|
|
||||||
double _beta;
|
double _beta;
|
||||||
|
unsigned _nb;
|
||||||
|
eoDetSingleBitFlip<EOT> _bitflip;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Bucket mutation which assign probability for each bucket
|
/** Bucket mutation which assign probability for each bucket
|
||||||
|
*
|
||||||
|
* @warning Highly untested code, use with caution.
|
||||||
*
|
*
|
||||||
* From:
|
* From:
|
||||||
* Carola Doerr, Johann Dréo, Alexis Robbes
|
* Carola Doerr, Johann Dreo, Alexis Robbes
|
||||||
*/
|
*/
|
||||||
template<class EOT>
|
template<class EOT>
|
||||||
class eoBucketBitMutation : public eoStandardBitMutation<EOT>
|
class eoBucketBitMutation : public eoMonOp<EOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoBucketBitMutation(std::vector<double> bucketsSizes, std::vector<double> bucketValues) :
|
eoBucketBitMutation(std::vector<std::vector<int>> buckets, std::vector<double> bucketsValues) :
|
||||||
_bucketsSizes(bucketsSizes),
|
_buckets(buckets),
|
||||||
_bucketValues(bucketValues)
|
_bucketsValues(bucketsValues)
|
||||||
|
|
||||||
{
|
{
|
||||||
assert(bucketsSizes.size() != bucketValues.size());
|
assert(buckets.size() == bucketsValues.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool operator()(EOT& chrom)
|
virtual bool operator()(EOT& chrom)
|
||||||
{
|
{
|
||||||
|
_nb = customlaw(chrom.size(), _buckets, _bucketsValues);
|
||||||
this->_nb = customlaw(chrom.size(), _bucketsSizes, _bucketValues);
|
_bitflip.number_bits(_nb);
|
||||||
// BitFlip operator is bound to the _nb reference,
|
return _bitflip(chrom);
|
||||||
// thus one don't need to re-instantiate.
|
|
||||||
return this->_bitflip(chrom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string className() const {return "eoBucketBitMutation";}
|
virtual std::string className() const {return "eoBucketBitMutation";}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
double customlaw(unsigned n, std::vector<double> bucketsSizes, std::vector<double> bucketValues)
|
double customlaw(unsigned n, std::vector<std::vector<int>> buckets, std::vector<double> bucketsValues)
|
||||||
{
|
{
|
||||||
int targetBucketIndex = eo::rng.roulette_wheel(bucketValues);
|
int bucketIndex = eo::rng.roulette_wheel(bucketsValues);
|
||||||
int nb = 0;
|
int startBit = buckets[bucketIndex][0];
|
||||||
int bucketIndex = 0;
|
int endBit = buckets[bucketIndex][1];
|
||||||
while (nb < n && bucketIndex <= targetBucketIndex)
|
int gapBit = endBit - startBit;
|
||||||
{
|
|
||||||
if (bucketIndex < targetBucketIndex) nb += int(n*bucketsSizes[bucketIndex]);
|
int nbBits;
|
||||||
else nb += int(eo::rng.uniform(1, n*bucketsSizes[targetBucketIndex]));
|
if (gapBit > 0) {
|
||||||
|
nbBits = rand() % gapBit + startBit;
|
||||||
|
} else {
|
||||||
|
nbBits = endBit;
|
||||||
}
|
}
|
||||||
if (nb > n) nb = n;
|
return nbBits;
|
||||||
|
|
||||||
return nb;
|
|
||||||
}
|
}
|
||||||
|
std::vector<double> _bucketsValues;
|
||||||
|
std::vector<std::vector<int>> _buckets;
|
||||||
|
|
||||||
std::vector<double> _bucketsSizes;
|
unsigned _nb;
|
||||||
std::vector<double> _bucketValues;
|
eoDetSingleBitFlip<EOT> _bitflip;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _eoStandardBitMutation_h_
|
#endif // _eoStandardBitMutation_h_
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@ eoAlgoFoundryFastGA<Bits>& make_foundry(eoFunctorStore& store, eoInit<Bits>& ini
|
||||||
foundry.crossovers.add< eo1PtBitXover<Bits> >();
|
foundry.crossovers.add< eo1PtBitXover<Bits> >();
|
||||||
|
|
||||||
/***** Mutations ****/
|
/***** Mutations ****/
|
||||||
double p = 1.0; // Probability of flipping eath bit.
|
// Use defaults for all operators (usually falls back to p=1/chrom.size()).
|
||||||
foundry.mutations.add< eoUniformBitMutation<Bits> >(p); // proba of flipping k bits, k drawn in uniform distrib
|
foundry.mutations.add< eoUniformBitMutation<Bits> >(); // proba of flipping k bits, k drawn in uniform distrib
|
||||||
foundry.mutations.add< eoStandardBitMutation<Bits> >(p); // proba of flipping k bits, k drawn in binomial distrib
|
foundry.mutations.add< eoStandardBitMutation<Bits> >(); // proba of flipping k bits, k drawn in binomial distrib
|
||||||
foundry.mutations.add< eoConditionalBitMutation<Bits> >(p); // proba of flipping k bits, k drawn in binomial distrib, minus zero
|
foundry.mutations.add< eoConditionalBitMutation<Bits> >(); // proba of flipping k bits, k drawn in binomial distrib, minus zero
|
||||||
foundry.mutations.add< eoShiftedBitMutation<Bits> >(p); // proba of flipping k bits, k drawn in binomial distrib, changing zeros to one
|
foundry.mutations.add< eoShiftedBitMutation<Bits> >(); // proba of flipping k bits, k drawn in binomial distrib, changing zeros to one
|
||||||
foundry.mutations.add< eoNormalBitMutation<Bits> >(p); // proba of flipping k bits, k drawn in normal distrib
|
foundry.mutations.add< eoNormalBitMutation<Bits> >(); // proba of flipping k bits, k drawn in normal distrib
|
||||||
foundry.mutations.add< eoFastBitMutation<Bits> >(p); // proba of flipping k bits, k drawn in powerlaw distrib
|
foundry.mutations.add< eoFastBitMutation<Bits> >(); // proba of flipping k bits, k drawn in powerlaw distrib
|
||||||
for(size_t i=1; i < 11; i+=1) {
|
for(size_t i=1; i < 11; i+=1) {
|
||||||
foundry.mutations.add< eoDetSingleBitFlip<Bits> >(i); // mutate k bits without duplicates
|
foundry.mutations.add< eoDetSingleBitFlip<Bits> >(i); // mutate k bits without duplicates
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue