Orfeo Toolbox  3.16
itkLBFGSBOptimizer.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkLBFGSBOptimizer.cxx,v $
5  Language: C++
6  Date: $Date: 2010-05-12 19:38:30 $
7  Version: $Revision: 1.19 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkLBFGSBOptimizer_txx
18 #define __itkLBFGSBOptimizer_txx
19 
20 #include "itkLBFGSBOptimizer.h"
21 #include "vnl/algo/vnl_lbfgsb.h"
22 #include <vnl/vnl_math.h>
23 
24 extern "C" {
25  extern double v3p_netlib_dpmeps_();
26 }
27 
28 namespace itk
29 {
30 
31 
39  public vnl_lbfgsb
40 {
41 public:
43  typedef vnl_lbfgsb Superclass;
44 
46  LBFGSBOptimizerHelper( vnl_cost_function& f,
47  LBFGSBOptimizer* itkObj );
48 
50  virtual bool report_iter();
51 
52 private:
54 };
55 
56 
57 
58 
64 {
65  m_OptimizerInitialized = false;
66  m_VnlOptimizer = 0;
67  m_Trace = false;
68 
69  m_LowerBound = InternalBoundValueType(0);
70  m_UpperBound = InternalBoundValueType(0);
71  m_BoundSelection = InternalBoundSelectionType(0);
72 
73  m_CostFunctionConvergenceFactor = 1e+7;
74  m_ProjectedGradientTolerance = 1e-5;
75  m_MaximumNumberOfIterations = 500;
76  m_MaximumNumberOfEvaluations = 500;
77  m_MaximumNumberOfCorrections = 5;
78  m_CurrentIteration = 0;
79  m_InfinityNormOfProjectedGradient = 0.0;
80  m_StopConditionDescription.str("");
81 
82 }
83 
84 
90 {
91  delete m_VnlOptimizer;
92 }
93 
97 void
99 ::PrintSelf( std::ostream& os, Indent indent) const
100 {
101  Superclass::PrintSelf(os, indent);
102  os << indent << "Trace: ";
103  if ( m_Trace )
104  {
105  os << "On";
106  }
107  else
108  { os << "Off";
109  }
110  os << std::endl;
111 
112  os << indent << "LowerBound: " << m_LowerBound << std::endl;
113  os << indent << "UpperBound: " << m_UpperBound << std::endl;
114  os << indent << "BoundSelection: " << m_BoundSelection << std::endl;
115 
116  os << indent << "CostFunctionConvergenceFactor: " <<
117  m_CostFunctionConvergenceFactor << std::endl;
118 
119  os << indent << "ProjectedGradientTolerance: " <<
120  m_ProjectedGradientTolerance << std::endl;
121 
122  os << indent << "MaximumNumberOfIterations: " <<
123  m_MaximumNumberOfIterations << std::endl;
124 
125  os << indent << "MaximumNumberOfEvaluations: " <<
126  m_MaximumNumberOfEvaluations << std::endl;
127 
128  os << indent << "MaximumNumberOfCorrections: " <<
129  m_MaximumNumberOfCorrections << std::endl;
130 
131  os << indent << "CurrentIteration: " <<
132  m_CurrentIteration << std::endl;
133 
134  os << indent << "Value: " <<
135  this->GetValue() << std::endl;
136 
137  os << indent << "InfinityNormOfProjectedGradient: " <<
138  m_InfinityNormOfProjectedGradient << std::endl;
139 
140  if( this->m_VnlOptimizer )
141  {
142  os << indent << "Vnl LBFGSB Failure Code: " <<
143  this->m_VnlOptimizer->get_failure_code() << std::endl;
144  }
145 }
146 
150 void
152 ::SetTrace( bool flag )
153 {
154  if ( flag == m_Trace )
155  {
156  return;
157  }
158 
159  m_Trace = flag;
160  if ( m_OptimizerInitialized )
161  {
162  m_VnlOptimizer->set_trace( m_Trace );
163  }
164 
165  this->Modified();
166 }
167 
171 void
174 const BoundValueType& value )
175 {
176  m_LowerBound = value;
177  if( m_OptimizerInitialized )
178  {
179  m_VnlOptimizer->set_lower_bound( m_LowerBound );
180  }
181 
182  this->Modified();
183 }
184 
188 const
193 {
194  return m_LowerBound;
195 }
196 
202 ::GetValue() const
203 {
204  return this->GetCachedValue();
205 }
206 
210 void
213 const BoundValueType& value )
214 {
215  m_UpperBound = value;
216  if( m_OptimizerInitialized )
217  {
218  m_VnlOptimizer->set_upper_bound( m_UpperBound );
219  }
220 
221  this->Modified();
222 }
223 
227 const
232 {
233  return m_UpperBound;
234 }
235 
236 
240 void
243 const BoundSelectionType& value )
244 {
245  m_BoundSelection = value;
246  if( m_OptimizerInitialized )
247  {
248  m_VnlOptimizer->set_bound_selection( m_BoundSelection );
249  }
250  this->Modified();
251 }
252 
256 const
261 {
262  return m_BoundSelection;
263 }
264 
265 
272 void
275 {
276  if( value < 1.0 )
277  {
278  itkExceptionMacro("Value " << value
279  << " is too small for SetCostFunctionConvergenceFactor()"
280  << "a typical range would be from 1.0 to 1e+12");
281  }
282  m_CostFunctionConvergenceFactor = value;
283  if( m_OptimizerInitialized )
284  {
285  m_VnlOptimizer->set_cost_function_convergence_factor(
286  m_CostFunctionConvergenceFactor );
287  }
288  this->Modified();
289 }
290 
291 
296 void
299 {
300  m_ProjectedGradientTolerance = value;
301  if( m_OptimizerInitialized )
302  {
303  m_VnlOptimizer->set_projected_gradient_tolerance(
304  m_ProjectedGradientTolerance );
305  }
306  this->Modified();
307 }
308 
309 
311 void
313 ::SetMaximumNumberOfIterations( unsigned int value )
314 {
315  m_MaximumNumberOfIterations = value;
316  this->Modified();
317 }
318 
319 
321 void
323 ::SetMaximumNumberOfEvaluations( unsigned int value )
324 {
325  m_MaximumNumberOfEvaluations = value;
326  if( m_OptimizerInitialized )
327  {
328  m_VnlOptimizer->set_max_function_evals( m_MaximumNumberOfEvaluations );
329  }
330  this->Modified();
331 }
332 
333 
335 void
337 ::SetMaximumNumberOfCorrections( unsigned int value )
338 {
339  m_MaximumNumberOfCorrections = value;
340  if( m_OptimizerInitialized )
341  {
342  m_VnlOptimizer->set_max_variable_metric_corrections(
343  m_MaximumNumberOfCorrections );
344  }
345  this->Modified();
346 }
347 
348 
352 void
355 {
356  m_CostFunction = costFunction;
357 
358  const unsigned int numberOfParameters =
359  costFunction->GetNumberOfParameters();
360 
361  CostFunctionAdaptorType * adaptor =
362  new CostFunctionAdaptorType( numberOfParameters );
363 
364  adaptor->SetCostFunction( costFunction );
365 
367  {
368  delete m_VnlOptimizer;
369  }
370 
371  this->SetCostFunctionAdaptor( adaptor );
372 
373  m_VnlOptimizer = new InternalOptimizerType( *adaptor, this );
374 
375  // set the optimizer parameters
376  m_VnlOptimizer->set_lower_bound( m_LowerBound );
377  m_VnlOptimizer->set_upper_bound( m_UpperBound );
378  m_VnlOptimizer->set_bound_selection( m_BoundSelection );
379  m_VnlOptimizer->set_cost_function_convergence_factor(
381  m_VnlOptimizer->set_projected_gradient_tolerance(
383  m_VnlOptimizer->set_max_function_evals( m_MaximumNumberOfEvaluations );
384  m_VnlOptimizer->set_max_variable_metric_corrections(
386 
387  m_OptimizerInitialized = true;
388 
389  this->Modified();
390 }
391 
392 
396 void
399 {
400 
401  // Check if all the bounds parameters are the same size as the initial parameters.
402  unsigned int numberOfParameters = m_CostFunction->GetNumberOfParameters();
403 
404  if ( this->GetInitialPosition().Size() < numberOfParameters )
405  {
406  itkExceptionMacro( << "InitialPosition array does not have sufficient number of elements" );
407  }
408 
409  if ( m_LowerBound.size() < numberOfParameters )
410  {
411  itkExceptionMacro( << "LowerBound array does not have sufficient number of elements" );
412  }
413 
414  if ( m_UpperBound.size() < numberOfParameters )
415  {
416  itkExceptionMacro( << "UppperBound array does not have sufficient number of elements" );
417  }
418 
419  if ( m_BoundSelection.size() < numberOfParameters )
420  {
421  itkExceptionMacro( << "BoundSelection array does not have sufficient number of elements" );
422  }
423 
424  if( this->GetMaximize() )
425  {
426  this->GetNonConstCostFunctionAdaptor()->NegateCostFunctionOn();
427  }
428 
429  this->SetCurrentPosition( this->GetInitialPosition() );
430 
431  ParametersType parameters( this->GetInitialPosition() );
432 
433  // Clear the description
434  m_StopConditionDescription.str("");
435 
436  // vnl optimizers return the solution by reference
437  // in the variable provided as initial position
438  m_VnlOptimizer->minimize( parameters );
439 
440  if ( parameters.size() != this->GetInitialPosition().Size() )
441  {
442  // set current position to initial position and throw an exception
443  this->SetCurrentPosition( this->GetInitialPosition() );
444  itkExceptionMacro( << "Error occured in optimization" );
445  }
446 
447  this->SetCurrentPosition( parameters );
448 
449  this->InvokeEvent( EndEvent() );
450 
451 }
452 
453 
454 /*-------------------------------------------------------------------------
455  * helper class
456  *-------------------------------------------------------------------------
457  */
458 
461 ::LBFGSBOptimizerHelper( vnl_cost_function& f,
462  LBFGSBOptimizer* itkObj )
463  : vnl_lbfgsb( f ),
464  m_ItkObj( itkObj )
465 {
466 }
467 
468 
470 bool
473 {
474  Superclass::report_iter();
475 
476  m_ItkObj->m_InfinityNormOfProjectedGradient =
477  this->get_inf_norm_projected_gradient();
478 
479  m_ItkObj->InvokeEvent( IterationEvent() );
480 
481  m_ItkObj->m_CurrentIteration = this->num_iterations_;
482 
483  // Return true to terminate the optimization loop.
484  if( this->num_iterations_ > m_ItkObj->m_MaximumNumberOfIterations )
485  {
486  m_ItkObj->m_StopConditionDescription <<
487  "Too many iterations. Iterations = " <<
488  m_ItkObj->m_MaximumNumberOfIterations;
489  return true;
490  }
491  else
492  {
493  return false;
494  }
495 }
496 
497 const std::string
500 {
501  if (m_VnlOptimizer)
502  {
504  m_StopConditionDescription << this->GetNameOfClass() << ": ";
505  switch (m_VnlOptimizer->get_failure_code())
506  {
507  case vnl_nonlinear_minimizer::ERROR_FAILURE:
508  m_StopConditionDescription << "Failure";
509  break;
510  case vnl_nonlinear_minimizer::ERROR_DODGY_INPUT:
511  m_StopConditionDescription << "Dodgy input";
512  break;
513  case vnl_nonlinear_minimizer::CONVERGED_FTOL:
514  m_StopConditionDescription << "Function tolerance reached after "
516  << " iterations. "
517  << "The relative reduction of the cost function <= "
519  << " = CostFunctionConvergenceFactor ("
521  << ") * machine precision ("
522  << v3p_netlib_dpmeps_()
523  << ").";
524  break;
525  case vnl_nonlinear_minimizer::CONVERGED_XTOL:
526  m_StopConditionDescription << "Solution tolerance reached";
527  break;
528  case vnl_nonlinear_minimizer::CONVERGED_XFTOL:
529  m_StopConditionDescription << "Solution and Function tolerance both reached";
530  break;
531  case vnl_nonlinear_minimizer::CONVERGED_GTOL:
532  m_StopConditionDescription << "Gradient tolerance reached. "
533  << "Projected gradient tolerance is "
535  break;
536  case vnl_nonlinear_minimizer::FAILED_TOO_MANY_ITERATIONS:
537  m_StopConditionDescription << "Too many iterations. Iterations = "
539  break;
540  case vnl_nonlinear_minimizer::FAILED_FTOL_TOO_SMALL:
541  m_StopConditionDescription << "Function tolerance too small";
542  break;
543  case vnl_nonlinear_minimizer::FAILED_XTOL_TOO_SMALL:
544  m_StopConditionDescription << "Solution tolerance too small";
545  break;
546  case vnl_nonlinear_minimizer::FAILED_GTOL_TOO_SMALL:
547  m_StopConditionDescription << "Gradient tolerance too small";
548  break;
549  case vnl_nonlinear_minimizer::FAILED_USER_REQUEST:
550  break;
551  }
552  return m_StopConditionDescription.str();
553  }
554  else
555  {
556  return std::string("");
557  }
558 }
559 
560 } // end namespace itk
561 
562 #endif

Generated at Sat Feb 2 2013 23:50:58 for Orfeo Toolbox with doxygen 1.8.1.1