ga/src/reproductions/fixedsize.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 "gaconfig.h"
00021 #include "factory.h"
00022 #include "core/genome.h"
00023 #include "core/selection.h"
00024 #include "core/mutation.h"
00025 #include "core/crossover.h"
00026 #include "reproductions/fixedsize.h"
00027 #include "randomgenerator.h"
00028 
00029 namespace farsa {
00030 
00031 FixedSize::FixedSize()
00032     : Reproduction() {
00033     sel = 0;
00034     muta = 0;
00035     cross = 0;
00036     isElitism = false;
00037     nElited = 0;
00038     probCrossover = 0;
00039 }
00040 
00041 FixedSize::~FixedSize() {
00042     //--- nothing to do
00043 }
00044 
00045 Genome* FixedSize::reproduction( const Genome* genome ) {
00046     Q_ASSERT_X( sel != 0,
00047                 "FixedSize::reproduction",
00048                 "You must set a Selection object before calling this method" );
00049     Q_ASSERT_X( muta != 0,
00050                 "FixedSize::reproduction",
00051                 "You must set a Mutation object before calling this method" );
00052     Q_ASSERT_X( cross != 0 || probCrossover == 0 ,
00053                 "FixedSize::reproduction",
00054                 "You must set a Crossover object before calling this method" );
00055     Q_ASSERT_X( nElited >= 0,
00056                 "FixedSize::reproduction",
00057                 "The number of Elited Genotypes must be greater than zero" );
00058     
00059     Genome* ret = new Genome( 0, genome->at(0) );
00060     muta->setGenome( genome );
00061     cross->setGenome( genome );
00062     sel->setGenome( genome );
00063     int left = genome->size();
00064     if ( isElitism ) {
00065         for( int i=0; i<nElited; i++ ) {
00066             ret->append( genome->at(i) );
00067         }
00068         left -= nElited;
00069     }
00070     for( int i=0; i<left; i++ ) {
00071         //--- Select a Genotype, and create a copy of it
00072         ret->append( sel->select() );
00073         //--- crossover
00074         if ( globalRNG->getBool( probCrossover ) ) {
00075             cross->crossover( ret->last(), sel->select() );
00076         }
00077         //--- mutation
00078         muta->mutate( ret->last() );
00079     }
00080     return ret;
00081 }
00082 
00083 void FixedSize::setMutation( Mutation* muta ) {
00084     this->muta = muta;
00085     this->muta->setGA( GA() );
00086 }
00087 
00088 Mutation* FixedSize::mutation() {
00089     return muta;
00090 }
00091 
00092 void FixedSize::setSelection( Selection* sel ) {
00093     this->sel = sel;
00094     this->sel->setGA( GA() );
00095 }
00096 
00097 Selection* FixedSize::selection() {
00098     return sel;
00099 }
00100 
00101 void FixedSize::setCrossover( Crossover* cross ) {
00102     this->cross = cross;
00103     this->cross->setGA( GA() );
00104 }
00105 
00106 Crossover* FixedSize::crossover() {
00107     return cross;
00108 }
00109 
00110 void FixedSize::setCrossoverRate( double prob ) {
00111     this->probCrossover = prob;
00112 }
00113 
00114 double FixedSize::crossoverRate() {
00115     return probCrossover;
00116 }
00117 
00118 void FixedSize::enableElitism( bool enable ) {
00119     isElitism = enable;
00120 }
00121 
00122 bool FixedSize::isElitismEnabled() {
00123     return isElitism;
00124 }
00125 
00126 void FixedSize::setNumberElited( unsigned int nelited ) {
00127     this->nElited = nelited;
00128 }
00129 
00130 int FixedSize::numberElited() {
00131     return nElited;
00132 }
00133 
00134 void FixedSize::configure( ConfigurationParameters& params, QString prefix ) {
00135     setMutation( params.getObjectFromGroup<Mutation>( prefix + QString( "MUTATION" ) ) );
00136     setSelection( params.getObjectFromGroup<Selection>( prefix + QString( "SELECTION" ) ) );
00137     setCrossover( params.getObjectFromGroup<Crossover>( prefix + QString( "CROSSOVER" ) ) );
00138     probCrossover = params.getValue( prefix + QString( "crossoverRate" ) ).toDouble();
00139     isElitism = ! (params.getValue( prefix + QString( "elitism" ) ).compare( "true", Qt::CaseInsensitive ) );
00140     nElited = params.getValue( prefix + QString( "nelited" ) ).toInt();
00141 }
00142 
00143 void FixedSize::save( ConfigurationParameters& params, QString prefix ) {
00144     params.createParameter( prefix, QString("type"), "FixedSize" );
00145     params.createParameter( prefix, QString("crossoverRate"), QString("%1").arg( probCrossover ) );
00146     params.createParameter( prefix, QString("elitism"), isElitism ? "true" : "false" );
00147     params.createParameter( prefix, QString("nelited"), QString("%1").arg( nElited ) );
00148     //--- MUTATION
00149     if ( mutation() ) {
00150         mutation()->save( params, params.createSubGroup( prefix, "MUTATION" ) );
00151     }
00152     //--- SELECTION
00153     if ( selection() ) {
00154         selection()->save( params, params.createSubGroup( prefix, "SELECTION" ) );
00155     }
00156     //-- CROSSOVER
00157     if ( crossover() ) {
00158         crossover()->save( params, params.createSubGroup( prefix, "CROSSOVER" ) );
00159     }
00160 }
00161 
00162 void FixedSize::describe( QString type ) {
00163     Descriptor d = addTypeDescription( type, "Create a new generation mantaining constant the number of individuals", "It apply the selection, crossover and mutation operators without changing the size of the Genome" );
00164     d.describeReal( "crossoverRate" ).limits( 0, 1 ).def( 0.1 ).help( "The probability to apply the crossover operator" );
00165     d.describeBool( "elitism" ).def( false ).help( "Enable/Disable the elitism" );
00166     d.describeInt( "nelited" ).limits( 0, INT_MAX ).def( 10 ).help( "The number of individual to copy exactly to the new generation; only if elitism is true" );
00167     d.describeSubgroup( "MUTATION" ).type( "Mutation" ).props( IsMandatory ).help( "The mutation operator used to mutate Genotypes" );
00168     d.describeSubgroup( "SELECTION" ).type( "Selection" ).props( IsMandatory ).help( "The selection operator used to select Genotypes for reproduction" );
00169     d.describeSubgroup( "CROSSOVER" ).type( "Crossover" ).props( IsMandatory ).help( "The crossover operator used to generate offsprings from Genotypes" );
00170 }
00171 
00172 } // end namespace farsa