00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef EIGEN_LEVENBERGMARQUARDT_H
00020 #define EIGEN_LEVENBERGMARQUARDT_H
00021
00022
00023 namespace Eigen {
00024 namespace LevenbergMarquardtSpace {
00025 enum Status {
00026 NotStarted = -2,
00027 Running = -1,
00028 ImproperInputParameters = 0,
00029 RelativeReductionTooSmall = 1,
00030 RelativeErrorTooSmall = 2,
00031 RelativeErrorAndReductionTooSmall = 3,
00032 CosinusTooSmall = 4,
00033 TooManyFunctionEvaluation = 5,
00034 FtolTooSmall = 6,
00035 XtolTooSmall = 7,
00036 GtolTooSmall = 8,
00037 UserAsked = 9
00038 };
00039 }
00040
00041 template <typename _Scalar, int NX=Dynamic, int NY=Dynamic>
00042 struct DenseFunctor
00043 {
00044 typedef _Scalar Scalar;
00045 enum {
00046 InputsAtCompileTime = NX,
00047 ValuesAtCompileTime = NY
00048 };
00049 typedef Matrix<Scalar,InputsAtCompileTime,1> InputType;
00050 typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
00051 typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
00052 typedef ColPivHouseholderQR<JacobianType> QRSolver;
00053 const int m_inputs, m_values;
00054
00055 DenseFunctor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
00056 DenseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
00057
00058 int inputs() const { return m_inputs; }
00059 int values() const { return m_values; }
00060
00061
00062
00063
00064
00065
00066 };
00067
00068 template <typename _Scalar, typename _Index>
00069 struct SparseFunctor
00070 {
00071 typedef _Scalar Scalar;
00072 typedef _Index Index;
00073 typedef Matrix<Scalar,Dynamic,1> InputType;
00074 typedef Matrix<Scalar,Dynamic,1> ValueType;
00075 typedef SparseMatrix<Scalar, ColMajor, Index> JacobianType;
00076 typedef SparseQR<JacobianType, COLAMDOrdering<int> > QRSolver;
00077 enum {
00078 InputsAtCompileTime = Dynamic,
00079 ValuesAtCompileTime = Dynamic
00080 };
00081
00082 SparseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
00083
00084 int inputs() const { return m_inputs; }
00085 int values() const { return m_values; }
00086
00087 const int m_inputs, m_values;
00088
00089
00090
00091
00092
00093
00094 };
00095 namespace internal {
00096 template <typename QRSolver, typename VectorType>
00097 void lmpar2(const QRSolver &qr, const VectorType &diag, const VectorType &qtb,
00098 typename VectorType::Scalar m_delta, typename VectorType::Scalar &par,
00099 VectorType &x);
00100 }
00109 template<typename _FunctorType>
00110 class LevenbergMarquardt : internal::no_assignment_operator
00111 {
00112 public:
00113 typedef _FunctorType FunctorType;
00114 typedef typename FunctorType::QRSolver QRSolver;
00115 typedef typename FunctorType::JacobianType JacobianType;
00116 typedef typename JacobianType::Scalar Scalar;
00117 typedef typename JacobianType::RealScalar RealScalar;
00118 typedef typename JacobianType::Index Index;
00119 typedef typename QRSolver::Index PermIndex;
00120 typedef Matrix<Scalar,Dynamic,1> FVectorType;
00121 typedef PermutationMatrix<Dynamic,Dynamic> PermutationType;
00122 public:
00123 LevenbergMarquardt(FunctorType& functor)
00124 : m_functor(functor),m_nfev(0),m_njev(0),m_fnorm(0.0),m_gnorm(0),
00125 m_isInitialized(false),m_info(InvalidInput)
00126 {
00127 resetParameters();
00128 m_useExternalScaling=false;
00129 }
00130
00131 LevenbergMarquardtSpace::Status minimize(FVectorType &x);
00132 LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x);
00133 LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x);
00134 LevenbergMarquardtSpace::Status lmder1(
00135 FVectorType &x,
00136 const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
00137 );
00138 static LevenbergMarquardtSpace::Status lmdif1(
00139 FunctorType &functor,
00140 FVectorType &x,
00141 Index *nfev,
00142 const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
00143 );
00144
00146 void resetParameters()
00147 {
00148 m_factor = 100.;
00149 m_maxfev = 400;
00150 m_ftol = std::sqrt(NumTraits<RealScalar>::epsilon());
00151 m_xtol = std::sqrt(NumTraits<RealScalar>::epsilon());
00152 m_gtol = 0. ;
00153 m_epsfcn = 0. ;
00154 }
00155
00157 void setXtol(RealScalar xtol) { m_xtol = xtol; }
00158
00160 void setFtol(RealScalar ftol) { m_ftol = ftol; }
00161
00163 void setGtol(RealScalar gtol) { m_gtol = gtol; }
00164
00166 void setFactor(RealScalar factor) { m_factor = factor; }
00167
00169 void setEpsilon (RealScalar epsfcn) { m_epsfcn = epsfcn; }
00170
00172 void setMaxfev(Index maxfev) {m_maxfev = maxfev; }
00173
00175 void setExternalScaling(bool value) {m_useExternalScaling = value; }
00176
00178 FVectorType& diag() {return m_diag; }
00179
00181 Index iterations() { return m_iter; }
00182
00184 Index nfev() { return m_nfev; }
00185
00187 Index njev() { return m_njev; }
00188
00190 RealScalar fnorm() {return m_fnorm; }
00191
00193 RealScalar gnorm() {return m_gnorm; }
00194
00196 RealScalar lm_param(void) { return m_par; }
00197
00200 FVectorType& fvec() {return m_fvec; }
00201
00204 JacobianType& jacobian() {return m_fjac; }
00205
00209 JacobianType& matrixR() {return m_rfactor; }
00210
00213 PermutationType permutation() {return m_permutation; }
00214
00224 ComputationInfo info() const
00225 {
00226
00227 return m_info;
00228 }
00229 private:
00230 JacobianType m_fjac;
00231 JacobianType m_rfactor;
00232 FunctorType &m_functor;
00233 FVectorType m_fvec, m_qtf, m_diag;
00234 Index n;
00235 Index m;
00236 Index m_nfev;
00237 Index m_njev;
00238 RealScalar m_fnorm;
00239 RealScalar m_gnorm;
00240 RealScalar m_factor;
00241 Index m_maxfev;
00242 RealScalar m_ftol;
00243 RealScalar m_xtol;
00244 RealScalar m_gtol;
00245 RealScalar m_epsfcn;
00246 Index m_iter;
00247 RealScalar m_delta;
00248 bool m_useExternalScaling;
00249 PermutationType m_permutation;
00250 FVectorType m_wa1, m_wa2, m_wa3, m_wa4;
00251 RealScalar m_par;
00252 bool m_isInitialized;
00253 ComputationInfo m_info;
00254 };
00255
00256 template<typename FunctorType>
00257 LevenbergMarquardtSpace::Status
00258 LevenbergMarquardt<FunctorType>::minimize(FVectorType &x)
00259 {
00260 LevenbergMarquardtSpace::Status status = minimizeInit(x);
00261 if (status==LevenbergMarquardtSpace::ImproperInputParameters) {
00262 m_isInitialized = true;
00263 return status;
00264 }
00265 do {
00266
00267 status = minimizeOneStep(x);
00268 } while (status==LevenbergMarquardtSpace::Running);
00269 m_isInitialized = true;
00270 return status;
00271 }
00272
00273 template<typename FunctorType>
00274 LevenbergMarquardtSpace::Status
00275 LevenbergMarquardt<FunctorType>::minimizeInit(FVectorType &x)
00276 {
00277 n = x.size();
00278 m = m_functor.values();
00279
00280 m_wa1.resize(n); m_wa2.resize(n); m_wa3.resize(n);
00281 m_wa4.resize(m);
00282 m_fvec.resize(m);
00283
00284 m_fjac.resize(m, n);
00285
00286 if (!m_useExternalScaling)
00287 m_diag.resize(n);
00288 eigen_assert( (!m_useExternalScaling || m_diag.size()==n) || "When m_useExternalScaling is set, the caller must provide a valid 'm_diag'");
00289 m_qtf.resize(n);
00290
00291
00292 m_nfev = 0;
00293 m_njev = 0;
00294
00295
00296 if (n <= 0 || m < n || m_ftol < 0. || m_xtol < 0. || m_gtol < 0. || m_maxfev <= 0 || m_factor <= 0.){
00297 m_info = InvalidInput;
00298 return LevenbergMarquardtSpace::ImproperInputParameters;
00299 }
00300
00301 if (m_useExternalScaling)
00302 for (Index j = 0; j < n; ++j)
00303 if (m_diag[j] <= 0.)
00304 {
00305 m_info = InvalidInput;
00306 return LevenbergMarquardtSpace::ImproperInputParameters;
00307 }
00308
00309
00310
00311 m_nfev = 1;
00312 if ( m_functor(x, m_fvec) < 0)
00313 return LevenbergMarquardtSpace::UserAsked;
00314 m_fnorm = m_fvec.stableNorm();
00315
00316
00317 m_par = 0.;
00318 m_iter = 1;
00319
00320 return LevenbergMarquardtSpace::NotStarted;
00321 }
00322
00323 template<typename FunctorType>
00324 LevenbergMarquardtSpace::Status
00325 LevenbergMarquardt<FunctorType>::lmder1(
00326 FVectorType &x,
00327 const Scalar tol
00328 )
00329 {
00330 n = x.size();
00331 m = m_functor.values();
00332
00333
00334 if (n <= 0 || m < n || tol < 0.)
00335 return LevenbergMarquardtSpace::ImproperInputParameters;
00336
00337 resetParameters();
00338 m_ftol = tol;
00339 m_xtol = tol;
00340 m_maxfev = 100*(n+1);
00341
00342 return minimize(x);
00343 }
00344
00345
00346 template<typename FunctorType>
00347 LevenbergMarquardtSpace::Status
00348 LevenbergMarquardt<FunctorType>::lmdif1(
00349 FunctorType &functor,
00350 FVectorType &x,
00351 Index *nfev,
00352 const Scalar tol
00353 )
00354 {
00355 Index n = x.size();
00356 Index m = functor.values();
00357
00358
00359 if (n <= 0 || m < n || tol < 0.)
00360 return LevenbergMarquardtSpace::ImproperInputParameters;
00361
00362 NumericalDiff<FunctorType> numDiff(functor);
00363
00364 LevenbergMarquardt<NumericalDiff<FunctorType> > lm(numDiff);
00365 lm.setFtol(tol);
00366 lm.setXtol(tol);
00367 lm.setMaxfev(200*(n+1));
00368
00369 LevenbergMarquardtSpace::Status info = LevenbergMarquardtSpace::Status(lm.minimize(x));
00370 if (nfev)
00371 * nfev = lm.nfev();
00372 return info;
00373 }
00374
00375 }
00376
00377 #endif // EIGEN_LEVENBERGMARQUARDT_H