ga/src/core/genome.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 "core/genome.h"
00021 #include "factory.h"
00022 #include <QtAlgorithms>
00023 
00024 namespace farsa {
00025 
00026 Genome::Genome() {
00027     prototype = NULL;
00028 }
00029 
00030 Genome::Genome( unsigned int numGenotype, unsigned int numBits ) {
00031     prototype = new Genotype( numBits );
00032     data.resize( numGenotype );
00033     for( unsigned int i=0; i<numGenotype; i++ ) {
00034         data[i] = new Genotype( numBits );
00035         data[i]->randomize();
00036     }
00037 }
00038 
00039 Genome::Genome( unsigned int numGenotype, const Genotype* prototype ) : ParameterSettableWithConfigureFunction() {
00040     this->prototype = prototype->clone();
00041     data.resize( numGenotype );
00042     for( unsigned int i=0; i<numGenotype; i++ ) {
00043         data[i] = prototype->clone();
00044         data[i]->randomize();
00045     }
00046 }
00047 
00048 Genome::Genome( const Genome& genome ) : ParameterSettableWithConfigureFunction() {
00049     this->prototype = genome.prototype->clone();
00050     data.resize( genome.data.size() );
00051     for( int i=0; i<data.size(); i++ ) {
00052         data[i] = genome.data[i]->clone();
00053     }
00054 }
00055 
00056 Genome::~Genome() {
00057     if ( prototype ) {
00058         delete prototype;
00059     }
00060     // The destruction of genotypes was added by Tomassino. It is not certain that
00061     // this won't create any problem...
00062     for( int i=0; i<data.size(); i++ ) {
00063         delete (data[i]);
00064     }
00065 }
00066 
00067 Genome& Genome::operator=( const Genome& right ) {
00068     this->prototype = right.prototype->clone();
00069     //--- destroy all memory allocated
00070     for( int i=0; i<data.size(); i++ ) {
00071         delete (data[i]);
00072     }
00073     data.resize( right.data.size() );
00074     for( unsigned int i=0; i<right.size(); i++ ) {
00075         data[i] = right.data[i]->clone();
00076     }
00077     return (*this);
00078 }
00079 
00080 void Genome::configure( ConfigurationParameters& params, QString prefix ) {
00081     for( int i=0; i<data.size(); i++ ) {
00082         delete (data[i]);
00083     }
00084     data.clear();
00085     this->prototype = params.getObjectFromGroup<Genotype>( prefix + QString( "GENOTYPE:prototype" ) );
00086     foreach( QString group, params.getGroupsWithPrefixList(prefix, QString( "GENOTYPES" )) ) {
00087         data.append( params.getObjectFromGroup<Genotype>( prefix + "/" + group ) );
00088     }
00089     int nindividuals = params.getValue( prefix + QString( "nindividuals" ) ).toInt();
00090     if ( data.size() != 0 && nindividuals != data.size() ) {
00091         qWarning() << "Genome configuration: nindividuals parameter should match the number of GENOTYPES specified.";
00092     }
00093     int loadedgens = data.size();
00094     data.resize( nindividuals );
00095     for( int i=loadedgens; i<nindividuals; i++ ) {
00096         data[i] = prototype->clone();
00097     }
00098 }
00099 
00100 void Genome::save( ConfigurationParameters& params, QString prefix ) {
00101     params.createParameter( prefix, QString("type"), "Genome" );
00102     params.createParameter( prefix, QString("nindividuals"), QString("%1").arg(data.size()) );
00103 
00104     this->prototype->save( params, params.createSubGroup( prefix, "GENOTYPE:prototype" ) );
00105 
00106     for( int i=0; i<data.size(); i++ ) {
00107         data[i]->save( params, params.createSubGroup( prefix, QString("GENOTYPES:%1").arg(i) ) );
00108     }
00109 }
00110 
00111 void Genome::describe( QString type ) {
00112     Descriptor d = addTypeDescription( type, "A population of Genotypes" );
00113     d.describeInt( "nindividuals" ).limits( 1, INT_MAX ).def( 100 ).props( IsMandatory ).help( "The number of Genotypes contained by the Genome" );
00114     d.describeSubgroup( "GENOTYPE:prototype" ).type( "Genotype" ).props( IsMandatory ).help( "The prototype of Genotypes contained by the Genome" );
00115     d.describeSubgroup( "GENOTYPE" ).type( "Genotype" ).props( AllowMultiple ).help( "The vector of all Genotypes contained by the Genome" );
00116 }
00117 
00118 unsigned int Genome::size() const {
00119     return data.size();
00120 }
00121 
00122 void Genome::clearAll() {
00123     data.clear();
00124 }
00125 
00126 void Genome::append( const Genotype* genotype ) {
00127     data.append( genotype->clone() );
00128     return;
00129 }
00130 
00131 Genotype* Genome::at( unsigned int i ) {
00132     return data[i];
00133 }
00134 
00135 const Genotype* Genome::at( unsigned int i ) const {
00136     return data[i];
00137 }
00138 
00139 Genotype* Genome::last() {
00140     return data.last();
00141 }
00142 
00143 const Genotype* Genome::last() const {
00144     return data.last();
00145 }
00146 
00147 unsigned int Genome::find( const Genotype* g ) {
00148     for( int i=0; i<data.size(); i++ ) {
00149         if ( g == data[i] ) return i;
00150     }
00151     return -1;
00152 }
00153 
00154 void Genome::set( unsigned int i, Genotype* g ) {
00155     data[i] = g->clone();
00156 }
00157 
00158 const Genotype* Genome::operator[]( unsigned int i ) const {
00159     return data[i];
00160 }
00161 
00162 Genotype* Genome::operator[]( unsigned int i ) {
00163     return data[i];
00164 }
00165 
00166 void Genome::randomize() {
00167     //--- can be parallelizable
00168     for( int i=0; i<data.size(); i++ ) {
00169         data[i]->randomize();
00170     }
00171 }
00172 
00173 } // end namespace farsa