freEvolutionaryStrategyOptimizerController.cxx

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: freEvolutionaryStrategyOptimizerController.cxx,v $
00007   Language:  C++
00008 
00009 
00010   Copyright (c) 2007 Ralf o Floca (Department of Medical Informatics,
00011   Institute for Medical Biometry and Informatics, University of Heidelberg,
00012   Germany). All rights reserved.
00013   See FREECopyright.txt or http://www.mi.med.uni-hd.de/free/copyright.htm
00014   for details.
00015 
00016      This software is distributed WITHOUT ANY WARRANTY; without even 
00017      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00018      PURPOSE.  See the above copyright notices for more information.
00019 
00020 =========================================================================*/
00021 
00022 #include "freEvolutionaryStrategyOptimizerController.h"
00023 #include "freExceptions.h"
00024 
00025 #include "freESParentSelectorControllerBase.h"
00026 #include "freESRecombinatorControllerBase.h"
00027 #include "freESMutationControllerBase.h"
00028 #include "freESSelectionControllerBase.h"
00029 
00030 namespace FREE
00031 {
00032 
00036 
00037 
00038 DefineParameterMacro(EvolutionaryStrategyOptimizerController,MutateIntitialPopulation,"MutateIntitialPopulation","Indicates if the starting population will be mutated one time befor beginning the evolutionary process. Usefull if the population is generated automatically.");
00039 DefineParameterMacro(EvolutionaryStrategyOptimizerController,IntitialPopulation,"IntitialPopulation","The starting population for the optimization process. Every layer is one individuals, the values are the objective parameters. If the initial population is empty the initial position of the transform will be used to generate the starting population.");
00040 DefineParameterMacro(EvolutionaryStrategyOptimizerController,NumberOfParents,"NumberOfParents","Number of parents in every generation. Equals the term Mu in evolutionary strategies.");
00041 DefineParameterMacro(EvolutionaryStrategyOptimizerController,NumberOfChildren,"NumberOfChildren","Number of parents in every generation. Equals the term lambda in evolutionary strategies.");
00042 DefineParameterMacro(EvolutionaryStrategyOptimizerController,Threshold,"Threshold","Threshold for the best individual in the population. If this treshold is reached, the optimization process will stop.");
00043 
00044 EvolutionaryStrategyOptimizerController::
00045 EvolutionaryStrategyOptimizerController()
00046 {
00047   //Profile settings
00048   this->UpdateControllerID(ControllerID::EvolutionaryStrategyOptimizerController);
00049   this->m_Description = "Optimizes by an evolutionary strategy search approach.";
00050 };
00051 
00052 void
00053 EvolutionaryStrategyOptimizerController::
00054 GenerateProfile(CtrlProfile::ControllerProfile& profile,
00055                 const SessionComponentCache* pComponentCache,
00056                 bool bRegardOldSetup) const
00057 {
00058   Superclass::GenerateProfile(profile,pComponentCache,bRegardOldSetup);
00059 
00060   //Parameters
00061   profile.Parameters().AddParameter(cParam_MutateIntitialPopulation,CtrlProfile::Parameter::PVTBool,cParamDsc_MutateIntitialPopulation,1,"false");
00062   profile.Parameters().AddParameter(cParam_IntitialPopulation,CtrlProfile::Parameter::PVTDouble,cParamDsc_IntitialPopulation,1,"0",-1);
00063   profile.Parameters().AddParameter(cParam_Threshold,CtrlProfile::Parameter::PVTDouble,cParam_Threshold,1,"0.0001",-1,true);
00064   profile.Parameters().AddParameter(cParam_NumberOfParents,Parameter::PVTULong,cParamDsc_NumberOfParents,1,"2",-1,true);
00065   profile.Parameters().AddParameter(cParam_NumberOfChildren,Parameter::PVTULong,cParamDsc_NumberOfChildren,1,"5",-1,true);
00066 
00067   //Subcomponents
00068   profile.SubComponents().AddSubComponent("ParentSelector",1,csUndefinedController,"Selection of the parents for the generation of a new indivudual.");
00069   profile.SubComponents().AddSubComponent("Recombinator",1,csUndefinedController,"Recombination of selected parents to a new individual.");
00070   profile.SubComponents().AddSubComponent("Mutation",1,csUndefinedController,"Mutation of new individuals.");
00071   profile.SubComponents().AddSubComponent("Selection",1,csUndefinedController,"Selection of the whole population, including the new individual, to generate the next generation.");
00072 
00073   //Requirements
00074         CtrlProfile::ProfileOption* pOption;
00075 
00076     //parent selector
00077         pOption = profile.Requirements().AddRequirement("ParentSelector")->AddProfileOption();
00078         pOption->Inheritance().AddAncestor(ControllerID::ESParentSelectorControllerBase);
00079         pOption->CheckForInheritance();
00080 
00081     //recombinator
00082         pOption = profile.Requirements().AddRequirement("Recombinator")->AddProfileOption();
00083         pOption->Inheritance().AddAncestor(ControllerID::ESRecombinatorControllerBase);
00084         pOption->CheckForInheritance();
00085 
00086     //mutation
00087         pOption = profile.Requirements().AddRequirement("Mutation")->AddProfileOption();
00088         pOption->Inheritance().AddAncestor(ControllerID::ESMutationControllerBase);
00089         pOption->CheckForInheritance();
00090 
00091     //selection
00092         pOption = profile.Requirements().AddRequirement("Selection")->AddProfileOption();
00093         pOption->Inheritance().AddAncestor(ControllerID::ESSelectionControllerBase);
00094         pOption->CheckForInheritance();
00095 };
00096 
00097 GenericComponentType*
00098 EvolutionaryStrategyOptimizerController::
00099 GetSubComponentCasted(ComponentType* pMainComponent, const ComponentID& compID,
00100                       SessionComponentCache* pMainComponentCache) const
00101 {
00102         if (compID == "ParentSelector") return pMainComponent->GetParentSelector();
00103         if (compID == "Recombinator") return pMainComponent->GetRecombinator();
00104         if (compID == "Mutation") return pMainComponent->GetMutation();
00105         if (compID == "Selection") return pMainComponent->GetSelection();
00106         return Superclass::GetSubComponentCasted(pMainComponent, compID, pMainComponentCache);
00107 }; 
00108 
00109 void
00110 EvolutionaryStrategyOptimizerController::
00111 SetSubComponentCasted(GenericComponentType* pSubComponent,
00112                                                                                                                                                  ComponentType* pMainComponent,
00113                                                                                                                                                  const ComponentID compID,
00114                                      SessionComponentCache* pMainComponentCache) const
00115 {
00116         if (compID == "ParentSelector") pMainComponent->SetParentSelector(dynamic_cast<ComponentType::ParentSelectorType*>(pSubComponent));
00117         if (compID == "Recombinator") pMainComponent->SetRecombinator(dynamic_cast<ComponentType::RecombinatorType*>(pSubComponent));
00118         if (compID == "Mutation") pMainComponent->SetMutation(dynamic_cast<ComponentType::MutationType*>(pSubComponent));
00119         if (compID == "Selection") pMainComponent->SetSelection(dynamic_cast<ComponentType::SelectionType*>(pSubComponent));
00120   else Superclass::SetSubComponentCasted(pSubComponent, pMainComponent, compID, pMainComponentCache);
00121 };
00122 
00123 void
00124 EvolutionaryStrategyOptimizerController::
00125 ActualizeMainComponent(ComponentType* pMainComponent,
00126                        SessionComponentCache* pComponentCache, SessionInfo* pSessionInfo,
00127                                                                                          const unsigned int& iActLevel) const
00128 {
00129   Superclass::ActualizeMainComponent(pMainComponent, pComponentCache,
00130                                      pSessionInfo, iActLevel);
00131 
00132   bool bMutateIntitialPopulation;
00133   double dThreshold;
00134   unsigned long lNumberOfParents;
00135   unsigned long lNumberOfChildren;
00136 
00137   try
00138   {
00139     SessionAccessor::GetParameterValue(pComponentCache,cParam_MutateIntitialPopulation,bMutateIntitialPopulation,0,iActLevel,true);
00140     SessionAccessor::GetParameterValue(pComponentCache,cParam_Threshold,dThreshold,0,iActLevel,true);
00141     SessionAccessor::GetParameterValue(pComponentCache,cParam_NumberOfParents,lNumberOfParents,0,iActLevel,true);
00142     SessionAccessor::GetParameterValue(pComponentCache,cParam_NumberOfChildren,lNumberOfChildren,0,iActLevel,true);
00143   }
00144   catchAllNPassMacro("Error while retrieving parameter values.");
00145 
00146   pMainComponent->SetMutateIntitialPopulation(bMutateIntitialPopulation);
00147   pMainComponent->SetThreshold(dThreshold);
00148   pMainComponent->SetNumberOfParents(lNumberOfParents);
00149   pMainComponent->SetNumberOfChildren(lNumberOfChildren);
00150 
00151   Parameter::Pointer smpInitialPopulation = SessionAccessor::GetParameter(pComponentCache, cParam_IntitialPopulation);
00152 
00153   if (smpInitialPopulation.IsNull()) throwCtrlExceptionMacro("","Error; cannot find parameter for initial population");
00154 
00155   if (smpInitialPopulation->LayerCount()>0)
00156   {
00157     /*there is an initial population*/
00158     if (smpInitialPopulation->LayerCount()!=lNumberOfParents) throwCtrlExceptionMacro("","Error; size of initial population is not equal to number of parents per generation. Please check validity of setup. Parent number: "<< lNumberOfParents <<"; Size of initial population: "<< smpInitialPopulation->LayerCount());
00159   
00160     /*insert initial population */
00161 
00162     ComponentType::PopulationPointer population = ComponentType::PopulationType::New();
00163 
00164     population->Reserve(lNumberOfParents);
00165 
00166     for (unsigned long index = 0; index<smpInitialPopulation->LayerCount(); index++)
00167     {
00168       ParameterLayer* pLayer = smpInitialPopulation->GetParameterLayer(index);
00169       ComponentType::IndividualType::Pointer individual = ComponentType::IndividualType::New();
00170 
00171       for (unsigned long iPos = 0; iPos<pLayer->Size(); iPos++)
00172       {
00173         double dValue;
00174         pLayer->GetValue(dValue,iPos);
00175         individual->ObjectiveParameters().push_back(dValue);
00176       }
00177 
00178       individual->SetIndividualID(population->GenerateUniqueIndividualID());
00179       individual->SetGenerationID(population->GetGenerationID());
00180 
00181       population->InsertElement(index, individual);
00182     }
00183 
00184     pMainComponent->Initialize(*(population.GetPointer()));
00185   }
00186 
00187 
00188   Parameter::Pointer smpDirection = pComponentCache->GetParentCache()->Controller()->GetParameter(pComponentCache->GetParentCache(),OptimizerOwnerControllerInterface::cParam_MinimizeToOptimize);
00189   if (smpDirection.IsNull()) throwCtrlExceptionMacro("","Cannot retrieve optimization direction via optimizer owner. Parameter \"MinimizeToOptimize\" is unknown. Please ensure valid session and setup");
00190   bool bMinimize;
00191   smpDirection->GetParameterValue(bMinimize);
00192   pMainComponent->SetMaximize( !bMinimize);
00193 };
00194 
00195 void
00196 EvolutionaryStrategyOptimizerController::
00197 SetStatisticEntryMainComponent(StatisticEntry& rStatisticEntry,
00198                                              ComponentType* pMainComponent,
00199                                              SessionComponentCache* pMainComponentCache,
00200                                              SessionInfo* pSessionInfo,
00201                                              StatisticDictionary& rDictionary) const
00202 {
00203   Superclass::SetStatisticEntryMainComponent(rStatisticEntry,pMainComponent,pMainComponentCache,pSessionInfo,rDictionary);
00204   
00205   std::string sIDPath = pMainComponentCache->GetIDPath();
00206   StatisticValueDefinition* pValueDef = rDictionary.GetValueDefinitionByName(sIDPath, "ID");
00207   StatisticValueDefinition* pValueDef_Best = rDictionary.GetValueDefinitionByName(sIDPath, "BestFitness");
00208     
00209   if (!pValueDef) //Entry is not recorded yet, so do so.
00210   {
00211     pValueDef = rDictionary.AddValueDefinition(sIDPath,"ID","ID of an individual");
00212   }
00213 
00214   if (!pValueDef_Best) //Entry is not recorded yet, so do so.
00215   {
00216     pValueDef_Best = rDictionary.AddValueDefinition(sIDPath,"BestFitness","Best fitness value in this generation.");
00217     rDictionary.AddValueDefinition(sIDPath,"BestIndividual","Best individual in this generation.");
00218     rDictionary.AddValueDefinition(sIDPath,"BestFitnessEver","Best fitness value ever occured.");
00219     rDictionary.AddValueDefinition(sIDPath,"BestIndividualEver","Best individual ever occured.");
00220   }
00221 
00222   StatisticEntryDefinition* pEntryDef = rDictionary.GetEntryDefinitionByName(sIDPath, "NewChild");
00223     
00224   if (!pEntryDef) //Entry is not recorded yet, so do so.
00225   {
00226     pEntryDef = rDictionary.AddEntryDefinition(sIDPath,"NewChild",pMainComponentCache->GetControllerID(),"a new Child of this generation.");
00227     rDictionary.AddEntryDefinition(sIDPath,"Next Generation",pMainComponentCache->GetControllerID(),"IDs of the individuals that remain in the population.");
00228     rDictionary.AddEntryDefinition(sIDPath,"Victims",pMainComponentCache->GetControllerID(),"IDs of the individuals removed by the selection.");
00229   }
00230 
00231   /* get heritage map and use it when generating child info*/
00232   const ComponentType::HeritageMapType& parentSelections = pMainComponent->GetRecentParentSelections();
00233 
00234   /* generate new children info*/
00235   const ComponentType::PopulationPointer& children = pMainComponent->GetNewChildren();
00236   if (children.IsNotNull())
00237   {
00238     StatisticValueDefinition* pValueDef_Child = rDictionary.GetValueDefinitionByName(sIDPath, "Value");
00239     StatisticValueDefinition* pValueDef_Objective = rDictionary.GetValueDefinitionByName(sIDPath, "Objectiv #0");
00240     StatisticValueDefinition* pValueDef_Strategic = rDictionary.GetValueDefinitionByName(sIDPath, "Strategic #0");
00241     
00242     for (unsigned long index= 0; index<children->Size(); index++)
00243     {
00244       ComponentType::IndividualPointer child = children->ElementAt(index);
00245 
00246       //check of value definitions for children already exist, if not add them
00247       if (!pValueDef_Child)
00248       {
00249         pValueDef_Child = rDictionary.AddValueDefinition(sIDPath,"Value","value of the child");
00250         rDictionary.AddValueDefinition(sIDPath,"Parents","ID of the parents");
00251 
00252         if (child->ObjectiveParameters().size()>0)
00253         {
00254           pValueDef_Objective = rDictionary.AddValueDefinition(sIDPath,"Objectiv #0","objective parameter of the individual");
00255           for (long index2= 1; index2<child->ObjectiveParameters().size(); index2++)
00256           {
00257             rDictionary.AddValueDefinition(sIDPath,"Objectiv #"+Convert::ToStr(index2),"objective parameter of the individual");
00258           }
00259         }
00260         if (child->StrategicParameters().size()>0)
00261         {
00262           pValueDef_Strategic = rDictionary.AddValueDefinition(sIDPath,"Strategic #0","strategic parameter of the individual");
00263           for (long index2= 1; index2<child->StrategicParameters().size(); index2++)
00264           {
00265             rDictionary.AddValueDefinition(sIDPath,"Strategic #"+Convert::ToStr(index2),"strategic parameter of the individual");
00266           }
00267         }
00268       }
00269 
00270       //generate entry for new child
00271       StatisticEntry* pNewChildEntry = rStatisticEntry.CreateChildEntry();
00272       pNewChildEntry->SetRefID(pEntryDef->GetRefID());
00273 
00274       pNewChildEntry->AddValue(Convert::ToStr(child->GetIndividualID()),pValueDef->GetRefID());
00275 
00276       //objective value
00277       pNewChildEntry->AddValue(Convert::ToStr(child->GetObjectiveValue()),pValueDef_Child->GetRefID());
00278 
00279       //compile parental info
00280       std::string sParents = "";
00281       ComponentType::HeritageMapType::const_iterator parentFinding = parentSelections.find(child->GetIndividualID());
00282       if (parentFinding ==parentSelections.end()) throwCtrlExceptionMacro("","Cannot find parents of new child individual. Please ensure valid session and setup. Child ID: "<<child->GetIndividualID());
00283       ComponentType::IndividualSelectionType parents = parentFinding->second;
00284 
00285       for (long index2= 0; index2<parents.size(); index2++)
00286       {
00287         sParents += Convert::ToStr(parents[index2]);
00288         if (index2<parents.size()-1) sParents += ", ";
00289       }
00290       pNewChildEntry->AddValue(sParents,pValueDef_Child->GetRefID()+1);
00291 
00292       //objective parameters
00293       for (long index2= 0; index2<child->ObjectiveParameters().size(); index2++)
00294       {
00295         pNewChildEntry->AddValue(Convert::ToStr((child->ObjectiveParameters())[index2]),pValueDef_Objective->GetRefID()+index2);
00296       }
00297 
00298       //strategic parameters
00299       for (long index2= 0; index2<child->StrategicParameters().size(); index2++)
00300       {
00301         pNewChildEntry->AddValue(Convert::ToStr(((child->StrategicParameters())[index2])->GetValue()),pValueDef_Strategic->GetRefID()+index2);
00302       }
00303 
00304       pNewChildEntry->CloseEntry();
00305     }
00306   }
00307 
00308 
00309   /*Next generation*/
00310   StatisticEntry* pGenerationEntry = rStatisticEntry.CreateChildEntry();
00311   pGenerationEntry->SetRefID(pEntryDef->GetRefID()+1);
00312 
00313   const ComponentType::PopulationPointer& nextGen = pMainComponent->GetPopulation();
00314   if (nextGen.IsNotNull())
00315   {
00316     for (long index= 0; index<nextGen->size(); index++)
00317     {
00318       ComponentType::IndividualPointer nextGenIndividual = nextGen->ElementAt(index);
00319       if (nextGenIndividual.IsNotNull()) pGenerationEntry->AddValue(Convert::ToStr(nextGenIndividual->GetIndividualID()),pValueDef->GetRefID());
00320     }
00321   }
00322   pGenerationEntry->CloseEntry();
00323 
00324   /*Victims*/
00325   StatisticEntry* pVictimsEntry = rStatisticEntry.CreateChildEntry();
00326   pVictimsEntry->SetRefID(pEntryDef->GetRefID()+2);
00327 
00328   const ComponentType::PopulationPointer& victims = pMainComponent->GetRecentPopulationSelections();
00329   if (victims.IsNotNull())
00330   {
00331     for (long index= 0; index<victims->size(); index++)
00332     {
00333       ComponentType::IndividualPointer victim = victims->ElementAt(index);
00334       if (victim.IsNotNull()) pVictimsEntry->AddValue(Convert::ToStr(victim->GetIndividualID()),pValueDef->GetRefID());
00335     }
00336   }
00337   pVictimsEntry->CloseEntry();
00338 
00339   /*Best fitness*/
00340   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetCurrentCost()),pValueDef_Best->GetRefID());
00341 
00342   /*Best individual*/
00343   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetBestIndividual()->GetIndividualID()),pValueDef_Best->GetRefID()+1);
00344 
00345   /*Best fitness ever*/
00346   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetBestIndividualEver()->GetObjectiveValue()),pValueDef_Best->GetRefID()+2);
00347 
00348   /*Best individual ever*/
00349   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetBestIndividualEver()->GetIndividualID()),pValueDef_Best->GetRefID()+3);
00350 };
00351 
00352 EvolutionaryStrategyOptimizerController::MeasuresType
00353 EvolutionaryStrategyOptimizerController::
00354 GetCurrentValue(ComponentType* pOptimizer) const
00355 {
00356         MeasuresType values(1);
00357         values.Fill(pOptimizer->GetValue());
00358         return values;
00359 };
00360 
00361 } //end of namespace free

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