Eigen-Contrib  5.0.1
 
Loading...
Searching...
No Matches
LevenbergMarquardt.h
1// -*- coding: utf-8
2// vim: set fileencoding=utf-8
3// SPDX-License-Identifier: MPL-2.0
4
5// This file is part of Eigen, a lightweight C++ template library
6// for linear algebra.
7//
8// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
9//
10// This Source Code Form is subject to the terms of the Mozilla
11// Public License v. 2.0. If a copy of the MPL was not distributed
12// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
13
14#ifndef EIGEN_LEVENBERGMARQUARDT__H
15#define EIGEN_LEVENBERGMARQUARDT__H
16
17// IWYU pragma: private
18#include "./InternalHeaderCheck.h"
19
20namespace Eigen {
21
22namespace LevenbergMarquardtSpace {
23enum Status {
24 NotStarted = -2,
25 Running = -1,
26 ImproperInputParameters = 0,
27 RelativeReductionTooSmall = 1,
28 RelativeErrorTooSmall = 2,
29 RelativeErrorAndReductionTooSmall = 3,
30 CosinusTooSmall = 4,
31 TooManyFunctionEvaluation = 5,
32 FtolTooSmall = 6,
33 XtolTooSmall = 7,
34 GtolTooSmall = 8,
35 UserAsked = 9
36};
37}
38
47template <typename FunctorType, typename Scalar = double>
49 static Scalar sqrt_epsilon() {
50 using std::sqrt;
51 return sqrt(NumTraits<Scalar>::epsilon());
52 }
53
54 public:
55 LevenbergMarquardt(FunctorType &_functor) : functor(_functor) {
56 nfev = njev = iter = 0;
57 fnorm = gnorm = 0.;
58 useExternalScaling = false;
59 }
60
61 typedef DenseIndex Index;
62
63 struct Parameters {
64 Parameters()
65 : factor(Scalar(100.)),
66 maxfev(400),
67 ftol(sqrt_epsilon()),
68 xtol(sqrt_epsilon()),
69 gtol(Scalar(0.)),
70 epsfcn(Scalar(0.)) {}
71 Scalar factor;
72 Index maxfev; // maximum number of function evaluation
73 Scalar ftol;
74 Scalar xtol;
75 Scalar gtol;
76 Scalar epsfcn;
77 };
78
79 typedef Matrix<Scalar, Dynamic, 1> FVectorType;
80 typedef Matrix<Scalar, Dynamic, Dynamic> JacobianType;
81
82 LevenbergMarquardtSpace::Status lmder1(FVectorType &x, const Scalar tol = sqrt_epsilon());
83
84 LevenbergMarquardtSpace::Status minimize(FVectorType &x);
85 LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x);
86 LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x);
87
88 static LevenbergMarquardtSpace::Status lmdif1(FunctorType &functor, FVectorType &x, Index *nfev,
89 const Scalar tol = sqrt_epsilon());
90
91 LevenbergMarquardtSpace::Status lmstr1(FVectorType &x, const Scalar tol = sqrt_epsilon());
92
93 LevenbergMarquardtSpace::Status minimizeOptimumStorage(FVectorType &x);
94 LevenbergMarquardtSpace::Status minimizeOptimumStorageInit(FVectorType &x);
95 LevenbergMarquardtSpace::Status minimizeOptimumStorageOneStep(FVectorType &x);
96
97 void resetParameters(void) { parameters = Parameters(); }
98
99 Parameters parameters;
100 FVectorType fvec, qtf, diag;
101 JacobianType fjac;
102 PermutationMatrix<Dynamic, Dynamic> permutation;
103 Index nfev;
104 Index njev;
105 Index iter;
106 Scalar fnorm, gnorm;
107 bool useExternalScaling;
108
109 Scalar lm_param(void) const { return par; }
110
111 private:
112 FunctorType &functor;
113 Index n;
114 Index m;
115 FVectorType wa1, wa2, wa3, wa4;
116
117 Scalar par, sum;
118 Scalar temp, temp1, temp2;
119 Scalar delta;
120 Scalar ratio;
121 Scalar pnorm, xnorm, fnorm1, actred, dirder, prered;
122
123 LevenbergMarquardt &operator=(const LevenbergMarquardt &) = delete;
124};
125
126template <typename FunctorType, typename Scalar>
127LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::lmder1(FVectorType &x, const Scalar tol) {
128 n = x.size();
129 m = functor.values();
130
131 /* check the input parameters for errors. */
132 if (n <= 0 || m < n || tol < 0.) return LevenbergMarquardtSpace::ImproperInputParameters;
133
134 resetParameters();
135 parameters.ftol = tol;
136 parameters.xtol = tol;
137 parameters.maxfev = 100 * (n + 1);
138
139 return minimize(x);
140}
141
142template <typename FunctorType, typename Scalar>
143LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimize(FVectorType &x) {
144 LevenbergMarquardtSpace::Status status = minimizeInit(x);
145 if (status == LevenbergMarquardtSpace::ImproperInputParameters) return status;
146 do {
147 status = minimizeOneStep(x);
148 } while (status == LevenbergMarquardtSpace::Running);
149 return status;
150}
151
152template <typename FunctorType, typename Scalar>
153LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeInit(FVectorType &x) {
154 n = x.size();
155 m = functor.values();
156
157 wa1.resize(n);
158 wa2.resize(n);
159 wa3.resize(n);
160 wa4.resize(m);
161 fvec.resize(m);
162 fjac.resize(m, n);
163 if (!useExternalScaling) diag.resize(n);
164 eigen_assert((!useExternalScaling || diag.size() == n) &&
165 "When useExternalScaling is set, the caller must provide a valid 'diag'");
166 qtf.resize(n);
167
168 /* Function Body */
169 nfev = 0;
170 njev = 0;
171
172 /* check the input parameters for errors. */
173 if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. ||
174 parameters.maxfev <= 0 || parameters.factor <= 0.)
175 return LevenbergMarquardtSpace::ImproperInputParameters;
176
177 if (useExternalScaling)
178 for (Index j = 0; j < n; ++j)
179 if (diag[j] <= 0.) return LevenbergMarquardtSpace::ImproperInputParameters;
180
181 /* evaluate the function at the starting point */
182 /* and calculate its norm. */
183 nfev = 1;
184 if (functor(x, fvec) < 0) return LevenbergMarquardtSpace::UserAsked;
185 fnorm = fvec.stableNorm();
186
187 /* initialize levenberg-marquardt parameter and iteration counter. */
188 par = 0.;
189 iter = 1;
190
191 return LevenbergMarquardtSpace::NotStarted;
192}
193
194template <typename FunctorType, typename Scalar>
195LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOneStep(FVectorType &x) {
196 using std::abs;
197 using std::sqrt;
198
199 eigen_assert(x.size() == n); // check the caller is not cheating us
200
201 /* calculate the jacobian matrix. */
202 Index df_ret = functor.df(x, fjac);
203 if (df_ret < 0) return LevenbergMarquardtSpace::UserAsked;
204 if (df_ret > 0)
205 // numerical diff, we evaluated the function df_ret times
206 nfev += df_ret;
207 else
208 njev++;
209
210 /* compute the qr factorization of the jacobian. */
211 wa2 = fjac.colwise().blueNorm();
213 fjac = qrfac.matrixQR();
214 permutation = qrfac.colsPermutation();
215
216 /* on the first iteration and if external scaling is not used, scale according */
217 /* to the norms of the columns of the initial jacobian. */
218 if (iter == 1) {
219 if (!useExternalScaling)
220 for (Index j = 0; j < n; ++j) diag[j] = (wa2[j] == 0.) ? 1. : wa2[j];
221
222 /* on the first iteration, calculate the norm of the scaled x */
223 /* and initialize the step bound delta. */
224 xnorm = diag.cwiseProduct(x).stableNorm();
225 delta = parameters.factor * xnorm;
226 if (delta == 0.) delta = parameters.factor;
227 }
228
229 /* form (q transpose)*fvec and store the first n components in */
230 /* qtf. */
231 wa4 = fvec;
232 wa4.applyOnTheLeft(qrfac.householderQ().adjoint());
233 qtf = wa4.head(n);
234
235 /* compute the norm of the scaled gradient. */
236 gnorm = 0.;
237 if (fnorm != 0.)
238 for (Index j = 0; j < n; ++j)
239 if (wa2[permutation.indices()[j]] != 0.)
240 gnorm = (std::max)(gnorm,
241 abs(fjac.col(j).head(j + 1).dot(qtf.head(j + 1) / fnorm) / wa2[permutation.indices()[j]]));
242
243 /* test for convergence of the gradient norm. */
244 if (gnorm <= parameters.gtol) return LevenbergMarquardtSpace::CosinusTooSmall;
245
246 /* rescale if necessary. */
247 if (!useExternalScaling) diag = diag.cwiseMax(wa2);
248
249 do {
250 /* determine the levenberg-marquardt parameter. */
251 internal::lmpar2<Scalar>(qrfac, diag, qtf, delta, par, wa1);
252
253 /* store the direction p and x + p. calculate the norm of p. */
254 wa1 = -wa1;
255 wa2 = x + wa1;
256 pnorm = diag.cwiseProduct(wa1).stableNorm();
257
258 /* on the first iteration, adjust the initial step bound. */
259 if (iter == 1) delta = (std::min)(delta, pnorm);
260
261 /* evaluate the function at x + p and calculate its norm. */
262 if (functor(wa2, wa4) < 0) return LevenbergMarquardtSpace::UserAsked;
263 ++nfev;
264 fnorm1 = wa4.stableNorm();
265
266 /* compute the scaled actual reduction. */
267 actred = -1.;
268 if (Scalar(.1) * fnorm1 < fnorm) actred = 1. - numext::abs2(fnorm1 / fnorm);
269
270 /* compute the scaled predicted reduction and */
271 /* the scaled directional derivative. */
272 wa3.noalias() = fjac.template triangularView<Upper>() * (qrfac.colsPermutation().inverse() * wa1);
273 temp1 = numext::abs2(wa3.stableNorm() / fnorm);
274 temp2 = numext::abs2(sqrt(par) * pnorm / fnorm);
275 prered = temp1 + temp2 / Scalar(.5);
276 dirder = -(temp1 + temp2);
277
278 /* compute the ratio of the actual to the predicted */
279 /* reduction. */
280 ratio = 0.;
281 if (prered != 0.) ratio = actred / prered;
282
283 /* update the step bound. */
284 if (ratio <= Scalar(.25)) {
285 if (actred >= 0.) temp = Scalar(.5);
286 if (actred < 0.) temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred);
287 if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1)) temp = Scalar(.1);
288 /* Computing MIN */
289 delta = temp * (std::min)(delta, pnorm / Scalar(.1));
290 par /= temp;
291 } else if (!(par != 0. && ratio < Scalar(.75))) {
292 delta = pnorm / Scalar(.5);
293 par = Scalar(.5) * par;
294 }
295
296 /* test for successful iteration. */
297 if (ratio >= Scalar(1e-4)) {
298 /* successful iteration. update x, fvec, and their norms. */
299 x = wa2;
300 wa2 = diag.cwiseProduct(x);
301 fvec = wa4;
302 xnorm = wa2.stableNorm();
303 fnorm = fnorm1;
304 ++iter;
305 }
306
307 /* tests for convergence. */
308 if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. &&
309 delta <= parameters.xtol * xnorm)
310 return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall;
311 if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
312 return LevenbergMarquardtSpace::RelativeReductionTooSmall;
313 if (delta <= parameters.xtol * xnorm) return LevenbergMarquardtSpace::RelativeErrorTooSmall;
314
315 /* tests for termination and stringent tolerances. */
316 if (nfev >= parameters.maxfev) return LevenbergMarquardtSpace::TooManyFunctionEvaluation;
317 if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() &&
318 Scalar(.5) * ratio <= 1.)
319 return LevenbergMarquardtSpace::FtolTooSmall;
320 if (delta <= NumTraits<Scalar>::epsilon() * xnorm) return LevenbergMarquardtSpace::XtolTooSmall;
321 if (gnorm <= NumTraits<Scalar>::epsilon()) return LevenbergMarquardtSpace::GtolTooSmall;
322
323 } while (ratio < Scalar(1e-4));
324
325 return LevenbergMarquardtSpace::Running;
326}
327
328template <typename FunctorType, typename Scalar>
329LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::lmstr1(FVectorType &x, const Scalar tol) {
330 n = x.size();
331 m = functor.values();
332
333 /* check the input parameters for errors. */
334 if (n <= 0 || m < n || tol < 0.) return LevenbergMarquardtSpace::ImproperInputParameters;
335
336 resetParameters();
337 parameters.ftol = tol;
338 parameters.xtol = tol;
339 parameters.maxfev = 100 * (n + 1);
340
341 return minimizeOptimumStorage(x);
342}
343
344template <typename FunctorType, typename Scalar>
345LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOptimumStorageInit(FVectorType &x) {
346 n = x.size();
347 m = functor.values();
348
349 wa1.resize(n);
350 wa2.resize(n);
351 wa3.resize(n);
352 wa4.resize(m);
353 fvec.resize(m);
354 // Only R is stored in fjac. Q is only used to compute 'qtf', which is
355 // Q.transpose()*rhs. qtf will be updated using givens rotation,
356 // instead of storing them in Q.
357 // The purpose is to only use a nxn matrix, instead of mxn here, so
358 // that we can handle cases where m>>n :
359 fjac.resize(n, n);
360 if (!useExternalScaling) diag.resize(n);
361 eigen_assert((!useExternalScaling || diag.size() == n) &&
362 "When useExternalScaling is set, the caller must provide a valid 'diag'");
363 qtf.resize(n);
364
365 /* Function Body */
366 nfev = 0;
367 njev = 0;
368
369 /* check the input parameters for errors. */
370 if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. ||
371 parameters.maxfev <= 0 || parameters.factor <= 0.)
372 return LevenbergMarquardtSpace::ImproperInputParameters;
373
374 if (useExternalScaling)
375 for (Index j = 0; j < n; ++j)
376 if (diag[j] <= 0.) return LevenbergMarquardtSpace::ImproperInputParameters;
377
378 /* evaluate the function at the starting point */
379 /* and calculate its norm. */
380 nfev = 1;
381 if (functor(x, fvec) < 0) return LevenbergMarquardtSpace::UserAsked;
382 fnorm = fvec.stableNorm();
383
384 /* initialize levenberg-marquardt parameter and iteration counter. */
385 par = 0.;
386 iter = 1;
387
388 return LevenbergMarquardtSpace::NotStarted;
389}
390
391template <typename FunctorType, typename Scalar>
392LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOptimumStorageOneStep(FVectorType &x) {
393 using std::abs;
394 using std::sqrt;
395
396 eigen_assert(x.size() == n); // check the caller is not cheating us
397
398 Index i, j;
399 bool sing;
400
401 /* compute the qr factorization of the jacobian matrix */
402 /* calculated one row at a time, while simultaneously */
403 /* forming (q transpose)*fvec and storing the first */
404 /* n components in qtf. */
405 qtf.fill(0.);
406 fjac.fill(0.);
407 Index rownb = 2;
408 for (i = 0; i < m; ++i) {
409 if (functor.df(x, wa3, rownb) < 0) return LevenbergMarquardtSpace::UserAsked;
410 internal::rwupdt<Scalar>(fjac, wa3, qtf, fvec[i]);
411 ++rownb;
412 }
413 ++njev;
414
415 /* if the jacobian is rank deficient, call qrfac to */
416 /* reorder its columns and update the components of qtf. */
417 sing = false;
418 for (j = 0; j < n; ++j) {
419 if (fjac(j, j) == 0.) sing = true;
420 wa2[j] = fjac.col(j).head(j).stableNorm();
421 }
422 permutation.setIdentity(n);
423 if (sing) {
424 wa2 = fjac.colwise().blueNorm();
425 // TODO: We have no unit test covering this code path, do not modify
426 // until it is carefully tested
428 fjac = qrfac.matrixQR();
429 wa1 = fjac.diagonal();
430 fjac.diagonal() = qrfac.hCoeffs();
431 permutation = qrfac.colsPermutation();
432 // TODO: Avoid this:
433 for (Index ii = 0; ii < fjac.cols(); ii++)
434 fjac.col(ii).segment(ii + 1, fjac.rows() - ii - 1) *= fjac(ii, ii); // rescale vectors
435
436 for (j = 0; j < n; ++j) {
437 if (fjac(j, j) != 0.) {
438 sum = 0.;
439 for (i = j; i < n; ++i) sum += fjac(i, j) * qtf[i];
440 temp = -sum / fjac(j, j);
441 for (i = j; i < n; ++i) qtf[i] += fjac(i, j) * temp;
442 }
443 fjac(j, j) = wa1[j];
444 }
445 }
446
447 /* on the first iteration and if external scaling is not used, scale according */
448 /* to the norms of the columns of the initial jacobian. */
449 if (iter == 1) {
450 if (!useExternalScaling)
451 for (j = 0; j < n; ++j) diag[j] = (wa2[j] == 0.) ? 1. : wa2[j];
452
453 /* on the first iteration, calculate the norm of the scaled x */
454 /* and initialize the step bound delta. */
455 xnorm = diag.cwiseProduct(x).stableNorm();
456 delta = parameters.factor * xnorm;
457 if (delta == 0.) delta = parameters.factor;
458 }
459
460 /* compute the norm of the scaled gradient. */
461 gnorm = 0.;
462 if (fnorm != 0.)
463 for (j = 0; j < n; ++j)
464 if (wa2[permutation.indices()[j]] != 0.)
465 gnorm = (std::max)(gnorm,
466 abs(fjac.col(j).head(j + 1).dot(qtf.head(j + 1) / fnorm) / wa2[permutation.indices()[j]]));
467
468 /* test for convergence of the gradient norm. */
469 if (gnorm <= parameters.gtol) return LevenbergMarquardtSpace::CosinusTooSmall;
470
471 /* rescale if necessary. */
472 if (!useExternalScaling) diag = diag.cwiseMax(wa2);
473
474 do {
475 /* determine the levenberg-marquardt parameter. */
476 internal::lmpar<Scalar>(fjac, permutation.indices(), diag, qtf, delta, par, wa1);
477
478 /* store the direction p and x + p. calculate the norm of p. */
479 wa1 = -wa1;
480 wa2 = x + wa1;
481 pnorm = diag.cwiseProduct(wa1).stableNorm();
482
483 /* on the first iteration, adjust the initial step bound. */
484 if (iter == 1) delta = (std::min)(delta, pnorm);
485
486 /* evaluate the function at x + p and calculate its norm. */
487 if (functor(wa2, wa4) < 0) return LevenbergMarquardtSpace::UserAsked;
488 ++nfev;
489 fnorm1 = wa4.stableNorm();
490
491 /* compute the scaled actual reduction. */
492 actred = -1.;
493 if (Scalar(.1) * fnorm1 < fnorm) actred = 1. - numext::abs2(fnorm1 / fnorm);
494
495 /* compute the scaled predicted reduction and */
496 /* the scaled directional derivative. */
497 wa3.noalias() = fjac.topLeftCorner(n, n).template triangularView<Upper>() * (permutation.inverse() * wa1);
498 temp1 = numext::abs2(wa3.stableNorm() / fnorm);
499 temp2 = numext::abs2(sqrt(par) * pnorm / fnorm);
500 prered = temp1 + temp2 / Scalar(.5);
501 dirder = -(temp1 + temp2);
502
503 /* compute the ratio of the actual to the predicted */
504 /* reduction. */
505 ratio = 0.;
506 if (prered != 0.) ratio = actred / prered;
507
508 /* update the step bound. */
509 if (ratio <= Scalar(.25)) {
510 if (actred >= 0.) temp = Scalar(.5);
511 if (actred < 0.) temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred);
512 if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1)) temp = Scalar(.1);
513 /* Computing MIN */
514 delta = temp * (std::min)(delta, pnorm / Scalar(.1));
515 par /= temp;
516 } else if (!(par != 0. && ratio < Scalar(.75))) {
517 delta = pnorm / Scalar(.5);
518 par = Scalar(.5) * par;
519 }
520
521 /* test for successful iteration. */
522 if (ratio >= Scalar(1e-4)) {
523 /* successful iteration. update x, fvec, and their norms. */
524 x = wa2;
525 wa2 = diag.cwiseProduct(x);
526 fvec = wa4;
527 xnorm = wa2.stableNorm();
528 fnorm = fnorm1;
529 ++iter;
530 }
531
532 /* tests for convergence. */
533 if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. &&
534 delta <= parameters.xtol * xnorm)
535 return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall;
536 if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
537 return LevenbergMarquardtSpace::RelativeReductionTooSmall;
538 if (delta <= parameters.xtol * xnorm) return LevenbergMarquardtSpace::RelativeErrorTooSmall;
539
540 /* tests for termination and stringent tolerances. */
541 if (nfev >= parameters.maxfev) return LevenbergMarquardtSpace::TooManyFunctionEvaluation;
542 if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() &&
543 Scalar(.5) * ratio <= 1.)
544 return LevenbergMarquardtSpace::FtolTooSmall;
545 if (delta <= NumTraits<Scalar>::epsilon() * xnorm) return LevenbergMarquardtSpace::XtolTooSmall;
546 if (gnorm <= NumTraits<Scalar>::epsilon()) return LevenbergMarquardtSpace::GtolTooSmall;
547
548 } while (ratio < Scalar(1e-4));
549
550 return LevenbergMarquardtSpace::Running;
551}
552
553template <typename FunctorType, typename Scalar>
554LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOptimumStorage(FVectorType &x) {
555 LevenbergMarquardtSpace::Status status = minimizeOptimumStorageInit(x);
556 if (status == LevenbergMarquardtSpace::ImproperInputParameters) return status;
557 do {
558 status = minimizeOptimumStorageOneStep(x);
559 } while (status == LevenbergMarquardtSpace::Running);
560 return status;
561}
562
563template <typename FunctorType, typename Scalar>
564LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::lmdif1(FunctorType &functor, FVectorType &x,
565 Index *nfev, const Scalar tol) {
566 Index n = x.size();
567 Index m = functor.values();
568
569 /* check the input parameters for errors. */
570 if (n <= 0 || m < n || tol < 0.) return LevenbergMarquardtSpace::ImproperInputParameters;
571
572 NumericalDiff<FunctorType> numDiff(functor);
573 // embedded LevenbergMarquardt
575 lm.parameters.ftol = tol;
576 lm.parameters.xtol = tol;
577 lm.parameters.maxfev = 200 * (n + 1);
578
579 LevenbergMarquardtSpace::Status info = LevenbergMarquardtSpace::Status(lm.minimize(x));
580 if (nfev) *nfev = lm.nfev;
581 return info;
582}
583
584} // end namespace Eigen
585
586#endif // EIGEN_LEVENBERGMARQUARDT__H
587
588// vim: ai ts=4 sts=4 et sw=4
Performs non linear optimization over a non-linear function, using a variant of the Levenberg Marquar...
Definition LevenbergMarquardt.h:104
void resetParameters()
Definition LevenbergMarquardt.h:136
RealScalar lm_param(void) const
Definition LevenbergMarquardt.h:205
Definition NumericalDiff.h:51
Namespace containing all symbols from the Eigen library.