/*========================================================================= * * Copyright NumFOCUS * * 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 * * https://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. * *=========================================================================*/ #include "itkExhaustiveOptimizer.h" namespace itk { ExhaustiveOptimizer::ExhaustiveOptimizer() = default; void ExhaustiveOptimizer::StartOptimization() { this->StartWalking(); } void ExhaustiveOptimizer::StartWalking() { itkDebugMacro("StartWalking"); this->InvokeEvent(StartEvent()); m_StopConditionDescription.str(""); m_StopConditionDescription << this->GetNameOfClass() << ": Running"; ParametersType initialPos = this->GetInitialPosition(); m_MinimumMetricValuePosition = initialPos; m_MaximumMetricValuePosition = initialPos; MeasureType initialValue = this->GetValue(this->GetInitialPosition()); m_MaximumMetricValue = initialValue; m_MinimumMetricValue = initialValue; m_CurrentIteration = 0; m_MaximumNumberOfIterations = 1; const unsigned int spaceDimension = this->GetInitialPosition().GetSize(); for (unsigned int i = 0; i < spaceDimension; ++i) { m_MaximumNumberOfIterations *= (2 * m_NumberOfSteps[i] + 1); } m_CurrentIndex.SetSize(spaceDimension); m_CurrentIndex.Fill(0); const ScalesType & scales = this->GetScales(); // Make sure the scales have been set properly if (scales.size() != spaceDimension) { itkExceptionMacro("The size of Scales is " << scales.size() << ", but the NumberOfParameters is " << spaceDimension << '.'); } // Setup first grid position. ParametersType position(spaceDimension); for (unsigned int i = 0; i < spaceDimension; ++i) { position[i] = this->GetInitialPosition()[i] - m_NumberOfSteps[i] * m_StepLength * scales[i]; } this->SetCurrentPosition(position); itkDebugMacro("Calling ResumeWalking"); this->ResumeWalking(); } void ExhaustiveOptimizer::ResumeWalking() { itkDebugMacro("ResumeWalk"); m_Stop = false; while (!m_Stop) { ParametersType currentPosition = this->GetCurrentPosition(); if (m_Stop) { StopWalking(); break; } m_CurrentValue = this->GetValue(currentPosition); if (m_CurrentValue > m_MaximumMetricValue) { m_MaximumMetricValue = m_CurrentValue; m_MaximumMetricValuePosition = currentPosition; } if (m_CurrentValue < m_MinimumMetricValue) { m_MinimumMetricValue = m_CurrentValue; m_MinimumMetricValuePosition = currentPosition; } if (m_Stop) { this->StopWalking(); break; } m_StopConditionDescription.str(""); m_StopConditionDescription << this->GetNameOfClass() << ": Running. " << "@ index " << this->GetCurrentIndex() << " value is " << this->GetCurrentValue(); this->InvokeEvent(IterationEvent()); this->AdvanceOneStep(); ++m_CurrentIteration; } } void ExhaustiveOptimizer::StopWalking() { itkDebugMacro("StopWalking"); m_Stop = true; this->InvokeEvent(EndEvent()); } void ExhaustiveOptimizer::AdvanceOneStep() { itkDebugMacro("AdvanceOneStep"); const unsigned int spaceDimension = m_CostFunction->GetNumberOfParameters(); ParametersType newPosition(spaceDimension); IncrementIndex(newPosition); itkDebugMacro("new position = " << newPosition); this->SetCurrentPosition(newPosition); } void ExhaustiveOptimizer::IncrementIndex(ParametersType & newPosition) { unsigned int idx = 0; const unsigned int spaceDimension = m_CostFunction->GetNumberOfParameters(); while (idx < spaceDimension) { m_CurrentIndex[idx]++; if (m_CurrentIndex[idx] > (2 * m_NumberOfSteps[idx])) { m_CurrentIndex[idx] = 0; ++idx; } else { break; } } if (idx == spaceDimension) { m_Stop = true; m_StopConditionDescription.str(""); m_StopConditionDescription << this->GetNameOfClass() << ": " << "Completed sampling of parametric space of size " << spaceDimension; } const ScalesType & scales = this->GetScales(); for (unsigned int i = 0; i < spaceDimension; ++i) { newPosition[i] = (m_CurrentIndex[i] - m_NumberOfSteps[i]) * m_StepLength * scales[i] + this->GetInitialPosition()[i]; } } const std::string ExhaustiveOptimizer::GetStopConditionDescription() const { return m_StopConditionDescription.str(); } void ExhaustiveOptimizer::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "CurrentValue: " << static_cast::PrintType>(m_CurrentValue) << std::endl; os << indent << "NumberOfSteps: " << static_cast::PrintType>(m_NumberOfSteps) << std::endl; os << indent << "CurrentIteration: " << static_cast::PrintType>(m_CurrentIteration) << std::endl; os << indent << "Stop: " << (m_Stop ? "On" : "Off") << std::endl; os << indent << "CurrentParameter: " << m_CurrentParameter << std::endl; os << indent << "StepLength: " << m_StepLength << std::endl; os << indent << "CurrentIndex: " << m_CurrentIndex << std::endl; os << indent << "MaximumNumberOfIterations: " << static_cast::PrintType>(m_MaximumNumberOfIterations) << std::endl; os << indent << "MaximumMetricValue: " << static_cast::PrintType>(m_MaximumMetricValue) << std::endl; os << indent << "MinimumMetricValue: " << static_cast::PrintType>(m_MinimumMetricValue) << std::endl; os << indent << "MinimumMetricValuePosition: " << m_MinimumMetricValuePosition << std::endl; os << indent << "MaximumMetricValuePosition: " << m_MaximumMetricValuePosition << std::endl; os << indent << "StopConditionDescription: " << m_StopConditionDescription.str() << std::endl; } } // end namespace itk