/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkMultiStartOptimizerv4_hxx #define itkMultiStartOptimizerv4_hxx #include "itkMultiStartOptimizerv4.h" namespace itk { //------------------------------------------------------------------- template MultiStartOptimizerv4Template ::MultiStartOptimizerv4Template(): m_Stop(false) { this->m_NumberOfIterations = static_cast(0); this->m_StopCondition = MAXIMUM_NUMBER_OF_ITERATIONS; this->m_StopConditionDescription << this->GetNameOfClass() << ": "; this->m_BestParametersIndex= static_cast(0); this->m_MaximumMetricValue=NumericTraits::max(); this->m_MinimumMetricValue = this->m_MaximumMetricValue; m_LocalOptimizer = ITK_NULLPTR; } //------------------------------------------------------------------- template MultiStartOptimizerv4Template ::~MultiStartOptimizerv4Template() {} //------------------------------------------------------------------- template void MultiStartOptimizerv4Template ::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Stop condition:"<< this->m_StopCondition << std::endl; os << indent << "Stop condition description: " << this->m_StopConditionDescription.str() << std::endl; } //------------------------------------------------------------------- template typename MultiStartOptimizerv4Template::ParametersListType & MultiStartOptimizerv4Template ::GetParametersList() { return this->m_ParametersList; } /** Set the list of parameters over which to search */ template void MultiStartOptimizerv4Template ::SetParametersList(typename MultiStartOptimizerv4Template::ParametersListType & p) { if( p != this->m_ParametersList ) { this->m_ParametersList = p; this->Modified(); } } /** Get the list of metric values that we produced after the multi-start search. */ template const typename MultiStartOptimizerv4Template::MetricValuesListType & MultiStartOptimizerv4Template ::GetMetricValuesList() const { return this->m_MetricValuesList; } //------------------------------------------------------------------- template typename MultiStartOptimizerv4Template::ParametersType MultiStartOptimizerv4Template ::GetBestParameters( ) { return this->m_ParametersList[m_BestParametersIndex]; } //------------------------------------------------------------------- template void MultiStartOptimizerv4Template ::InstantiateLocalOptimizer() { LocalOptimizerPointer optimizer = LocalOptimizerType::New(); optimizer->SetLearningRate( static_cast(1.e-1) ); optimizer->SetNumberOfIterations( 25 ); this->m_LocalOptimizer=optimizer; } //------------------------------------------------------------------- template const typename MultiStartOptimizerv4Template::StopConditionReturnStringType MultiStartOptimizerv4Template ::GetStopConditionDescription() const { return this->m_StopConditionDescription.str(); } //------------------------------------------------------------------- template void MultiStartOptimizerv4Template ::StopOptimization(void) { itkDebugMacro( "StopOptimization called with a description - " << this->GetStopConditionDescription() ); this->m_Stop = true; this->m_Metric->SetParameters( this->m_ParametersList[ this->m_BestParametersIndex ] ); this->InvokeEvent( EndEvent() ); } /** * Start and run the optimization */ template void MultiStartOptimizerv4Template ::StartOptimization( bool doOnlyInitialization ) { itkDebugMacro("StartOptimization"); this->m_NumberOfIterations= static_cast( this->m_ParametersList.size() ); this->m_MetricValuesList.clear(); this->m_BestParametersIndex = static_cast(0); this->m_MinimumMetricValue = this->m_MaximumMetricValue; /* Must call the superclass version for basic validation and setup */ if ( this->m_NumberOfIterations > static_cast(0) ) { Superclass::StartOptimization( doOnlyInitialization ); } this->m_CurrentIteration = static_cast(0); if( ! doOnlyInitialization ) { if ( this->m_NumberOfIterations > static_cast(0) ) { this->ResumeOptimization(); } } } /** * Resume optimization. */ template void MultiStartOptimizerv4Template ::ResumeOptimization() { this->m_StopConditionDescription.str(""); this->m_StopConditionDescription << this->GetNameOfClass() << ": "; this->InvokeEvent( StartEvent() ); this->m_Stop = false; while( ! this->m_Stop ) { /* Compute metric value */ try { this->m_Metric->SetParameters( this->m_ParametersList[ this->m_CurrentIteration ] ); if ( this->m_LocalOptimizer ) { this->m_LocalOptimizer->SetMetric( this->m_Metric ); this->m_LocalOptimizer->StartOptimization(); this->m_ParametersList[this->m_CurrentIteration] = this->m_Metric->GetParameters(); } this->m_CurrentMetricValue = this->m_Metric->GetValue(); this->m_MetricValuesList.push_back(this->m_CurrentMetricValue); } catch ( ExceptionObject & ) { /** We simply ignore this exception because it may just be a bad starting point. * We hope that other start points are better. */ itkWarningMacro("An exception occurred in sub-optimization number " << this->m_CurrentIteration << ". If too many of these occur, you may need to set a different set of initial parameters."); } if ( this->m_CurrentMetricValue < this->m_MinimumMetricValue ) { this->m_MinimumMetricValue=this->m_CurrentMetricValue; this->m_BestParametersIndex = this->m_CurrentIteration; } /* Check if optimization has been stopped externally. * (Presumably this could happen from a multi-threaded client app?) */ if ( this->m_Stop ) { this->m_StopConditionDescription << "StopOptimization() called"; break; } this->InvokeEvent( IterationEvent() ); /* Update and check iteration count */ this->m_CurrentIteration++; if ( this->m_CurrentIteration >= this->m_NumberOfIterations ) { this->m_StopConditionDescription << "Maximum number of iterations (" << this->m_NumberOfIterations << ") exceeded."; this->m_StopCondition = MAXIMUM_NUMBER_OF_ITERATIONS; this->StopOptimization(); break; } } //while (!m_Stop) } } //namespace itk #endif