00001
00002
00003
00004
00005
00006 #include <stdio.h>
00007
00008 #include "main.h"
00009 #include <unsupported/Eigen/NonLinearOptimization>
00010
00011
00012
00013 #include <Eigen/src/Core/util/DisableStupidWarnings.h>
00014
00015 using std::sqrt;
00016
00017 int fcn_chkder(const VectorXd &x, VectorXd &fvec, MatrixXd &fjac, int iflag)
00018 {
00019
00020
00021 int i;
00022 assert(15 == fvec.size());
00023 assert(3 == x.size());
00024 double tmp1, tmp2, tmp3, tmp4;
00025 static const double y[15]={1.4e-1, 1.8e-1, 2.2e-1, 2.5e-1, 2.9e-1, 3.2e-1, 3.5e-1,
00026 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39};
00027
00028
00029 if (iflag == 0)
00030 return 0;
00031
00032 if (iflag != 2)
00033 for (i=0; i<15; i++) {
00034 tmp1 = i+1;
00035 tmp2 = 16-i-1;
00036 tmp3 = tmp1;
00037 if (i >= 8) tmp3 = tmp2;
00038 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
00039 }
00040 else {
00041 for (i = 0; i < 15; i++) {
00042 tmp1 = i+1;
00043 tmp2 = 16-i-1;
00044
00045
00046
00047
00048 tmp3 = tmp2;
00049 if (i >= 8) tmp3 = tmp2;
00050 tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4=tmp4*tmp4;
00051 fjac(i,0) = -1.;
00052 fjac(i,1) = tmp1*tmp2/tmp4;
00053 fjac(i,2) = tmp1*tmp3/tmp4;
00054 }
00055 }
00056 return 0;
00057 }
00058
00059
00060 void testChkder()
00061 {
00062 const int m=15, n=3;
00063 VectorXd x(n), fvec(m), xp, fvecp(m), err;
00064 MatrixXd fjac(m,n);
00065 VectorXi ipvt;
00066
00067
00068
00069 x << 9.2e-1, 1.3e-1, 5.4e-1;
00070
00071 internal::chkder(x, fvec, fjac, xp, fvecp, 1, err);
00072 fcn_chkder(x, fvec, fjac, 1);
00073 fcn_chkder(x, fvec, fjac, 2);
00074 fcn_chkder(xp, fvecp, fjac, 1);
00075 internal::chkder(x, fvec, fjac, xp, fvecp, 2, err);
00076
00077 fvecp -= fvec;
00078
00079
00080 VectorXd fvec_ref(m), fvecp_ref(m), err_ref(m);
00081 fvec_ref <<
00082 -1.181606, -1.429655, -1.606344,
00083 -1.745269, -1.840654, -1.921586,
00084 -1.984141, -2.022537, -2.468977,
00085 -2.827562, -3.473582, -4.437612,
00086 -6.047662, -9.267761, -18.91806;
00087 fvecp_ref <<
00088 -7.724666e-09, -3.432406e-09, -2.034843e-10,
00089 2.313685e-09, 4.331078e-09, 5.984096e-09,
00090 7.363281e-09, 8.53147e-09, 1.488591e-08,
00091 2.33585e-08, 3.522012e-08, 5.301255e-08,
00092 8.26666e-08, 1.419747e-07, 3.19899e-07;
00093 err_ref <<
00094 0.1141397, 0.09943516, 0.09674474,
00095 0.09980447, 0.1073116, 0.1220445,
00096 0.1526814, 1, 1,
00097 1, 1, 1,
00098 1, 1, 1;
00099
00100 VERIFY_IS_APPROX(fvec, fvec_ref);
00101 VERIFY_IS_APPROX(fvecp, fvecp_ref);
00102 VERIFY_IS_APPROX(err, err_ref);
00103 }
00104
00105
00106 template<typename _Scalar, int NX=Dynamic, int NY=Dynamic>
00107 struct Functor
00108 {
00109 typedef _Scalar Scalar;
00110 enum {
00111 InputsAtCompileTime = NX,
00112 ValuesAtCompileTime = NY
00113 };
00114 typedef Matrix<Scalar,InputsAtCompileTime,1> InputType;
00115 typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
00116 typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
00117
00118 const int m_inputs, m_values;
00119
00120 Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
00121 Functor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
00122
00123 int inputs() const { return m_inputs; }
00124 int values() const { return m_values; }
00125
00126
00127
00128 };
00129
00130 struct lmder_functor : Functor<double>
00131 {
00132 lmder_functor(void): Functor<double>(3,15) {}
00133 int operator()(const VectorXd &x, VectorXd &fvec) const
00134 {
00135 double tmp1, tmp2, tmp3;
00136 static const double y[15] = {1.4e-1, 1.8e-1, 2.2e-1, 2.5e-1, 2.9e-1, 3.2e-1, 3.5e-1,
00137 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39};
00138
00139 for (int i = 0; i < values(); i++)
00140 {
00141 tmp1 = i+1;
00142 tmp2 = 16 - i - 1;
00143 tmp3 = (i>=8)? tmp2 : tmp1;
00144 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
00145 }
00146 return 0;
00147 }
00148
00149 int df(const VectorXd &x, MatrixXd &fjac) const
00150 {
00151 double tmp1, tmp2, tmp3, tmp4;
00152 for (int i = 0; i < values(); i++)
00153 {
00154 tmp1 = i+1;
00155 tmp2 = 16 - i - 1;
00156 tmp3 = (i>=8)? tmp2 : tmp1;
00157 tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4 = tmp4*tmp4;
00158 fjac(i,0) = -1;
00159 fjac(i,1) = tmp1*tmp2/tmp4;
00160 fjac(i,2) = tmp1*tmp3/tmp4;
00161 }
00162 return 0;
00163 }
00164 };
00165
00166 void testLmder1()
00167 {
00168 int n=3, info;
00169
00170 VectorXd x;
00171
00172
00173 x.setConstant(n, 1.);
00174
00175
00176 lmder_functor functor;
00177 LevenbergMarquardt<lmder_functor> lm(functor);
00178 info = lm.lmder1(x);
00179
00180
00181 VERIFY_IS_EQUAL(info, 1);
00182 VERIFY_IS_EQUAL(lm.nfev, 6);
00183 VERIFY_IS_EQUAL(lm.njev, 5);
00184
00185
00186 VERIFY_IS_APPROX(lm.fvec.blueNorm(), 0.09063596);
00187
00188
00189 VectorXd x_ref(n);
00190 x_ref << 0.08241058, 1.133037, 2.343695;
00191 VERIFY_IS_APPROX(x, x_ref);
00192 }
00193
00194 void testLmder()
00195 {
00196 const int m=15, n=3;
00197 int info;
00198 double fnorm, covfac;
00199 VectorXd x;
00200
00201
00202 x.setConstant(n, 1.);
00203
00204
00205 lmder_functor functor;
00206 LevenbergMarquardt<lmder_functor> lm(functor);
00207 info = lm.minimize(x);
00208
00209
00210 VERIFY_IS_EQUAL(info, 1);
00211 VERIFY_IS_EQUAL(lm.nfev, 6);
00212 VERIFY_IS_EQUAL(lm.njev, 5);
00213
00214
00215 fnorm = lm.fvec.blueNorm();
00216 VERIFY_IS_APPROX(fnorm, 0.09063596);
00217
00218
00219 VectorXd x_ref(n);
00220 x_ref << 0.08241058, 1.133037, 2.343695;
00221 VERIFY_IS_APPROX(x, x_ref);
00222
00223
00224 covfac = fnorm*fnorm/(m-n);
00225 internal::covar(lm.fjac, lm.permutation.indices());
00226
00227 MatrixXd cov_ref(n,n);
00228 cov_ref <<
00229 0.0001531202, 0.002869941, -0.002656662,
00230 0.002869941, 0.09480935, -0.09098995,
00231 -0.002656662, -0.09098995, 0.08778727;
00232
00233
00234
00235 MatrixXd cov;
00236 cov = covfac*lm.fjac.topLeftCorner<n,n>();
00237 VERIFY_IS_APPROX( cov, cov_ref);
00238
00239
00240 }
00241
00242 struct hybrj_functor : Functor<double>
00243 {
00244 hybrj_functor(void) : Functor<double>(9,9) {}
00245
00246 int operator()(const VectorXd &x, VectorXd &fvec)
00247 {
00248 double temp, temp1, temp2;
00249 const int n = x.size();
00250 assert(fvec.size()==n);
00251 for (int k = 0; k < n; k++)
00252 {
00253 temp = (3. - 2.*x[k])*x[k];
00254 temp1 = 0.;
00255 if (k) temp1 = x[k-1];
00256 temp2 = 0.;
00257 if (k != n-1) temp2 = x[k+1];
00258 fvec[k] = temp - temp1 - 2.*temp2 + 1.;
00259 }
00260 return 0;
00261 }
00262 int df(const VectorXd &x, MatrixXd &fjac)
00263 {
00264 const int n = x.size();
00265 assert(fjac.rows()==n);
00266 assert(fjac.cols()==n);
00267 for (int k = 0; k < n; k++)
00268 {
00269 for (int j = 0; j < n; j++)
00270 fjac(k,j) = 0.;
00271 fjac(k,k) = 3.- 4.*x[k];
00272 if (k) fjac(k,k-1) = -1.;
00273 if (k != n-1) fjac(k,k+1) = -2.;
00274 }
00275 return 0;
00276 }
00277 };
00278
00279
00280 void testHybrj1()
00281 {
00282 const int n=9;
00283 int info;
00284 VectorXd x(n);
00285
00286
00287 x.setConstant(n, -1.);
00288
00289
00290 hybrj_functor functor;
00291 HybridNonLinearSolver<hybrj_functor> solver(functor);
00292 info = solver.hybrj1(x);
00293
00294
00295 VERIFY_IS_EQUAL(info, 1);
00296 VERIFY_IS_EQUAL(solver.nfev, 11);
00297 VERIFY_IS_EQUAL(solver.njev, 1);
00298
00299
00300 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00301
00302
00303
00304 VectorXd x_ref(n);
00305 x_ref <<
00306 -0.5706545, -0.6816283, -0.7017325,
00307 -0.7042129, -0.701369, -0.6918656,
00308 -0.665792, -0.5960342, -0.4164121;
00309 VERIFY_IS_APPROX(x, x_ref);
00310 }
00311
00312 void testHybrj()
00313 {
00314 const int n=9;
00315 int info;
00316 VectorXd x(n);
00317
00318
00319 x.setConstant(n, -1.);
00320
00321
00322
00323 hybrj_functor functor;
00324 HybridNonLinearSolver<hybrj_functor> solver(functor);
00325 solver.diag.setConstant(n, 1.);
00326 solver.useExternalScaling = true;
00327 info = solver.solve(x);
00328
00329
00330 VERIFY_IS_EQUAL(info, 1);
00331 VERIFY_IS_EQUAL(solver.nfev, 11);
00332 VERIFY_IS_EQUAL(solver.njev, 1);
00333
00334
00335 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00336
00337
00338
00339 VectorXd x_ref(n);
00340 x_ref <<
00341 -0.5706545, -0.6816283, -0.7017325,
00342 -0.7042129, -0.701369, -0.6918656,
00343 -0.665792, -0.5960342, -0.4164121;
00344 VERIFY_IS_APPROX(x, x_ref);
00345
00346 }
00347
00348 struct hybrd_functor : Functor<double>
00349 {
00350 hybrd_functor(void) : Functor<double>(9,9) {}
00351 int operator()(const VectorXd &x, VectorXd &fvec) const
00352 {
00353 double temp, temp1, temp2;
00354 const int n = x.size();
00355
00356 assert(fvec.size()==n);
00357 for (int k=0; k < n; k++)
00358 {
00359 temp = (3. - 2.*x[k])*x[k];
00360 temp1 = 0.;
00361 if (k) temp1 = x[k-1];
00362 temp2 = 0.;
00363 if (k != n-1) temp2 = x[k+1];
00364 fvec[k] = temp - temp1 - 2.*temp2 + 1.;
00365 }
00366 return 0;
00367 }
00368 };
00369
00370 void testHybrd1()
00371 {
00372 int n=9, info;
00373 VectorXd x(n);
00374
00375
00376 x.setConstant(n, -1.);
00377
00378
00379 hybrd_functor functor;
00380 HybridNonLinearSolver<hybrd_functor> solver(functor);
00381 info = solver.hybrd1(x);
00382
00383
00384 VERIFY_IS_EQUAL(info, 1);
00385 VERIFY_IS_EQUAL(solver.nfev, 20);
00386
00387
00388 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00389
00390
00391 VectorXd x_ref(n);
00392 x_ref << -0.5706545, -0.6816283, -0.7017325, -0.7042129, -0.701369, -0.6918656, -0.665792, -0.5960342, -0.4164121;
00393 VERIFY_IS_APPROX(x, x_ref);
00394 }
00395
00396 void testHybrd()
00397 {
00398 const int n=9;
00399 int info;
00400 VectorXd x;
00401
00402
00403 x.setConstant(n, -1.);
00404
00405
00406 hybrd_functor functor;
00407 HybridNonLinearSolver<hybrd_functor> solver(functor);
00408 solver.parameters.nb_of_subdiagonals = 1;
00409 solver.parameters.nb_of_superdiagonals = 1;
00410 solver.diag.setConstant(n, 1.);
00411 solver.useExternalScaling = true;
00412 info = solver.solveNumericalDiff(x);
00413
00414
00415 VERIFY_IS_EQUAL(info, 1);
00416 VERIFY_IS_EQUAL(solver.nfev, 14);
00417
00418
00419 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00420
00421
00422 VectorXd x_ref(n);
00423 x_ref <<
00424 -0.5706545, -0.6816283, -0.7017325,
00425 -0.7042129, -0.701369, -0.6918656,
00426 -0.665792, -0.5960342, -0.4164121;
00427 VERIFY_IS_APPROX(x, x_ref);
00428 }
00429
00430 struct lmstr_functor : Functor<double>
00431 {
00432 lmstr_functor(void) : Functor<double>(3,15) {}
00433 int operator()(const VectorXd &x, VectorXd &fvec)
00434 {
00435
00436 double tmp1, tmp2, tmp3;
00437 static const double y[15]={1.4e-1, 1.8e-1, 2.2e-1, 2.5e-1, 2.9e-1, 3.2e-1, 3.5e-1,
00438 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39};
00439
00440 assert(15==fvec.size());
00441 assert(3==x.size());
00442
00443 for (int i=0; i<15; i++)
00444 {
00445 tmp1 = i+1;
00446 tmp2 = 16 - i - 1;
00447 tmp3 = (i>=8)? tmp2 : tmp1;
00448 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
00449 }
00450 return 0;
00451 }
00452 int df(const VectorXd &x, VectorXd &jac_row, VectorXd::Index rownb)
00453 {
00454 assert(x.size()==3);
00455 assert(jac_row.size()==x.size());
00456 double tmp1, tmp2, tmp3, tmp4;
00457
00458 int i = rownb-2;
00459 tmp1 = i+1;
00460 tmp2 = 16 - i - 1;
00461 tmp3 = (i>=8)? tmp2 : tmp1;
00462 tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4 = tmp4*tmp4;
00463 jac_row[0] = -1;
00464 jac_row[1] = tmp1*tmp2/tmp4;
00465 jac_row[2] = tmp1*tmp3/tmp4;
00466 return 0;
00467 }
00468 };
00469
00470 void testLmstr1()
00471 {
00472 const int n=3;
00473 int info;
00474
00475 VectorXd x(n);
00476
00477
00478 x.setConstant(n, 1.);
00479
00480
00481 lmstr_functor functor;
00482 LevenbergMarquardt<lmstr_functor> lm(functor);
00483 info = lm.lmstr1(x);
00484
00485
00486 VERIFY_IS_EQUAL(info, 1);
00487 VERIFY_IS_EQUAL(lm.nfev, 6);
00488 VERIFY_IS_EQUAL(lm.njev, 5);
00489
00490
00491 VERIFY_IS_APPROX(lm.fvec.blueNorm(), 0.09063596);
00492
00493
00494 VectorXd x_ref(n);
00495 x_ref << 0.08241058, 1.133037, 2.343695 ;
00496 VERIFY_IS_APPROX(x, x_ref);
00497 }
00498
00499 void testLmstr()
00500 {
00501 const int n=3;
00502 int info;
00503 double fnorm;
00504 VectorXd x(n);
00505
00506
00507 x.setConstant(n, 1.);
00508
00509
00510 lmstr_functor functor;
00511 LevenbergMarquardt<lmstr_functor> lm(functor);
00512 info = lm.minimizeOptimumStorage(x);
00513
00514
00515 VERIFY_IS_EQUAL(info, 1);
00516 VERIFY_IS_EQUAL(lm.nfev, 6);
00517 VERIFY_IS_EQUAL(lm.njev, 5);
00518
00519
00520 fnorm = lm.fvec.blueNorm();
00521 VERIFY_IS_APPROX(fnorm, 0.09063596);
00522
00523
00524 VectorXd x_ref(n);
00525 x_ref << 0.08241058, 1.133037, 2.343695;
00526 VERIFY_IS_APPROX(x, x_ref);
00527
00528 }
00529
00530 struct lmdif_functor : Functor<double>
00531 {
00532 lmdif_functor(void) : Functor<double>(3,15) {}
00533 int operator()(const VectorXd &x, VectorXd &fvec) const
00534 {
00535 int i;
00536 double tmp1,tmp2,tmp3;
00537 static const double y[15]={1.4e-1,1.8e-1,2.2e-1,2.5e-1,2.9e-1,3.2e-1,3.5e-1,3.9e-1,
00538 3.7e-1,5.8e-1,7.3e-1,9.6e-1,1.34e0,2.1e0,4.39e0};
00539
00540 assert(x.size()==3);
00541 assert(fvec.size()==15);
00542 for (i=0; i<15; i++)
00543 {
00544 tmp1 = i+1;
00545 tmp2 = 15 - i;
00546 tmp3 = tmp1;
00547
00548 if (i >= 8) tmp3 = tmp2;
00549 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
00550 }
00551 return 0;
00552 }
00553 };
00554
00555 void testLmdif1()
00556 {
00557 const int n=3;
00558 int info;
00559
00560 VectorXd x(n), fvec(15);
00561
00562
00563 x.setConstant(n, 1.);
00564
00565
00566 lmdif_functor functor;
00567 DenseIndex nfev;
00568 info = LevenbergMarquardt<lmdif_functor>::lmdif1(functor, x, &nfev);
00569
00570
00571 VERIFY_IS_EQUAL(info, 1);
00572 VERIFY_IS_EQUAL(nfev, 26);
00573
00574
00575 functor(x, fvec);
00576 VERIFY_IS_APPROX(fvec.blueNorm(), 0.09063596);
00577
00578
00579 VectorXd x_ref(n);
00580 x_ref << 0.0824106, 1.1330366, 2.3436947;
00581 VERIFY_IS_APPROX(x, x_ref);
00582
00583 }
00584
00585 void testLmdif()
00586 {
00587 const int m=15, n=3;
00588 int info;
00589 double fnorm, covfac;
00590 VectorXd x(n);
00591
00592
00593 x.setConstant(n, 1.);
00594
00595
00596 lmdif_functor functor;
00597 NumericalDiff<lmdif_functor> numDiff(functor);
00598 LevenbergMarquardt<NumericalDiff<lmdif_functor> > lm(numDiff);
00599 info = lm.minimize(x);
00600
00601
00602 VERIFY_IS_EQUAL(info, 1);
00603 VERIFY_IS_EQUAL(lm.nfev, 26);
00604
00605
00606 fnorm = lm.fvec.blueNorm();
00607 VERIFY_IS_APPROX(fnorm, 0.09063596);
00608
00609
00610 VectorXd x_ref(n);
00611 x_ref << 0.08241058, 1.133037, 2.343695;
00612 VERIFY_IS_APPROX(x, x_ref);
00613
00614
00615 covfac = fnorm*fnorm/(m-n);
00616 internal::covar(lm.fjac, lm.permutation.indices());
00617
00618 MatrixXd cov_ref(n,n);
00619 cov_ref <<
00620 0.0001531202, 0.002869942, -0.002656662,
00621 0.002869942, 0.09480937, -0.09098997,
00622 -0.002656662, -0.09098997, 0.08778729;
00623
00624
00625
00626 MatrixXd cov;
00627 cov = covfac*lm.fjac.topLeftCorner<n,n>();
00628 VERIFY_IS_APPROX( cov, cov_ref);
00629
00630
00631 }
00632
00633 struct chwirut2_functor : Functor<double>
00634 {
00635 chwirut2_functor(void) : Functor<double>(3,54) {}
00636 static const double m_x[54];
00637 static const double m_y[54];
00638 int operator()(const VectorXd &b, VectorXd &fvec)
00639 {
00640 int i;
00641
00642 assert(b.size()==3);
00643 assert(fvec.size()==54);
00644 for(i=0; i<54; i++) {
00645 double x = m_x[i];
00646 fvec[i] = exp(-b[0]*x)/(b[1]+b[2]*x) - m_y[i];
00647 }
00648 return 0;
00649 }
00650 int df(const VectorXd &b, MatrixXd &fjac)
00651 {
00652 assert(b.size()==3);
00653 assert(fjac.rows()==54);
00654 assert(fjac.cols()==3);
00655 for(int i=0; i<54; i++) {
00656 double x = m_x[i];
00657 double factor = 1./(b[1]+b[2]*x);
00658 double e = exp(-b[0]*x);
00659 fjac(i,0) = -x*e*factor;
00660 fjac(i,1) = -e*factor*factor;
00661 fjac(i,2) = -x*e*factor*factor;
00662 }
00663 return 0;
00664 }
00665 };
00666 const double chwirut2_functor::m_x[54] = { 0.500E0, 1.000E0, 1.750E0, 3.750E0, 5.750E0, 0.875E0, 2.250E0, 3.250E0, 5.250E0, 0.750E0, 1.750E0, 2.750E0, 4.750E0, 0.625E0, 1.250E0, 2.250E0, 4.250E0, .500E0, 3.000E0, .750E0, 3.000E0, 1.500E0, 6.000E0, 3.000E0, 6.000E0, 1.500E0, 3.000E0, .500E0, 2.000E0, 4.000E0, .750E0, 2.000E0, 5.000E0, .750E0, 2.250E0, 3.750E0, 5.750E0, 3.000E0, .750E0, 2.500E0, 4.000E0, .750E0, 2.500E0, 4.000E0, .750E0, 2.500E0, 4.000E0, .500E0, 6.000E0, 3.000E0, .500E0, 2.750E0, .500E0, 1.750E0};
00667 const double chwirut2_functor::m_y[54] = { 92.9000E0 ,57.1000E0 ,31.0500E0 ,11.5875E0 ,8.0250E0 ,63.6000E0 ,21.4000E0 ,14.2500E0 ,8.4750E0 ,63.8000E0 ,26.8000E0 ,16.4625E0 ,7.1250E0 ,67.3000E0 ,41.0000E0 ,21.1500E0 ,8.1750E0 ,81.5000E0 ,13.1200E0 ,59.9000E0 ,14.6200E0 ,32.9000E0 ,5.4400E0 ,12.5600E0 ,5.4400E0 ,32.0000E0 ,13.9500E0 ,75.8000E0 ,20.0000E0 ,10.4200E0 ,59.5000E0 ,21.6700E0 ,8.5500E0 ,62.0000E0 ,20.2000E0 ,7.7600E0 ,3.7500E0 ,11.8100E0 ,54.7000E0 ,23.7000E0 ,11.5500E0 ,61.3000E0 ,17.7000E0 ,8.7400E0 ,59.2000E0 ,16.3000E0 ,8.6200E0 ,81.0000E0 ,4.8700E0 ,14.6200E0 ,81.7000E0 ,17.1700E0 ,81.3000E0 ,28.9000E0 };
00668
00669
00670 void testNistChwirut2(void)
00671 {
00672 const int n=3;
00673 int info;
00674
00675 VectorXd x(n);
00676
00677
00678
00679
00680 x<< 0.1, 0.01, 0.02;
00681
00682 chwirut2_functor functor;
00683 LevenbergMarquardt<chwirut2_functor> lm(functor);
00684 info = lm.minimize(x);
00685
00686
00687 VERIFY_IS_EQUAL(info, 1);
00688 VERIFY_IS_EQUAL(lm.nfev, 10);
00689 VERIFY_IS_EQUAL(lm.njev, 8);
00690
00691 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.1304802941E+02);
00692
00693 VERIFY_IS_APPROX(x[0], 1.6657666537E-01);
00694 VERIFY_IS_APPROX(x[1], 5.1653291286E-03);
00695 VERIFY_IS_APPROX(x[2], 1.2150007096E-02);
00696
00697
00698
00699
00700 x<< 0.15, 0.008, 0.010;
00701
00702 lm.resetParameters();
00703 lm.parameters.ftol = 1.E6*NumTraits<double>::epsilon();
00704 lm.parameters.xtol = 1.E6*NumTraits<double>::epsilon();
00705 info = lm.minimize(x);
00706
00707
00708 VERIFY_IS_EQUAL(info, 1);
00709 VERIFY_IS_EQUAL(lm.nfev, 7);
00710 VERIFY_IS_EQUAL(lm.njev, 6);
00711
00712 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.1304802941E+02);
00713
00714 VERIFY_IS_APPROX(x[0], 1.6657666537E-01);
00715 VERIFY_IS_APPROX(x[1], 5.1653291286E-03);
00716 VERIFY_IS_APPROX(x[2], 1.2150007096E-02);
00717 }
00718
00719
00720 struct misra1a_functor : Functor<double>
00721 {
00722 misra1a_functor(void) : Functor<double>(2,14) {}
00723 static const double m_x[14];
00724 static const double m_y[14];
00725 int operator()(const VectorXd &b, VectorXd &fvec)
00726 {
00727 assert(b.size()==2);
00728 assert(fvec.size()==14);
00729 for(int i=0; i<14; i++) {
00730 fvec[i] = b[0]*(1.-exp(-b[1]*m_x[i])) - m_y[i] ;
00731 }
00732 return 0;
00733 }
00734 int df(const VectorXd &b, MatrixXd &fjac)
00735 {
00736 assert(b.size()==2);
00737 assert(fjac.rows()==14);
00738 assert(fjac.cols()==2);
00739 for(int i=0; i<14; i++) {
00740 fjac(i,0) = (1.-exp(-b[1]*m_x[i]));
00741 fjac(i,1) = (b[0]*m_x[i]*exp(-b[1]*m_x[i]));
00742 }
00743 return 0;
00744 }
00745 };
00746 const double misra1a_functor::m_x[14] = { 77.6E0, 114.9E0, 141.1E0, 190.8E0, 239.9E0, 289.0E0, 332.8E0, 378.4E0, 434.8E0, 477.3E0, 536.8E0, 593.1E0, 689.1E0, 760.0E0};
00747 const double misra1a_functor::m_y[14] = { 10.07E0, 14.73E0, 17.94E0, 23.93E0, 29.61E0, 35.18E0, 40.02E0, 44.82E0, 50.76E0, 55.05E0, 61.01E0, 66.40E0, 75.47E0, 81.78E0};
00748
00749
00750 void testNistMisra1a(void)
00751 {
00752 const int n=2;
00753 int info;
00754
00755 VectorXd x(n);
00756
00757
00758
00759
00760 x<< 500., 0.0001;
00761
00762 misra1a_functor functor;
00763 LevenbergMarquardt<misra1a_functor> lm(functor);
00764 info = lm.minimize(x);
00765
00766
00767 VERIFY_IS_EQUAL(info, 1);
00768 VERIFY_IS_EQUAL(lm.nfev, 19);
00769 VERIFY_IS_EQUAL(lm.njev, 15);
00770
00771 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.2455138894E-01);
00772
00773 VERIFY_IS_APPROX(x[0], 2.3894212918E+02);
00774 VERIFY_IS_APPROX(x[1], 5.5015643181E-04);
00775
00776
00777
00778
00779 x<< 250., 0.0005;
00780
00781 info = lm.minimize(x);
00782
00783
00784 VERIFY_IS_EQUAL(info, 1);
00785 VERIFY_IS_EQUAL(lm.nfev, 5);
00786 VERIFY_IS_EQUAL(lm.njev, 4);
00787
00788 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.2455138894E-01);
00789
00790 VERIFY_IS_APPROX(x[0], 2.3894212918E+02);
00791 VERIFY_IS_APPROX(x[1], 5.5015643181E-04);
00792 }
00793
00794 struct hahn1_functor : Functor<double>
00795 {
00796 hahn1_functor(void) : Functor<double>(7,236) {}
00797 static const double m_x[236];
00798 int operator()(const VectorXd &b, VectorXd &fvec)
00799 {
00800 static const double m_y[236] = { .591E0 , 1.547E0 , 2.902E0 , 2.894E0 , 4.703E0 , 6.307E0 , 7.03E0 , 7.898E0 , 9.470E0 , 9.484E0 , 10.072E0 , 10.163E0 , 11.615E0 , 12.005E0 , 12.478E0 , 12.982E0 , 12.970E0 , 13.926E0 , 14.452E0 , 14.404E0 , 15.190E0 , 15.550E0 , 15.528E0 , 15.499E0 , 16.131E0 , 16.438E0 , 16.387E0 , 16.549E0 , 16.872E0 , 16.830E0 , 16.926E0 , 16.907E0 , 16.966E0 , 17.060E0 , 17.122E0 , 17.311E0 , 17.355E0 , 17.668E0 , 17.767E0 , 17.803E0 , 17.765E0 , 17.768E0 , 17.736E0 , 17.858E0 , 17.877E0 , 17.912E0 , 18.046E0 , 18.085E0 , 18.291E0 , 18.357E0 , 18.426E0 , 18.584E0 , 18.610E0 , 18.870E0 , 18.795E0 , 19.111E0 , .367E0 , .796E0 , 0.892E0 , 1.903E0 , 2.150E0 , 3.697E0 , 5.870E0 , 6.421E0 , 7.422E0 , 9.944E0 , 11.023E0 , 11.87E0 , 12.786E0 , 14.067E0 , 13.974E0 , 14.462E0 , 14.464E0 , 15.381E0 , 15.483E0 , 15.59E0 , 16.075E0 , 16.347E0 , 16.181E0 , 16.915E0 , 17.003E0 , 16.978E0 , 17.756E0 , 17.808E0 , 17.868E0 , 18.481E0 , 18.486E0 , 19.090E0 , 16.062E0 , 16.337E0 , 16.345E0 ,
00801 16.388E0 , 17.159E0 , 17.116E0 , 17.164E0 , 17.123E0 , 17.979E0 , 17.974E0 , 18.007E0 , 17.993E0 , 18.523E0 , 18.669E0 , 18.617E0 , 19.371E0 , 19.330E0 , 0.080E0 , 0.248E0 , 1.089E0 , 1.418E0 , 2.278E0 , 3.624E0 , 4.574E0 , 5.556E0 , 7.267E0 , 7.695E0 , 9.136E0 , 9.959E0 , 9.957E0 , 11.600E0 , 13.138E0 , 13.564E0 , 13.871E0 , 13.994E0 , 14.947E0 , 15.473E0 , 15.379E0 , 15.455E0 , 15.908E0 , 16.114E0 , 17.071E0 , 17.135E0 , 17.282E0 , 17.368E0 , 17.483E0 , 17.764E0 , 18.185E0 , 18.271E0 , 18.236E0 , 18.237E0 , 18.523E0 , 18.627E0 , 18.665E0 , 19.086E0 , 0.214E0 , 0.943E0 , 1.429E0 , 2.241E0 , 2.951E0 , 3.782E0 , 4.757E0 , 5.602E0 , 7.169E0 , 8.920E0 , 10.055E0 , 12.035E0 , 12.861E0 , 13.436E0 , 14.167E0 , 14.755E0 , 15.168E0 , 15.651E0 , 15.746E0 , 16.216E0 , 16.445E0 , 16.965E0 , 17.121E0 , 17.206E0 , 17.250E0 , 17.339E0 , 17.793E0 , 18.123E0 , 18.49E0 , 18.566E0 , 18.645E0 , 18.706E0 , 18.924E0 , 19.1E0 , 0.375E0 , 0.471E0 , 1.504E0 , 2.204E0 , 2.813E0 , 4.765E0 , 9.835E0 , 10.040E0 , 11.946E0 , 12.596E0 ,
00802 13.303E0 , 13.922E0 , 14.440E0 , 14.951E0 , 15.627E0 , 15.639E0 , 15.814E0 , 16.315E0 , 16.334E0 , 16.430E0 , 16.423E0 , 17.024E0 , 17.009E0 , 17.165E0 , 17.134E0 , 17.349E0 , 17.576E0 , 17.848E0 , 18.090E0 , 18.276E0 , 18.404E0 , 18.519E0 , 19.133E0 , 19.074E0 , 19.239E0 , 19.280E0 , 19.101E0 , 19.398E0 , 19.252E0 , 19.89E0 , 20.007E0 , 19.929E0 , 19.268E0 , 19.324E0 , 20.049E0 , 20.107E0 , 20.062E0 , 20.065E0 , 19.286E0 , 19.972E0 , 20.088E0 , 20.743E0 , 20.83E0 , 20.935E0 , 21.035E0 , 20.93E0 , 21.074E0 , 21.085E0 , 20.935E0 };
00803
00804
00805
00806 assert(b.size()==7);
00807 assert(fvec.size()==236);
00808 for(int i=0; i<236; i++) {
00809 double x=m_x[i], xx=x*x, xxx=xx*x;
00810 fvec[i] = (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) / (1.+b[4]*x+b[5]*xx+b[6]*xxx) - m_y[i];
00811 }
00812 return 0;
00813 }
00814
00815 int df(const VectorXd &b, MatrixXd &fjac)
00816 {
00817 assert(b.size()==7);
00818 assert(fjac.rows()==236);
00819 assert(fjac.cols()==7);
00820 for(int i=0; i<236; i++) {
00821 double x=m_x[i], xx=x*x, xxx=xx*x;
00822 double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx);
00823 fjac(i,0) = 1.*fact;
00824 fjac(i,1) = x*fact;
00825 fjac(i,2) = xx*fact;
00826 fjac(i,3) = xxx*fact;
00827 fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact;
00828 fjac(i,4) = x*fact;
00829 fjac(i,5) = xx*fact;
00830 fjac(i,6) = xxx*fact;
00831 }
00832 return 0;
00833 }
00834 };
00835 const double hahn1_functor::m_x[236] = { 24.41E0 , 34.82E0 , 44.09E0 , 45.07E0 , 54.98E0 , 65.51E0 , 70.53E0 , 75.70E0 , 89.57E0 , 91.14E0 , 96.40E0 , 97.19E0 , 114.26E0 , 120.25E0 , 127.08E0 , 133.55E0 , 133.61E0 , 158.67E0 , 172.74E0 , 171.31E0 , 202.14E0 , 220.55E0 , 221.05E0 , 221.39E0 , 250.99E0 , 268.99E0 , 271.80E0 , 271.97E0 , 321.31E0 , 321.69E0 , 330.14E0 , 333.03E0 , 333.47E0 , 340.77E0 , 345.65E0 , 373.11E0 , 373.79E0 , 411.82E0 , 419.51E0 , 421.59E0 , 422.02E0 , 422.47E0 , 422.61E0 , 441.75E0 , 447.41E0 , 448.7E0 , 472.89E0 , 476.69E0 , 522.47E0 , 522.62E0 , 524.43E0 , 546.75E0 , 549.53E0 , 575.29E0 , 576.00E0 , 625.55E0 , 20.15E0 , 28.78E0 , 29.57E0 , 37.41E0 , 39.12E0 , 50.24E0 , 61.38E0 , 66.25E0 , 73.42E0 , 95.52E0 , 107.32E0 , 122.04E0 , 134.03E0 , 163.19E0 , 163.48E0 , 175.70E0 , 179.86E0 , 211.27E0 , 217.78E0 , 219.14E0 , 262.52E0 , 268.01E0 , 268.62E0 , 336.25E0 , 337.23E0 , 339.33E0 , 427.38E0 , 428.58E0 , 432.68E0 , 528.99E0 , 531.08E0 , 628.34E0 , 253.24E0 , 273.13E0 , 273.66E0 ,
00836 282.10E0 , 346.62E0 , 347.19E0 , 348.78E0 , 351.18E0 , 450.10E0 , 450.35E0 , 451.92E0 , 455.56E0 , 552.22E0 , 553.56E0 , 555.74E0 , 652.59E0 , 656.20E0 , 14.13E0 , 20.41E0 , 31.30E0 , 33.84E0 , 39.70E0 , 48.83E0 , 54.50E0 , 60.41E0 , 72.77E0 , 75.25E0 , 86.84E0 , 94.88E0 , 96.40E0 , 117.37E0 , 139.08E0 , 147.73E0 , 158.63E0 , 161.84E0 , 192.11E0 , 206.76E0 , 209.07E0 , 213.32E0 , 226.44E0 , 237.12E0 , 330.90E0 , 358.72E0 , 370.77E0 , 372.72E0 , 396.24E0 , 416.59E0 , 484.02E0 , 495.47E0 , 514.78E0 , 515.65E0 , 519.47E0 , 544.47E0 , 560.11E0 , 620.77E0 , 18.97E0 , 28.93E0 , 33.91E0 , 40.03E0 , 44.66E0 , 49.87E0 , 55.16E0 , 60.90E0 , 72.08E0 , 85.15E0 , 97.06E0 , 119.63E0 , 133.27E0 , 143.84E0 , 161.91E0 , 180.67E0 , 198.44E0 , 226.86E0 , 229.65E0 , 258.27E0 , 273.77E0 , 339.15E0 , 350.13E0 , 362.75E0 , 371.03E0 , 393.32E0 , 448.53E0 , 473.78E0 , 511.12E0 , 524.70E0 , 548.75E0 , 551.64E0 , 574.02E0 , 623.86E0 , 21.46E0 , 24.33E0 , 33.43E0 , 39.22E0 , 44.18E0 , 55.02E0 , 94.33E0 , 96.44E0 , 118.82E0 , 128.48E0 ,
00837 141.94E0 , 156.92E0 , 171.65E0 , 190.00E0 , 223.26E0 , 223.88E0 , 231.50E0 , 265.05E0 , 269.44E0 , 271.78E0 , 273.46E0 , 334.61E0 , 339.79E0 , 349.52E0 , 358.18E0 , 377.98E0 , 394.77E0 , 429.66E0 , 468.22E0 , 487.27E0 , 519.54E0 , 523.03E0 , 612.99E0 , 638.59E0 , 641.36E0 , 622.05E0 , 631.50E0 , 663.97E0 , 646.9E0 , 748.29E0 , 749.21E0 , 750.14E0 , 647.04E0 , 646.89E0 , 746.9E0 , 748.43E0 , 747.35E0 , 749.27E0 , 647.61E0 , 747.78E0 , 750.51E0 , 851.37E0 , 845.97E0 , 847.54E0 , 849.93E0 , 851.61E0 , 849.75E0 , 850.98E0 , 848.23E0};
00838
00839
00840 void testNistHahn1(void)
00841 {
00842 const int n=7;
00843 int info;
00844
00845 VectorXd x(n);
00846
00847
00848
00849
00850 x<< 10., -1., .05, -.00001, -.05, .001, -.000001;
00851
00852 hahn1_functor functor;
00853 LevenbergMarquardt<hahn1_functor> lm(functor);
00854 info = lm.minimize(x);
00855
00856
00857 VERIFY_IS_EQUAL(info, 1);
00858 VERIFY_IS_EQUAL(lm.nfev, 11);
00859 VERIFY_IS_EQUAL(lm.njev, 10);
00860
00861 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.5324382854E+00);
00862
00863 VERIFY_IS_APPROX(x[0], 1.0776351733E+00);
00864 VERIFY_IS_APPROX(x[1],-1.2269296921E-01);
00865 VERIFY_IS_APPROX(x[2], 4.0863750610E-03);
00866 VERIFY_IS_APPROX(x[3],-1.426264e-06);
00867 VERIFY_IS_APPROX(x[4],-5.7609940901E-03);
00868 VERIFY_IS_APPROX(x[5], 2.4053735503E-04);
00869 VERIFY_IS_APPROX(x[6],-1.2314450199E-07);
00870
00871
00872
00873
00874 x<< .1, -.1, .005, -.000001, -.005, .0001, -.0000001;
00875
00876 info = lm.minimize(x);
00877
00878
00879 VERIFY_IS_EQUAL(info, 1);
00880 VERIFY_IS_EQUAL(lm.nfev, 11);
00881 VERIFY_IS_EQUAL(lm.njev, 10);
00882
00883 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.5324382854E+00);
00884
00885 VERIFY_IS_APPROX(x[0], 1.077640);
00886 VERIFY_IS_APPROX(x[1], -0.1226933);
00887 VERIFY_IS_APPROX(x[2], 0.004086383);
00888 VERIFY_IS_APPROX(x[3], -1.426277e-06);
00889 VERIFY_IS_APPROX(x[4],-5.7609940901E-03);
00890 VERIFY_IS_APPROX(x[5], 0.00024053772);
00891 VERIFY_IS_APPROX(x[6], -1.231450e-07);
00892
00893 }
00894
00895 struct misra1d_functor : Functor<double>
00896 {
00897 misra1d_functor(void) : Functor<double>(2,14) {}
00898 static const double x[14];
00899 static const double y[14];
00900 int operator()(const VectorXd &b, VectorXd &fvec)
00901 {
00902 assert(b.size()==2);
00903 assert(fvec.size()==14);
00904 for(int i=0; i<14; i++) {
00905 fvec[i] = b[0]*b[1]*x[i]/(1.+b[1]*x[i]) - y[i];
00906 }
00907 return 0;
00908 }
00909 int df(const VectorXd &b, MatrixXd &fjac)
00910 {
00911 assert(b.size()==2);
00912 assert(fjac.rows()==14);
00913 assert(fjac.cols()==2);
00914 for(int i=0; i<14; i++) {
00915 double den = 1.+b[1]*x[i];
00916 fjac(i,0) = b[1]*x[i] / den;
00917 fjac(i,1) = b[0]*x[i]*(den-b[1]*x[i])/den/den;
00918 }
00919 return 0;
00920 }
00921 };
00922 const double misra1d_functor::x[14] = { 77.6E0, 114.9E0, 141.1E0, 190.8E0, 239.9E0, 289.0E0, 332.8E0, 378.4E0, 434.8E0, 477.3E0, 536.8E0, 593.1E0, 689.1E0, 760.0E0};
00923 const double misra1d_functor::y[14] = { 10.07E0, 14.73E0, 17.94E0, 23.93E0, 29.61E0, 35.18E0, 40.02E0, 44.82E0, 50.76E0, 55.05E0, 61.01E0, 66.40E0, 75.47E0, 81.78E0};
00924
00925
00926 void testNistMisra1d(void)
00927 {
00928 const int n=2;
00929 int info;
00930
00931 VectorXd x(n);
00932
00933
00934
00935
00936 x<< 500., 0.0001;
00937
00938 misra1d_functor functor;
00939 LevenbergMarquardt<misra1d_functor> lm(functor);
00940 info = lm.minimize(x);
00941
00942
00943 VERIFY_IS_EQUAL(info, 3);
00944 VERIFY_IS_EQUAL(lm.nfev, 9);
00945 VERIFY_IS_EQUAL(lm.njev, 7);
00946
00947 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6419295283E-02);
00948
00949 VERIFY_IS_APPROX(x[0], 4.3736970754E+02);
00950 VERIFY_IS_APPROX(x[1], 3.0227324449E-04);
00951
00952
00953
00954
00955 x<< 450., 0.0003;
00956
00957 info = lm.minimize(x);
00958
00959
00960 VERIFY_IS_EQUAL(info, 1);
00961 VERIFY_IS_EQUAL(lm.nfev, 4);
00962 VERIFY_IS_EQUAL(lm.njev, 3);
00963
00964 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6419295283E-02);
00965
00966 VERIFY_IS_APPROX(x[0], 4.3736970754E+02);
00967 VERIFY_IS_APPROX(x[1], 3.0227324449E-04);
00968 }
00969
00970
00971 struct lanczos1_functor : Functor<double>
00972 {
00973 lanczos1_functor(void) : Functor<double>(6,24) {}
00974 static const double x[24];
00975 static const double y[24];
00976 int operator()(const VectorXd &b, VectorXd &fvec)
00977 {
00978 assert(b.size()==6);
00979 assert(fvec.size()==24);
00980 for(int i=0; i<24; i++)
00981 fvec[i] = b[0]*exp(-b[1]*x[i]) + b[2]*exp(-b[3]*x[i]) + b[4]*exp(-b[5]*x[i]) - y[i];
00982 return 0;
00983 }
00984 int df(const VectorXd &b, MatrixXd &fjac)
00985 {
00986 assert(b.size()==6);
00987 assert(fjac.rows()==24);
00988 assert(fjac.cols()==6);
00989 for(int i=0; i<24; i++) {
00990 fjac(i,0) = exp(-b[1]*x[i]);
00991 fjac(i,1) = -b[0]*x[i]*exp(-b[1]*x[i]);
00992 fjac(i,2) = exp(-b[3]*x[i]);
00993 fjac(i,3) = -b[2]*x[i]*exp(-b[3]*x[i]);
00994 fjac(i,4) = exp(-b[5]*x[i]);
00995 fjac(i,5) = -b[4]*x[i]*exp(-b[5]*x[i]);
00996 }
00997 return 0;
00998 }
00999 };
01000 const double lanczos1_functor::x[24] = { 0.000000000000E+00, 5.000000000000E-02, 1.000000000000E-01, 1.500000000000E-01, 2.000000000000E-01, 2.500000000000E-01, 3.000000000000E-01, 3.500000000000E-01, 4.000000000000E-01, 4.500000000000E-01, 5.000000000000E-01, 5.500000000000E-01, 6.000000000000E-01, 6.500000000000E-01, 7.000000000000E-01, 7.500000000000E-01, 8.000000000000E-01, 8.500000000000E-01, 9.000000000000E-01, 9.500000000000E-01, 1.000000000000E+00, 1.050000000000E+00, 1.100000000000E+00, 1.150000000000E+00 };
01001 const double lanczos1_functor::y[24] = { 2.513400000000E+00 ,2.044333373291E+00 ,1.668404436564E+00 ,1.366418021208E+00 ,1.123232487372E+00 ,9.268897180037E-01 ,7.679338563728E-01 ,6.388775523106E-01 ,5.337835317402E-01 ,4.479363617347E-01 ,3.775847884350E-01 ,3.197393199326E-01 ,2.720130773746E-01 ,2.324965529032E-01 ,1.996589546065E-01 ,1.722704126914E-01 ,1.493405660168E-01 ,1.300700206922E-01 ,1.138119324644E-01 ,1.000415587559E-01 ,8.833209084540E-02 ,7.833544019350E-02 ,6.976693743449E-02 ,6.239312536719E-02 };
01002
01003
01004 void testNistLanczos1(void)
01005 {
01006 const int n=6;
01007 int info;
01008
01009 VectorXd x(n);
01010
01011
01012
01013
01014 x<< 1.2, 0.3, 5.6, 5.5, 6.5, 7.6;
01015
01016 lanczos1_functor functor;
01017 LevenbergMarquardt<lanczos1_functor> lm(functor);
01018 info = lm.minimize(x);
01019
01020
01021 VERIFY_IS_EQUAL(info, 2);
01022 VERIFY_IS_EQUAL(lm.nfev, 79);
01023 VERIFY_IS_EQUAL(lm.njev, 72);
01024
01025 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.430899764097e-25);
01026
01027 VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
01028 VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
01029 VERIFY_IS_APPROX(x[2], 8.6070000013E-01);
01030 VERIFY_IS_APPROX(x[3], 3.0000000002E+00);
01031 VERIFY_IS_APPROX(x[4], 1.5575999998E+00);
01032 VERIFY_IS_APPROX(x[5], 5.0000000001E+00);
01033
01034
01035
01036
01037 x<< 0.5, 0.7, 3.6, 4.2, 4., 6.3;
01038
01039 info = lm.minimize(x);
01040
01041
01042 VERIFY_IS_EQUAL(info, 2);
01043 VERIFY_IS_EQUAL(lm.nfev, 9);
01044 VERIFY_IS_EQUAL(lm.njev, 8);
01045
01046 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.428595533845e-25);
01047
01048 VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
01049 VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
01050 VERIFY_IS_APPROX(x[2], 8.6070000013E-01);
01051 VERIFY_IS_APPROX(x[3], 3.0000000002E+00);
01052 VERIFY_IS_APPROX(x[4], 1.5575999998E+00);
01053 VERIFY_IS_APPROX(x[5], 5.0000000001E+00);
01054
01055 }
01056
01057 struct rat42_functor : Functor<double>
01058 {
01059 rat42_functor(void) : Functor<double>(3,9) {}
01060 static const double x[9];
01061 static const double y[9];
01062 int operator()(const VectorXd &b, VectorXd &fvec)
01063 {
01064 assert(b.size()==3);
01065 assert(fvec.size()==9);
01066 for(int i=0; i<9; i++) {
01067 fvec[i] = b[0] / (1.+exp(b[1]-b[2]*x[i])) - y[i];
01068 }
01069 return 0;
01070 }
01071
01072 int df(const VectorXd &b, MatrixXd &fjac)
01073 {
01074 assert(b.size()==3);
01075 assert(fjac.rows()==9);
01076 assert(fjac.cols()==3);
01077 for(int i=0; i<9; i++) {
01078 double e = exp(b[1]-b[2]*x[i]);
01079 fjac(i,0) = 1./(1.+e);
01080 fjac(i,1) = -b[0]*e/(1.+e)/(1.+e);
01081 fjac(i,2) = +b[0]*e*x[i]/(1.+e)/(1.+e);
01082 }
01083 return 0;
01084 }
01085 };
01086 const double rat42_functor::x[9] = { 9.000E0, 14.000E0, 21.000E0, 28.000E0, 42.000E0, 57.000E0, 63.000E0, 70.000E0, 79.000E0 };
01087 const double rat42_functor::y[9] = { 8.930E0 ,10.800E0 ,18.590E0 ,22.330E0 ,39.350E0 ,56.110E0 ,61.730E0 ,64.620E0 ,67.080E0 };
01088
01089
01090 void testNistRat42(void)
01091 {
01092 const int n=3;
01093 int info;
01094
01095 VectorXd x(n);
01096
01097
01098
01099
01100 x<< 100., 1., 0.1;
01101
01102 rat42_functor functor;
01103 LevenbergMarquardt<rat42_functor> lm(functor);
01104 info = lm.minimize(x);
01105
01106
01107 VERIFY_IS_EQUAL(info, 1);
01108 VERIFY_IS_EQUAL(lm.nfev, 10);
01109 VERIFY_IS_EQUAL(lm.njev, 8);
01110
01111 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.0565229338E+00);
01112
01113 VERIFY_IS_APPROX(x[0], 7.2462237576E+01);
01114 VERIFY_IS_APPROX(x[1], 2.6180768402E+00);
01115 VERIFY_IS_APPROX(x[2], 6.7359200066E-02);
01116
01117
01118
01119
01120 x<< 75., 2.5, 0.07;
01121
01122 info = lm.minimize(x);
01123
01124
01125 VERIFY_IS_EQUAL(info, 1);
01126 VERIFY_IS_EQUAL(lm.nfev, 6);
01127 VERIFY_IS_EQUAL(lm.njev, 5);
01128
01129 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.0565229338E+00);
01130
01131 VERIFY_IS_APPROX(x[0], 7.2462237576E+01);
01132 VERIFY_IS_APPROX(x[1], 2.6180768402E+00);
01133 VERIFY_IS_APPROX(x[2], 6.7359200066E-02);
01134 }
01135
01136 struct MGH10_functor : Functor<double>
01137 {
01138 MGH10_functor(void) : Functor<double>(3,16) {}
01139 static const double x[16];
01140 static const double y[16];
01141 int operator()(const VectorXd &b, VectorXd &fvec)
01142 {
01143 assert(b.size()==3);
01144 assert(fvec.size()==16);
01145 for(int i=0; i<16; i++)
01146 fvec[i] = b[0] * exp(b[1]/(x[i]+b[2])) - y[i];
01147 return 0;
01148 }
01149 int df(const VectorXd &b, MatrixXd &fjac)
01150 {
01151 assert(b.size()==3);
01152 assert(fjac.rows()==16);
01153 assert(fjac.cols()==3);
01154 for(int i=0; i<16; i++) {
01155 double factor = 1./(x[i]+b[2]);
01156 double e = exp(b[1]*factor);
01157 fjac(i,0) = e;
01158 fjac(i,1) = b[0]*factor*e;
01159 fjac(i,2) = -b[1]*b[0]*factor*factor*e;
01160 }
01161 return 0;
01162 }
01163 };
01164 const double MGH10_functor::x[16] = { 5.000000E+01, 5.500000E+01, 6.000000E+01, 6.500000E+01, 7.000000E+01, 7.500000E+01, 8.000000E+01, 8.500000E+01, 9.000000E+01, 9.500000E+01, 1.000000E+02, 1.050000E+02, 1.100000E+02, 1.150000E+02, 1.200000E+02, 1.250000E+02 };
01165 const double MGH10_functor::y[16] = { 3.478000E+04, 2.861000E+04, 2.365000E+04, 1.963000E+04, 1.637000E+04, 1.372000E+04, 1.154000E+04, 9.744000E+03, 8.261000E+03, 7.030000E+03, 6.005000E+03, 5.147000E+03, 4.427000E+03, 3.820000E+03, 3.307000E+03, 2.872000E+03 };
01166
01167
01168 void testNistMGH10(void)
01169 {
01170 const int n=3;
01171 int info;
01172
01173 VectorXd x(n);
01174
01175
01176
01177
01178 x<< 2., 400000., 25000.;
01179
01180 MGH10_functor functor;
01181 LevenbergMarquardt<MGH10_functor> lm(functor);
01182 info = lm.minimize(x);
01183
01184
01185 VERIFY_IS_EQUAL(info, 2);
01186 VERIFY_IS_EQUAL(lm.nfev, 284 );
01187 VERIFY_IS_EQUAL(lm.njev, 249 );
01188
01189 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7945855171E+01);
01190
01191 VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
01192 VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
01193 VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
01194
01195
01196
01197
01198 x<< 0.02, 4000., 250.;
01199
01200 info = lm.minimize(x);
01201
01202
01203 VERIFY_IS_EQUAL(info, 3);
01204 VERIFY_IS_EQUAL(lm.nfev, 126);
01205 VERIFY_IS_EQUAL(lm.njev, 116);
01206
01207 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7945855171E+01);
01208
01209 VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
01210 VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
01211 VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
01212 }
01213
01214
01215 struct BoxBOD_functor : Functor<double>
01216 {
01217 BoxBOD_functor(void) : Functor<double>(2,6) {}
01218 static const double x[6];
01219 int operator()(const VectorXd &b, VectorXd &fvec)
01220 {
01221 static const double y[6] = { 109., 149., 149., 191., 213., 224. };
01222 assert(b.size()==2);
01223 assert(fvec.size()==6);
01224 for(int i=0; i<6; i++)
01225 fvec[i] = b[0]*(1.-exp(-b[1]*x[i])) - y[i];
01226 return 0;
01227 }
01228 int df(const VectorXd &b, MatrixXd &fjac)
01229 {
01230 assert(b.size()==2);
01231 assert(fjac.rows()==6);
01232 assert(fjac.cols()==2);
01233 for(int i=0; i<6; i++) {
01234 double e = exp(-b[1]*x[i]);
01235 fjac(i,0) = 1.-e;
01236 fjac(i,1) = b[0]*x[i]*e;
01237 }
01238 return 0;
01239 }
01240 };
01241 const double BoxBOD_functor::x[6] = { 1., 2., 3., 5., 7., 10. };
01242
01243
01244 void testNistBoxBOD(void)
01245 {
01246 const int n=2;
01247 int info;
01248
01249 VectorXd x(n);
01250
01251
01252
01253
01254 x<< 1., 1.;
01255
01256 BoxBOD_functor functor;
01257 LevenbergMarquardt<BoxBOD_functor> lm(functor);
01258 lm.parameters.ftol = 1.E6*NumTraits<double>::epsilon();
01259 lm.parameters.xtol = 1.E6*NumTraits<double>::epsilon();
01260 lm.parameters.factor = 10.;
01261 info = lm.minimize(x);
01262
01263
01264 VERIFY_IS_EQUAL(info, 1);
01265 VERIFY_IS_EQUAL(lm.nfev, 31);
01266 VERIFY_IS_EQUAL(lm.njev, 25);
01267
01268 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.1680088766E+03);
01269
01270 VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
01271 VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
01272
01273
01274
01275
01276 x<< 100., 0.75;
01277
01278 lm.resetParameters();
01279 lm.parameters.ftol = NumTraits<double>::epsilon();
01280 lm.parameters.xtol = NumTraits<double>::epsilon();
01281 info = lm.minimize(x);
01282
01283
01284 VERIFY_IS_EQUAL(info, 1);
01285 VERIFY_IS_EQUAL(lm.nfev, 15 );
01286 VERIFY_IS_EQUAL(lm.njev, 14 );
01287
01288 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.1680088766E+03);
01289
01290 VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
01291 VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
01292 }
01293
01294 struct MGH17_functor : Functor<double>
01295 {
01296 MGH17_functor(void) : Functor<double>(5,33) {}
01297 static const double x[33];
01298 static const double y[33];
01299 int operator()(const VectorXd &b, VectorXd &fvec)
01300 {
01301 assert(b.size()==5);
01302 assert(fvec.size()==33);
01303 for(int i=0; i<33; i++)
01304 fvec[i] = b[0] + b[1]*exp(-b[3]*x[i]) + b[2]*exp(-b[4]*x[i]) - y[i];
01305 return 0;
01306 }
01307 int df(const VectorXd &b, MatrixXd &fjac)
01308 {
01309 assert(b.size()==5);
01310 assert(fjac.rows()==33);
01311 assert(fjac.cols()==5);
01312 for(int i=0; i<33; i++) {
01313 fjac(i,0) = 1.;
01314 fjac(i,1) = exp(-b[3]*x[i]);
01315 fjac(i,2) = exp(-b[4]*x[i]);
01316 fjac(i,3) = -x[i]*b[1]*exp(-b[3]*x[i]);
01317 fjac(i,4) = -x[i]*b[2]*exp(-b[4]*x[i]);
01318 }
01319 return 0;
01320 }
01321 };
01322 const double MGH17_functor::x[33] = { 0.000000E+00, 1.000000E+01, 2.000000E+01, 3.000000E+01, 4.000000E+01, 5.000000E+01, 6.000000E+01, 7.000000E+01, 8.000000E+01, 9.000000E+01, 1.000000E+02, 1.100000E+02, 1.200000E+02, 1.300000E+02, 1.400000E+02, 1.500000E+02, 1.600000E+02, 1.700000E+02, 1.800000E+02, 1.900000E+02, 2.000000E+02, 2.100000E+02, 2.200000E+02, 2.300000E+02, 2.400000E+02, 2.500000E+02, 2.600000E+02, 2.700000E+02, 2.800000E+02, 2.900000E+02, 3.000000E+02, 3.100000E+02, 3.200000E+02 };
01323 const double MGH17_functor::y[33] = { 8.440000E-01, 9.080000E-01, 9.320000E-01, 9.360000E-01, 9.250000E-01, 9.080000E-01, 8.810000E-01, 8.500000E-01, 8.180000E-01, 7.840000E-01, 7.510000E-01, 7.180000E-01, 6.850000E-01, 6.580000E-01, 6.280000E-01, 6.030000E-01, 5.800000E-01, 5.580000E-01, 5.380000E-01, 5.220000E-01, 5.060000E-01, 4.900000E-01, 4.780000E-01, 4.670000E-01, 4.570000E-01, 4.480000E-01, 4.380000E-01, 4.310000E-01, 4.240000E-01, 4.200000E-01, 4.140000E-01, 4.110000E-01, 4.060000E-01 };
01324
01325
01326 void testNistMGH17(void)
01327 {
01328 const int n=5;
01329 int info;
01330
01331 VectorXd x(n);
01332
01333
01334
01335
01336 x<< 50., 150., -100., 1., 2.;
01337
01338 MGH17_functor functor;
01339 LevenbergMarquardt<MGH17_functor> lm(functor);
01340 lm.parameters.ftol = NumTraits<double>::epsilon();
01341 lm.parameters.xtol = NumTraits<double>::epsilon();
01342 lm.parameters.maxfev = 1000;
01343 info = lm.minimize(x);
01344
01345
01346 VERIFY_IS_EQUAL(info, 2);
01347 VERIFY_IS_EQUAL(lm.nfev, 602 );
01348 VERIFY_IS_EQUAL(lm.njev, 545 );
01349
01350 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.4648946975E-05);
01351
01352 VERIFY_IS_APPROX(x[0], 3.7541005211E-01);
01353 VERIFY_IS_APPROX(x[1], 1.9358469127E+00);
01354 VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
01355 VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
01356 VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
01357
01358
01359
01360
01361 x<< 0.5 ,1.5 ,-1 ,0.01 ,0.02;
01362
01363 lm.resetParameters();
01364 info = lm.minimize(x);
01365
01366
01367 VERIFY_IS_EQUAL(info, 1);
01368 VERIFY_IS_EQUAL(lm.nfev, 18);
01369 VERIFY_IS_EQUAL(lm.njev, 15);
01370
01371 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.4648946975E-05);
01372
01373 VERIFY_IS_APPROX(x[0], 3.7541005211E-01);
01374 VERIFY_IS_APPROX(x[1], 1.9358469127E+00);
01375 VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
01376 VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
01377 VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
01378 }
01379
01380 struct MGH09_functor : Functor<double>
01381 {
01382 MGH09_functor(void) : Functor<double>(4,11) {}
01383 static const double _x[11];
01384 static const double y[11];
01385 int operator()(const VectorXd &b, VectorXd &fvec)
01386 {
01387 assert(b.size()==4);
01388 assert(fvec.size()==11);
01389 for(int i=0; i<11; i++) {
01390 double x = _x[i], xx=x*x;
01391 fvec[i] = b[0]*(xx+x*b[1])/(xx+x*b[2]+b[3]) - y[i];
01392 }
01393 return 0;
01394 }
01395 int df(const VectorXd &b, MatrixXd &fjac)
01396 {
01397 assert(b.size()==4);
01398 assert(fjac.rows()==11);
01399 assert(fjac.cols()==4);
01400 for(int i=0; i<11; i++) {
01401 double x = _x[i], xx=x*x;
01402 double factor = 1./(xx+x*b[2]+b[3]);
01403 fjac(i,0) = (xx+x*b[1]) * factor;
01404 fjac(i,1) = b[0]*x* factor;
01405 fjac(i,2) = - b[0]*(xx+x*b[1]) * x * factor * factor;
01406 fjac(i,3) = - b[0]*(xx+x*b[1]) * factor * factor;
01407 }
01408 return 0;
01409 }
01410 };
01411 const double MGH09_functor::_x[11] = { 4., 2., 1., 5.E-1 , 2.5E-01, 1.670000E-01, 1.250000E-01, 1.E-01, 8.330000E-02, 7.140000E-02, 6.250000E-02 };
01412 const double MGH09_functor::y[11] = { 1.957000E-01, 1.947000E-01, 1.735000E-01, 1.600000E-01, 8.440000E-02, 6.270000E-02, 4.560000E-02, 3.420000E-02, 3.230000E-02, 2.350000E-02, 2.460000E-02 };
01413
01414
01415 void testNistMGH09(void)
01416 {
01417 const int n=4;
01418 int info;
01419
01420 VectorXd x(n);
01421
01422
01423
01424
01425 x<< 25., 39, 41.5, 39.;
01426
01427 MGH09_functor functor;
01428 LevenbergMarquardt<MGH09_functor> lm(functor);
01429 lm.parameters.maxfev = 1000;
01430 info = lm.minimize(x);
01431
01432
01433 VERIFY_IS_EQUAL(info, 1);
01434 VERIFY_IS_EQUAL(lm.nfev, 490 );
01435 VERIFY_IS_EQUAL(lm.njev, 376 );
01436
01437 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 3.0750560385E-04);
01438
01439 VERIFY_IS_APPROX(x[0], 0.1928077089);
01440 VERIFY_IS_APPROX(x[1], 0.19126423573);
01441 VERIFY_IS_APPROX(x[2], 0.12305309914);
01442 VERIFY_IS_APPROX(x[3], 0.13605395375);
01443
01444
01445
01446
01447 x<< 0.25, 0.39, 0.415, 0.39;
01448
01449 lm.resetParameters();
01450 info = lm.minimize(x);
01451
01452
01453 VERIFY_IS_EQUAL(info, 1);
01454 VERIFY_IS_EQUAL(lm.nfev, 18);
01455 VERIFY_IS_EQUAL(lm.njev, 16);
01456
01457 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 3.0750560385E-04);
01458
01459 VERIFY_IS_APPROX(x[0], 0.19280781);
01460 VERIFY_IS_APPROX(x[1], 0.19126265);
01461 VERIFY_IS_APPROX(x[2], 0.12305280);
01462 VERIFY_IS_APPROX(x[3], 0.13605322);
01463 }
01464
01465
01466
01467 struct Bennett5_functor : Functor<double>
01468 {
01469 Bennett5_functor(void) : Functor<double>(3,154) {}
01470 static const double x[154];
01471 static const double y[154];
01472 int operator()(const VectorXd &b, VectorXd &fvec)
01473 {
01474 assert(b.size()==3);
01475 assert(fvec.size()==154);
01476 for(int i=0; i<154; i++)
01477 fvec[i] = b[0]* pow(b[1]+x[i],-1./b[2]) - y[i];
01478 return 0;
01479 }
01480 int df(const VectorXd &b, MatrixXd &fjac)
01481 {
01482 assert(b.size()==3);
01483 assert(fjac.rows()==154);
01484 assert(fjac.cols()==3);
01485 for(int i=0; i<154; i++) {
01486 double e = pow(b[1]+x[i],-1./b[2]);
01487 fjac(i,0) = e;
01488 fjac(i,1) = - b[0]*e/b[2]/(b[1]+x[i]);
01489 fjac(i,2) = b[0]*e*log(b[1]+x[i])/b[2]/b[2];
01490 }
01491 return 0;
01492 }
01493 };
01494 const double Bennett5_functor::x[154] = { 7.447168E0, 8.102586E0, 8.452547E0, 8.711278E0, 8.916774E0, 9.087155E0, 9.232590E0, 9.359535E0, 9.472166E0, 9.573384E0, 9.665293E0, 9.749461E0, 9.827092E0, 9.899128E0, 9.966321E0, 10.029280E0, 10.088510E0, 10.144430E0, 10.197380E0, 10.247670E0, 10.295560E0, 10.341250E0, 10.384950E0, 10.426820E0, 10.467000E0, 10.505640E0, 10.542830E0, 10.578690E0, 10.613310E0, 10.646780E0, 10.679150E0, 10.710520E0, 10.740920E0, 10.770440E0, 10.799100E0, 10.826970E0, 10.854080E0, 10.880470E0, 10.906190E0, 10.931260E0, 10.955720E0, 10.979590E0, 11.002910E0, 11.025700E0, 11.047980E0, 11.069770E0, 11.091100E0, 11.111980E0, 11.132440E0, 11.152480E0, 11.172130E0, 11.191410E0, 11.210310E0, 11.228870E0, 11.247090E0, 11.264980E0, 11.282560E0, 11.299840E0, 11.316820E0, 11.333520E0, 11.349940E0, 11.366100E0, 11.382000E0, 11.397660E0, 11.413070E0, 11.428240E0, 11.443200E0, 11.457930E0, 11.472440E0, 11.486750E0, 11.500860E0, 11.514770E0, 11.528490E0, 11.542020E0, 11.555380E0, 11.568550E0,
01495 11.581560E0, 11.594420E0, 11.607121E0, 11.619640E0, 11.632000E0, 11.644210E0, 11.656280E0, 11.668200E0, 11.679980E0, 11.691620E0, 11.703130E0, 11.714510E0, 11.725760E0, 11.736880E0, 11.747890E0, 11.758780E0, 11.769550E0, 11.780200E0, 11.790730E0, 11.801160E0, 11.811480E0, 11.821700E0, 11.831810E0, 11.841820E0, 11.851730E0, 11.861550E0, 11.871270E0, 11.880890E0, 11.890420E0, 11.899870E0, 11.909220E0, 11.918490E0, 11.927680E0, 11.936780E0, 11.945790E0, 11.954730E0, 11.963590E0, 11.972370E0, 11.981070E0, 11.989700E0, 11.998260E0, 12.006740E0, 12.015150E0, 12.023490E0, 12.031760E0, 12.039970E0, 12.048100E0, 12.056170E0, 12.064180E0, 12.072120E0, 12.080010E0, 12.087820E0, 12.095580E0, 12.103280E0, 12.110920E0, 12.118500E0, 12.126030E0, 12.133500E0, 12.140910E0, 12.148270E0, 12.155570E0, 12.162830E0, 12.170030E0, 12.177170E0, 12.184270E0, 12.191320E0, 12.198320E0, 12.205270E0, 12.212170E0, 12.219030E0, 12.225840E0, 12.232600E0, 12.239320E0, 12.245990E0, 12.252620E0, 12.259200E0, 12.265750E0, 12.272240E0 };
01496 const double Bennett5_functor::y[154] = { -34.834702E0 ,-34.393200E0 ,-34.152901E0 ,-33.979099E0 ,-33.845901E0 ,-33.732899E0 ,-33.640301E0 ,-33.559200E0 ,-33.486801E0 ,-33.423100E0 ,-33.365101E0 ,-33.313000E0 ,-33.260899E0 ,-33.217400E0 ,-33.176899E0 ,-33.139198E0 ,-33.101601E0 ,-33.066799E0 ,-33.035000E0 ,-33.003101E0 ,-32.971298E0 ,-32.942299E0 ,-32.916302E0 ,-32.890202E0 ,-32.864101E0 ,-32.841000E0 ,-32.817799E0 ,-32.797501E0 ,-32.774300E0 ,-32.757000E0 ,-32.733799E0 ,-32.716400E0 ,-32.699100E0 ,-32.678799E0 ,-32.661400E0 ,-32.644001E0 ,-32.626701E0 ,-32.612202E0 ,-32.597698E0 ,-32.583199E0 ,-32.568699E0 ,-32.554298E0 ,-32.539799E0 ,-32.525299E0 ,-32.510799E0 ,-32.499199E0 ,-32.487598E0 ,-32.473202E0 ,-32.461601E0 ,-32.435501E0 ,-32.435501E0 ,-32.426800E0 ,-32.412300E0 ,-32.400799E0 ,-32.392101E0 ,-32.380501E0 ,-32.366001E0 ,-32.357300E0 ,-32.348598E0 ,-32.339901E0 ,-32.328400E0 ,-32.319698E0 ,-32.311001E0 ,-32.299400E0 ,-32.290699E0 ,-32.282001E0 ,-32.273300E0 ,-32.264599E0 ,-32.256001E0 ,-32.247299E0
01497 ,-32.238602E0 ,-32.229900E0 ,-32.224098E0 ,-32.215401E0 ,-32.203800E0 ,-32.198002E0 ,-32.189400E0 ,-32.183601E0 ,-32.174900E0 ,-32.169102E0 ,-32.163300E0 ,-32.154598E0 ,-32.145901E0 ,-32.140099E0 ,-32.131401E0 ,-32.125599E0 ,-32.119801E0 ,-32.111198E0 ,-32.105400E0 ,-32.096699E0 ,-32.090900E0 ,-32.088001E0 ,-32.079300E0 ,-32.073502E0 ,-32.067699E0 ,-32.061901E0 ,-32.056099E0 ,-32.050301E0 ,-32.044498E0 ,-32.038799E0 ,-32.033001E0 ,-32.027199E0 ,-32.024300E0 ,-32.018501E0 ,-32.012699E0 ,-32.004002E0 ,-32.001099E0 ,-31.995300E0 ,-31.989500E0 ,-31.983700E0 ,-31.977900E0 ,-31.972099E0 ,-31.969299E0 ,-31.963501E0 ,-31.957701E0 ,-31.951900E0 ,-31.946100E0 ,-31.940300E0 ,-31.937401E0 ,-31.931601E0 ,-31.925800E0 ,-31.922899E0 ,-31.917101E0 ,-31.911301E0 ,-31.908400E0 ,-31.902599E0 ,-31.896900E0 ,-31.893999E0 ,-31.888201E0 ,-31.885300E0 ,-31.882401E0 ,-31.876600E0 ,-31.873699E0 ,-31.867901E0 ,-31.862101E0 ,-31.859200E0 ,-31.856300E0 ,-31.850500E0 ,-31.844700E0 ,-31.841801E0 ,-31.838900E0 ,-31.833099E0 ,-31.830200E0 ,
01498 -31.827299E0 ,-31.821600E0 ,-31.818701E0 ,-31.812901E0 ,-31.809999E0 ,-31.807100E0 ,-31.801300E0 ,-31.798401E0 ,-31.795500E0 ,-31.789700E0 ,-31.786800E0 };
01499
01500
01501 void testNistBennett5(void)
01502 {
01503 const int n=3;
01504 int info;
01505
01506 VectorXd x(n);
01507
01508
01509
01510
01511 x<< -2000., 50., 0.8;
01512
01513 Bennett5_functor functor;
01514 LevenbergMarquardt<Bennett5_functor> lm(functor);
01515 lm.parameters.maxfev = 1000;
01516 info = lm.minimize(x);
01517
01518
01519 VERIFY_IS_EQUAL(info, 1);
01520 VERIFY_IS_EQUAL(lm.nfev, 758);
01521 VERIFY_IS_EQUAL(lm.njev, 744);
01522
01523 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.2404744073E-04);
01524
01525 VERIFY_IS_APPROX(x[0], -2.5235058043E+03);
01526 VERIFY_IS_APPROX(x[1], 4.6736564644E+01);
01527 VERIFY_IS_APPROX(x[2], 9.3218483193E-01);
01528
01529
01530
01531 x<< -1500., 45., 0.85;
01532
01533 lm.resetParameters();
01534 info = lm.minimize(x);
01535
01536
01537 VERIFY_IS_EQUAL(info, 1);
01538 VERIFY_IS_EQUAL(lm.nfev, 203);
01539 VERIFY_IS_EQUAL(lm.njev, 192);
01540
01541 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.2404744073E-04);
01542
01543 VERIFY_IS_APPROX(x[0], -2523.3007865);
01544 VERIFY_IS_APPROX(x[1], 46.735705771);
01545 VERIFY_IS_APPROX(x[2], 0.93219881891);
01546 }
01547
01548 struct thurber_functor : Functor<double>
01549 {
01550 thurber_functor(void) : Functor<double>(7,37) {}
01551 static const double _x[37];
01552 static const double _y[37];
01553 int operator()(const VectorXd &b, VectorXd &fvec)
01554 {
01555
01556 assert(b.size()==7);
01557 assert(fvec.size()==37);
01558 for(int i=0; i<37; i++) {
01559 double x=_x[i], xx=x*x, xxx=xx*x;
01560 fvec[i] = (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) / (1.+b[4]*x+b[5]*xx+b[6]*xxx) - _y[i];
01561 }
01562 return 0;
01563 }
01564 int df(const VectorXd &b, MatrixXd &fjac)
01565 {
01566 assert(b.size()==7);
01567 assert(fjac.rows()==37);
01568 assert(fjac.cols()==7);
01569 for(int i=0; i<37; i++) {
01570 double x=_x[i], xx=x*x, xxx=xx*x;
01571 double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx);
01572 fjac(i,0) = 1.*fact;
01573 fjac(i,1) = x*fact;
01574 fjac(i,2) = xx*fact;
01575 fjac(i,3) = xxx*fact;
01576 fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact;
01577 fjac(i,4) = x*fact;
01578 fjac(i,5) = xx*fact;
01579 fjac(i,6) = xxx*fact;
01580 }
01581 return 0;
01582 }
01583 };
01584 const double thurber_functor::_x[37] = { -3.067E0, -2.981E0, -2.921E0, -2.912E0, -2.840E0, -2.797E0, -2.702E0, -2.699E0, -2.633E0, -2.481E0, -2.363E0, -2.322E0, -1.501E0, -1.460E0, -1.274E0, -1.212E0, -1.100E0, -1.046E0, -0.915E0, -0.714E0, -0.566E0, -0.545E0, -0.400E0, -0.309E0, -0.109E0, -0.103E0, 0.010E0, 0.119E0, 0.377E0, 0.790E0, 0.963E0, 1.006E0, 1.115E0, 1.572E0, 1.841E0, 2.047E0, 2.200E0 };
01585 const double thurber_functor::_y[37] = { 80.574E0, 84.248E0, 87.264E0, 87.195E0, 89.076E0, 89.608E0, 89.868E0, 90.101E0, 92.405E0, 95.854E0, 100.696E0, 101.060E0, 401.672E0, 390.724E0, 567.534E0, 635.316E0, 733.054E0, 759.087E0, 894.206E0, 990.785E0, 1090.109E0, 1080.914E0, 1122.643E0, 1178.351E0, 1260.531E0, 1273.514E0, 1288.339E0, 1327.543E0, 1353.863E0, 1414.509E0, 1425.208E0, 1421.384E0, 1442.962E0, 1464.350E0, 1468.705E0, 1447.894E0, 1457.628E0};
01586
01587
01588 void testNistThurber(void)
01589 {
01590 const int n=7;
01591 int info;
01592
01593 VectorXd x(n);
01594
01595
01596
01597
01598 x<< 1000 ,1000 ,400 ,40 ,0.7,0.3,0.0 ;
01599
01600 thurber_functor functor;
01601 LevenbergMarquardt<thurber_functor> lm(functor);
01602 lm.parameters.ftol = 1.E4*NumTraits<double>::epsilon();
01603 lm.parameters.xtol = 1.E4*NumTraits<double>::epsilon();
01604 info = lm.minimize(x);
01605
01606
01607 VERIFY_IS_EQUAL(info, 1);
01608 VERIFY_IS_EQUAL(lm.nfev, 39);
01609 VERIFY_IS_EQUAL(lm.njev, 36);
01610
01611 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6427082397E+03);
01612
01613 VERIFY_IS_APPROX(x[0], 1.2881396800E+03);
01614 VERIFY_IS_APPROX(x[1], 1.4910792535E+03);
01615 VERIFY_IS_APPROX(x[2], 5.8323836877E+02);
01616 VERIFY_IS_APPROX(x[3], 7.5416644291E+01);
01617 VERIFY_IS_APPROX(x[4], 9.6629502864E-01);
01618 VERIFY_IS_APPROX(x[5], 3.9797285797E-01);
01619 VERIFY_IS_APPROX(x[6], 4.9727297349E-02);
01620
01621
01622
01623
01624 x<< 1300 ,1500 ,500 ,75 ,1 ,0.4 ,0.05 ;
01625
01626 lm.resetParameters();
01627 lm.parameters.ftol = 1.E4*NumTraits<double>::epsilon();
01628 lm.parameters.xtol = 1.E4*NumTraits<double>::epsilon();
01629 info = lm.minimize(x);
01630
01631
01632 VERIFY_IS_EQUAL(info, 1);
01633 VERIFY_IS_EQUAL(lm.nfev, 29);
01634 VERIFY_IS_EQUAL(lm.njev, 28);
01635
01636 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6427082397E+03);
01637
01638 VERIFY_IS_APPROX(x[0], 1.2881396800E+03);
01639 VERIFY_IS_APPROX(x[1], 1.4910792535E+03);
01640 VERIFY_IS_APPROX(x[2], 5.8323836877E+02);
01641 VERIFY_IS_APPROX(x[3], 7.5416644291E+01);
01642 VERIFY_IS_APPROX(x[4], 9.6629502864E-01);
01643 VERIFY_IS_APPROX(x[5], 3.9797285797E-01);
01644 VERIFY_IS_APPROX(x[6], 4.9727297349E-02);
01645 }
01646
01647 struct rat43_functor : Functor<double>
01648 {
01649 rat43_functor(void) : Functor<double>(4,15) {}
01650 static const double x[15];
01651 static const double y[15];
01652 int operator()(const VectorXd &b, VectorXd &fvec)
01653 {
01654 assert(b.size()==4);
01655 assert(fvec.size()==15);
01656 for(int i=0; i<15; i++)
01657 fvec[i] = b[0] * pow(1.+exp(b[1]-b[2]*x[i]),-1./b[3]) - y[i];
01658 return 0;
01659 }
01660 int df(const VectorXd &b, MatrixXd &fjac)
01661 {
01662 assert(b.size()==4);
01663 assert(fjac.rows()==15);
01664 assert(fjac.cols()==4);
01665 for(int i=0; i<15; i++) {
01666 double e = exp(b[1]-b[2]*x[i]);
01667 double power = -1./b[3];
01668 fjac(i,0) = pow(1.+e, power);
01669 fjac(i,1) = power*b[0]*e*pow(1.+e, power-1.);
01670 fjac(i,2) = -power*b[0]*e*x[i]*pow(1.+e, power-1.);
01671 fjac(i,3) = b[0]*power*power*log(1.+e)*pow(1.+e, power);
01672 }
01673 return 0;
01674 }
01675 };
01676 const double rat43_functor::x[15] = { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15. };
01677 const double rat43_functor::y[15] = { 16.08, 33.83, 65.80, 97.20, 191.55, 326.20, 386.87, 520.53, 590.03, 651.92, 724.93, 699.56, 689.96, 637.56, 717.41 };
01678
01679
01680 void testNistRat43(void)
01681 {
01682 const int n=4;
01683 int info;
01684
01685 VectorXd x(n);
01686
01687
01688
01689
01690 x<< 100., 10., 1., 1.;
01691
01692 rat43_functor functor;
01693 LevenbergMarquardt<rat43_functor> lm(functor);
01694 lm.parameters.ftol = 1.E6*NumTraits<double>::epsilon();
01695 lm.parameters.xtol = 1.E6*NumTraits<double>::epsilon();
01696 info = lm.minimize(x);
01697
01698
01699 VERIFY_IS_EQUAL(info, 1);
01700 VERIFY_IS_EQUAL(lm.nfev, 27);
01701 VERIFY_IS_EQUAL(lm.njev, 20);
01702
01703 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7864049080E+03);
01704
01705 VERIFY_IS_APPROX(x[0], 6.9964151270E+02);
01706 VERIFY_IS_APPROX(x[1], 5.2771253025E+00);
01707 VERIFY_IS_APPROX(x[2], 7.5962938329E-01);
01708 VERIFY_IS_APPROX(x[3], 1.2792483859E+00);
01709
01710
01711
01712
01713 x<< 700., 5., 0.75, 1.3;
01714
01715 lm.resetParameters();
01716 lm.parameters.ftol = 1.E5*NumTraits<double>::epsilon();
01717 lm.parameters.xtol = 1.E5*NumTraits<double>::epsilon();
01718 info = lm.minimize(x);
01719
01720
01721 VERIFY_IS_EQUAL(info, 1);
01722 VERIFY_IS_EQUAL(lm.nfev, 9);
01723 VERIFY_IS_EQUAL(lm.njev, 8);
01724
01725 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7864049080E+03);
01726
01727 VERIFY_IS_APPROX(x[0], 6.9964151270E+02);
01728 VERIFY_IS_APPROX(x[1], 5.2771253025E+00);
01729 VERIFY_IS_APPROX(x[2], 7.5962938329E-01);
01730 VERIFY_IS_APPROX(x[3], 1.2792483859E+00);
01731 }
01732
01733
01734
01735 struct eckerle4_functor : Functor<double>
01736 {
01737 eckerle4_functor(void) : Functor<double>(3,35) {}
01738 static const double x[35];
01739 static const double y[35];
01740 int operator()(const VectorXd &b, VectorXd &fvec)
01741 {
01742 assert(b.size()==3);
01743 assert(fvec.size()==35);
01744 for(int i=0; i<35; i++)
01745 fvec[i] = b[0]/b[1] * exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/(b[1]*b[1])) - y[i];
01746 return 0;
01747 }
01748 int df(const VectorXd &b, MatrixXd &fjac)
01749 {
01750 assert(b.size()==3);
01751 assert(fjac.rows()==35);
01752 assert(fjac.cols()==3);
01753 for(int i=0; i<35; i++) {
01754 double b12 = b[1]*b[1];
01755 double e = exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/b12);
01756 fjac(i,0) = e / b[1];
01757 fjac(i,1) = ((x[i]-b[2])*(x[i]-b[2])/b12-1.) * b[0]*e/b12;
01758 fjac(i,2) = (x[i]-b[2])*e*b[0]/b[1]/b12;
01759 }
01760 return 0;
01761 }
01762 };
01763 const double eckerle4_functor::x[35] = { 400.0, 405.0, 410.0, 415.0, 420.0, 425.0, 430.0, 435.0, 436.5, 438.0, 439.5, 441.0, 442.5, 444.0, 445.5, 447.0, 448.5, 450.0, 451.5, 453.0, 454.5, 456.0, 457.5, 459.0, 460.5, 462.0, 463.5, 465.0, 470.0, 475.0, 480.0, 485.0, 490.0, 495.0, 500.0};
01764 const double eckerle4_functor::y[35] = { 0.0001575, 0.0001699, 0.0002350, 0.0003102, 0.0004917, 0.0008710, 0.0017418, 0.0046400, 0.0065895, 0.0097302, 0.0149002, 0.0237310, 0.0401683, 0.0712559, 0.1264458, 0.2073413, 0.2902366, 0.3445623, 0.3698049, 0.3668534, 0.3106727, 0.2078154, 0.1164354, 0.0616764, 0.0337200, 0.0194023, 0.0117831, 0.0074357, 0.0022732, 0.0008800, 0.0004579, 0.0002345, 0.0001586, 0.0001143, 0.0000710 };
01765
01766
01767 void testNistEckerle4(void)
01768 {
01769 const int n=3;
01770 int info;
01771
01772 VectorXd x(n);
01773
01774
01775
01776
01777 x<< 1., 10., 500.;
01778
01779 eckerle4_functor functor;
01780 LevenbergMarquardt<eckerle4_functor> lm(functor);
01781 info = lm.minimize(x);
01782
01783
01784 VERIFY_IS_EQUAL(info, 1);
01785 VERIFY_IS_EQUAL(lm.nfev, 18);
01786 VERIFY_IS_EQUAL(lm.njev, 15);
01787
01788 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.4635887487E-03);
01789
01790 VERIFY_IS_APPROX(x[0], 1.5543827178);
01791 VERIFY_IS_APPROX(x[1], 4.0888321754);
01792 VERIFY_IS_APPROX(x[2], 4.5154121844E+02);
01793
01794
01795
01796
01797 x<< 1.5, 5., 450.;
01798
01799 info = lm.minimize(x);
01800
01801
01802 VERIFY_IS_EQUAL(info, 1);
01803 VERIFY_IS_EQUAL(lm.nfev, 7);
01804 VERIFY_IS_EQUAL(lm.njev, 6);
01805
01806 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.4635887487E-03);
01807
01808 VERIFY_IS_APPROX(x[0], 1.5543827178);
01809 VERIFY_IS_APPROX(x[1], 4.0888321754);
01810 VERIFY_IS_APPROX(x[2], 4.5154121844E+02);
01811 }
01812
01813 void test_NonLinearOptimization()
01814 {
01815
01816 CALL_SUBTEST(testChkder());
01817 CALL_SUBTEST(testLmder1());
01818 CALL_SUBTEST(testLmder());
01819 CALL_SUBTEST(testHybrj1());
01820 CALL_SUBTEST(testHybrj());
01821 CALL_SUBTEST(testHybrd1());
01822 CALL_SUBTEST(testHybrd());
01823 CALL_SUBTEST(testLmstr1());
01824 CALL_SUBTEST(testLmstr());
01825 CALL_SUBTEST(testLmdif1());
01826 CALL_SUBTEST(testLmdif());
01827
01828
01829 CALL_SUBTEST(testNistMisra1a());
01830 CALL_SUBTEST(testNistChwirut2());
01831
01832
01833 CALL_SUBTEST(testNistHahn1());
01834 CALL_SUBTEST(testNistMisra1d());
01835
01836
01837
01838
01839 CALL_SUBTEST(testNistRat42());
01840
01841 CALL_SUBTEST(testNistBoxBOD());
01842
01843 CALL_SUBTEST(testNistBennett5());
01844 CALL_SUBTEST(testNistThurber());
01845 CALL_SUBTEST(testNistRat43());
01846 CALL_SUBTEST(testNistEckerle4());
01847 }
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870