freESCMAMutation.txx

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   F.R.E.E. - flexible registration evaluation engine
00004   Version:   v.1.0.0
00005   Date:      $Date: 2006/09/01 12:00:00 $
00006   Module:    $RCSfile: freESCMAMutation.txx,v $
00007   Language:  C++
00008 
00009 
00010 
00011   Copyright (c) 2007 Ralf o Floca (Department of Medical Informatics,
00012   Institute for Medical Biometry and Informatics, University of Heidelberg,
00013   Germany). All rights reserved.
00014   See FREECopyright.txt or http://www.mi.med.uni-hd.de/free/copyright.htm
00015   for details.
00016 
00017      This software is distributed WITHOUT ANY WARRANTY; without even 
00018      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00019      PURPOSE.  See the above copyright notices for more information.
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   //calculate Mu_eff
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   //calculate Mu_cov;
00089   m_Mu_cov = 1.0 / m_Mu_eff;
00090 
00091   //calculate C_c;
00092   m_C_c = 4.0 / ( 4.0+lN);
00093 
00094   //calculate C_cov;
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   //calculate C_sigma;
00099   m_C_sigma = (m_Mu_eff+2.0) / (lN+m_Mu_eff+3.0);
00100 
00101   //calculate D_sigma;
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   //get any individual of the population to determine the number of objective values
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   //no initialze the members properly
00140   m_CurMatrix = MatrixType(m_ObjectiveCount,m_ObjectiveCount,0.0);
00141   m_CurMatrix.fill_diagonal(1.0);
00142 
00143   m_CurCentroid = ComputeCentroid(population); //VectorType(m_ObjectiveCount,0.0);
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   //compute the next strategic paremter (that will be used for the upcoming individuals
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   //store the newly computed parameters as new current paremeters
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   //get the strategic parameters
00201   ConvertStrategicPopulationParametersToMember(pPopulation->StrategicParameters());
00202 
00203   //decompose covariance matrix
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   //get random vector;
00211   VectorType z = GetRandomVector(m_ObjectiveCount);
00212 
00213   //compute mutation vector
00214   VectorType mutationVector = z.pre_multiply(d);
00215   mutationVector = mutationVector.pre_multiply(b);
00216   mutationVector = mutationVector*m_CurStepLength;
00217 
00218   //mutate individual
00219   for (unsigned long index = 0; index<pIndividual->ObjectiveParameters().size(); index++)
00220   {
00221     typename IndividualType::ObjectiveParameterType mutatedParameter = (pIndividual->ObjectiveParameters())[index];
00222 
00223     //mutate parameter
00224     mutatedParameter += mutationVector[index] / this->m_GeneralObjectiveScales[index];
00225     
00226     //set new value;
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   //number of parameters stored; 1 marix, 3 vectors and 1 scalar
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   //load covariance matrix
00247   for (MatrixType::iterator pos = m_CurMatrix.begin(); pos != m_CurMatrix.end(); ++pos)
00248   {
00249     *pos = (ownParameters[lCurParamIndex])->GetValue();
00250     lCurParamIndex++;
00251   }
00252 
00253   //load current centroid
00254   for (VectorType::iterator pos = m_CurCentroid.begin(); pos != m_CurCentroid.end(); ++pos)
00255   {
00256     *pos = (ownParameters[lCurParamIndex])->GetValue();
00257     lCurParamIndex++;
00258   }
00259 
00260   //load current evolution path vector for covariance matrix
00261   for (VectorType::iterator pos = m_CurMatrixPath.begin(); pos != m_CurMatrixPath.end(); ++pos)
00262   {
00263     *pos = (ownParameters[lCurParamIndex])->GetValue();
00264     lCurParamIndex++;
00265   }
00266 
00267   //load current evolution path vector for step length
00268   for (VectorType::iterator pos = m_CurStepPath.begin(); pos != m_CurStepPath.end(); ++pos)
00269   {
00270     *pos = (ownParameters[lCurParamIndex])->GetValue();
00271     lCurParamIndex++;
00272   }
00273 
00274   //load current evolution step length
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   //Store covariance matrix
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   //Store current centroid
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   //Store current evolution path vector for covariance matrix
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   //Store current evolution path vector for step length control
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   //Store current step length
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   //remove scaling of parameters for internal computation.
00365   //The rescaling will be done when mutating new individual.
00366   //pathes, steplength and covariance matrix are without scale
00367   //TODO: Better option would be to change the estimation of
00368   //n-dimensional variate in the step length computation to a
00369   //scaled version.
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   //rank one update
00386   MatrixType rankOneUpdate = outer_product(nextMatrixPath,nextMatrixPath);
00387   
00388   //compute rank my update
00389     //find all new individuals of the last generation
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     //calculate matrix
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       //remove scaling of parameters for internal computation.
00411       //The rescaling will be done when mutating new individual.
00412       //pathes, steplength and covariance matrix are without scale
00413       //TODO: Better option would be to change the estimation of
00414       //n-dimensional variate in the step length computation to a
00415       //scaled version.
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   //compute C^-1/2 to scale the path independently from the direction
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   //remove scaling of parameters for internal computation.
00449   //The rescaling will be done when mutating new individual.
00450   //pathes, steplength and covariance matrix are without scale
00451   //TODO: Better option would be to change the estimation of
00452   //n-dimensional variate in the step length computation to a
00453   //scaled version.
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   //damping value d_sigma (see Hansen) is skipped because it is nearly 1
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 } // end of namespace ES
00512 } // end of namespace FREE
00513 
00514 #endif

Generated at Sat Oct 13 15:53:27 2007 for f.r.e.e. - Flexible Registration and Evaluation Engine by doxygen 1.5.3 written by Dimitri van Heesch, © 1997-2000