signedrangegenotype.cpp
1 /********************************************************************************
2  * FARSA Genetic Algorithm Library *
3  * Copyright (C) 2007-2008 Gianluca Massera <emmegian@yahoo.it> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the Free Software *
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
18  ********************************************************************************/
19 
20 #include "genotypes/signedrangegenotype.h"
21 #include <cmath>
22 #include "configurationparameters.h"
23 
24 namespace farsa {
25 
26 #if defined(_WIN32) && !defined(__MINGW32__)
27 /* replacement of Unix rint() for Windows */
28 static int rint (double x) {
29  char *buf;
30  int i,dec,sig;
31  buf = _fcvt(x, 0, &dec, &sig);
32  i = atoi(buf);
33  if( sig == 1 ) {
34  i = i * -1;
35  }
36  return i;
37 }
38 #endif
39 
40 SignedRangeGenotype::SignedRangeGenotype( unsigned int numGenes, double max, unsigned int bitPrec )
41  : DoubleGenotype( numGenes, -max, +max, bitPrec ) {
42  Q_ASSERT_X( bitPrec > 1,
43  "SignedRangeGenotype Constructor",
44  "bitPrecision parameters must be greater than 1" );
45  dx = ( maxValue() ) / ( std::pow(2.0f, (int)(bitPrec-1)) - 1 );
46 }
47 
49  //--- nothing to do
50 }
51 
53  : DoubleGenotype( genotype ) {
54  this->dx = genotype.dx;
55 }
56 
58  SignedRangeGenotype* genodouble = (SignedRangeGenotype*)( &genotype );
59  copyDataFrom( genodouble );
60  this->numgenes = genodouble->numgenes;
61  this->bitprec = genodouble->bitprec;
62  this->maxv = genodouble->maxv;
63  this->minv = genodouble->minv;
64  this->dx = genodouble->dx;
65  return *this;
66 }
67 
69  numgenes = params.getValue( prefix + QString( "ngenes" ) ).toInt();
70  Q_ASSERT_X( numgenes > 0,
71  "SignedRangeGenotype::configure",
72  "The ngenes must be present in the config file and its value must be greater than zero" );
73  bitprec = params.getValue( prefix + QString( "nbits" ) ).toInt();
74  Q_ASSERT_X( bitprec > 1,
75  "SignedRangeGenotype::configure",
76  "The nbits must be greater than 1 !! Check your config file" );
77  maxv = params.getValue( prefix + QString( "maxValue" ) ).toDouble();
78  minv = -maxv;
79  Q_ASSERT_X( maxv > 0,
80  "SignedRangeGenotype::configure",
81  "The maxValue must be greater than zero!! Check you config file" );
83  dx = ( maxValue() ) / ( std::pow(2.0f, (int)(bitprec-1)) - 1 );
84  QString zipdata = params.getValue( prefix + QString( "data" ) );
85  if ( !zipdata.isNull() ) {
86  fromCompressedString( zipdata );
87  }
88  QStringList valuesList = params.getValue( prefix + QString( "fitness" ) )
89  .split( QRegExp("\\s+"), QString::SkipEmptyParts );
90  fitnessv.resize(0);
91  foreach( QString avalue, valuesList ) {
92  fitnessv << avalue.toDouble();
93  }
94  rankv = params.getValue( prefix + QString( "rank" ) ).toDouble();
95  notesv = params.getValue( prefix + QString( "notes" ) );
96 }
97 
98 void SignedRangeGenotype::save( ConfigurationParameters& params, QString prefix ) {
99  params.createParameter( prefix, QString("type"), "SignedRange" );
100  params.createParameter( prefix, QString("ngenes"), QString("%1").arg( numgenes ) );
101  params.createParameter( prefix, QString("nbits"), QString("%1").arg( bitprec ) );
102  params.createParameter( prefix, QString("maxValue"), QString("%1").arg( maxv ) );
103  QString fitstring;
104  foreach( double avalue, fitnessv ) {
105  fitstring.append( QString("%1 ").arg(avalue) );
106  }
107  params.createParameter( prefix, QString("fitness"), fitstring );
108  params.createParameter( prefix, QString("data"), toCompressedString() );
109  params.createParameter( prefix, QString("rank"), QString("%1").arg(rankv) );
110  params.createParameter( prefix, QString("notes"), notesv );
111 }
112 
113 void SignedRangeGenotype::describe( QString type ) {
114  Descriptor d = addTypeDescription( type, "SignedRangeGenotype encode a vector of real values, each value correspond to a gene" );
115  d.describeInt( "ngenes" ).limits( 1, INT_MAX ).def( 8 ).props( IsMandatory ).help( "The number of real values represented by the Genotype" );
116  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)" );
117  d.describeReal( "maxValue" ).def( 5.0 ).help( "The absolute maximum value representable. Look at the help of nbits for details" );
118  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" );
119  d.describeString( "data" ).help( "The bits composing the Genotype stored in a compressed string" );
120  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" );
121 }
122 
123 double SignedRangeGenotype::at( unsigned int i ) {
124  Q_ASSERT_X( (i+1)*bitprec <= size(),
125  "SignedRangeGenotype::at",
126  "The value requested is beyond the dimension of this Genotype" );
127  double ret = extractUInt( i*bitprec+1, (i+1)*bitprec );
128  //--- first bit (MSB) represent the sign: 0 positive, 1 negative
129  if ( bit( i*bitprec ) ) {
130  return -(dx*ret);
131  } else {
132  return +(dx*ret);
133  }
134 }
135 
136 void SignedRangeGenotype::set( unsigned int i, double value ) {
137  Q_ASSERT_X( (i+1)*bitprec <= size(),
138  "SignedRangeGenotype::set",
139  "The value to be set is beyond the dimension of this Genotype" );
140  value = qMin( maxv, value );
141  value = qMax( -maxv, value );
142  unsigned int intP = (unsigned int)( rint( qAbs(value)/dx ) );
143  insertUInt( (unsigned int)intP, i*bitprec+1, (i+1)*bitprec );
144  if ( value < 0 ) {
145  Genotype::set( i*bitprec );
146  } else {
148  }
149  return;
150 }
151 
153  return ( new SignedRangeGenotype( *this ) );
154 }
155 
156 } // end namespace farsa