13 #ifndef EIGEN_LEVENBERGMARQUARDT__H 14 #define EIGEN_LEVENBERGMARQUARDT__H 18 namespace LevenbergMarquardtSpace {
45 template<
typename FunctorType,
typename Scalar=
double>
50 : functor(_functor) { nfev = njev = iter = 0; fnorm = gnorm = 0.; useExternalScaling=
false; }
56 : factor(Scalar(100.))
61 , epsfcn(Scalar(0.)) {}
101 FVectorType fvec,
qtf, diag;
115 FVectorType wa1, wa2, wa3,
wa4;
121 Scalar pnorm,
xnorm, fnorm1, actred, dirder, prered;
126 template<
typename FunctorType,
typename Scalar>
134 m = functor.values();
137 if (n <= 0 || m < n || tol < 0.)
141 parameters.ftol = tol;
142 parameters.xtol = tol;
143 parameters.maxfev = 100*(n+1);
149 template<
typename FunctorType,
typename Scalar>
157 status = minimizeOneStep(x);
162 template<
typename FunctorType,
typename Scalar>
167 m = functor.values();
169 wa1.
resize(n); wa2.resize(n); wa3.resize(n);
173 if (!useExternalScaling)
175 eigen_assert( (!useExternalScaling || diag.size()==n) ||
"When useExternalScaling is set, the caller must provide a valid 'diag'");
183 if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0.)
186 if (useExternalScaling)
187 for (Index j = 0; j < n; ++j)
194 if ( functor(x, fvec) < 0)
196 fnorm = fvec.stableNorm();
205 template<
typename FunctorType,
typename Scalar>
215 Index df_ret = functor.df(x, fjac);
224 wa2 = fjac.colwise().blueNorm();
232 if (!useExternalScaling)
233 for (Index j = 0; j < n; ++j)
234 diag[j] = (wa2[j]==0.)? 1. : wa2[j];
238 xnorm = diag.cwiseProduct(x).stableNorm();
239 delta = parameters.factor * xnorm;
241 delta = parameters.factor;
253 for (Index j = 0; j < n; ++j)
254 if (wa2[permutation.indices()[j]] != 0.)
255 gnorm = (std::max)(gnorm,
abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
258 if (gnorm <= parameters.gtol)
262 if (!useExternalScaling)
263 diag = diag.cwiseMax(wa2);
268 internal::lmpar2<Scalar>(qrfac, diag, qtf, delta,
par, wa1);
273 pnorm = diag.cwiseProduct(wa1).stableNorm();
277 delta = (std::min)(delta,pnorm);
280 if ( functor(wa2, wa4) < 0)
283 fnorm1 = wa4.stableNorm();
287 if (Scalar(.1) * fnorm1 < fnorm)
292 wa3 = fjac.template triangularView<Upper>() * (qrfac.colsPermutation().inverse() *wa1);
295 prered = temp1 + temp2 / Scalar(.5);
296 dirder = -(temp1 + temp2);
302 ratio = actred / prered;
305 if (ratio <= Scalar(.25)) {
309 temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred);
310 if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1))
313 delta = temp * (std::min)(delta, pnorm / Scalar(.1));
315 }
else if (!(par != 0. && ratio < Scalar(.75))) {
316 delta = pnorm / Scalar(.5);
317 par = Scalar(.5) *
par;
321 if (ratio >= Scalar(1e-4)) {
324 wa2 = diag.cwiseProduct(x);
326 xnorm = wa2.stableNorm();
332 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
334 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
336 if (delta <= parameters.xtol * xnorm)
340 if (nfev >= parameters.maxfev)
349 }
while (ratio < Scalar(1e-4));
354 template<
typename FunctorType,
typename Scalar>
362 m = functor.values();
365 if (n <= 0 || m < n || tol < 0.)
369 parameters.ftol = tol;
370 parameters.xtol = tol;
371 parameters.maxfev = 100*(n+1);
373 return minimizeOptimumStorage(x);
376 template<
typename FunctorType,
typename Scalar>
381 m = functor.values();
383 wa1.
resize(n); wa2.resize(n); wa3.resize(n);
392 if (!useExternalScaling)
394 eigen_assert( (!useExternalScaling || diag.size()==n) ||
"When useExternalScaling is set, the caller must provide a valid 'diag'");
402 if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0.)
405 if (useExternalScaling)
406 for (Index j = 0; j < n; ++j)
413 if ( functor(x, fvec) < 0)
415 fnorm = fvec.stableNorm();
425 template<
typename FunctorType,
typename Scalar>
444 for (i = 0; i < m; ++i) {
446 internal::rwupdt<Scalar>(fjac, wa3, qtf, fvec[i]);
454 for (j = 0; j < n; ++j) {
457 wa2[j] = fjac.col(j).head(j).stableNorm();
459 permutation.setIdentity(n);
461 wa2 = fjac.colwise().blueNorm();
466 wa1 = fjac.diagonal();
467 fjac.diagonal() = qrfac.
hCoeffs();
470 for(Index ii=0; ii< fjac.cols(); ii++) fjac.col(ii).segment(ii+1, fjac.rows()-ii-1) *= fjac(ii,ii);
472 for (j = 0; j < n; ++j) {
473 if (fjac(j,j) != 0.) {
475 for (i = j; i < n; ++i)
476 sum += fjac(i,j) * qtf[i];
477 temp = -sum / fjac(j,j);
478 for (i = j; i < n; ++i)
479 qtf[i] += fjac(i,j) * temp;
488 if (!useExternalScaling)
489 for (j = 0; j < n; ++j)
490 diag[j] = (wa2[j]==0.)? 1. : wa2[j];
494 xnorm = diag.cwiseProduct(x).stableNorm();
495 delta = parameters.factor * xnorm;
497 delta = parameters.factor;
503 for (j = 0; j < n; ++j)
504 if (wa2[permutation.indices()[j]] != 0.)
505 gnorm = (std::max)(gnorm,
abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
508 if (gnorm <= parameters.gtol)
512 if (!useExternalScaling)
513 diag = diag.cwiseMax(wa2);
518 internal::lmpar<Scalar>(fjac, permutation.indices(), diag, qtf, delta,
par, wa1);
523 pnorm = diag.cwiseProduct(wa1).stableNorm();
527 delta = (std::min)(delta,pnorm);
530 if ( functor(wa2, wa4) < 0)
533 fnorm1 = wa4.stableNorm();
537 if (Scalar(.1) * fnorm1 < fnorm)
542 wa3 = fjac.topLeftCorner(n,n).template triangularView<Upper>() * (permutation.inverse() * wa1);
545 prered = temp1 + temp2 / Scalar(.5);
546 dirder = -(temp1 + temp2);
552 ratio = actred / prered;
555 if (ratio <= Scalar(.25)) {
559 temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred);
560 if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1))
563 delta = temp * (std::min)(delta, pnorm / Scalar(.1));
565 }
else if (!(par != 0. && ratio < Scalar(.75))) {
566 delta = pnorm / Scalar(.5);
567 par = Scalar(.5) *
par;
571 if (ratio >= Scalar(1e-4)) {
574 wa2 = diag.cwiseProduct(x);
576 xnorm = wa2.stableNorm();
582 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
584 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
586 if (delta <= parameters.xtol * xnorm)
590 if (nfev >= parameters.maxfev)
599 }
while (ratio < Scalar(1e-4));
604 template<
typename FunctorType,
typename Scalar>
612 status = minimizeOptimumStorageOneStep(x);
617 template<
typename FunctorType,
typename Scalar>
620 FunctorType &functor,
627 Index m = functor.values();
630 if (n <= 0 || m < n || tol < 0.)
648 #endif // EIGEN_LEVENBERGMARQUARDT__H
const PermutationType & colsPermutation() const
LevenbergMarquardtSpace::Status minimize(FVectorType &x)
static LevenbergMarquardtSpace::Status lmdif1(FunctorType &functor, FVectorType &x, Index *nfev, const Scalar tol=std::sqrt(NumTraits< Scalar >::epsilon()))
IntermediateState sqrt(const Expression &arg)
LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x)
Performs non linear optimization over a non-linear function, using a variant of the Levenberg Marquar...
LevenbergMarquardtSpace::Status minimizeOptimumStorageInit(FVectorType &x)
iterative scaling algorithm to equilibrate rows and column norms in matrices
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
EIGEN_STRONG_INLINE const CwiseUnaryOp< internal::scalar_abs2_op< Scalar >, const Derived > abs2() const
EIGEN_STRONG_INLINE const CwiseUnaryOp< internal::scalar_abs_op< Scalar >, const Derived > abs() const
void resetParameters(void)
LevenbergMarquardtSpace::Status lmstr1(FVectorType &x, const Scalar tol=std::sqrt(NumTraits< Scalar >::epsilon()))
HouseholderSequenceType householderQ(void) const
Householder rank-revealing QR decomposition of a matrix with column-pivoting.
const MatrixType & matrixQR() const
EIGEN_STRONG_INLINE void resize(Index nbRows, Index nbCols)
PermutationMatrix< Dynamic, Dynamic > permutation
const HCoeffsType & hCoeffs() const
Matrix< Scalar, Dynamic, Dynamic > JacobianType
Matrix< Scalar, Dynamic, 1 > FVectorType
LevenbergMarquardtSpace::Status minimizeOptimumStorageOneStep(FVectorType &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex
LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x)
LevenbergMarquardtSpace::Status minimizeOptimumStorage(FVectorType &x)
LevenbergMarquardtSpace::Status lmder1(FVectorType &x, const Scalar tol=std::sqrt(NumTraits< Scalar >::epsilon()))
LevenbergMarquardt(FunctorType &_functor)