1 /*
2  *  Open BEAGLE
3  *  Copyright (C) 2001-2007 by Christian Gagne and Marc Parizeau
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2.1 of the License, or (at your option) any later version.
9  *
10  *  This library 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 GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  *  Contact:
20  *  Laboratoire de Vision et Systemes Numeriques
21  *  Departement de genie electrique et de genie informatique
22  *  Universite Laval, Quebec, Canada, G1K 7P4
23  *  http://vision.gel.ulaval.ca
24  *
25  */
26 
27 /*!
28  *  \file   beagle/GA/src/CrossoverBlendFltVecOp.cpp
29  *  \brief  Source code of class GA::CrossoverBlendFltVec.
30  *  \author Christian Gagne
31  *  \author Marc Parizeau
32  *  $Revision: 1.14.2.2 $
33  *  $Date: 2007/05/11 19:18:44 $
34  */
35 
36 #include "beagle/GA.hpp"
37 
38 #include <cfloat>
39 #include <float.h>
40 #include <cmath>
41 #include <algorithm>
42 #include <string>
43 
44 using namespace std;
45 using namespace Beagle;
46 
47 
48 /*!
49  *  \brief Construct a real-valued GA blend crossover operator.
50  *  \param inMatingPbName Mating probability parameter name.
51  *  \param inName Name of the operator.
52  */
CrossoverBlendFltVecOp(string inMatingPbName,string inName)53 Beagle::GA::CrossoverBlendFltVecOp::CrossoverBlendFltVecOp(string inMatingPbName,
54                                                            string inName) :
55   CrossoverOp(inMatingPbName, inName)
56 { }
57 
58 
59 /*!
60  *  \brief Initialize the real-valued GA blend crossover operator.
61  *  \param ioSystem System of the evolution.
62  */
initialize(Beagle::System & ioSystem)63 void Beagle::GA::CrossoverBlendFltVecOp::initialize(Beagle::System& ioSystem)
64 {
65   Beagle_StackTraceBeginM();
66   CrossoverOp::initialize(ioSystem);
67 
68   if(ioSystem.getRegister().isRegistered(mMatingProbaName)) {
69     ioSystem.getRegister().deleteEntry(mMatingProbaName);
70   }
71 
72   if(ioSystem.getRegister().isRegistered(mMatingProbaName)) {
73     mMatingProba = castHandleT<Float>(ioSystem.getRegister()[mMatingProbaName]);
74   } else {
75     mMatingProba = new Float(float(0.3));
76     Register::Description lDescription(
77       "Individual blend crossover prob.",
78       "Float",
79       "0.3",
80       "Real-valued GA blend crossover probability of a single individual."
81     );
82     ioSystem.getRegister().addEntry(mMatingProbaName, mMatingProba, lDescription);
83   }
84 
85   if(ioSystem.getRegister().isRegistered("ga.float.maxvalue")) {
86     mMaxValue = castHandleT<DoubleArray>(ioSystem.getRegister()["ga.float.maxvalue"]);
87   } else {
88     mMaxValue = new DoubleArray(1,DBL_MAX);
89     std::ostringstream lOSS;
90     lOSS << "Maximum values assigned to vector's floats. ";
91     lOSS << "Value can be a scalar, which limit the value for all float ";
92     lOSS << "vector parameters, or a vector which limit the value for the parameters ";
93     lOSS << "individually. If the maximum value is smaller than the ";
94     lOSS << "float vector size, the limit used for the last values of the float vector ";
95     lOSS << "is equal to the last value of the maximum value vector.";
96     Register::Description lDescription(
97       "Maximum vector values",
98       "DoubleArray",
99       dbl2str(DBL_MAX),
100       lOSS.str().c_str()
101     );
102     ioSystem.getRegister().addEntry("ga.float.maxvalue", mMaxValue, lDescription);
103   }
104 
105   if(ioSystem.getRegister().isRegistered("ga.float.minvalue")) {
106     mMinValue = castHandleT<DoubleArray>(ioSystem.getRegister()["ga.float.minvalue"]);
107   } else {
108     mMinValue = new DoubleArray(1,-DBL_MAX);
109     std::ostringstream lOSS;
110     lOSS << "Minimum  values assigned to vector's floats. ";
111     lOSS << "Value can be a scalar, which limit the value for all float ";
112     lOSS << "vector parameters, or a vector which limit the value for the parameters ";
113     lOSS << "individually. If the minimum value is smaller than the ";
114     lOSS << "float vector size, the limit used for the last values of the float vector ";
115     lOSS << "is equal to the last value of the minimum value vector.";
116     Register::Description lDescription(
117       "Minimum values",
118       "DoubleArray",
119       dbl2str(-DBL_MAX),
120       lOSS.str().c_str()
121     );
122     ioSystem.getRegister().addEntry("ga.float.minvalue", mMinValue, lDescription);
123   }
124 
125   if(ioSystem.getRegister().isRegistered("ga.float.inc")) {
126     mIncValue = castHandleT<DoubleArray>(ioSystem.getRegister()["ga.float.inc"]);
127   } else {
128     mIncValue = new DoubleArray(1,0.0);
129     std::ostringstream lOSS;
130     lOSS << "Increments of valid values assigned to vector's floats. ";
131     lOSS << "Value can be a scalar, which limit the value for all float ";
132     lOSS << "vector parameters, or a vector which limit the value for the parameters ";
133     lOSS << "individually. If the value is not evenly divisible by the ";
134     lOSS << "increment, the value will be set to the closest valid ";
135     lOSS << "value.";
136     Register::Description lDescription(
137       "Increments of valid values",
138       "DoubleArray",
139       "0.0",
140       lOSS.str().c_str()
141     );
142     ioSystem.getRegister().addEntry("ga.float.inc", mIncValue, lDescription);
143   }
144 
145   if(ioSystem.getRegister().isRegistered("ga.cxblend.alpha")) {
146     mAlpha = castHandleT<Double>(ioSystem.getRegister()["ga.cxblend.alpha"]);
147   } else {
148     mAlpha = new Double(0.5);
149     Register::Description lDescription(
150       "Blend crossover alpha value",
151       "Double",
152       "0.5",
153       "GA blend crossover alpha parameter moduling amplitude of operation."
154     );
155     ioSystem.getRegister().addEntry("ga.cxblend.alpha", mAlpha, lDescription);
156   }
157   Beagle_StackTraceEndM("void GA::CrossoverBlendFltVecOp::initialize(System& ioSystem)");
158 }
159 
160 
161 /*!
162  *  \brief Mate two GA individuals for real-valued GA blend crossover.
163  *  \param ioIndiv1   First individual to mate.
164  *  \param ioContext1 Evolutionary context of the first individual.
165  *  \param ioIndiv2   Second individual to mate.
166  *  \param ioContext2 Evolutionary context of the second individual.
167  *  \return True if the individuals are effectively mated, false if not.
168  */
mate(Beagle::Individual & ioIndiv1,Beagle::Context & ioContext1,Beagle::Individual & ioIndiv2,Beagle::Context & ioContext2)169 bool Beagle::GA::CrossoverBlendFltVecOp::mate(Beagle::Individual& ioIndiv1,
170                                               Beagle::Context&    ioContext1,
171                                               Beagle::Individual& ioIndiv2,
172                                               Beagle::Context&    ioContext2)
173 {
174   Beagle_StackTraceBeginM();
175   unsigned int lNbGenotypes = minOf<unsigned int>(ioIndiv1.size(), ioIndiv2.size());
176   if(lNbGenotypes == 0) return false;
177 
178   Beagle_LogDebugM(
179     ioContext1.getSystem().getLogger(),
180     "crossover", "Beagle::GA::CrossoverBlendFltVec",
181     string("The first individual mated is (before real-valued GA blend crossover): ")+
182     ioIndiv1.serialize()
183   );
184   Beagle_LogDebugM(
185     ioContext1.getSystem().getLogger(),
186     "crossover", "Beagle::GA::CrossoverBlendFltVec",
187     string("The second individual mated is (before real-valued GA blend crossover): ")+
188     ioIndiv2.serialize()
189   );
190 
191   for(unsigned int i=0; i<lNbGenotypes; ++i) {
192     GA::FloatVector::Handle lFloatVector1 = castHandleT<FloatVector>(ioIndiv1[i]);
193     GA::FloatVector::Handle lFloatVector2 = castHandleT<FloatVector>(ioIndiv2[i]);
194     const unsigned int lSize = minOf<unsigned int>(lFloatVector1->size(), lFloatVector2->size());
195     for(unsigned int j=0; j<lSize; ++j) {
196       const double lMaxVal = j<mMaxValue->size() ? (*mMaxValue)[j] : mMaxValue->back();
197       const double lMinVal = j<mMinValue->size() ? (*mMinValue)[j] : mMinValue->back();
198       const double lIncVal = j<mIncValue->size() ? (*mIncValue)[j] : mIncValue->back();
199       const double lU_i = ioContext1.getSystem().getRandomizer().rollUniform();
200       const double lGamma_i = ((1.0+2.0*mAlpha->getWrappedValue())*lU_i)-mAlpha->getWrappedValue();
201       const double lX1_i = (*lFloatVector1)[j];
202       const double lX2_i = (*lFloatVector2)[j];
203       (*lFloatVector1)[j] = ((1.0-lGamma_i)*lX1_i) + (lGamma_i*lX2_i);
204       (*lFloatVector2)[j] = (lGamma_i*lX1_i) + ((1.0-lGamma_i)*lX2_i);
205       if(lIncVal!=0.0) {
206         (*lFloatVector1)[j] = lIncVal * round((*lFloatVector1)[j] / lIncVal);
207         (*lFloatVector2)[j] = lIncVal * round((*lFloatVector2)[j] / lIncVal);
208       }
209       if((*lFloatVector1)[j] > lMaxVal) (*lFloatVector1)[j] = lMaxVal;
210       if((*lFloatVector1)[j] < lMinVal) (*lFloatVector1)[j] = lMinVal;
211       if((*lFloatVector2)[j] > lMaxVal) (*lFloatVector2)[j] = lMaxVal;
212       if((*lFloatVector2)[j] < lMinVal) (*lFloatVector2)[j] = lMinVal;
213     }
214   }
215 
216   Beagle_LogDebugM(
217     ioContext1.getSystem().getLogger(),
218     "crossover", "Beagle::GA::CrossoverBlendFltVec",
219     string("The first individual mated is (after real-valued GA blend crossover): ")+
220     ioIndiv1.serialize()
221   );
222   Beagle_LogDebugM(
223     ioContext1.getSystem().getLogger(),
224     "crossover", "Beagle::GA::CrossoverBlendFltVec",
225     string("The second individual mated is (after real-valued GA blend crossover): ")+
226     ioIndiv2.serialize()
227   );
228 
229   return true;
230   Beagle_StackTraceEndM("bool GA::CrossoverBlendFltVecOp::mate(Individual& ioIndiv1, Context& ioContext1, Individual& ioIndiv2, Context& ioContext2)");
231 }
232 
233 
234