File indexing completed on 2025-01-18 09:57:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef EIGEN_LEVENBERGMARQUARDT_H
0020 #define EIGEN_LEVENBERGMARQUARDT_H
0021
0022
0023 namespace Eigen {
0024 namespace LevenbergMarquardtSpace {
0025 enum Status {
0026 NotStarted = -2,
0027 Running = -1,
0028 ImproperInputParameters = 0,
0029 RelativeReductionTooSmall = 1,
0030 RelativeErrorTooSmall = 2,
0031 RelativeErrorAndReductionTooSmall = 3,
0032 CosinusTooSmall = 4,
0033 TooManyFunctionEvaluation = 5,
0034 FtolTooSmall = 6,
0035 XtolTooSmall = 7,
0036 GtolTooSmall = 8,
0037 UserAsked = 9
0038 };
0039 }
0040
0041 template <typename _Scalar, int NX=Dynamic, int NY=Dynamic>
0042 struct DenseFunctor
0043 {
0044 typedef _Scalar Scalar;
0045 enum {
0046 InputsAtCompileTime = NX,
0047 ValuesAtCompileTime = NY
0048 };
0049 typedef Matrix<Scalar,InputsAtCompileTime,1> InputType;
0050 typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
0051 typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
0052 typedef ColPivHouseholderQR<JacobianType> QRSolver;
0053 const int m_inputs, m_values;
0054
0055 DenseFunctor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
0056 DenseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
0057
0058 int inputs() const { return m_inputs; }
0059 int values() const { return m_values; }
0060
0061
0062
0063
0064
0065
0066 };
0067
0068 template <typename _Scalar, typename _Index>
0069 struct SparseFunctor
0070 {
0071 typedef _Scalar Scalar;
0072 typedef _Index Index;
0073 typedef Matrix<Scalar,Dynamic,1> InputType;
0074 typedef Matrix<Scalar,Dynamic,1> ValueType;
0075 typedef SparseMatrix<Scalar, ColMajor, Index> JacobianType;
0076 typedef SparseQR<JacobianType, COLAMDOrdering<int> > QRSolver;
0077 enum {
0078 InputsAtCompileTime = Dynamic,
0079 ValuesAtCompileTime = Dynamic
0080 };
0081
0082 SparseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
0083
0084 int inputs() const { return m_inputs; }
0085 int values() const { return m_values; }
0086
0087 const int m_inputs, m_values;
0088
0089
0090
0091
0092
0093
0094 };
0095 namespace internal {
0096 template <typename QRSolver, typename VectorType>
0097 void lmpar2(const QRSolver &qr, const VectorType &diag, const VectorType &qtb,
0098 typename VectorType::Scalar m_delta, typename VectorType::Scalar &par,
0099 VectorType &x);
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109 template<typename _FunctorType>
0110 class LevenbergMarquardt : internal::no_assignment_operator
0111 {
0112 public:
0113 typedef _FunctorType FunctorType;
0114 typedef typename FunctorType::QRSolver QRSolver;
0115 typedef typename FunctorType::JacobianType JacobianType;
0116 typedef typename JacobianType::Scalar Scalar;
0117 typedef typename JacobianType::RealScalar RealScalar;
0118 typedef typename QRSolver::StorageIndex PermIndex;
0119 typedef Matrix<Scalar,Dynamic,1> FVectorType;
0120 typedef PermutationMatrix<Dynamic,Dynamic,int> PermutationType;
0121 public:
0122 LevenbergMarquardt(FunctorType& functor)
0123 : m_functor(functor),m_nfev(0),m_njev(0),m_fnorm(0.0),m_gnorm(0),
0124 m_isInitialized(false),m_info(InvalidInput)
0125 {
0126 resetParameters();
0127 m_useExternalScaling=false;
0128 }
0129
0130 LevenbergMarquardtSpace::Status minimize(FVectorType &x);
0131 LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x);
0132 LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x);
0133 LevenbergMarquardtSpace::Status lmder1(
0134 FVectorType &x,
0135 const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
0136 );
0137 static LevenbergMarquardtSpace::Status lmdif1(
0138 FunctorType &functor,
0139 FVectorType &x,
0140 Index *nfev,
0141 const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon())
0142 );
0143
0144
0145 void resetParameters()
0146 {
0147 using std::sqrt;
0148
0149 m_factor = 100.;
0150 m_maxfev = 400;
0151 m_ftol = sqrt(NumTraits<RealScalar>::epsilon());
0152 m_xtol = sqrt(NumTraits<RealScalar>::epsilon());
0153 m_gtol = 0. ;
0154 m_epsfcn = 0. ;
0155 }
0156
0157
0158 void setXtol(RealScalar xtol) { m_xtol = xtol; }
0159
0160
0161 void setFtol(RealScalar ftol) { m_ftol = ftol; }
0162
0163
0164 void setGtol(RealScalar gtol) { m_gtol = gtol; }
0165
0166
0167 void setFactor(RealScalar factor) { m_factor = factor; }
0168
0169
0170 void setEpsilon (RealScalar epsfcn) { m_epsfcn = epsfcn; }
0171
0172
0173 void setMaxfev(Index maxfev) {m_maxfev = maxfev; }
0174
0175
0176 void setExternalScaling(bool value) {m_useExternalScaling = value; }
0177
0178
0179 RealScalar xtol() const {return m_xtol; }
0180
0181
0182 RealScalar ftol() const {return m_ftol; }
0183
0184
0185 RealScalar gtol() const {return m_gtol; }
0186
0187
0188 RealScalar factor() const {return m_factor; }
0189
0190
0191 RealScalar epsilon() const {return m_epsfcn; }
0192
0193
0194 Index maxfev() const {return m_maxfev; }
0195
0196
0197 FVectorType& diag() {return m_diag; }
0198
0199
0200 Index iterations() { return m_iter; }
0201
0202
0203 Index nfev() { return m_nfev; }
0204
0205
0206 Index njev() { return m_njev; }
0207
0208
0209 RealScalar fnorm() {return m_fnorm; }
0210
0211
0212 RealScalar gnorm() {return m_gnorm; }
0213
0214
0215 RealScalar lm_param(void) { return m_par; }
0216
0217
0218
0219 FVectorType& fvec() {return m_fvec; }
0220
0221
0222
0223 JacobianType& jacobian() {return m_fjac; }
0224
0225
0226
0227
0228 JacobianType& matrixR() {return m_rfactor; }
0229
0230
0231
0232 PermutationType permutation() {return m_permutation; }
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 ComputationInfo info() const
0244 {
0245
0246 return m_info;
0247 }
0248 private:
0249 JacobianType m_fjac;
0250 JacobianType m_rfactor;
0251 FunctorType &m_functor;
0252 FVectorType m_fvec, m_qtf, m_diag;
0253 Index n;
0254 Index m;
0255 Index m_nfev;
0256 Index m_njev;
0257 RealScalar m_fnorm;
0258 RealScalar m_gnorm;
0259 RealScalar m_factor;
0260 Index m_maxfev;
0261 RealScalar m_ftol;
0262 RealScalar m_xtol;
0263 RealScalar m_gtol;
0264 RealScalar m_epsfcn;
0265 Index m_iter;
0266 RealScalar m_delta;
0267 bool m_useExternalScaling;
0268 PermutationType m_permutation;
0269 FVectorType m_wa1, m_wa2, m_wa3, m_wa4;
0270 RealScalar m_par;
0271 bool m_isInitialized;
0272 ComputationInfo m_info;
0273 };
0274
0275 template<typename FunctorType>
0276 LevenbergMarquardtSpace::Status
0277 LevenbergMarquardt<FunctorType>::minimize(FVectorType &x)
0278 {
0279 LevenbergMarquardtSpace::Status status = minimizeInit(x);
0280 if (status==LevenbergMarquardtSpace::ImproperInputParameters) {
0281 m_isInitialized = true;
0282 return status;
0283 }
0284 do {
0285
0286 status = minimizeOneStep(x);
0287 } while (status==LevenbergMarquardtSpace::Running);
0288 m_isInitialized = true;
0289 return status;
0290 }
0291
0292 template<typename FunctorType>
0293 LevenbergMarquardtSpace::Status
0294 LevenbergMarquardt<FunctorType>::minimizeInit(FVectorType &x)
0295 {
0296 n = x.size();
0297 m = m_functor.values();
0298
0299 m_wa1.resize(n); m_wa2.resize(n); m_wa3.resize(n);
0300 m_wa4.resize(m);
0301 m_fvec.resize(m);
0302
0303 m_fjac.resize(m, n);
0304
0305 if (!m_useExternalScaling)
0306 m_diag.resize(n);
0307 eigen_assert( (!m_useExternalScaling || m_diag.size()==n) && "When m_useExternalScaling is set, the caller must provide a valid 'm_diag'");
0308 m_qtf.resize(n);
0309
0310
0311 m_nfev = 0;
0312 m_njev = 0;
0313
0314
0315 if (n <= 0 || m < n || m_ftol < 0. || m_xtol < 0. || m_gtol < 0. || m_maxfev <= 0 || m_factor <= 0.){
0316 m_info = InvalidInput;
0317 return LevenbergMarquardtSpace::ImproperInputParameters;
0318 }
0319
0320 if (m_useExternalScaling)
0321 for (Index j = 0; j < n; ++j)
0322 if (m_diag[j] <= 0.)
0323 {
0324 m_info = InvalidInput;
0325 return LevenbergMarquardtSpace::ImproperInputParameters;
0326 }
0327
0328
0329
0330 m_nfev = 1;
0331 if ( m_functor(x, m_fvec) < 0)
0332 return LevenbergMarquardtSpace::UserAsked;
0333 m_fnorm = m_fvec.stableNorm();
0334
0335
0336 m_par = 0.;
0337 m_iter = 1;
0338
0339 return LevenbergMarquardtSpace::NotStarted;
0340 }
0341
0342 template<typename FunctorType>
0343 LevenbergMarquardtSpace::Status
0344 LevenbergMarquardt<FunctorType>::lmder1(
0345 FVectorType &x,
0346 const Scalar tol
0347 )
0348 {
0349 n = x.size();
0350 m = m_functor.values();
0351
0352
0353 if (n <= 0 || m < n || tol < 0.)
0354 return LevenbergMarquardtSpace::ImproperInputParameters;
0355
0356 resetParameters();
0357 m_ftol = tol;
0358 m_xtol = tol;
0359 m_maxfev = 100*(n+1);
0360
0361 return minimize(x);
0362 }
0363
0364
0365 template<typename FunctorType>
0366 LevenbergMarquardtSpace::Status
0367 LevenbergMarquardt<FunctorType>::lmdif1(
0368 FunctorType &functor,
0369 FVectorType &x,
0370 Index *nfev,
0371 const Scalar tol
0372 )
0373 {
0374 Index n = x.size();
0375 Index m = functor.values();
0376
0377
0378 if (n <= 0 || m < n || tol < 0.)
0379 return LevenbergMarquardtSpace::ImproperInputParameters;
0380
0381 NumericalDiff<FunctorType> numDiff(functor);
0382
0383 LevenbergMarquardt<NumericalDiff<FunctorType> > lm(numDiff);
0384 lm.setFtol(tol);
0385 lm.setXtol(tol);
0386 lm.setMaxfev(200*(n+1));
0387
0388 LevenbergMarquardtSpace::Status info = LevenbergMarquardtSpace::Status(lm.minimize(x));
0389 if (nfev)
0390 * nfev = lm.nfev();
0391 return info;
0392 }
0393
0394 }
0395
0396 #endif