ga/src/genotypes/signedrangegenotype.cpp

00001 /********************************************************************************
00002  *  FARSA Genetic Algorithm Library                                             *
00003  *  Copyright (C) 2007-2008 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 
00020 #include "genotypes/signedrangegenotype.h"
00021 #include <cmath>
00022 #include "configurationparameters.h"
00023 
00024 namespace farsa {
00025 
00026 #if defined(_WIN32) && !defined(__MINGW32__)
00027 /* replacement of Unix rint() for Windows */
00028 static int rint (double x) {
00029     char *buf;
00030     int i,dec,sig;
00031     buf = _fcvt(x, 0, &dec, &sig);
00032     i = atoi(buf);
00033     if( sig == 1 ) {
00034         i = i * -1;
00035     }
00036     return i;
00037 }
00038 #endif
00039 
00040 SignedRangeGenotype::SignedRangeGenotype( unsigned int numGenes, double max, unsigned int bitPrec )
00041     : DoubleGenotype( numGenes, -max, +max, bitPrec ) {
00042     Q_ASSERT_X( bitPrec > 1,
00043                 "SignedRangeGenotype Constructor",
00044                 "bitPrecision parameters must be greater than 1" );
00045     dx = ( maxValue() ) / ( std::pow(2.0f, (int)(bitPrec-1)) - 1 );
00046 }
00047 
00048 SignedRangeGenotype::~SignedRangeGenotype() {
00049     //--- nothing to do
00050 }
00051 
00052 SignedRangeGenotype::SignedRangeGenotype( const SignedRangeGenotype& genotype )
00053     : DoubleGenotype( genotype ) {
00054     this->dx = genotype.dx;
00055 }
00056 
00057 SignedRangeGenotype& SignedRangeGenotype::operator=( const Genotype& genotype ) {
00058     SignedRangeGenotype* genodouble = (SignedRangeGenotype*)( &genotype );
00059     copyDataFrom( genodouble );
00060     this->numgenes = genodouble->numgenes;
00061     this->bitprec = genodouble->bitprec;
00062     this->maxv = genodouble->maxv;
00063     this->minv = genodouble->minv;
00064     this->dx = genodouble->dx;
00065     return *this;
00066 }
00067 
00068 void SignedRangeGenotype::configure( ConfigurationParameters& params, QString prefix ) {
00069     numgenes = params.getValue( prefix + QString( "ngenes" ) ).toInt();
00070     Q_ASSERT_X( numgenes > 0,
00071                 "SignedRangeGenotype::configure",
00072                 "The ngenes must be present in the config file and its value must be greater than zero" );
00073     bitprec = params.getValue( prefix + QString( "nbits" ) ).toInt();
00074     Q_ASSERT_X( bitprec > 1,
00075                 "SignedRangeGenotype::configure",
00076                 "The nbits must be greater than 1 !! Check your config file" );
00077     maxv = params.getValue( prefix + QString( "maxValue" ) ).toDouble();
00078     minv = -maxv;
00079     Q_ASSERT_X( maxv > 0,
00080                 "SignedRangeGenotype::configure",
00081                 "The maxValue must be greater than zero!! Check you config file" );
00082     resize( numgenes*bitprec );
00083     dx = ( maxValue() ) / ( std::pow(2.0f, (int)(bitprec-1)) - 1 );
00084     QString zipdata = params.getValue( prefix + QString( "data" ) );
00085     if ( !zipdata.isNull() ) {
00086         fromCompressedString( zipdata );
00087     }
00088     QStringList valuesList = params.getValue( prefix + QString( "fitness" ) )
00089                                     .split( QRegExp("\\s+"), QString::SkipEmptyParts );
00090     fitnessv.resize(0);
00091     foreach( QString avalue, valuesList ) {
00092         fitnessv << avalue.toDouble();
00093     }
00094     rankv = params.getValue( prefix + QString( "rank" ) ).toDouble();
00095     notesv = params.getValue( prefix + QString( "notes" ) );
00096 }
00097 
00098 void SignedRangeGenotype::save( ConfigurationParameters& params, QString prefix ) {
00099     params.createParameter( prefix, QString("type"), "SignedRange" );
00100     params.createParameter( prefix, QString("ngenes"), QString("%1").arg( numgenes ) );
00101     params.createParameter( prefix, QString("nbits"), QString("%1").arg( bitprec ) );
00102     params.createParameter( prefix, QString("maxValue"), QString("%1").arg( maxv ) );
00103     QString fitstring;
00104     foreach( double avalue, fitnessv ) {
00105         fitstring.append( QString("%1 ").arg(avalue) );
00106     }
00107     params.createParameter( prefix, QString("fitness"), fitstring );
00108     params.createParameter( prefix, QString("data"), toCompressedString() );
00109     params.createParameter( prefix, QString("rank"), QString("%1").arg(rankv) );
00110     params.createParameter( prefix, QString("notes"), notesv );
00111 }
00112 
00113 void SignedRangeGenotype::describe( QString type ) {
00114     Descriptor d = addTypeDescription( type, "SignedRangeGenotype encode a vector of real values, each value correspond to a gene" );
00115     d.describeInt( "ngenes" ).limits( 1, INT_MAX ).def( 8 ).props( IsMandatory ).help( "The number of real values represented by the Genotype" );
00116     d.describeInt( "nbits" ).limits( 4, 32 ).def( 16 ).help( "The number of bits used to encode one real value", "The SignedRangeGenotype encode the real value in a discrete way inside a boundary; Supposing nbits is 4, then 4 bits are used to encode a real value where the first bit represent the sign, and the other three represents the number of discretization of the interval from -maxValue to +maxValue. In this way, the representation of zero is always present and has two encoding: 0000 (-0) and 1000 (+0)" );
00117     d.describeReal( "maxValue" ).def( 5.0 ).help( "The absolute maximum value representable. Look at the help of nbits for details" );
00118     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" );
00119     d.describeString( "data" ).help( "The bits composing the Genotype stored in a compressed string" );
00120     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" );
00121 }
00122 
00123 double SignedRangeGenotype::at( unsigned int i ) {
00124     Q_ASSERT_X( (i+1)*bitprec <= size(),
00125                 "SignedRangeGenotype::at",
00126                 "The value requested is beyond the dimension of this Genotype" );
00127     double ret = extractUInt( i*bitprec+1, (i+1)*bitprec );
00128     //--- first bit (MSB) represent the sign: 0 positive, 1 negative
00129     if ( bit( i*bitprec ) ) {
00130         return -(dx*ret);
00131     } else {
00132         return +(dx*ret);
00133     }
00134 }
00135 
00136 void SignedRangeGenotype::set( unsigned int i, double value ) {
00137     Q_ASSERT_X( (i+1)*bitprec <= size(),
00138                 "SignedRangeGenotype::set",
00139                 "The value to be set is beyond the dimension of this Genotype" );
00140     value = qMin( maxv, value );
00141     value = qMax( -maxv, value );
00142     unsigned int intP = (unsigned int)( rint( qAbs(value)/dx ) );
00143     insertUInt( (unsigned int)intP, i*bitprec+1, (i+1)*bitprec );
00144     if ( value < 0 ) {
00145         Genotype::set( i*bitprec );
00146     } else {
00147         Genotype::unset( i*bitprec );
00148     }
00149     return;
00150 }
00151 
00152 SignedRangeGenotype* SignedRangeGenotype::clone() const {
00153     return ( new SignedRangeGenotype( *this ) );
00154 }
00155 
00156 } // end namespace farsa