fixedsize.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 "gaconfig.h"
21 #include "factory.h"
22 #include "core/genome.h"
23 #include "core/selection.h"
24 #include "core/mutation.h"
25 #include "core/crossover.h"
26 #include "reproductions/fixedsize.h"
27 #include "randomgenerator.h"
28 
29 namespace farsa {
30 
32  : Reproduction() {
33  sel = 0;
34  muta = 0;
35  cross = 0;
36  isElitism = false;
37  nElited = 0;
38  probCrossover = 0;
39 }
40 
42  //--- nothing to do
43 }
44 
46  Q_ASSERT_X( sel != 0,
47  "FixedSize::reproduction",
48  "You must set a Selection object before calling this method" );
49  Q_ASSERT_X( muta != 0,
50  "FixedSize::reproduction",
51  "You must set a Mutation object before calling this method" );
52  Q_ASSERT_X( cross != 0 || probCrossover == 0 ,
53  "FixedSize::reproduction",
54  "You must set a Crossover object before calling this method" );
55  Q_ASSERT_X( nElited >= 0,
56  "FixedSize::reproduction",
57  "The number of Elited Genotypes must be greater than zero" );
58 
59  Genome* ret = new Genome( 0, genome->at(0) );
60  muta->setGenome( genome );
61  cross->setGenome( genome );
62  sel->setGenome( genome );
63  int left = genome->size();
64  if ( isElitism ) {
65  for( int i=0; i<nElited; i++ ) {
66  ret->append( genome->at(i) );
67  }
68  left -= nElited;
69  }
70  for( int i=0; i<left; i++ ) {
71  //--- Select a Genotype, and create a copy of it
72  ret->append( sel->select() );
73  //--- crossover
74  if ( globalRNG->getBool( probCrossover ) ) {
75  cross->crossover( ret->last(), sel->select() );
76  }
77  //--- mutation
78  muta->mutate( ret->last() );
79  }
80  return ret;
81 }
82 
84  this->muta = muta;
85  this->muta->setGA( GA() );
86 }
87 
89  return muta;
90 }
91 
93  this->sel = sel;
94  this->sel->setGA( GA() );
95 }
96 
98  return sel;
99 }
100 
102  this->cross = cross;
103  this->cross->setGA( GA() );
104 }
105 
107  return cross;
108 }
109 
110 void FixedSize::setCrossoverRate( double prob ) {
111  this->probCrossover = prob;
112 }
113 
115  return probCrossover;
116 }
117 
118 void FixedSize::enableElitism( bool enable ) {
119  isElitism = enable;
120 }
121 
123  return isElitism;
124 }
125 
126 void FixedSize::setNumberElited( unsigned int nelited ) {
127  this->nElited = nelited;
128 }
129 
131  return nElited;
132 }
133 
134 void FixedSize::configure( ConfigurationParameters& params, QString prefix ) {
135  setMutation( params.getObjectFromGroup<Mutation>( prefix + QString( "MUTATION" ) ) );
136  setSelection( params.getObjectFromGroup<Selection>( prefix + QString( "SELECTION" ) ) );
137  setCrossover( params.getObjectFromGroup<Crossover>( prefix + QString( "CROSSOVER" ) ) );
138  probCrossover = params.getValue( prefix + QString( "crossoverRate" ) ).toDouble();
139  isElitism = ! (params.getValue( prefix + QString( "elitism" ) ).compare( "true", Qt::CaseInsensitive ) );
140  nElited = params.getValue( prefix + QString( "nelited" ) ).toInt();
141 }
142 
143 void FixedSize::save( ConfigurationParameters& params, QString prefix ) {
144  params.createParameter( prefix, QString("type"), "FixedSize" );
145  params.createParameter( prefix, QString("crossoverRate"), QString("%1").arg( probCrossover ) );
146  params.createParameter( prefix, QString("elitism"), isElitism ? "true" : "false" );
147  params.createParameter( prefix, QString("nelited"), QString("%1").arg( nElited ) );
148  //--- MUTATION
149  if ( mutation() ) {
150  mutation()->save( params, params.createSubGroup( prefix, "MUTATION" ) );
151  }
152  //--- SELECTION
153  if ( selection() ) {
154  selection()->save( params, params.createSubGroup( prefix, "SELECTION" ) );
155  }
156  //-- CROSSOVER
157  if ( crossover() ) {
158  crossover()->save( params, params.createSubGroup( prefix, "CROSSOVER" ) );
159  }
160 }
161 
162 void FixedSize::describe( QString type ) {
163  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" );
164  d.describeReal( "crossoverRate" ).limits( 0, 1 ).def( 0.1 ).help( "The probability to apply the crossover operator" );
165  d.describeBool( "elitism" ).def( false ).help( "Enable/Disable the elitism" );
166  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" );
167  d.describeSubgroup( "MUTATION" ).type( "Mutation" ).props( IsMandatory ).help( "The mutation operator used to mutate Genotypes" );
168  d.describeSubgroup( "SELECTION" ).type( "Selection" ).props( IsMandatory ).help( "The selection operator used to select Genotypes for reproduction" );
169  d.describeSubgroup( "CROSSOVER" ).type( "Crossover" ).props( IsMandatory ).help( "The crossover operator used to generate offsprings from Genotypes" );
170 }
171 
172 } // end namespace farsa