ObjectiveFunction.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_ObjectiveFunction_H
21 #define MIRTK_ObjectiveFunction_H
22 
23 #include "mirtk/Observable.h"
24 
25 
26 namespace mirtk {
27 
28 
29 /**
30  * Interface for objective function of an optimization problem.
31  *
32  * An objective function can be minimized/maximized using a specialization
33  * of the irtkLocalOptimizer base class.
34  */
36 {
37  mirtkAbstractMacro(ObjectiveFunction);
38 
39 protected:
40 
41  /// Default step length used for gradient approximation
42  mirtkAttributeMacro(double, StepLength);
43 
44 public:
45 
46  /// Destructor
47  virtual ~ObjectiveFunction() = 0;
48 
49  // ---------------------------------------------------------------------------
50  // Function parameters (DoFs)
51 
52  /// Get number of DoFs
53  ///
54  /// \returns Number of free function parameters.
55  virtual int NumberOfDOFs() const = 0;
56 
57  /// Set function parameter values
58  ///
59  /// This is function can be used to set the parameters of the objective function
60  /// to particular values. In particular, it can be used to restore the function
61  /// parameters after a failed incremental update which did not result in the
62  /// desired improvement.
63  ///
64  /// \param[in] x Function parameter (DoF) values.
65  virtual void Put(const double *x) = 0;
66 
67  /// Get function parameter value
68  ///
69  /// \param[in] i Function parameter (DoF) index.
70  ///
71  /// \returns Value of specified function parameter (DoF).
72  virtual double Get(int i) const = 0;
73 
74  /// Get function parameter values
75  ///
76  /// This function can be used to store a backup of the current funtion parameter
77  /// values before an update such that these can be restored using the Put
78  /// member function if the update did not result in the desired change of the
79  /// overall objective function value.
80  ///
81  /// \param[in] x Function parameter (DoF) values.
82  virtual void Get(double *x) const = 0;
83 
84  /// Add change (i.e., scaled gradient) to each parameter value
85  ///
86  /// This function updates each DoF of the objective function given a vector
87  /// of corresponding changes, i.e., the computed gradient of the objective
88  /// function w.r.t. these parameters or a desired change computed otherwise.
89  ///
90  /// \param[in,out] dx Change of each function parameter (DoF) as computed by the
91  /// Gradient member function and scaled by a chosen step length.
92  /// The change of a parameter may be modified by this function
93  /// in order to satisfy the hard constraints (if any).
94  ///
95  /// \returns Maximum change of function parameter.
96  virtual double Step(double *dx) = 0;
97 
98  /// Update internal state after change of parameters
99  ///
100  /// \param[in] gradient Update also internal state required for evaluation of
101  /// gradient of objective function.
102  virtual void Update(bool gradient = true);
103 
104  /// Update objective function after convergence
105  ///
106  /// This function may be called by the optimizer after the optimization of
107  /// the current objective function has converged or the improvement is
108  /// insignificant. It allows the objective function to modify itself
109  /// considering the current estimate of the parameters (DoFs). For example,
110  /// the fiducial registration error term of a registration energy function
111  /// could update the point correspondences.
112  ///
113  /// \returns Whether the objective function has changed.
114  virtual bool Upgrade();
115 
116  // ---------------------------------------------------------------------------
117  // Evaluation
118 
119  /// Evaluate objective function value
120  virtual double Value() = 0;
121 
122  /// Evaluate data fidelity gradient of objective function w.r.t its DoFs
123  ///
124  /// \param[in] step Step length for finite differences.
125  /// \param[out] dx Data fidelity gradient of objective function.
126  /// \param[out] sgn_chg Whether function parameter value is allowed to
127  /// change sign when stepping along the computed gradient.
128  virtual void DataFidelityGradient(double *dx, double step = .0, bool *sgn_chg = nullptr);
129 
130  /// Add model constraint gradient of objective function w.r.t its DoFs
131  ///
132  /// \param[in] step Step length for finite differences.
133  /// \param[out] dx Gradient of objective function, e.g., either initialised to zero or
134  /// the data fidelity gradient computed beforehand using DataFidelityGradient.
135  /// \param[out] sgn_chg Whether function parameter value is allowed to
136  /// change sign when stepping along the computed gradient.
137  virtual void AddConstraintGradient(double *dx, double step = .0, bool *sgn_chg = nullptr);
138 
139  /// Evaluate gradient of objective function w.r.t its DoFs
140  ///
141  /// When the data fidelity and/or gradient of model constraints need to be
142  /// evaluated separately, use the following code instead:
143  /// \code
144  /// double *gradient; // allocate with number of DoFs
145  /// ObjectiveFunction *func; // pointer to objective function instance
146  /// func->DataFideltiyGradient(gradient);
147  /// func->AddConstraintGradient(gradient);
148  /// \endcode
149  ///
150  /// \param[in] step Step length for finite differences.
151  /// \param[out] dx Gradient of objective function.
152  /// \param[out] sgn_chg Whether function parameter value is allowed to
153  /// change sign when stepping along the computed gradient.
154  virtual void Gradient(double *dx, double step = .0, bool *sgn_chg = nullptr) = 0;
155 
156  /// Compute norm of gradient of objective function
157  ///
158  /// This norm is used to define a unit for the step length used by gradient
159  /// descent methods. It is, for example, the maximum absolute value norm for
160  /// linear transformations and the maximum control point displacement for FFDs.
161  /// The computation of the norm may be done after conjugating the gradient
162  /// vector obtained using the Gradient member function.
163  ///
164  /// \param[in] dx Gradient of objective function.
165  virtual double GradientNorm(const double *dx) const = 0;
166 
167  /// Adjust step length range
168  ///
169  /// \param[in] dx Gradient of objective function.
170  /// \param[inout] min Minimum step length.
171  /// \param[inout] max Maximum step length.
172  virtual void GradientStep(const double *dx, double &min, double &max) const;
173 
174  /// Evaluate objective function
175  ///
176  /// This function first updates the internal state of the function object
177  /// if required due to a previous change of the function parameters and then
178  /// evaluates the current function value. If \p dx is not \c NULL, the
179  /// gradient of the objective function is computed as well.
180  ///
181  /// \param[in] step Step length for finite differences.
182  /// \param[out] dx Gradient of objective function.
183  /// If \c NULL, only the function value is computed.
184  /// \param[out] sgn_chg Whether function parameter value is allowed to
185  /// change sign when stepping along the computed gradient.
186  /// Ignord if \p dx is \c NULL.
187  ///
188  /// \returns Value of the objective function.
189  virtual double Evaluate(double *dx = NULL, double step = .0, bool *sgn_chg = NULL);
190 };
191 
192 ////////////////////////////////////////////////////////////////////////////////
193 // Inline definitions
194 ////////////////////////////////////////////////////////////////////////////////
195 
196 // -----------------------------------------------------------------------------
198 {
199 }
200 
201 // -----------------------------------------------------------------------------
202 inline void ObjectiveFunction::Update(bool)
203 {
204 }
205 
206 // -----------------------------------------------------------------------------
208 {
209  return false;
210 }
211 
212 // -----------------------------------------------------------------------------
213 inline void ObjectiveFunction::GradientStep(const double *, double &, double &) const
214 {
215  // By default, step length range chosen by user/optimizer
216 }
217 
218 // -----------------------------------------------------------------------------
219 inline void ObjectiveFunction::DataFidelityGradient(double *dx, double step, bool *sgn_chg)
220 {
221  // By default, objective function is not separated into data fidelity and constraint terms.
222  this->Gradient(dx, step, sgn_chg);
223 }
224 
225 // -----------------------------------------------------------------------------
226 inline void ObjectiveFunction::AddConstraintGradient(double *, double, bool *)
227 {
228  // By default, already included in DataFidelityGradient
229 }
230 
231 // -----------------------------------------------------------------------------
232 inline double ObjectiveFunction::Evaluate(double *dx, double step, bool *sgn_chg)
233 {
234  this->Update(dx != NULL);
235  if (dx) {
236  if (step <= .0) step = _StepLength;
237  this->Gradient(dx, step, sgn_chg);
238  }
239  return this->Value();
240 }
241 
242 
243 } // namespace mirtk
244 
245 #endif // MIRTK_ObjectiveFunction_H
virtual void AddConstraintGradient(double *dx, double step=.0, bool *sgn_chg=nullptr)
virtual double Step(double *dx)=0
virtual void Put(const double *x)=0
virtual double Get(int i) const =0
virtual int NumberOfDOFs() const =0
virtual double Evaluate(double *dx=NULL, double step=.0, bool *sgn_chg=NULL)
virtual void Update(bool gradient=true)
Definition: IOConfig.h:41
virtual void DataFidelityGradient(double *dx, double step=.0, bool *sgn_chg=nullptr)
mirtkAttributeMacro(double, StepLength)
Default step length used for gradient approximation.
virtual ~ObjectiveFunction()=0
Destructor.
virtual double Value()=0
Evaluate objective function value.
virtual double GradientNorm(const double *dx) const =0
virtual void GradientStep(const double *dx, double &min, double &max) const
virtual void Gradient(double *dx, double step=.0, bool *sgn_chg=nullptr)=0