13 #ifndef EIGEN_LEVENBERGMARQUARDT__H 14 #define EIGEN_LEVENBERGMARQUARDT__H 18 namespace LevenbergMarquardtSpace {
45 template<
typename FunctorType,
typename Scalar=
double>
56 : functor(_functor) { nfev = njev = iter = 0; fnorm = gnorm = 0.; useExternalScaling=
false; }
64 , ftol(sqrt_epsilon())
65 , xtol(sqrt_epsilon())
81 const Scalar tol = sqrt_epsilon()
92 const Scalar tol = sqrt_epsilon()
97 const Scalar tol = sqrt_epsilon()
107 FVectorType fvec,
qtf, diag;
122 FVectorType wa1, wa2, wa3,
wa4;
133 template<
typename FunctorType,
typename Scalar>
141 m = functor.values();
144 if (n <= 0 || m < n || tol < 0.)
148 parameters.ftol = tol;
149 parameters.xtol = tol;
150 parameters.maxfev = 100*(n+1);
156 template<
typename FunctorType,
typename Scalar>
164 status = minimizeOneStep(x);
169 template<
typename FunctorType,
typename Scalar>
174 m = functor.values();
176 wa1.
resize(n); wa2.resize(n); wa3.resize(n);
180 if (!useExternalScaling)
182 eigen_assert( (!useExternalScaling || diag.size()==n) &&
"When useExternalScaling is set, the caller must provide a valid 'diag'");
190 if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0.)
193 if (useExternalScaling)
194 for (Index j = 0; j < n; ++j)
201 if ( functor(x, fvec) < 0)
203 fnorm = fvec.stableNorm();
212 template<
typename FunctorType,
typename Scalar>
222 Index df_ret = functor.df(x, fjac);
231 wa2 = fjac.colwise().blueNorm();
233 fjac = qrfac.matrixQR();
234 permutation = qrfac.colsPermutation();
239 if (!useExternalScaling)
240 for (Index j = 0; j < n; ++j)
241 diag[j] = (wa2[j]==0.)? 1. : wa2[j];
245 xnorm = diag.cwiseProduct(x).stableNorm();
246 delta = parameters.factor * xnorm;
248 delta = parameters.factor;
254 wa4.applyOnTheLeft(qrfac.householderQ().adjoint());
260 for (Index j = 0; j < n; ++j)
261 if (wa2[permutation.indices()[j]] != 0.)
262 gnorm = (
std::max)(gnorm,
abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
265 if (gnorm <= parameters.gtol)
269 if (!useExternalScaling)
270 diag = diag.cwiseMax(wa2);
275 internal::lmpar2<Scalar>(qrfac, diag, qtf, delta, par, wa1);
280 pnorm = diag.cwiseProduct(wa1).stableNorm();
284 delta = (std::min)(delta,pnorm);
287 if ( functor(wa2, wa4) < 0)
290 fnorm1 = wa4.stableNorm();
294 if (
Scalar(.1) * fnorm1 < fnorm)
299 wa3 = fjac.template triangularView<Upper>() * (qrfac.colsPermutation().inverse() *wa1);
302 prered = temp1 + temp2 /
Scalar(.5);
303 dirder = -(temp1 + temp2);
309 ratio = actred / prered;
312 if (ratio <=
Scalar(.25)) {
316 temp =
Scalar(.5) * dirder / (dirder +
Scalar(.5) * actred);
320 delta = temp * (std::min)(delta, pnorm /
Scalar(.1));
322 }
else if (!(par != 0. && ratio <
Scalar(.75))) {
323 delta = pnorm /
Scalar(.5);
328 if (ratio >=
Scalar(1e-4)) {
331 wa2 = diag.cwiseProduct(x);
333 xnorm = wa2.stableNorm();
339 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol &&
Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
341 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol &&
Scalar(.5) * ratio <= 1.)
343 if (delta <= parameters.xtol * xnorm)
347 if (nfev >= parameters.maxfev)
356 }
while (ratio <
Scalar(1e-4));
361 template<
typename FunctorType,
typename Scalar>
369 m = functor.values();
372 if (n <= 0 || m < n || tol < 0.)
376 parameters.ftol = tol;
377 parameters.xtol = tol;
378 parameters.maxfev = 100*(n+1);
380 return minimizeOptimumStorage(x);
383 template<
typename FunctorType,
typename Scalar>
388 m = functor.values();
390 wa1.
resize(n); wa2.resize(n); wa3.resize(n);
399 if (!useExternalScaling)
401 eigen_assert( (!useExternalScaling || diag.size()==n) &&
"When useExternalScaling is set, the caller must provide a valid 'diag'");
409 if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0.)
412 if (useExternalScaling)
413 for (Index j = 0; j < n; ++j)
420 if ( functor(x, fvec) < 0)
422 fnorm = fvec.stableNorm();
432 template<
typename FunctorType,
typename Scalar>
451 for (i = 0; i < m; ++i) {
453 internal::rwupdt<Scalar>(fjac, wa3, qtf, fvec[i]);
461 for (j = 0; j < n; ++j) {
464 wa2[j] = fjac.col(j).head(j).stableNorm();
466 permutation.setIdentity(n);
468 wa2 = fjac.colwise().blueNorm();
473 wa1 = fjac.diagonal();
474 fjac.diagonal() = qrfac.
hCoeffs();
477 for(Index ii=0; ii< fjac.cols(); ii++) fjac.col(ii).segment(ii+1, fjac.rows()-ii-1) *= fjac(ii,ii);
479 for (j = 0; j < n; ++j) {
480 if (fjac(j,j) != 0.) {
482 for (i = j; i < n; ++i)
483 sum += fjac(i,j) * qtf[i];
484 temp = -
sum / fjac(j,j);
485 for (i = j; i < n; ++i)
486 qtf[i] += fjac(i,j) * temp;
495 if (!useExternalScaling)
496 for (j = 0; j < n; ++j)
497 diag[j] = (wa2[j]==0.)? 1. : wa2[j];
501 xnorm = diag.cwiseProduct(x).stableNorm();
502 delta = parameters.factor * xnorm;
504 delta = parameters.factor;
510 for (j = 0; j < n; ++j)
511 if (wa2[permutation.indices()[j]] != 0.)
512 gnorm = (
std::max)(gnorm,
abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]]));
515 if (gnorm <= parameters.gtol)
519 if (!useExternalScaling)
520 diag = diag.cwiseMax(wa2);
525 internal::lmpar<Scalar>(fjac, permutation.indices(), diag, qtf, delta, par, wa1);
530 pnorm = diag.cwiseProduct(wa1).stableNorm();
534 delta = (std::min)(delta,pnorm);
537 if ( functor(wa2, wa4) < 0)
540 fnorm1 = wa4.stableNorm();
544 if (
Scalar(.1) * fnorm1 < fnorm)
549 wa3 = fjac.topLeftCorner(n,n).template triangularView<Upper>() * (permutation.inverse() * wa1);
552 prered = temp1 + temp2 /
Scalar(.5);
553 dirder = -(temp1 + temp2);
559 ratio = actred / prered;
562 if (ratio <=
Scalar(.25)) {
566 temp =
Scalar(.5) * dirder / (dirder +
Scalar(.5) * actred);
570 delta = temp * (std::min)(delta, pnorm /
Scalar(.1));
572 }
else if (!(par != 0. && ratio <
Scalar(.75))) {
573 delta = pnorm /
Scalar(.5);
578 if (ratio >=
Scalar(1e-4)) {
581 wa2 = diag.cwiseProduct(x);
583 xnorm = wa2.stableNorm();
589 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol &&
Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm)
591 if (
abs(actred) <= parameters.ftol && prered <= parameters.ftol &&
Scalar(.5) * ratio <= 1.)
593 if (delta <= parameters.xtol * xnorm)
597 if (nfev >= parameters.maxfev)
606 }
while (ratio <
Scalar(1e-4));
611 template<
typename FunctorType,
typename Scalar>
619 status = minimizeOptimumStorageOneStep(x);
624 template<
typename FunctorType,
typename Scalar>
634 Index m = functor.values();
637 if (n <= 0 || m < n || tol < 0.)
655 #endif // EIGEN_LEVENBERGMARQUARDT__H
const PermutationType & colsPermutation() const
LevenbergMarquardtSpace::Status minimize(FVectorType &x)
Matrix< Scalar, Dynamic, Dynamic > JacobianType
static LevenbergMarquardtSpace::Status lmdif1(FunctorType &functor, FVectorType &x, Index *nfev, const Scalar tol=std::sqrt(NumTraits< Scalar >::epsilon()))
LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x)
static Scalar sqrt_epsilon()
Matrix< Scalar, Dynamic, 1 > FVectorType
Performs non linear optimization over a non-linear function, using a variant of the Levenberg Marquar...
PermutationMatrix< Dynamic, Dynamic > permutation
JacobianType::Scalar Scalar
LevenbergMarquardtSpace::Status minimizeOptimumStorageInit(FVectorType &x)
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const AbsReturnType abs() const
void resetParameters(void)
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() max(const half &a, const half &b)
LevenbergMarquardtSpace::Status lmstr1(FVectorType &x, const Scalar tol=sqrt_epsilon())
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Householder rank-revealing QR decomposition of a matrix with column-pivoting.
const MatrixType & matrixQR() const
const mpreal sum(const mpreal tab[], const unsigned long int n, int &status, mp_rnd_t mode=mpreal::get_default_rnd())
const HCoeffsType & hCoeffs() const
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Abs2ReturnType abs2() const
LevenbergMarquardtSpace::Status minimizeOptimumStorageOneStep(FVectorType &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex
LevenbergMarquardt(FunctorType &_functor)
LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x)
LevenbergMarquardtSpace::Status minimizeOptimumStorage(FVectorType &x)
LevenbergMarquardtSpace::Status lmder1(FVectorType &x, const Scalar tol=std::sqrt(NumTraits< Scalar >::epsilon()))