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