LineSearch.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_LineSearch_H
21 #define MIRTK_LineSearch_H
22 
23 #include "mirtk/LocalOptimizer.h"
24 
25 #include "mirtk/Math.h"
26 
27 
28 namespace mirtk {
29 
30 
31 /// Enumeration of available line search strategies
33 {
34  LS_None, ///< No line search
35  // Add new enumeration values below
36  LS_Adaptive, ///< Inexact line search with adaptive step length
37  LS_Brent, ///< Numerical recipes linmin function using Brent's method
38  LS_LinMin = LS_Brent, ///< Alias for LS_Brent
39  // Add new enumeration values above
40  LS_Last
41 };
42 
43 
44 /**
45  * Finds optimal step length along given search direction
46  */
47 class LineSearch : public LocalOptimizer
48 {
49  mirtkAbstractMacro(LineSearch);
50 
51  // ---------------------------------------------------------------------------
52  // Attributes
53 
54  /// Direction of line search
55  mirtkPublicAggregateMacro(double, Direction);
56 
57  /// Whether to perform line search in opposite direction
58  mirtkPublicAttributeMacro(bool, Revert);
59 
60  /// Initial objective function value
61  mirtkPublicAttributeMacro(double, CurrentValue);
62 
63  /// Maximum number of search iterations
64  mirtkPublicAttributeMacro(int, NumberOfIterations);
65 
66  /// Minimum length of step
67  mirtkPublicAttributeMacro(double, MinStepLength);
68 
69  /// Maximum length of step
70  mirtkPublicAttributeMacro(double, MaxStepLength);
71 
72  /// Unit of step length, e.g., maximum gradient norm
73  mirtkPublicAttributeMacro(double, StepLengthUnit);
74 
75  /// Initial/final/optimal step length
76  mirtkPublicAttributeMacro(double, StepLength);
77 
78  /// Copy attributes of this class from another instance
79  void CopyAttributes(const LineSearch &);
80 
81  // ---------------------------------------------------------------------------
82  // Construction/Destruction
83 protected:
84 
85  /// Constructor
86  LineSearch(ObjectiveFunction * = NULL);
87 
88  /// Copy constructor
89  LineSearch(const LineSearch &);
90 
91  /// Assignment operator
93 
94 public:
95 
96  /// Instantiate line search implementing specified strategy
98 
99  /// Destructor
100  virtual ~LineSearch();
101 
102  /// Line search strategy implemented by this line search
103  virtual LineSearchStrategy Strategy() const = 0;
104 
105  // ---------------------------------------------------------------------------
106  // Parameters
107 
108  // Import other overloads
110 
111  /// Set parameter value from string
112  virtual bool Set(const char *, const char *);
113 
114  /// Get parameters as key/value as string map
115  virtual ParameterList Parameter() const;
116 
117  // ---------------------------------------------------------------------------
118  // Optimization
119 
120  /// Initialize optimization
121  virtual void Initialize();
122 
123  /// Make optimal step along search direction
124  /// \returns New value of objective function or previous if no step successful
125  virtual double Run() = 0;
126 };
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 // Auxiliary macros for line search implementation
130 ////////////////////////////////////////////////////////////////////////////////
131 
132 // -----------------------------------------------------------------------------
133 #define mirtkLineSearchMacro(name, strategy) \
134  mirtkObjectMacro(name); \
135  public: \
136  /** Optimization method implemented by this optimizer */ \
137  virtual mirtk::OptimizationMethod OptimizationMethod() const \
138  { \
139  return OM_LineSearch; \
140  } \
141  /** Line search strategy implemented by this line search */ \
142  virtual mirtk::LineSearchStrategy Strategy() const { return strategy; } \
143  private:
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 // Inline definitions
147 ////////////////////////////////////////////////////////////////////////////////
148 
149 // -----------------------------------------------------------------------------
150 template <>
151 inline string ToString(const LineSearchStrategy &m, int w, char c, bool left)
152 {
153  const char *str;
154  switch (m) {
155  case LS_None: str = "None"; break;
156  case LS_Adaptive: str = "Adaptive"; break;
157  case LS_Brent: str = "Brent"; break;
158  default: str = "Unknown"; break;
159  }
160  return ToString(str, w, c, left);
161 }
162 
163 // -----------------------------------------------------------------------------
164 template <>
165 inline bool FromString(const char *str, LineSearchStrategy &m)
166 {
167  m = LS_None;
168  if (strcmp(str, "None") == 0) return true;
169  if (strcmp(str, "linmin") == 0 || strcmp(str, "LinMin") == 0) m = LS_Brent;
170  if (m == LS_None) {
171  m = static_cast<LineSearchStrategy>(LS_Last - 1);
172  while (m != LS_None) {
173  if (ToString(m) == str) break;
174  m = static_cast<LineSearchStrategy>(m - 1);
175  }
176  }
177  return m != LS_None;
178 }
179 
180 // -----------------------------------------------------------------------------
181 // For use by subclass Run implementation to get current function value
182 inline double LineSearch::Run()
183 {
184  if (IsNaN(_CurrentValue)) {
185  Function()->Update(false);
186  _CurrentValue = Function()->Value();
187  }
188  return _CurrentValue;
189 }
190 
191 
192 } // namespace mirtk
193 
194 #endif // MIRTK_LineSearch_H
No line search.
Definition: LineSearch.h:34
LineSearch(ObjectiveFunction *=NULL)
Constructor.
virtual ~LineSearch()
Destructor.
MIRTKCU_API bool IsNaN(double x)
Check if floating point value is not a number (NaN)
Definition: Math.h:91
Inexact line search with adaptive step length.
Definition: LineSearch.h:36
Array< Pair< string, string > > ParameterList
Ordered list of parameter name/value pairs.
Definition: Object.h:38
Alias for LS_Brent.
Definition: LineSearch.h:38
virtual ParameterList Parameter() const
Get parameters as key/value as string map.
virtual ParameterList Parameter() const
Get parameters as key/value as string map.
virtual void Initialize()
Initialize optimization.
Definition: IOConfig.h:41
virtual bool Set(const char *, const char *)
Set parameter value from string.
LineSearch & operator=(const LineSearch &)
Assignment operator.
Numerical recipes linmin function using Brent&#39;s method.
Definition: LineSearch.h:37
string ToString(const EnergyMeasure &value, int w, char c, bool left)
Convert energy measure enumeration value to string.
static LineSearch * New(LineSearchStrategy &, ObjectiveFunction *=NULL)
Instantiate line search implementing specified strategy.
bool FromString(const char *str, EnergyMeasure &value)
Convert energy measure string to enumeration value.
virtual double Run()=0
Definition: LineSearch.h:182
virtual LineSearchStrategy Strategy() const =0
Line search strategy implemented by this line search.
LineSearchStrategy
Enumeration of available line search strategies.
Definition: LineSearch.h:32