17 #ifndef __itkSPSAOptimizer_cxx
18 #define __itkSPSAOptimizer_cxx
38 itkDebugMacro(
"Constructor" );
40 m_CurrentIteration = 0;
43 m_StateOfConvergenceDecayRate = 0.9;
45 m_StateOfConvergence = 0;
46 m_MaximumNumberOfIterations = 100;
47 m_MinimumNumberOfIterations = 10;
48 m_GradientMagnitude = 0.0;
49 m_NumberOfPerturbations = 1;
53 m_A = m_MaximumNumberOfIterations / 10;
67 Superclass::PrintSelf( os, indent );
69 os << indent <<
"a: " << m_Sa << std::endl;
70 os << indent <<
"A: " << m_A << std::endl;
71 os << indent <<
"Alpha: " << m_Alpha << std::endl;
72 os << indent <<
"c: " << m_Sc << std::endl;
73 os << indent <<
"Gamma: " << m_Gamma << std::endl;
74 os << indent <<
"Tolerance: " << m_Tolerance << std::endl;
75 os << indent <<
"GradientMagnitude: " << m_GradientMagnitude << std::endl;
76 os << indent <<
"StateOfConvergenceDecayRate: " << m_StateOfConvergenceDecayRate << std::endl;
77 os << indent <<
"Gradient: " << m_Gradient << std::endl;
78 os << indent <<
"StateOfConvergence: " << m_StateOfConvergence << std::endl;
80 os << indent <<
"NumberOfPerturbations: " << m_NumberOfPerturbations << std::endl;
82 os << indent <<
"LearningRate: "
83 << m_LearningRate << std::endl;
85 os << indent <<
"MaximumNumberOfIterations: "
86 << m_MaximumNumberOfIterations << std::endl;
87 os << indent <<
"MinimumNumberOfIterations: "
88 << m_MinimumNumberOfIterations << std::endl;
90 os << indent <<
"Maximize: "
91 << m_Maximize << std::endl;
93 os << indent <<
"CurrentIteration: "
94 << m_CurrentIteration;
97 os << indent <<
"CostFunction: "
100 os << indent <<
"StopCondition: "
119 return this->Superclass::GetValue( parameters );
136 return this->GetValue( this->GetCurrentPosition() );
146 itkDebugMacro(
"StartOptimization" );
150 itkExceptionMacro(<<
"No objective function defined! ");
154 const unsigned int spaceDimension =
155 m_CostFunction->GetNumberOfParameters();
156 if ( spaceDimension != this->GetInitialPosition().GetSize() )
158 itkExceptionMacro(<<
"Number of parameters not correct!");
161 m_CurrentIteration = 0;
163 m_StateOfConvergence = 0.0;
165 this->SetCurrentPosition( this->GetInitialPosition() );
166 this->ResumeOptimization();
179 itkDebugMacro(
"ResumeOptimization" );
195 m_CurrentIteration++;
197 if( m_CurrentIteration >= m_MaximumNumberOfIterations )
199 m_StopCondition = MaximumNumberOfIterations;
205 if ( (m_StateOfConvergence < m_Tolerance)
206 && (m_CurrentIteration >= m_MinimumNumberOfIterations) )
208 m_StopCondition = BelowTolerance;
212 m_StateOfConvergence *= m_StateOfConvergenceDecayRate;
224 itkDebugMacro(
"StopOptimization" );
237 itkDebugMacro(
"AdvanceOneStep" );
241 if( this->m_Maximize )
251 const unsigned int spaceDimension =
252 m_CostFunction->GetNumberOfParameters();
257 const ParametersType & currentPosition = this->GetCurrentPosition();
264 this->ComputeGradient(currentPosition, m_Gradient);
270 m_StopCondition = MetricError;
277 const double ak = this->Compute_a( m_CurrentIteration );
284 newPosition = currentPosition + (direction * ak) * m_Gradient;
285 this->SetCurrentPosition( newPosition );
288 m_GradientMagnitude = m_Gradient.magnitude();
291 m_StateOfConvergence += ak * m_GradientMagnitude;
305 return static_cast<double>(
306 m_Sa / vcl_pow( m_A + k + 1, m_Alpha ) );
320 return static_cast<double>(
321 m_Sc / vcl_pow( k + 1, m_Gamma ) );
336 m_Delta = DerivativeType( spaceDimension );
338 const ScalesType & scales = this->GetScales();
341 if (scales.size() != spaceDimension)
343 itkExceptionMacro(<<
"The size of Scales is "
345 <<
", but the NumberOfParameters for the CostFunction is "
350 for (
unsigned int j = 0; j < spaceDimension; j++ )
353 m_Delta[ j ] = 2 * Math::Round<int>( this->m_Generator->GetUniformVariate (0.0f, 1.0f) ) - 1;
360 m_Delta[j] /= scales[j];
372 DerivativeType & gradient)
375 const unsigned int spaceDimension = parameters.
GetSize();
392 for (
unsigned long perturbation = 1;
400 for (
unsigned int j = 0; j < spaceDimension; j++ )
402 thetaplus[j] = parameters[ j ] + ck *
m_Delta[ j ];
403 thetamin[j] = parameters[ j ] - ck * m_Delta[ j ];
407 const double valueplus = this->
GetValue( thetaplus );
410 const double valuemin = this->
GetValue( thetamin );
413 const double valuediff = ( valueplus - valuemin ) / ( 2 * ck );
414 for (
unsigned int j = 0; j < spaceDimension; j++ )
417 gradient[ j ] += valuediff /
m_Delta[j];
422 for (
unsigned int j = 0; j < spaceDimension; j++ )
475 unsigned long numberOfGradientEstimates,
476 double initialStepSize)
483 itkExceptionMacro(<<
"No objective function defined! ");
487 const unsigned int spaceDimension =
492 if ( spaceDimension != initialPosition.
GetSize() )
494 itkExceptionMacro(<<
"Number of parameters not correct!");
499 averageAbsoluteGradient.Fill(0.0);
501 for (
unsigned long n=1; n<= numberOfGradientEstimates; ++n)
504 for (
unsigned int j = 0; j < spaceDimension; j++ )
506 averageAbsoluteGradient[j] += vcl_fabs(
m_Gradient[j]);
509 averageAbsoluteGradient /=
static_cast<double>(numberOfGradientEstimates);
513 averageAbsoluteGradient.max_value() );
522 ::itk::OStringStream reason;
527 reason <<
"Unknown stop condition";
530 reason <<
"Maximum number of iterations exceeded. Number of iterations is "
534 reason <<
"Below tolerance. " <<
"Tolerance is " <<
m_Tolerance;
537 reason <<
"Metric error";
540 reason <<
" No reason given for termination ";
549 #endif // end #ifndef __itkSPSAOptimizer_cxx