00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _freESCMAMutation_txx
00023 #define _freESCMAMutation_txx
00024
00025 #include "freESCMAMutation.h"
00026
00027 #include "vnl/vnl_sample.h"
00028 #include "vnl/algo/vnl_symmetric_eigensystem.h"
00029
00030 namespace FREE
00031 {
00032 namespace ES
00033 {
00034
00035 template <class TIndividual>
00036 CMAMutation<TIndividual>
00037 ::CMAMutation()
00038 {
00039 m_Sigma = 1.0;
00040 m_Mu_eff = 1;
00041 m_C_c = 0.8;
00042 m_C_cov = 0.0;
00043 m_C_sigma = 0.6;
00044
00045 m_Mu = 1;
00046
00047 m_ObjectiveCount = 1;
00048 m_CurMatrix = MatrixType(1,1,0.0);
00049 m_CurCentroid = VectorType(1,0.0);
00050 m_CurMatrixPath = VectorType(1,0.0);
00051 m_CurStepPath = VectorType(1,0.0);
00052 m_CurStepLength = 1.0;
00053
00054 m_SearchPointSelector = 0;
00055 m_CentroidCombinator = 0;
00056 m_RandomGenerator = VariateGeneratorType::New();
00057 }
00058
00059 template <class TIndividual>
00060 void
00061 CMAMutation<TIndividual>
00062 ::InitializeControlValues_Mean(const long& lN)
00063 {
00064 m_Mu_cov = 1/m_Mu_eff;
00065
00066 m_C_c = 1.0/lN;
00067 m_C_cov = (std::min<double>(m_Mu_eff,lN*lN)) / (lN*lN);
00068 m_C_sigma = 1.0/lN;
00069 m_D_sigma = 1.0;
00070 };
00071
00072 template <class TIndividual>
00073 void
00074 CMAMutation<TIndividual>
00075 ::InitializeControlValues_Hansen(const long& lMu, const long& lN)
00076 {
00077 if (m_CentroidCombinator.IsNull()) itkExceptionMacro(<<"Error. Cannot initialize control values. No centroid combinator defined.");
00078 typename CentroidCombinatorType::WeightVectorType weights = m_CentroidCombinator->GetWeights(lMu);
00079
00080
00081 m_Mu_eff = 0;
00082 for (typename CentroidCombinatorType::WeightVectorType::iterator pos = weights.begin(); pos != weights.end(); ++pos)
00083 {
00084 m_Mu_eff += (*pos) * (*pos);
00085 }
00086 m_Mu_eff = 1.0 / m_Mu_eff;
00087
00088
00089 m_Mu_cov = 1.0 / m_Mu_eff;
00090
00091
00092 m_C_c = 4.0 / ( 4.0+lN);
00093
00094
00095 m_C_cov = m_Mu_cov * (2.0/((lN+sqrt(2.0))*(lN+sqrt(2.0))));
00096 m_C_cov += (1.0-m_Mu_cov)*std::min(1.0,(2*m_Mu_eff - 1.0)/(((lN+2)*(lN+2))+m_Mu_eff));
00097
00098
00099 m_C_sigma = (m_Mu_eff+2.0) / (lN+m_Mu_eff+3.0);
00100
00101
00102 m_D_sigma = 1+ 2*std::max<double>(0,sqrt((m_Mu_eff-1.0) / (lN+1.0)) - 1.0) + m_C_sigma;
00103 };
00104
00105
00106 template <class TIndividual>
00107 void
00108 CMAMutation<TIndividual>
00109 ::SetSearchPointSelector( SearchPointSelectorType * pSearchPointSelector )
00110 {
00111 if (m_SearchPointSelector.GetPointer()!=pSearchPointSelector)
00112 {
00113 this->Modified();
00114 m_SearchPointSelector = pSearchPointSelector;
00115 }
00116 };
00117
00118 template <class TIndividual>
00119 void
00120 CMAMutation<TIndividual>
00121 ::SetCentroidCombinator( CentroidCombinatorType * pCentroidCombinator )
00122 {
00123 if (m_CentroidCombinator.GetPointer()!=pCentroidCombinator)
00124 {
00125 this->Modified();
00126 m_CentroidCombinator = pCentroidCombinator;
00127 }
00128 };
00129
00130 template <class TIndividual>
00131 void
00132 CMAMutation<TIndividual>
00133 ::RegisterStrategicPopulationParameters(PopulationType& population) const
00134 {
00135
00136 if (population.Size()<1) itkExceptionMacro(<<"Error. Need at least one individual in the population to determine number of objectiv values in order to properly register strategic population parameters.");
00137 m_ObjectiveCount = population.ElementAt(0)->ObjectiveParameters().size();
00138
00139
00140 m_CurMatrix = MatrixType(m_ObjectiveCount,m_ObjectiveCount,0.0);
00141 m_CurMatrix.fill_diagonal(1.0);
00142
00143 m_CurCentroid = ComputeCentroid(population);
00144
00145 m_CurMatrixPath = VectorType(m_ObjectiveCount,0.0);
00146 m_CurStepPath = VectorType(m_ObjectiveCount,0.0);
00147
00148 m_CurStepLength = m_Sigma;
00149
00150 ConvertMemberToStrategicPopulationParameters(population.StrategicParameters());
00151 };
00152
00153 template <class TIndividual>
00154 void
00155 CMAMutation<TIndividual>
00156 ::MutateStrategicPopulationParameters(PopulationType& population) const
00157 {
00158 ConvertStrategicPopulationParametersToMember(population.StrategicParameters());
00159
00160
00161 VectorType nextCentroid = ComputeCentroid(population);
00162
00163 VectorType nextMatrixPath = ComputeMatrixPath(m_CurMatrixPath, m_CurStepLength, m_CurCentroid, nextCentroid);
00164
00165 MatrixType nextCovMatrix = ComputeMatrix(m_CurMatrix, nextMatrixPath, m_CurStepLength, m_CurCentroid, population);
00166
00167 VectorType nextStepPath = ComputeStepPath(m_CurStepPath, m_CurMatrix, m_CurStepLength, m_CurCentroid, nextCentroid);
00168
00169 double nextStepLength = ComputeStepLength(m_CurStepLength, nextStepPath);
00170
00171
00172 m_CurCentroid = nextCentroid;
00173 m_CurMatrixPath = nextMatrixPath;
00174 m_CurMatrix = nextCovMatrix;
00175 m_CurStepPath = nextStepPath;
00176 m_CurStepLength = nextStepLength;
00177
00178 ConvertMemberToStrategicPopulationParameters(population.StrategicParameters());
00179 };
00180
00181 template <class TIndividual>
00182 double
00183 CMAMutation<TIndividual>
00184 ::MutateValue(const double& value)
00185 {
00186 itkExceptionMacro(<<"Functionality not yet implemented.");
00187 return 0;
00188 };
00189
00190 template <class TIndividual>
00191 void
00192 CMAMutation<TIndividual>
00193 ::MutateObjectivParameters(IndividualType* pIndividual, PopulationType* pPopulation) const
00194 {
00195 if (!pIndividual) itkExceptionMacro(<<"Error. Passed individual is Null.");
00196 if (!pPopulation) itkExceptionMacro(<<"Error. Passed population is Null.");
00197 if (pIndividual->ObjectiveParameters().size() != m_ObjectiveCount) itkExceptionMacro(<<"Error. Passed individual has not the expected number of objective parameters. Found: "<<pIndividual->ObjectiveParameters().size()<<"; expected: "<<this->m_ObjectiveCount);
00198 if (this->m_ObjectiveCount!=this->m_GeneralObjectiveScales.size()) itkExceptionMacro(<<"Error. Number of objective parameters and global scales are not equal. Ensure that scales have been set properly. Objective count:" << this->m_ObjectiveCount <<"; objective scales count: "<< this->m_GeneralObjectiveScales.size());
00199
00200
00201 ConvertStrategicPopulationParametersToMember(pPopulation->StrategicParameters());
00202
00203
00204 if (!m_CurMatrix.is_finite()) itkExceptionMacro(<<"Error. Current covariance matrix is not finite. Matrix: "<<m_CurMatrix);
00205 vnl_symmetric_eigensystem< double > eigensystem(m_CurMatrix);
00206
00207 MatrixType b = eigensystem.V;
00208 MatrixType d = (eigensystem.D.asMatrix())*(-1);
00209
00210
00211 VectorType z = GetRandomVector(m_ObjectiveCount);
00212
00213
00214 VectorType mutationVector = z.pre_multiply(d);
00215 mutationVector = mutationVector.pre_multiply(b);
00216 mutationVector = mutationVector*m_CurStepLength;
00217
00218
00219 for (unsigned long index = 0; index<pIndividual->ObjectiveParameters().size(); index++)
00220 {
00221 typename IndividualType::ObjectiveParameterType mutatedParameter = (pIndividual->ObjectiveParameters())[index];
00222
00223
00224 mutatedParameter += mutationVector[index] / this->m_GeneralObjectiveScales[index];
00225
00226
00227 (pIndividual->ObjectiveParameters())[index] = mutatedParameter;
00228 }
00229 };
00230
00231 template <class TIndividual>
00232 void
00233 CMAMutation<TIndividual>
00234 ::ConvertStrategicPopulationParametersToMember(PopulationStrategicParametersType& parameters) const
00235 {
00236 typename PopulationType::StrategicParametersType::SelectedParametersType ownParameters =
00237 parameters.GetStrategicParameters(this->GetNameOfClass());
00238
00239
00240 long lNeededParameterCount = (m_ObjectiveCount*m_ObjectiveCount)+3*m_ObjectiveCount+1;
00241
00242 if (ownParameters.size()!=lNeededParameterCount) throwExceptionMacro("Error. Invalid number of strategic parameters (one matrix (n*n), 3 vectors (n) and 1 scalar needed; n: number of objective values). Ensure that strategic parameters are properly registered. Expected parameter count:" << lNeededParameterCount <<"; current parameter count: "<< ownParameters.size());
00243
00244 long lCurParamIndex = 0;
00245
00246
00247 for (MatrixType::iterator pos = m_CurMatrix.begin(); pos != m_CurMatrix.end(); ++pos)
00248 {
00249 *pos = (ownParameters[lCurParamIndex])->GetValue();
00250 lCurParamIndex++;
00251 }
00252
00253
00254 for (VectorType::iterator pos = m_CurCentroid.begin(); pos != m_CurCentroid.end(); ++pos)
00255 {
00256 *pos = (ownParameters[lCurParamIndex])->GetValue();
00257 lCurParamIndex++;
00258 }
00259
00260
00261 for (VectorType::iterator pos = m_CurMatrixPath.begin(); pos != m_CurMatrixPath.end(); ++pos)
00262 {
00263 *pos = (ownParameters[lCurParamIndex])->GetValue();
00264 lCurParamIndex++;
00265 }
00266
00267
00268 for (VectorType::iterator pos = m_CurStepPath.begin(); pos != m_CurStepPath.end(); ++pos)
00269 {
00270 *pos = (ownParameters[lCurParamIndex])->GetValue();
00271 lCurParamIndex++;
00272 }
00273
00274
00275 m_CurStepLength = (ownParameters[lCurParamIndex])->GetValue();
00276 };
00277
00278 template <class TIndividual>
00279 void
00280 CMAMutation<TIndividual>
00281 ::ConvertMemberToStrategicPopulationParameters(PopulationStrategicParametersType& parameters) const
00282 {
00283 parameters.DeleteSelectedStrategicParameters(parameters.GetStrategicIDs(this->GetNameOfClass()));
00284
00285 typedef typename IndividualType::StrategicParameterPointer IndividualStrategicParameterPointer;
00286
00287 for (MatrixType::const_iterator pos = m_CurMatrix.begin(); pos != m_CurMatrix.end(); ++pos)
00288 {
00289 IndividualStrategicParameterPointer parameter = IndividualType::StrategicParameterType::New();
00290 parameter->SetValue(*pos);
00291 parameter->SetHandling(IndividualType::StrategicParameterType::HDynamic);
00292 parameter->SetOrigin(this->GetNameOfClass());
00293 parameters.push_back(parameter);
00294 }
00295
00296
00297 for (VectorType::const_iterator pos = m_CurCentroid.begin(); pos != m_CurCentroid.end(); ++pos)
00298 {
00299 IndividualStrategicParameterPointer parameter = IndividualType::StrategicParameterType::New();
00300 parameter->SetValue(*pos);
00301 parameter->SetHandling(IndividualType::StrategicParameterType::HDynamic);
00302 parameter->SetOrigin(this->GetNameOfClass());
00303 parameters.push_back(parameter);
00304 }
00305
00306
00307 for (VectorType::const_iterator pos = m_CurMatrixPath.begin(); pos != m_CurMatrixPath.end(); ++pos)
00308 {
00309 IndividualStrategicParameterPointer parameter = IndividualType::StrategicParameterType::New();
00310 parameter->SetValue(*pos);
00311 parameter->SetHandling(IndividualType::StrategicParameterType::HDynamic);
00312 parameter->SetOrigin(this->GetNameOfClass());
00313 parameters.push_back(parameter);
00314 }
00315
00316
00317 for (VectorType::const_iterator pos = m_CurStepPath.begin(); pos != m_CurStepPath.end(); ++pos)
00318 {
00319 IndividualStrategicParameterPointer parameter = IndividualType::StrategicParameterType::New();
00320 parameter->SetValue(*pos);
00321 parameter->SetHandling(IndividualType::StrategicParameterType::HDynamic);
00322 parameter->SetOrigin(this->GetNameOfClass());
00323 parameters.push_back(parameter);
00324 }
00325
00326
00327 IndividualStrategicParameterPointer parameter = IndividualType::StrategicParameterType::New();
00328 parameter->SetValue(m_CurStepLength);
00329 parameter->SetHandling(IndividualType::StrategicParameterType::HDynamic);
00330 parameter->SetOrigin(this->GetNameOfClass());
00331 parameters.push_back(parameter);
00332 };
00333
00334 template <class TIndividual>
00335 typename CMAMutation<TIndividual>::VectorType
00336 CMAMutation<TIndividual>::
00337 ComputeCentroid(PopulationType& rPopulation) const
00338 {
00339 if (m_SearchPointSelector.IsNull()) itkExceptionMacro(<<"Error. Cannot compute centroid. No point selector defined.");
00340 if (m_CentroidCombinator.IsNull()) itkExceptionMacro(<<"Error. Cannot compute centroid. No centroid combinator defined.");
00341
00342 typedef typename SearchPointSelectorType::ParentSelectionType PointSelection;
00343 PointSelection selection = m_SearchPointSelector->Select(rPopulation);
00344
00345 m_Mu = selection.size();
00346
00347 IndividualPointer centroidIndividual = m_CentroidCombinator->Recombine(selection);
00348
00349 VectorType centroid = ConvertObjectivParameterToVector(centroidIndividual.GetPointer());
00350
00351 return centroid;
00352 };
00353
00354 template <class TIndividual>
00355 typename CMAMutation<TIndividual>::VectorType
00356 CMAMutation<TIndividual>::
00357 ComputeMatrixPath(const VectorType& curMatrixPath, double curStepLength, const VectorType& curCentroid, const VectorType& nextCentroid) const
00358 {
00359 VectorType nextPath = (1 - m_C_c)*curMatrixPath;
00360 double temp = sqrt(m_C_c*(2-m_C_c)*m_Mu_eff);
00361
00362 VectorType diff = nextCentroid - curCentroid;
00363
00364
00365
00366
00367
00368
00369
00370 for (unsigned long index = 0; index<diff.size(); index++)
00371 {
00372 diff[index] = diff[index] * this->m_GeneralObjectiveScales[index];
00373 }
00374
00375 nextPath = nextPath + temp * (diff / curStepLength);
00376
00377 return nextPath;
00378 };
00379
00380 template <class TIndividual>
00381 typename CMAMutation<TIndividual>::MatrixType
00382 CMAMutation<TIndividual>::
00383 ComputeMatrix(const MatrixType& curMatrix, const VectorType& nextMatrixPath, double curStepLength, const VectorType& curCentroid, const PopulationType& population) const
00384 {
00385
00386 MatrixType rankOneUpdate = outer_product(nextMatrixPath,nextMatrixPath);
00387
00388
00389
00390 MatrixType rankMuUpdate(m_ObjectiveCount,m_ObjectiveCount,0.0);
00391
00392 typedef std::vector<const TIndividual*> SelectedIndividualsType;
00393 SelectedIndividualsType newIndividuals;
00394 for (typename PopulationType::const_iterator pos = population.begin(); pos!=population.end(); ++pos)
00395 {
00396 if ((*pos)->GetGenerationID()==population.GetGenerationID())
00397 {
00398 newIndividuals.push_back((*pos).GetPointer());
00399 }
00400 }
00401
00402
00403 if (newIndividuals.size())
00404 {
00405 for (typename SelectedIndividualsType::iterator pos = newIndividuals.begin(); pos!=newIndividuals.end(); ++pos)
00406 {
00407 VectorType individual = ConvertObjectivParameterToVector(*pos);
00408 VectorType variance = curStepLength*(individual - curCentroid);
00409
00410
00411
00412
00413
00414
00415
00416 for (unsigned long index = 0; index<variance.size(); index++)
00417 {
00418 variance[index] = variance[index] * this->m_GeneralObjectiveScales[index];
00419 }
00420
00421 rankMuUpdate = rankMuUpdate + outer_product(variance, variance);
00422 }
00423 rankMuUpdate = rankMuUpdate*(1/newIndividuals.size());
00424 }
00425
00426 MatrixType nextMatrix = (1-m_C_cov)*curMatrix + ((m_C_cov*m_Mu_cov)*rankOneUpdate) + (m_C_cov*(1-m_Mu_cov)*rankMuUpdate);
00427
00428 return nextMatrix;
00429 };
00430
00431 template <class TIndividual>
00432 typename CMAMutation<TIndividual>::VectorType
00433 CMAMutation<TIndividual>::
00434 ComputeStepPath(const VectorType& curStepPath,const MatrixType& curMatrix, double curStepLength, const VectorType& curCentroid, const VectorType& nextCentroid) const
00435 {
00436 VectorType nextPath = (1 - m_C_sigma)*curStepPath;
00437 double temp = sqrt(m_C_sigma*(2-m_C_sigma)*m_Mu_eff);
00438
00439
00440 vnl_symmetric_eigensystem< double > eigensystem(curMatrix);
00441
00442 MatrixType B = eigensystem.V;
00443 MatrixType D_inv = (eigensystem.D.asMatrix())*(-1);
00444 MatrixType B_inv = B.transpose();
00445
00446 VectorType diff = nextCentroid - curCentroid;
00447
00448
00449
00450
00451
00452
00453
00454 for (unsigned long index = 0; index<diff.size(); index++)
00455 {
00456 double debugCheck = diff[index] * this->m_GeneralObjectiveScales[index];
00457 diff[index] = debugCheck;
00458 }
00459
00460 nextPath = nextPath + temp * (B * D_inv * B_inv) * (diff / curStepLength);
00461
00462 return nextPath;
00463 };
00464
00465 template <class TIndividual>
00466 double
00467 CMAMutation<TIndividual>::
00468 ComputeStepLength(double curStepLength, const VectorType& nextStepPath) const
00469 {
00470 double estimatedN = sqrt((double)m_ObjectiveCount)*(1- (1/(4*m_ObjectiveCount)) + (1/(21*m_ObjectiveCount*m_ObjectiveCount)));
00471
00472 double debugCheck = nextStepPath.magnitude();
00473
00474 double nextStepLength = curStepLength * exp((m_C_sigma/m_D_sigma)*((nextStepPath.magnitude()/estimatedN) -1));
00475
00476 return nextStepLength;
00477 };
00478
00479 template <class TIndividual>
00480 typename CMAMutation<TIndividual>::VectorType
00481 CMAMutation<TIndividual>::
00482 ConvertObjectivParameterToVector(const IndividualType* pIndividual) const
00483 {
00484 if (!pIndividual) itkExceptionMacro(<<"Error. Cannot convert objective individual parameters; passed null pointer.");
00485
00486 VectorType vector = VectorType(pIndividual->ObjectiveParameters().size(),0.0);
00487
00488 for (int index = 0; index < vector.size(); index++)
00489 {
00490 vector[index] += (pIndividual->ObjectiveParameters())[index];
00491 }
00492 return vector;
00493 };
00494
00495 template <class TIndividual>
00496 typename CMAMutation<TIndividual>::VectorType
00497 CMAMutation<TIndividual>::
00498 GetRandomVector(unsigned long lSize) const
00499 {
00500 VectorType z = VectorType(lSize,0.0);
00501
00502 for (unsigned long index = 0; index<lSize; index++)
00503 {
00504 z[index] = m_RandomGenerator->GetVariate();
00505 }
00506
00507 return z;
00508 };
00509
00510
00511 }
00512 }
00513
00514 #endif