00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "core/genotype.h"
00021 #include "randomgenerator.h"
00022 #include <cmath>
00023 #include <cstring>
00024 #include "configurationparameters.h"
00025
00026 namespace farsa {
00027
00028 Genotype::Genotype( unsigned int size ) {
00029 sizev = size;
00030
00031 allocated = (unsigned int)( (size+1)/8 ) + 1;
00032 data = new unsigned char[allocated];
00033 fitnessv.resize(1);
00034 fitnessv[0] = 0.0;
00035 rankv = 0.0;
00036 notesv = "";
00037 }
00038
00039 Genotype::~Genotype() {
00040 delete []data;
00041 }
00042
00043 Genotype::Genotype( QString str, bool compressed ) {
00044 if ( !compressed ) {
00045 sizev = str.size();
00046
00047 allocated = (unsigned int)( (sizev+1)/8 ) + 1;
00048 data = new unsigned char[allocated];
00049 for( unsigned int i=0; i<sizev; i++ ) {
00050 if ( str[i] == '1' ) {
00051 set( i );
00052 } else {
00053 unset( i );
00054 }
00055 }
00056 } else {
00057 QByteArray temp2 = QByteArray::fromBase64( str.toAscii() );
00058 QByteArray temp = qUncompress( temp2 );
00059 sizev = temp.size();
00060
00061 allocated = (unsigned int)( (sizev+1)/8 ) + 1;
00062 data = new unsigned char[allocated];
00063 for( unsigned int i=0; i<sizev; i++ ) {
00064 if ( temp[i] == '1' ) {
00065 set( i );
00066 } else {
00067 unset( i );
00068 }
00069 }
00070 }
00071 fitnessv.resize(1);
00072 fitnessv[0] = 0.0;
00073 rankv = 0.0;
00074 notesv = "";
00075 }
00076
00077 Genotype::Genotype( const Genotype& genotype ) : ParameterSettableWithConfigureFunction() {
00078 sizev = genotype.sizev;
00079 allocated = genotype.allocated;
00080 data = new unsigned char[allocated];
00081 memcpy( data, genotype.data, allocated );
00082 fitnessv = genotype.fitnessv;
00083 rankv = genotype.rankv;
00084 notesv = genotype.notesv;
00085 }
00086
00087 Genotype& Genotype::operator=( const Genotype& genotype ) {
00088
00089 delete []data;
00090 sizev = genotype.sizev;
00091 allocated = genotype.allocated;
00092 data = new unsigned char[allocated];
00093 memcpy( data, genotype.data, allocated );
00094 fitnessv = genotype.fitnessv;
00095 rankv = genotype.rankv;
00096 notesv = genotype.notesv;
00097 return (*this);
00098 }
00099
00100 void Genotype::configure( ConfigurationParameters& params, QString prefix ) {
00101 int newsize = params.getValue( prefix + QString( "bitsize" ) ).toInt();
00102 Q_ASSERT_X( newsize > 0,
00103 "Genotype::configure",
00104 "The bitsize must be present in the config file and its value must be greater than zero" );
00105 resize( newsize );
00106 QString zipdata = params.getValue( prefix + QString( "data" ) );
00107 if ( !zipdata.isNull() ) {
00108 fromCompressedString( zipdata );
00109 }
00110 QStringList valuesList = params.getValue( prefix + QString( "fitness" ) )
00111 .split( QRegExp("\\s+"), QString::SkipEmptyParts );
00112 fitnessv.resize(0);
00113 foreach( QString avalue, valuesList ) {
00114 fitnessv << avalue.toDouble();
00115 }
00116 rankv = params.getValue( prefix + QString( "rank" ) ).toDouble();
00117 notesv = params.getValue( prefix + QString( "notes" ) );
00118 }
00119
00120 void Genotype::save( ConfigurationParameters& params, QString prefix ) {
00121 params.createParameter( prefix, QString("type"), "Genotype" );
00122 params.createParameter( prefix, QString("bitsize"), QString("%1").arg(sizev) );
00123 QString fitstring;
00124 foreach( double avalue, fitnessv ) {
00125 fitstring.append( QString("%1 ").arg(avalue) );
00126 }
00127 params.createParameter( prefix, QString("fitness"), fitstring );
00128 params.createParameter( prefix, QString("data"), toCompressedString() );
00129 params.createParameter( prefix, QString("rank"), QString("%1").arg(rankv) );
00130 params.createParameter( prefix, QString("notes"), notesv );
00131 }
00132
00133 void Genotype::describe( QString type ) {
00134 Descriptor d = addTypeDescription( type, "Genotype is a binary string, each bit correspond to a gene" );
00135 d.describeInt( "bitsize" ).limits( 1, INT_MAX ).def( 8 ).props( IsMandatory ).help( "The number of bits of the Genotype", "The Genotype is represented by a binary string of bitsize length" );
00136 d.describeReal( "fitness" ).props( IsList ).help( "The fitness of the Genotype", "The fitness of a Genotype support multi objective fitness; if you specify a vector of values they are considered different objectives of the fitness" );
00137 d.describeString( "data" ).help( "The bits composing the Genotype stored in a compressed string" );
00138 d.describeReal( "rank" ).help( "The rank indicate who is more fitted that others and how much; the values are dependent on the kind of GeneticAlgo used" );
00139 }
00140
00141 void Genotype::assign( const Genotype* genotype ) {
00142 Genotype& self = *this;
00143 self = *genotype;
00144 }
00145
00146 Genotype* Genotype::clone() const {
00147 return new Genotype( *this );
00148 }
00149
00150 unsigned int Genotype::size() const {
00151 return sizev;
00152 }
00153
00154 void Genotype::resize( unsigned int newsize ) {
00155
00156 unsigned int old_allocated = allocated;
00157 sizev = newsize;
00158 allocated = (unsigned int)( (sizev+1)/8 ) + 1;
00159 unsigned char* newdata = new unsigned char[allocated];
00160 memcpy( newdata, data, ( allocated < old_allocated ) ? allocated : old_allocated );
00161 delete []data;
00162 data = newdata;
00163 return;
00164 }
00165
00166 void Genotype::setFitness( double value ) {
00167 setObjective( 0, value );
00168 }
00169
00170 double Genotype::fitness() const {
00171 return objective(0);
00172 }
00173
00174 void Genotype::setObjective( int i, double value ) {
00175 fitnessv.resize( qMax( fitnessv.size(), i+1 ) );
00176 fitnessv[i] = value;
00177 }
00178
00179 double Genotype::objective( int i ) const {
00180 return fitnessv[i];
00181 }
00182
00183 int Genotype::numOfObjectives() const {
00184 return fitnessv.size();
00185 }
00186
00187 bool Genotype::dominatedBy( const Genotype* g ) {
00188 int numObjToCompare = qMin( fitnessv.size(), g->fitnessv.size() );
00189 bool allLessEq = true;
00190 bool oneLessStrictly = false;
00191 for( int i=0; i<numObjToCompare; i++ ) {
00192 if ( fitnessv[i] > g->fitnessv[i] ) {
00193 allLessEq = false;
00194 }
00195 if ( fitnessv[i] < g->fitnessv[i] ) {
00196 oneLessStrictly = true;
00197 }
00198 }
00199 return (allLessEq && oneLessStrictly);
00200 }
00201
00202 void Genotype::setRank( double r ) {
00203 rankv = r;
00204 }
00205
00206 double Genotype::rank() const {
00207 return rankv;
00208 }
00209
00210 bool Genotype::bit( unsigned int i ) const {
00211
00212 int id = i >> 3;
00213
00214
00215 unsigned char mask = 0x80 >> (i&7);
00216 return ( data[id] & mask );
00217 }
00218
00219 void Genotype::set( unsigned int i ) {
00220
00221 int id = i >> 3;
00222
00223
00224 unsigned char mask = 0x80 >> (i&7);
00225
00226 data[id] = data[id] | mask;
00227 }
00228
00229 void Genotype::unset( unsigned int i ) {
00230
00231 int id = i >> 3;
00232
00233
00234 unsigned char mask = 0x80 >> (i&7);
00235
00236 data[id] = data[id] & (~mask);
00237 }
00238
00239 void Genotype::toggle( unsigned int i ) {
00240
00241 int id = i >> 3;
00242
00243
00244 unsigned char mask = 0x80 >> (i&7);
00245
00246 data[id] = data[id] ^ mask;
00247 }
00248
00249 QString Genotype::notes() const {
00250 return notesv;
00251 }
00252
00253 void Genotype::setNotes( QString notes ) {
00254 notesv = notes;
00255 }
00256
00257 int Genotype::hammingDistance( const Genotype* other ) {
00258 int ret = 0;
00259 for( unsigned int i=0; i<sizev; i++ ) {
00260 ret += ( bit(i) == other->bit(i) );
00261 }
00262 return ret;
00263 }
00264
00265 void Genotype::randomize() {
00266 for( unsigned int i=0; i<sizev; i++ ) {
00267 if ( globalRNG->getBool( 0.5 ) ) {
00268 set( i );
00269 } else {
00270 unset( i );
00271 }
00272 }
00273 }
00274
00275 QString Genotype::toString() const {
00276 QString ret;
00277 ret.resize( sizev );
00278 for( unsigned int i=0; i<sizev; i++ ) {
00279 ret[i] = ( bit(i) ) ? '1' : '0';
00280 }
00281 return ret;
00282 }
00283
00284 void Genotype::fromString( QString str ) {
00285 int dim = qMin( (int)sizev, str.size() );
00286 for( int i=0; i<dim; i++ ) {
00287 if ( str[i] == '1' ) {
00288 set( i );
00289 } else {
00290 unset( i );
00291 }
00292 }
00293 }
00294
00295 QString Genotype::toCompressedString() const {
00296 QByteArray temp;
00297 temp.resize( sizev );
00298 for( unsigned int i=0; i<sizev; i++ ) {
00299 temp[i] = ( bit(i) ) ? '1' : '0';
00300 }
00301 QByteArray temp2 = qCompress( temp, 9 );
00302 return temp2.toBase64();
00303 }
00304
00305 bool Genotype::fromCompressedString( QString str ) {
00306 QByteArray temp2 = QByteArray::fromBase64( str.toAscii() );
00307 QByteArray temp = qUncompress( temp2 );
00308 if ( temp.isEmpty() ) {
00309 return false;
00310 }
00311 int dim = qMin( (int)sizev, temp.size() );
00312 for( int i=0; i<dim; i++ ) {
00313 if ( temp[i] == '1' ) {
00314 set( i );
00315 } else {
00316 unset( i );
00317 }
00318 }
00319 return true;
00320 }
00321
00322 unsigned int Genotype::extractUInt( unsigned int startPos, unsigned int stopPos ) {
00323 if ( startPos >= sizev ) return 0;
00324
00325 stopPos = qMin( stopPos, sizev );
00326 unsigned int len = stopPos - startPos;
00327 unsigned int ret = 0;
00328 for( ; startPos<stopPos; startPos++ ) {
00329 len--;
00330 if ( bit(startPos) ) {
00331 ret += (unsigned int)( pow( 2.0f, (int)len ) );
00332 }
00333 }
00334 return ret;
00335 }
00336
00337 void Genotype::insertUInt( unsigned int value, unsigned int startPos, unsigned int stopPos ) {
00338 if ( startPos >= sizev ) return ;
00339
00340 stopPos = qMin( stopPos, sizev );
00341 for( ; stopPos!=startPos; stopPos-- ) {
00342 if ( value%2 == 1 ) {
00343 set( stopPos-1 );
00344 } else {
00345 unset( stopPos-1 );
00346 }
00347 value /= 2;
00348 }
00349 return;
00350 }
00351
00352 unsigned int Genotype::geneToBitIndex( unsigned int gene ) const {
00353 return gene;
00354 }
00355
00356 unsigned int Genotype::bitToGeneIndex( unsigned int bit ) const {
00357 return bit;
00358 }
00359
00360 void Genotype::copyDataFrom( Genotype* source ) {
00361
00362 delete []data;
00363 sizev = source->sizev;
00364 allocated = source->allocated;
00365 data = new unsigned char[allocated];
00366 memcpy( data, source->data, allocated );
00367 fitnessv = source->fitnessv;
00368 rankv = source->rankv;
00369 notesv = source->notesv;
00370 return;
00371 }
00372
00373 }