fix eoDetSingdeBitFlip: better algorithm

The old version was inefficient, using trial and errors.
This new version is a single pass algorithm.
This commit is contained in:
Johann Dreo 2020-07-05 17:59:30 +02:00
commit 75c2c6ab76

View file

@ -99,18 +99,19 @@ template<class Chrom> class eoDetBitFlip: public eoMonOp<Chrom>
}; };
/** eoDetSingleBitFlip --> changes exactly k bits with checking for duplicate /** Changes exactly k bits with checking for duplicate
\class eoDetSingleBitFlip eoBitOp.h ga/eoBitOp.h
\ingroup bitstring \ingroup bitstring
*/ */
template<class Chrom>
template<class Chrom> class eoDetSingleBitFlip: public eoMonOp<Chrom> class eoDetSingleBitFlip: public eoMonOp<Chrom>
{ {
public: public:
/** /**
* (Default) Constructor. * (Default) Constructor.
* @param _num_bit The number of bits to change * @param _num_bit The number of bits to change
* default is one - equivalent to eoOneBitFlip then * default is one - equivalent to eoOneBitFlip then
*
* @note: use a reference for num_bit, thus you may change and recall without having to re-instantiate.
*/ */
eoDetSingleBitFlip(const unsigned& _num_bit = 1): num_bit(_num_bit) {} eoDetSingleBitFlip(const unsigned& _num_bit = 1): num_bit(_num_bit) {}
@ -122,32 +123,34 @@ template<class Chrom> class eoDetSingleBitFlip: public eoMonOp<Chrom>
* @param chrom The cromosome which one bit is going to be changed. * @param chrom The cromosome which one bit is going to be changed.
*/ */
bool operator()(Chrom& chrom) bool operator()(Chrom& chrom)
{ {
std::vector< unsigned > selected; // All possible indices
std::vector< unsigned > indices;
indices.reserve(chrom.size());
for(unsigned i=0; i<chrom.size(); ++i) {
indices.push_back(i);
}
// check for duplicate // Shuffle indices
for (unsigned k=0; k<num_bit; k++) for(unsigned i=0; i<indices.size(); ++i) {
{ unsigned other = eo::rng.random(indices.size());
unsigned temp; std::swap(indices[i], indices[other]);
}
do // Flip at first indices
{ for(unsigned i=0; i<num_bit; ++i) {
temp = eo::rng.random( chrom.size() ); chrom[indices[i]] = !chrom[indices[i]];
} }
while ( find( selected.begin(), selected.end(), temp ) != selected.end() );
selected.push_back(temp); if(num_bit > 0) {
} return true;
} else {
return false;
}
}
for ( size_t i = 0; i < selected.size(); ++i ) protected:
{ const unsigned& num_bit;
chrom[i] = !chrom[i];
}
return true;
}
private:
unsigned num_bit;
}; };