Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
LevenbergMarquardtBase.hh
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #ifndef _LevenbergMarquardtBase_hh_
26 #define _LevenbergMarquardtBase_hh_
27 
28 #include <bias_config.h>
29 #include <Base/Math/Matrix.hh>
30 #include <Base/Math/Vector.hh>
31 #include <MathAlgo/Minpack.hh>
32 #include <MathAlgo/minpack/cminpack.h>
33 #include <stdio.h>
34 
35 namespace BIAS {
36 
37 /** @class LevenbergMarquardtBase
38  @brief Base interface for classes using non-linear optimization of
39  a target function using the Levenberg-Marquardt algorithm.
40 
41  @note Since this class used virtual function calls to evaluate the
42  target function of the Levenber-Marquardt instance, and data
43  is copied between BIAS data structure and arrays in every
44  iteration, it is not well suited for high-performance demands!
45  Use the direct Minpack interface from Minpack.hh instead when
46  you are targeting at performance!
47 
48  Provides a class interface to Minpack with convenient definition of
49  target function f(x) and Jacobian J(x).
50  @see Minpack.hh
51 
52  @author esquivel
53  @date 05/2010
54 */
55 
56  class BIASMathAlgo_EXPORT LevenbergMarquardtBase
57  {
58 
59  private:
60 
61  /// @brief Tolerance for Levenberg-Marquardt optimization
62  double LM_tolerance_;
63 
64  /// @brief Max. number of iterations for Levenberg-Marquardt algorithm
65  int LM_maxIters_;
66 
67  /// @brief Variables to store results of current computation step
68  double LM_squaredSum_;
69  int LM_numIters_;
70  BIAS::Vector<double> LM_parameters_;
71  BIAS::Vector<double> LM_residuals_;
72  BIAS::Matrix<double> LM_Jacobian_;
73 
74  public:
75 
77  {
78  LM_tolerance_ = MINPACK_DEF_TOLERANCE;
79  LM_maxIters_ = LM_DEF_MAX_ITER;
80  LM_squaredSum_ = 0;
81  LM_numIters_ = 0;
82  }
83 
85 
86  protected:
87 
88  /// @brief Compute residuals of target function f for input vector x.
89  /// @note Override this with the user specified target function.
90  virtual int LM_TargetFunction_(const BIAS::Vector<double> &x,
91  BIAS::Vector<double> &residuals) = 0;
92 
93  /// @brief Compute Jacobian J(x) of target function f evaluated at vector x
94  /// @note Override this with the user specified Jacobian function.
95  /// Otherwise, only a numerical approximation of J(x) will be used.
98  {
99  BIASERR("No analytic Jacobian defined for target function!");
100  BIASABORT;
101  return 0; // added to appease windows compiler
102  }
103 
104  public:
105 
106  /// @brief Set tolerance used to evaluate convergence
107  inline void LM_SetTolerance(const double tol)
108  { LM_tolerance_ = (tol > 0 ? tol : MINPACK_DEF_TOLERANCE); }
109 
110  /// @brief Return tolerance used to evaluate convergence
111  inline double LM_GetTolerance() const
112  { return LM_tolerance_; }
113 
114  /// @brief Set the maximal number of iterations to perform
115  inline void LM_SetMaxIterations(const int iters)
116  { LM_maxIters_ = (iters > 0 ? iters : LM_DEF_MAX_ITER); }
117 
118  /// @brief Return the maximal number of iterations to perform
119  inline int LM_GetMaxIterations() const
120  { return LM_maxIters_; }
121 
122  /// @brief Return the sum of squared errors from the last computation
123  inline double LM_GetSumOfSquaredErrors() const
124  { return LM_squaredSum_; }
125 
126  /// @brief Return the number of iterations performed in last computation
127  inline int LM_GetNumOfIterations() const
128  { return LM_numIters_; }
129 
130  /// @brief Return the resulting parameter vector x from last computation
132  { return LM_parameters_; }
133 
134  /// @brief Return the resulting residual vector f(x) from last computation
136  { return LM_residuals_; }
137 
138  /// @brief Return the resulting Jacobian J(x) from the last computation
140  { return LM_Jacobian_; }
141 
142  /** @brief Compute Levenberg-Marquardt algorithm using the user defined
143  target function f(x) implemented in LM_TargetFunction_,
144  and the analytic Jacobian J(x) implemented in LM_Jacobian_.
145  @return Returns value < 0 if computation failed, 0 for convergence,
146  and > 0 otherwise (see #LevenbergMarquardt in #Minpack.hh).
147  */
148  int LM_Compute(const int numResiduals, const int numParameters,
149  BIAS::Vector<double> &startX, BIAS::Vector<double> &resultX,
150  BIAS::Vector<double> &residuals);
151 
152  /** @brief Compute Levenberg-Marquardt algorithm using the user defined
153  target function f(x) implemented in LM_TargetFunction_.
154  The Jacobian of f is approximated numerically using the given
155  value epsilon.
156  @param epsilon is "an input variable used in determining a suitable
157  step length for the forward-difference approximation" of the
158  Jacobian of f (see documentation of minpack/fdjac2.c)
159  @return Returns value < 0 if computation failed, 0 for convergence,
160  and > 0 otherwise (see #LevenbergMarquardt in #Minpack.hh).
161  */
162  int LM_ComputeWithoutJacobian(const int numResiduals,
163  const int numParameters,
164  BIAS::Vector<double> &startX,
165  BIAS::Vector<double> &resultX,
166  BIAS::Vector<double> &residuals,
167  const double epsilon = LM_DEF_EPSILON);
168 
169  private:
170 
171  /// @brief Static target function with derivatives used by minpack
172  inline static int g_MinpackFunction(void *ptr, int m, int n,
173  const double *x,
174  double *fvec, double *fjac,
175  int ldfjac, int iflag)
176  {
177  LevenbergMarquardtBase *LM = static_cast<LevenbergMarquardtBase *>(ptr);
178  BIASASSERT(LM);
179  return LM->MinpackFunction_(m, n, x, fvec, fjac, ldfjac, iflag);
180  }
181 
182  /// @brief Static target function w/o derivatives used by minpack
183  inline static int g_MinpackFunctionWithoutJacobian(void *ptr, int m, int n,
184  const double *x,
185  double *fvec, int iflag)
186  {
187  LevenbergMarquardtBase *LM = static_cast<LevenbergMarquardtBase *>(ptr);
188  BIASASSERT(LM);
189  return LM->MinpackFunctionWithoutJacobian_(m, n, x, fvec, iflag);
190  }
191 
192  /// @brief Instance target function with derivatives used by minpack.
193  /// Calls either the user defined target function f(x) or computes
194  /// the Jacobian matrix J(x) for the current parameters x.
195  inline int MinpackFunction_(int m, int n, const double *x, double *fvec,
196  double *fjac, int ldfjac, int iflag)
197  {
198  int res = -1;
199  memcpy(LM_parameters_.GetData(), x, n * sizeof(double));
200  if (iflag == 1)
201  {
202  // Compute target function f(x) and store results internally
203  res = LM_TargetFunction_(LM_parameters_, LM_residuals_);
204  memcpy(fvec, LM_residuals_.GetData(), m * sizeof(double));
205  LM_numIters_++; // count evaluations of target function
206  }
207  else if (iflag == 2)
208  {
209  // Compute Jacobian J(x) and store results internally
210  res = LM_JacobianFunction_(LM_parameters_, LM_Jacobian_);
211  // @todo Test leading dimension ldfjac here!
212  double *f = fjac;
213  for (int i = 0; i < n; i++)
214  for (int j = 0; j < m; j++)
215  *(f++) = LM_Jacobian_[j][i];
216  }
217  else
218  {
219  // @todo What about other values for iflag?
220  res = iflag;
221  }
222  return res;
223  }
224 
225  /// @brief Instance target function w/o derivatives used by minpack.
226  /// Simply calls the user defined target function f(x) for
227  /// the current parameters x.
228  inline int MinpackFunctionWithoutJacobian_(int m, int n, const double *x,
229  double *fvec, int iflag)
230  {
231  int res = -1;
232  memcpy(LM_parameters_.GetData(), x, n * sizeof(double));
233  if (iflag == 0 || iflag == 1)
234  {
235  // Compute target function f(x) and store results internally
236  res = LM_TargetFunction_(LM_parameters_, LM_residuals_);
237  memcpy(fvec, LM_residuals_.GetData(), m * sizeof(double));
238  LM_numIters_++; // count evaluations of target function
239  }
240  else
241  {
242  // @todo What about other values for iflag?
243  res = iflag;
244  }
245  return res;
246  }
247 
248  };
249 }
250 #endif // _LevenbergMarquardtBase_hh_
BIAS::Vector< double > LM_GetParameterResult() const
Return the resulting parameter vector x from last computation.
Base interface for classes using non-linear optimization of a target function using the Levenberg-Mar...
int LM_GetMaxIterations() const
Return the maximal number of iterations to perform.
void LM_SetTolerance(const double tol)
Set tolerance used to evaluate convergence.
virtual int LM_JacobianFunction_(const BIAS::Vector< double > &x, BIAS::Matrix< double > &J)
Compute Jacobian J(x) of target function f evaluated at vector x.
double LM_GetSumOfSquaredErrors() const
Return the sum of squared errors from the last computation.
void LM_SetMaxIterations(const int iters)
Set the maximal number of iterations to perform.
BIAS::Vector< double > LM_GetResidualsResult() const
Return the resulting residual vector f(x) from last computation.
BIAS::Matrix< double > LM_GetJacobianResult() const
Return the resulting Jacobian J(x) from the last computation.
int LM_GetNumOfIterations() const
Return the number of iterations performed in last computation.
double LM_GetTolerance() const
Return tolerance used to evaluate convergence.