1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> 5 6 #include <stdio.h> 7 8 #include "main.h" 9 #include <unsupported/Eigen/NonLinearOptimization> 10 11 // This disables some useless Warnings on MSVC. 12 // It is intended to be done for this test only. 13 #include <Eigen/src/Core/util/DisableStupidWarnings.h> 14 15 // tolerance for chekcing number of iterations 16 #define LM_EVAL_COUNT_TOL 4/3 17 18 int fcn_chkder(const VectorXd &x, VectorXd &fvec, MatrixXd &fjac, int iflag) 19 { 20 /* subroutine fcn for chkder example. */ 21 22 int i; 23 assert(15 == fvec.size()); 24 assert(3 == x.size()); 25 double tmp1, tmp2, tmp3, tmp4; 26 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, 27 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39}; 28 29 30 if (iflag == 0) 31 return 0; 32 33 if (iflag != 2) 34 for (i=0; i<15; i++) { 35 tmp1 = i+1; 36 tmp2 = 16-i-1; 37 tmp3 = tmp1; 38 if (i >= 8) tmp3 = tmp2; 39 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3)); 40 } 41 else { 42 for (i = 0; i < 15; i++) { 43 tmp1 = i+1; 44 tmp2 = 16-i-1; 45 46 /* error introduced into next statement for illustration. */ 47 /* corrected statement should read tmp3 = tmp1 . */ 48 49 tmp3 = tmp2; 50 if (i >= 8) tmp3 = tmp2; 51 tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4=tmp4*tmp4; 52 fjac(i,0) = -1.; 53 fjac(i,1) = tmp1*tmp2/tmp4; 54 fjac(i,2) = tmp1*tmp3/tmp4; 55 } 56 } 57 return 0; 58 } 59 60 61 void testChkder() 62 { 63 const int m=15, n=3; 64 VectorXd x(n), fvec(m), xp, fvecp(m), err; 65 MatrixXd fjac(m,n); 66 VectorXi ipvt; 67 68 /* the following values should be suitable for */ 69 /* checking the jacobian matrix. */ 70 x << 9.2e-1, 1.3e-1, 5.4e-1; 71 72 internal::chkder(x, fvec, fjac, xp, fvecp, 1, err); 73 fcn_chkder(x, fvec, fjac, 1); 74 fcn_chkder(x, fvec, fjac, 2); 75 fcn_chkder(xp, fvecp, fjac, 1); 76 internal::chkder(x, fvec, fjac, xp, fvecp, 2, err); 77 78 fvecp -= fvec; 79 80 // check those 81 VectorXd fvec_ref(m), fvecp_ref(m), err_ref(m); 82 fvec_ref << 83 -1.181606, -1.429655, -1.606344, 84 -1.745269, -1.840654, -1.921586, 85 -1.984141, -2.022537, -2.468977, 86 -2.827562, -3.473582, -4.437612, 87 -6.047662, -9.267761, -18.91806; 88 fvecp_ref << 89 -7.724666e-09, -3.432406e-09, -2.034843e-10, 90 2.313685e-09, 4.331078e-09, 5.984096e-09, 91 7.363281e-09, 8.53147e-09, 1.488591e-08, 92 2.33585e-08, 3.522012e-08, 5.301255e-08, 93 8.26666e-08, 1.419747e-07, 3.19899e-07; 94 err_ref << 95 0.1141397, 0.09943516, 0.09674474, 96 0.09980447, 0.1073116, 0.1220445, 97 0.1526814, 1, 1, 98 1, 1, 1, 99 1, 1, 1; 100 101 VERIFY_IS_APPROX(fvec, fvec_ref); 102 VERIFY_IS_APPROX(fvecp, fvecp_ref); 103 VERIFY_IS_APPROX(err, err_ref); 104 } 105 106 // Generic functor 107 template<typename _Scalar, int NX=Dynamic, int NY=Dynamic> 108 struct Functor 109 { 110 typedef _Scalar Scalar; 111 enum { 112 InputsAtCompileTime = NX, 113 ValuesAtCompileTime = NY 114 }; 115 typedef Matrix<Scalar,InputsAtCompileTime,1> InputType; 116 typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType; 117 typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType; 118 119 const int m_inputs, m_values; 120 121 Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {} 122 Functor(int inputs, int values) : m_inputs(inputs), m_values(values) {} 123 124 int inputs() const { return m_inputs; } 125 int values() const { return m_values; } 126 127 // you should define that in the subclass : 128 // void operator() (const InputType& x, ValueType* v, JacobianType* _j=0) const; 129 }; 130 131 struct lmder_functor : Functor<double> 132 { 133 lmder_functor(void): Functor<double>(3,15) {} 134 int operator()(const VectorXd &x, VectorXd &fvec) const 135 { 136 double tmp1, tmp2, tmp3; 137 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, 138 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39}; 139 140 for (int i = 0; i < values(); i++) 141 { 142 tmp1 = i+1; 143 tmp2 = 16 - i - 1; 144 tmp3 = (i>=8)? tmp2 : tmp1; 145 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3)); 146 } 147 return 0; 148 } 149 150 int df(const VectorXd &x, MatrixXd &fjac) const 151 { 152 double tmp1, tmp2, tmp3, tmp4; 153 for (int i = 0; i < values(); i++) 154 { 155 tmp1 = i+1; 156 tmp2 = 16 - i - 1; 157 tmp3 = (i>=8)? tmp2 : tmp1; 158 tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4 = tmp4*tmp4; 159 fjac(i,0) = -1; 160 fjac(i,1) = tmp1*tmp2/tmp4; 161 fjac(i,2) = tmp1*tmp3/tmp4; 162 } 163 return 0; 164 } 165 }; 166 167 void testLmder1() 168 { 169 int n=3, info; 170 171 VectorXd x; 172 173 /* the following starting values provide a rough fit. */ 174 x.setConstant(n, 1.); 175 176 // do the computation 177 lmder_functor functor; 178 LevenbergMarquardt<lmder_functor> lm(functor); 179 info = lm.lmder1(x); 180 181 // check return value 182 VERIFY_IS_EQUAL(info, 1); 183 VERIFY_IS_EQUAL(lm.nfev, 6); 184 VERIFY_IS_EQUAL(lm.njev, 5); 185 186 // check norm 187 VERIFY_IS_APPROX(lm.fvec.blueNorm(), 0.09063596); 188 189 // check x 190 VectorXd x_ref(n); 191 x_ref << 0.08241058, 1.133037, 2.343695; 192 VERIFY_IS_APPROX(x, x_ref); 193 } 194 195 void testLmder() 196 { 197 const int m=15, n=3; 198 int info; 199 double fnorm, covfac; 200 VectorXd x; 201 202 /* the following starting values provide a rough fit. */ 203 x.setConstant(n, 1.); 204 205 // do the computation 206 lmder_functor functor; 207 LevenbergMarquardt<lmder_functor> lm(functor); 208 info = lm.minimize(x); 209 210 // check return values 211 VERIFY_IS_EQUAL(info, 1); 212 VERIFY_IS_EQUAL(lm.nfev, 6); 213 VERIFY_IS_EQUAL(lm.njev, 5); 214 215 // check norm 216 fnorm = lm.fvec.blueNorm(); 217 VERIFY_IS_APPROX(fnorm, 0.09063596); 218 219 // check x 220 VectorXd x_ref(n); 221 x_ref << 0.08241058, 1.133037, 2.343695; 222 VERIFY_IS_APPROX(x, x_ref); 223 224 // check covariance 225 covfac = fnorm*fnorm/(m-n); 226 internal::covar(lm.fjac, lm.permutation.indices()); // TODO : move this as a function of lm 227 228 MatrixXd cov_ref(n,n); 229 cov_ref << 230 0.0001531202, 0.002869941, -0.002656662, 231 0.002869941, 0.09480935, -0.09098995, 232 -0.002656662, -0.09098995, 0.08778727; 233 234 // std::cout << fjac*covfac << std::endl; 235 236 MatrixXd cov; 237 cov = covfac*lm.fjac.topLeftCorner<n,n>(); 238 VERIFY_IS_APPROX( cov, cov_ref); 239 // TODO: why isn't this allowed ? : 240 // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref); 241 } 242 243 struct hybrj_functor : Functor<double> 244 { 245 hybrj_functor(void) : Functor<double>(9,9) {} 246 247 int operator()(const VectorXd &x, VectorXd &fvec) 248 { 249 double temp, temp1, temp2; 250 const VectorXd::Index n = x.size(); 251 assert(fvec.size()==n); 252 for (VectorXd::Index k = 0; k < n; k++) 253 { 254 temp = (3. - 2.*x[k])*x[k]; 255 temp1 = 0.; 256 if (k) temp1 = x[k-1]; 257 temp2 = 0.; 258 if (k != n-1) temp2 = x[k+1]; 259 fvec[k] = temp - temp1 - 2.*temp2 + 1.; 260 } 261 return 0; 262 } 263 int df(const VectorXd &x, MatrixXd &fjac) 264 { 265 const VectorXd::Index n = x.size(); 266 assert(fjac.rows()==n); 267 assert(fjac.cols()==n); 268 for (VectorXd::Index k = 0; k < n; k++) 269 { 270 for (VectorXd::Index j = 0; j < n; j++) 271 fjac(k,j) = 0.; 272 fjac(k,k) = 3.- 4.*x[k]; 273 if (k) fjac(k,k-1) = -1.; 274 if (k != n-1) fjac(k,k+1) = -2.; 275 } 276 return 0; 277 } 278 }; 279 280 281 void testHybrj1() 282 { 283 const int n=9; 284 int info; 285 VectorXd x(n); 286 287 /* the following starting values provide a rough fit. */ 288 x.setConstant(n, -1.); 289 290 // do the computation 291 hybrj_functor functor; 292 HybridNonLinearSolver<hybrj_functor> solver(functor); 293 info = solver.hybrj1(x); 294 295 // check return value 296 VERIFY_IS_EQUAL(info, 1); 297 VERIFY_IS_EQUAL(solver.nfev, 11); 298 VERIFY_IS_EQUAL(solver.njev, 1); 299 300 // check norm 301 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08); 302 303 304 // check x 305 VectorXd x_ref(n); 306 x_ref << 307 -0.5706545, -0.6816283, -0.7017325, 308 -0.7042129, -0.701369, -0.6918656, 309 -0.665792, -0.5960342, -0.4164121; 310 VERIFY_IS_APPROX(x, x_ref); 311 } 312 313 void testHybrj() 314 { 315 const int n=9; 316 int info; 317 VectorXd x(n); 318 319 /* the following starting values provide a rough fit. */ 320 x.setConstant(n, -1.); 321 322 323 // do the computation 324 hybrj_functor functor; 325 HybridNonLinearSolver<hybrj_functor> solver(functor); 326 solver.diag.setConstant(n, 1.); 327 solver.useExternalScaling = true; 328 info = solver.solve(x); 329 330 // check return value 331 VERIFY_IS_EQUAL(info, 1); 332 VERIFY_IS_EQUAL(solver.nfev, 11); 333 VERIFY_IS_EQUAL(solver.njev, 1); 334 335 // check norm 336 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08); 337 338 339 // check x 340 VectorXd x_ref(n); 341 x_ref << 342 -0.5706545, -0.6816283, -0.7017325, 343 -0.7042129, -0.701369, -0.6918656, 344 -0.665792, -0.5960342, -0.4164121; 345 VERIFY_IS_APPROX(x, x_ref); 346 347 } 348 349 struct hybrd_functor : Functor<double> 350 { 351 hybrd_functor(void) : Functor<double>(9,9) {} 352 int operator()(const VectorXd &x, VectorXd &fvec) const 353 { 354 double temp, temp1, temp2; 355 const VectorXd::Index n = x.size(); 356 357 assert(fvec.size()==n); 358 for (VectorXd::Index k=0; k < n; k++) 359 { 360 temp = (3. - 2.*x[k])*x[k]; 361 temp1 = 0.; 362 if (k) temp1 = x[k-1]; 363 temp2 = 0.; 364 if (k != n-1) temp2 = x[k+1]; 365 fvec[k] = temp - temp1 - 2.*temp2 + 1.; 366 } 367 return 0; 368 } 369 }; 370 371 void testHybrd1() 372 { 373 int n=9, info; 374 VectorXd x(n); 375 376 /* the following starting values provide a rough solution. */ 377 x.setConstant(n, -1.); 378 379 // do the computation 380 hybrd_functor functor; 381 HybridNonLinearSolver<hybrd_functor> solver(functor); 382 info = solver.hybrd1(x); 383 384 // check return value 385 VERIFY_IS_EQUAL(info, 1); 386 VERIFY_IS_EQUAL(solver.nfev, 20); 387 388 // check norm 389 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08); 390 391 // check x 392 VectorXd x_ref(n); 393 x_ref << -0.5706545, -0.6816283, -0.7017325, -0.7042129, -0.701369, -0.6918656, -0.665792, -0.5960342, -0.4164121; 394 VERIFY_IS_APPROX(x, x_ref); 395 } 396 397 void testHybrd() 398 { 399 const int n=9; 400 int info; 401 VectorXd x; 402 403 /* the following starting values provide a rough fit. */ 404 x.setConstant(n, -1.); 405 406 // do the computation 407 hybrd_functor functor; 408 HybridNonLinearSolver<hybrd_functor> solver(functor); 409 solver.parameters.nb_of_subdiagonals = 1; 410 solver.parameters.nb_of_superdiagonals = 1; 411 solver.diag.setConstant(n, 1.); 412 solver.useExternalScaling = true; 413 info = solver.solveNumericalDiff(x); 414 415 // check return value 416 VERIFY_IS_EQUAL(info, 1); 417 VERIFY_IS_EQUAL(solver.nfev, 14); 418 419 // check norm 420 VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08); 421 422 // check x 423 VectorXd x_ref(n); 424 x_ref << 425 -0.5706545, -0.6816283, -0.7017325, 426 -0.7042129, -0.701369, -0.6918656, 427 -0.665792, -0.5960342, -0.4164121; 428 VERIFY_IS_APPROX(x, x_ref); 429 } 430 431 struct lmstr_functor : Functor<double> 432 { 433 lmstr_functor(void) : Functor<double>(3,15) {} 434 int operator()(const VectorXd &x, VectorXd &fvec) 435 { 436 /* subroutine fcn for lmstr1 example. */ 437 double tmp1, tmp2, tmp3; 438 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, 439 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39}; 440 441 assert(15==fvec.size()); 442 assert(3==x.size()); 443 444 for (int i=0; i<15; i++) 445 { 446 tmp1 = i+1; 447 tmp2 = 16 - i - 1; 448 tmp3 = (i>=8)? tmp2 : tmp1; 449 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3)); 450 } 451 return 0; 452 } 453 int df(const VectorXd &x, VectorXd &jac_row, VectorXd::Index rownb) 454 { 455 assert(x.size()==3); 456 assert(jac_row.size()==x.size()); 457 double tmp1, tmp2, tmp3, tmp4; 458 459 VectorXd::Index i = rownb-2; 460 tmp1 = i+1; 461 tmp2 = 16 - i - 1; 462 tmp3 = (i>=8)? tmp2 : tmp1; 463 tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4 = tmp4*tmp4; 464 jac_row[0] = -1; 465 jac_row[1] = tmp1*tmp2/tmp4; 466 jac_row[2] = tmp1*tmp3/tmp4; 467 return 0; 468 } 469 }; 470 471 void testLmstr1() 472 { 473 const int n=3; 474 int info; 475 476 VectorXd x(n); 477 478 /* the following starting values provide a rough fit. */ 479 x.setConstant(n, 1.); 480 481 // do the computation 482 lmstr_functor functor; 483 LevenbergMarquardt<lmstr_functor> lm(functor); 484 info = lm.lmstr1(x); 485 486 // check return value 487 VERIFY_IS_EQUAL(info, 1); 488 VERIFY_IS_EQUAL(lm.nfev, 6); 489 VERIFY_IS_EQUAL(lm.njev, 5); 490 491 // check norm 492 VERIFY_IS_APPROX(lm.fvec.blueNorm(), 0.09063596); 493 494 // check x 495 VectorXd x_ref(n); 496 x_ref << 0.08241058, 1.133037, 2.343695 ; 497 VERIFY_IS_APPROX(x, x_ref); 498 } 499 500 void testLmstr() 501 { 502 const int n=3; 503 int info; 504 double fnorm; 505 VectorXd x(n); 506 507 /* the following starting values provide a rough fit. */ 508 x.setConstant(n, 1.); 509 510 // do the computation 511 lmstr_functor functor; 512 LevenbergMarquardt<lmstr_functor> lm(functor); 513 info = lm.minimizeOptimumStorage(x); 514 515 // check return values 516 VERIFY_IS_EQUAL(info, 1); 517 VERIFY_IS_EQUAL(lm.nfev, 6); 518 VERIFY_IS_EQUAL(lm.njev, 5); 519 520 // check norm 521 fnorm = lm.fvec.blueNorm(); 522 VERIFY_IS_APPROX(fnorm, 0.09063596); 523 524 // check x 525 VectorXd x_ref(n); 526 x_ref << 0.08241058, 1.133037, 2.343695; 527 VERIFY_IS_APPROX(x, x_ref); 528 529 } 530 531 struct lmdif_functor : Functor<double> 532 { 533 lmdif_functor(void) : Functor<double>(3,15) {} 534 int operator()(const VectorXd &x, VectorXd &fvec) const 535 { 536 int i; 537 double tmp1,tmp2,tmp3; 538 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, 539 3.7e-1,5.8e-1,7.3e-1,9.6e-1,1.34e0,2.1e0,4.39e0}; 540 541 assert(x.size()==3); 542 assert(fvec.size()==15); 543 for (i=0; i<15; i++) 544 { 545 tmp1 = i+1; 546 tmp2 = 15 - i; 547 tmp3 = tmp1; 548 549 if (i >= 8) tmp3 = tmp2; 550 fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3)); 551 } 552 return 0; 553 } 554 }; 555 556 void testLmdif1() 557 { 558 const int n=3; 559 int info; 560 561 VectorXd x(n), fvec(15); 562 563 /* the following starting values provide a rough fit. */ 564 x.setConstant(n, 1.); 565 566 // do the computation 567 lmdif_functor functor; 568 DenseIndex nfev; 569 info = LevenbergMarquardt<lmdif_functor>::lmdif1(functor, x, &nfev); 570 571 // check return value 572 VERIFY_IS_EQUAL(info, 1); 573 VERIFY_IS_EQUAL(nfev, 26); 574 575 // check norm 576 functor(x, fvec); 577 VERIFY_IS_APPROX(fvec.blueNorm(), 0.09063596); 578 579 // check x 580 VectorXd x_ref(n); 581 x_ref << 0.0824106, 1.1330366, 2.3436947; 582 VERIFY_IS_APPROX(x, x_ref); 583 584 } 585 586 void testLmdif() 587 { 588 const int m=15, n=3; 589 int info; 590 double fnorm, covfac; 591 VectorXd x(n); 592 593 /* the following starting values provide a rough fit. */ 594 x.setConstant(n, 1.); 595 596 // do the computation 597 lmdif_functor functor; 598 NumericalDiff<lmdif_functor> numDiff(functor); 599 LevenbergMarquardt<NumericalDiff<lmdif_functor> > lm(numDiff); 600 info = lm.minimize(x); 601 602 // check return values 603 VERIFY_IS_EQUAL(info, 1); 604 VERIFY_IS_EQUAL(lm.nfev, 26); 605 606 // check norm 607 fnorm = lm.fvec.blueNorm(); 608 VERIFY_IS_APPROX(fnorm, 0.09063596); 609 610 // check x 611 VectorXd x_ref(n); 612 x_ref << 0.08241058, 1.133037, 2.343695; 613 VERIFY_IS_APPROX(x, x_ref); 614 615 // check covariance 616 covfac = fnorm*fnorm/(m-n); 617 internal::covar(lm.fjac, lm.permutation.indices()); // TODO : move this as a function of lm 618 619 MatrixXd cov_ref(n,n); 620 cov_ref << 621 0.0001531202, 0.002869942, -0.002656662, 622 0.002869942, 0.09480937, -0.09098997, 623 -0.002656662, -0.09098997, 0.08778729; 624 625 // std::cout << fjac*covfac << std::endl; 626 627 MatrixXd cov; 628 cov = covfac*lm.fjac.topLeftCorner<n,n>(); 629 VERIFY_IS_APPROX( cov, cov_ref); 630 // TODO: why isn't this allowed ? : 631 // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref); 632 } 633 634 struct chwirut2_functor : Functor<double> 635 { 636 chwirut2_functor(void) : Functor<double>(3,54) {} 637 static const double m_x[54]; 638 static const double m_y[54]; 639 int operator()(const VectorXd &b, VectorXd &fvec) 640 { 641 int i; 642 643 assert(b.size()==3); 644 assert(fvec.size()==54); 645 for(i=0; i<54; i++) { 646 double x = m_x[i]; 647 fvec[i] = exp(-b[0]*x)/(b[1]+b[2]*x) - m_y[i]; 648 } 649 return 0; 650 } 651 int df(const VectorXd &b, MatrixXd &fjac) 652 { 653 assert(b.size()==3); 654 assert(fjac.rows()==54); 655 assert(fjac.cols()==3); 656 for(int i=0; i<54; i++) { 657 double x = m_x[i]; 658 double factor = 1./(b[1]+b[2]*x); 659 double e = exp(-b[0]*x); 660 fjac(i,0) = -x*e*factor; 661 fjac(i,1) = -e*factor*factor; 662 fjac(i,2) = -x*e*factor*factor; 663 } 664 return 0; 665 } 666 }; 667 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}; 668 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 }; 669 670 // http://www.itl.nist.gov/div898/strd/nls/data/chwirut2.shtml 671 void testNistChwirut2(void) 672 { 673 const int n=3; 674 int info; 675 676 VectorXd x(n); 677 678 /* 679 * First try 680 */ 681 x<< 0.1, 0.01, 0.02; 682 // do the computation 683 chwirut2_functor functor; 684 LevenbergMarquardt<chwirut2_functor> lm(functor); 685 info = lm.minimize(x); 686 687 // check return value 688 VERIFY_IS_EQUAL(info, 1); 689 VERIFY_IS_EQUAL(lm.nfev, 10); 690 VERIFY_IS_EQUAL(lm.njev, 8); 691 // check norm^2 692 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.1304802941E+02); 693 // check x 694 VERIFY_IS_APPROX(x[0], 1.6657666537E-01); 695 VERIFY_IS_APPROX(x[1], 5.1653291286E-03); 696 VERIFY_IS_APPROX(x[2], 1.2150007096E-02); 697 698 /* 699 * Second try 700 */ 701 x<< 0.15, 0.008, 0.010; 702 // do the computation 703 lm.resetParameters(); 704 lm.parameters.ftol = 1.E6*NumTraits<double>::epsilon(); 705 lm.parameters.xtol = 1.E6*NumTraits<double>::epsilon(); 706 info = lm.minimize(x); 707 708 // check return value 709 VERIFY_IS_EQUAL(info, 1); 710 VERIFY_IS_EQUAL(lm.nfev, 7); 711 VERIFY_IS_EQUAL(lm.njev, 6); 712 // check norm^2 713 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.1304802941E+02); 714 // check x 715 VERIFY_IS_APPROX(x[0], 1.6657666537E-01); 716 VERIFY_IS_APPROX(x[1], 5.1653291286E-03); 717 VERIFY_IS_APPROX(x[2], 1.2150007096E-02); 718 } 719 720 721 struct misra1a_functor : Functor<double> 722 { 723 misra1a_functor(void) : Functor<double>(2,14) {} 724 static const double m_x[14]; 725 static const double m_y[14]; 726 int operator()(const VectorXd &b, VectorXd &fvec) 727 { 728 assert(b.size()==2); 729 assert(fvec.size()==14); 730 for(int i=0; i<14; i++) { 731 fvec[i] = b[0]*(1.-exp(-b[1]*m_x[i])) - m_y[i] ; 732 } 733 return 0; 734 } 735 int df(const VectorXd &b, MatrixXd &fjac) 736 { 737 assert(b.size()==2); 738 assert(fjac.rows()==14); 739 assert(fjac.cols()==2); 740 for(int i=0; i<14; i++) { 741 fjac(i,0) = (1.-exp(-b[1]*m_x[i])); 742 fjac(i,1) = (b[0]*m_x[i]*exp(-b[1]*m_x[i])); 743 } 744 return 0; 745 } 746 }; 747 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}; 748 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}; 749 750 // http://www.itl.nist.gov/div898/strd/nls/data/misra1a.shtml 751 void testNistMisra1a(void) 752 { 753 const int n=2; 754 int info; 755 756 VectorXd x(n); 757 758 /* 759 * First try 760 */ 761 x<< 500., 0.0001; 762 // do the computation 763 misra1a_functor functor; 764 LevenbergMarquardt<misra1a_functor> lm(functor); 765 info = lm.minimize(x); 766 767 // check return value 768 VERIFY_IS_EQUAL(info, 1); 769 VERIFY_IS_EQUAL(lm.nfev, 19); 770 VERIFY_IS_EQUAL(lm.njev, 15); 771 // check norm^2 772 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.2455138894E-01); 773 // check x 774 VERIFY_IS_APPROX(x[0], 2.3894212918E+02); 775 VERIFY_IS_APPROX(x[1], 5.5015643181E-04); 776 777 /* 778 * Second try 779 */ 780 x<< 250., 0.0005; 781 // do the computation 782 info = lm.minimize(x); 783 784 // check return value 785 VERIFY_IS_EQUAL(info, 1); 786 VERIFY_IS_EQUAL(lm.nfev, 5); 787 VERIFY_IS_EQUAL(lm.njev, 4); 788 // check norm^2 789 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.2455138894E-01); 790 // check x 791 VERIFY_IS_APPROX(x[0], 2.3894212918E+02); 792 VERIFY_IS_APPROX(x[1], 5.5015643181E-04); 793 } 794 795 struct hahn1_functor : Functor<double> 796 { 797 hahn1_functor(void) : Functor<double>(7,236) {} 798 static const double m_x[236]; 799 int operator()(const VectorXd &b, VectorXd &fvec) 800 { 801 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 , 802 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 , 803 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 }; 804 805 // int called=0; printf("call hahn1_functor with iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++; 806 807 assert(b.size()==7); 808 assert(fvec.size()==236); 809 for(int i=0; i<236; i++) { 810 double x=m_x[i], xx=x*x, xxx=xx*x; 811 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]; 812 } 813 return 0; 814 } 815 816 int df(const VectorXd &b, MatrixXd &fjac) 817 { 818 assert(b.size()==7); 819 assert(fjac.rows()==236); 820 assert(fjac.cols()==7); 821 for(int i=0; i<236; i++) { 822 double x=m_x[i], xx=x*x, xxx=xx*x; 823 double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx); 824 fjac(i,0) = 1.*fact; 825 fjac(i,1) = x*fact; 826 fjac(i,2) = xx*fact; 827 fjac(i,3) = xxx*fact; 828 fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact; 829 fjac(i,4) = x*fact; 830 fjac(i,5) = xx*fact; 831 fjac(i,6) = xxx*fact; 832 } 833 return 0; 834 } 835 }; 836 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 , 837 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 , 838 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}; 839 840 // http://www.itl.nist.gov/div898/strd/nls/data/hahn1.shtml 841 void testNistHahn1(void) 842 { 843 const int n=7; 844 int info; 845 846 VectorXd x(n); 847 848 /* 849 * First try 850 */ 851 x<< 10., -1., .05, -.00001, -.05, .001, -.000001; 852 // do the computation 853 hahn1_functor functor; 854 LevenbergMarquardt<hahn1_functor> lm(functor); 855 info = lm.minimize(x); 856 857 // check return value 858 VERIFY_IS_EQUAL(info, 1); 859 VERIFY_IS_EQUAL(lm.nfev, 11); 860 VERIFY_IS_EQUAL(lm.njev, 10); 861 // check norm^2 862 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.5324382854E+00); 863 // check x 864 VERIFY_IS_APPROX(x[0], 1.0776351733E+00); 865 VERIFY_IS_APPROX(x[1],-1.2269296921E-01); 866 VERIFY_IS_APPROX(x[2], 4.0863750610E-03); 867 VERIFY_IS_APPROX(x[3],-1.426264e-06); // shoulde be : -1.4262662514E-06 868 VERIFY_IS_APPROX(x[4],-5.7609940901E-03); 869 VERIFY_IS_APPROX(x[5], 2.4053735503E-04); 870 VERIFY_IS_APPROX(x[6],-1.2314450199E-07); 871 872 /* 873 * Second try 874 */ 875 x<< .1, -.1, .005, -.000001, -.005, .0001, -.0000001; 876 // do the computation 877 info = lm.minimize(x); 878 879 // check return value 880 VERIFY_IS_EQUAL(info, 1); 881 VERIFY_IS_EQUAL(lm.nfev, 11); 882 VERIFY_IS_EQUAL(lm.njev, 10); 883 // check norm^2 884 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.5324382854E+00); 885 // check x 886 VERIFY_IS_APPROX(x[0], 1.077640); // should be : 1.0776351733E+00 887 VERIFY_IS_APPROX(x[1], -0.1226933); // should be : -1.2269296921E-01 888 VERIFY_IS_APPROX(x[2], 0.004086383); // should be : 4.0863750610E-03 889 VERIFY_IS_APPROX(x[3], -1.426277e-06); // shoulde be : -1.4262662514E-06 890 VERIFY_IS_APPROX(x[4],-5.7609940901E-03); 891 VERIFY_IS_APPROX(x[5], 0.00024053772); // should be : 2.4053735503E-04 892 VERIFY_IS_APPROX(x[6], -1.231450e-07); // should be : -1.2314450199E-07 893 894 } 895 896 struct misra1d_functor : Functor<double> 897 { 898 misra1d_functor(void) : Functor<double>(2,14) {} 899 static const double x[14]; 900 static const double y[14]; 901 int operator()(const VectorXd &b, VectorXd &fvec) 902 { 903 assert(b.size()==2); 904 assert(fvec.size()==14); 905 for(int i=0; i<14; i++) { 906 fvec[i] = b[0]*b[1]*x[i]/(1.+b[1]*x[i]) - y[i]; 907 } 908 return 0; 909 } 910 int df(const VectorXd &b, MatrixXd &fjac) 911 { 912 assert(b.size()==2); 913 assert(fjac.rows()==14); 914 assert(fjac.cols()==2); 915 for(int i=0; i<14; i++) { 916 double den = 1.+b[1]*x[i]; 917 fjac(i,0) = b[1]*x[i] / den; 918 fjac(i,1) = b[0]*x[i]*(den-b[1]*x[i])/den/den; 919 } 920 return 0; 921 } 922 }; 923 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}; 924 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}; 925 926 // http://www.itl.nist.gov/div898/strd/nls/data/misra1d.shtml 927 void testNistMisra1d(void) 928 { 929 const int n=2; 930 int info; 931 932 VectorXd x(n); 933 934 /* 935 * First try 936 */ 937 x<< 500., 0.0001; 938 // do the computation 939 misra1d_functor functor; 940 LevenbergMarquardt<misra1d_functor> lm(functor); 941 info = lm.minimize(x); 942 943 // check return value 944 VERIFY_IS_EQUAL(info, 3); 945 VERIFY_IS_EQUAL(lm.nfev, 9); 946 VERIFY_IS_EQUAL(lm.njev, 7); 947 // check norm^2 948 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6419295283E-02); 949 // check x 950 VERIFY_IS_APPROX(x[0], 4.3736970754E+02); 951 VERIFY_IS_APPROX(x[1], 3.0227324449E-04); 952 953 /* 954 * Second try 955 */ 956 x<< 450., 0.0003; 957 // do the computation 958 info = lm.minimize(x); 959 960 // check return value 961 VERIFY_IS_EQUAL(info, 1); 962 VERIFY_IS_EQUAL(lm.nfev, 4); 963 VERIFY_IS_EQUAL(lm.njev, 3); 964 // check norm^2 965 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6419295283E-02); 966 // check x 967 VERIFY_IS_APPROX(x[0], 4.3736970754E+02); 968 VERIFY_IS_APPROX(x[1], 3.0227324449E-04); 969 } 970 971 972 struct lanczos1_functor : Functor<double> 973 { 974 lanczos1_functor(void) : Functor<double>(6,24) {} 975 static const double x[24]; 976 static const double y[24]; 977 int operator()(const VectorXd &b, VectorXd &fvec) 978 { 979 assert(b.size()==6); 980 assert(fvec.size()==24); 981 for(int i=0; i<24; i++) 982 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]; 983 return 0; 984 } 985 int df(const VectorXd &b, MatrixXd &fjac) 986 { 987 assert(b.size()==6); 988 assert(fjac.rows()==24); 989 assert(fjac.cols()==6); 990 for(int i=0; i<24; i++) { 991 fjac(i,0) = exp(-b[1]*x[i]); 992 fjac(i,1) = -b[0]*x[i]*exp(-b[1]*x[i]); 993 fjac(i,2) = exp(-b[3]*x[i]); 994 fjac(i,3) = -b[2]*x[i]*exp(-b[3]*x[i]); 995 fjac(i,4) = exp(-b[5]*x[i]); 996 fjac(i,5) = -b[4]*x[i]*exp(-b[5]*x[i]); 997 } 998 return 0; 999 } 1000 }; 1001 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 }; 1002 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 }; 1003 1004 // http://www.itl.nist.gov/div898/strd/nls/data/lanczos1.shtml 1005 void testNistLanczos1(void) 1006 { 1007 const int n=6; 1008 int info; 1009 1010 VectorXd x(n); 1011 1012 /* 1013 * First try 1014 */ 1015 x<< 1.2, 0.3, 5.6, 5.5, 6.5, 7.6; 1016 // do the computation 1017 lanczos1_functor functor; 1018 LevenbergMarquardt<lanczos1_functor> lm(functor); 1019 info = lm.minimize(x); 1020 1021 // check return value 1022 VERIFY_IS_EQUAL(info, 2); 1023 VERIFY_IS_EQUAL(lm.nfev, 79); 1024 VERIFY_IS_EQUAL(lm.njev, 72); 1025 // check norm^2 1026 std::cout.precision(30); 1027 std::cout << lm.fvec.squaredNorm() << "\n"; 1028 VERIFY(lm.fvec.squaredNorm() <= 1.4307867721E-25); 1029 // check x 1030 VERIFY_IS_APPROX(x[0], 9.5100000027E-02); 1031 VERIFY_IS_APPROX(x[1], 1.0000000001E+00); 1032 VERIFY_IS_APPROX(x[2], 8.6070000013E-01); 1033 VERIFY_IS_APPROX(x[3], 3.0000000002E+00); 1034 VERIFY_IS_APPROX(x[4], 1.5575999998E+00); 1035 VERIFY_IS_APPROX(x[5], 5.0000000001E+00); 1036 1037 /* 1038 * Second try 1039 */ 1040 x<< 0.5, 0.7, 3.6, 4.2, 4., 6.3; 1041 // do the computation 1042 info = lm.minimize(x); 1043 1044 // check return value 1045 VERIFY_IS_EQUAL(info, 2); 1046 VERIFY_IS_EQUAL(lm.nfev, 9); 1047 VERIFY_IS_EQUAL(lm.njev, 8); 1048 // check norm^2 1049 VERIFY(lm.fvec.squaredNorm() <= 1.4307867721E-25); 1050 // check x 1051 VERIFY_IS_APPROX(x[0], 9.5100000027E-02); 1052 VERIFY_IS_APPROX(x[1], 1.0000000001E+00); 1053 VERIFY_IS_APPROX(x[2], 8.6070000013E-01); 1054 VERIFY_IS_APPROX(x[3], 3.0000000002E+00); 1055 VERIFY_IS_APPROX(x[4], 1.5575999998E+00); 1056 VERIFY_IS_APPROX(x[5], 5.0000000001E+00); 1057 1058 } 1059 1060 struct rat42_functor : Functor<double> 1061 { 1062 rat42_functor(void) : Functor<double>(3,9) {} 1063 static const double x[9]; 1064 static const double y[9]; 1065 int operator()(const VectorXd &b, VectorXd &fvec) 1066 { 1067 assert(b.size()==3); 1068 assert(fvec.size()==9); 1069 for(int i=0; i<9; i++) { 1070 fvec[i] = b[0] / (1.+exp(b[1]-b[2]*x[i])) - y[i]; 1071 } 1072 return 0; 1073 } 1074 1075 int df(const VectorXd &b, MatrixXd &fjac) 1076 { 1077 assert(b.size()==3); 1078 assert(fjac.rows()==9); 1079 assert(fjac.cols()==3); 1080 for(int i=0; i<9; i++) { 1081 double e = exp(b[1]-b[2]*x[i]); 1082 fjac(i,0) = 1./(1.+e); 1083 fjac(i,1) = -b[0]*e/(1.+e)/(1.+e); 1084 fjac(i,2) = +b[0]*e*x[i]/(1.+e)/(1.+e); 1085 } 1086 return 0; 1087 } 1088 }; 1089 const double rat42_functor::x[9] = { 9.000E0, 14.000E0, 21.000E0, 28.000E0, 42.000E0, 57.000E0, 63.000E0, 70.000E0, 79.000E0 }; 1090 const double rat42_functor::y[9] = { 8.930E0 ,10.800E0 ,18.590E0 ,22.330E0 ,39.350E0 ,56.110E0 ,61.730E0 ,64.620E0 ,67.080E0 }; 1091 1092 // http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky2.shtml 1093 void testNistRat42(void) 1094 { 1095 const int n=3; 1096 int info; 1097 1098 VectorXd x(n); 1099 1100 /* 1101 * First try 1102 */ 1103 x<< 100., 1., 0.1; 1104 // do the computation 1105 rat42_functor functor; 1106 LevenbergMarquardt<rat42_functor> lm(functor); 1107 info = lm.minimize(x); 1108 1109 // check return value 1110 VERIFY_IS_EQUAL(info, 1); 1111 VERIFY_IS_EQUAL(lm.nfev, 10); 1112 VERIFY_IS_EQUAL(lm.njev, 8); 1113 // check norm^2 1114 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.0565229338E+00); 1115 // check x 1116 VERIFY_IS_APPROX(x[0], 7.2462237576E+01); 1117 VERIFY_IS_APPROX(x[1], 2.6180768402E+00); 1118 VERIFY_IS_APPROX(x[2], 6.7359200066E-02); 1119 1120 /* 1121 * Second try 1122 */ 1123 x<< 75., 2.5, 0.07; 1124 // do the computation 1125 info = lm.minimize(x); 1126 1127 // check return value 1128 VERIFY_IS_EQUAL(info, 1); 1129 VERIFY_IS_EQUAL(lm.nfev, 6); 1130 VERIFY_IS_EQUAL(lm.njev, 5); 1131 // check norm^2 1132 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.0565229338E+00); 1133 // check x 1134 VERIFY_IS_APPROX(x[0], 7.2462237576E+01); 1135 VERIFY_IS_APPROX(x[1], 2.6180768402E+00); 1136 VERIFY_IS_APPROX(x[2], 6.7359200066E-02); 1137 } 1138 1139 struct MGH10_functor : Functor<double> 1140 { 1141 MGH10_functor(void) : Functor<double>(3,16) {} 1142 static const double x[16]; 1143 static const double y[16]; 1144 int operator()(const VectorXd &b, VectorXd &fvec) 1145 { 1146 assert(b.size()==3); 1147 assert(fvec.size()==16); 1148 for(int i=0; i<16; i++) 1149 fvec[i] = b[0] * exp(b[1]/(x[i]+b[2])) - y[i]; 1150 return 0; 1151 } 1152 int df(const VectorXd &b, MatrixXd &fjac) 1153 { 1154 assert(b.size()==3); 1155 assert(fjac.rows()==16); 1156 assert(fjac.cols()==3); 1157 for(int i=0; i<16; i++) { 1158 double factor = 1./(x[i]+b[2]); 1159 double e = exp(b[1]*factor); 1160 fjac(i,0) = e; 1161 fjac(i,1) = b[0]*factor*e; 1162 fjac(i,2) = -b[1]*b[0]*factor*factor*e; 1163 } 1164 return 0; 1165 } 1166 }; 1167 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 }; 1168 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 }; 1169 1170 // http://www.itl.nist.gov/div898/strd/nls/data/mgh10.shtml 1171 void testNistMGH10(void) 1172 { 1173 const int n=3; 1174 int info; 1175 1176 VectorXd x(n); 1177 1178 /* 1179 * First try 1180 */ 1181 x<< 2., 400000., 25000.; 1182 // do the computation 1183 MGH10_functor functor; 1184 LevenbergMarquardt<MGH10_functor> lm(functor); 1185 info = lm.minimize(x); 1186 1187 // check return value 1188 VERIFY_IS_EQUAL(info, 2); 1189 VERIFY_IS_EQUAL(lm.nfev, 284 ); 1190 VERIFY_IS_EQUAL(lm.njev, 249 ); 1191 // check norm^2 1192 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7945855171E+01); 1193 // check x 1194 VERIFY_IS_APPROX(x[0], 5.6096364710E-03); 1195 VERIFY_IS_APPROX(x[1], 6.1813463463E+03); 1196 VERIFY_IS_APPROX(x[2], 3.4522363462E+02); 1197 1198 /* 1199 * Second try 1200 */ 1201 x<< 0.02, 4000., 250.; 1202 // do the computation 1203 info = lm.minimize(x); 1204 1205 // check return value 1206 VERIFY_IS_EQUAL(info, 3); 1207 VERIFY_IS_EQUAL(lm.nfev, 126); 1208 VERIFY_IS_EQUAL(lm.njev, 116); 1209 // check norm^2 1210 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7945855171E+01); 1211 // check x 1212 VERIFY_IS_APPROX(x[0], 5.6096364710E-03); 1213 VERIFY_IS_APPROX(x[1], 6.1813463463E+03); 1214 VERIFY_IS_APPROX(x[2], 3.4522363462E+02); 1215 } 1216 1217 1218 struct BoxBOD_functor : Functor<double> 1219 { 1220 BoxBOD_functor(void) : Functor<double>(2,6) {} 1221 static const double x[6]; 1222 int operator()(const VectorXd &b, VectorXd &fvec) 1223 { 1224 static const double y[6] = { 109., 149., 149., 191., 213., 224. }; 1225 assert(b.size()==2); 1226 assert(fvec.size()==6); 1227 for(int i=0; i<6; i++) 1228 fvec[i] = b[0]*(1.-exp(-b[1]*x[i])) - y[i]; 1229 return 0; 1230 } 1231 int df(const VectorXd &b, MatrixXd &fjac) 1232 { 1233 assert(b.size()==2); 1234 assert(fjac.rows()==6); 1235 assert(fjac.cols()==2); 1236 for(int i=0; i<6; i++) { 1237 double e = exp(-b[1]*x[i]); 1238 fjac(i,0) = 1.-e; 1239 fjac(i,1) = b[0]*x[i]*e; 1240 } 1241 return 0; 1242 } 1243 }; 1244 const double BoxBOD_functor::x[6] = { 1., 2., 3., 5., 7., 10. }; 1245 1246 // http://www.itl.nist.gov/div898/strd/nls/data/boxbod.shtml 1247 void testNistBoxBOD(void) 1248 { 1249 const int n=2; 1250 int info; 1251 1252 VectorXd x(n); 1253 1254 /* 1255 * First try 1256 */ 1257 x<< 1., 1.; 1258 // do the computation 1259 BoxBOD_functor functor; 1260 LevenbergMarquardt<BoxBOD_functor> lm(functor); 1261 lm.parameters.ftol = 1.E6*NumTraits<double>::epsilon(); 1262 lm.parameters.xtol = 1.E6*NumTraits<double>::epsilon(); 1263 lm.parameters.factor = 10.; 1264 info = lm.minimize(x); 1265 1266 // check return value 1267 VERIFY_IS_EQUAL(info, 1); 1268 VERIFY(lm.nfev < 31); // 31 1269 VERIFY(lm.njev < 25); // 25 1270 // check norm^2 1271 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.1680088766E+03); 1272 // check x 1273 VERIFY_IS_APPROX(x[0], 2.1380940889E+02); 1274 VERIFY_IS_APPROX(x[1], 5.4723748542E-01); 1275 1276 /* 1277 * Second try 1278 */ 1279 x<< 100., 0.75; 1280 // do the computation 1281 lm.resetParameters(); 1282 lm.parameters.ftol = NumTraits<double>::epsilon(); 1283 lm.parameters.xtol = NumTraits<double>::epsilon(); 1284 info = lm.minimize(x); 1285 1286 // check return value 1287 VERIFY_IS_EQUAL(info, 1); 1288 VERIFY_IS_EQUAL(lm.nfev, 15 ); 1289 VERIFY_IS_EQUAL(lm.njev, 14 ); 1290 // check norm^2 1291 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.1680088766E+03); 1292 // check x 1293 VERIFY_IS_APPROX(x[0], 2.1380940889E+02); 1294 VERIFY_IS_APPROX(x[1], 5.4723748542E-01); 1295 } 1296 1297 struct MGH17_functor : Functor<double> 1298 { 1299 MGH17_functor(void) : Functor<double>(5,33) {} 1300 static const double x[33]; 1301 static const double y[33]; 1302 int operator()(const VectorXd &b, VectorXd &fvec) 1303 { 1304 assert(b.size()==5); 1305 assert(fvec.size()==33); 1306 for(int i=0; i<33; i++) 1307 fvec[i] = b[0] + b[1]*exp(-b[3]*x[i]) + b[2]*exp(-b[4]*x[i]) - y[i]; 1308 return 0; 1309 } 1310 int df(const VectorXd &b, MatrixXd &fjac) 1311 { 1312 assert(b.size()==5); 1313 assert(fjac.rows()==33); 1314 assert(fjac.cols()==5); 1315 for(int i=0; i<33; i++) { 1316 fjac(i,0) = 1.; 1317 fjac(i,1) = exp(-b[3]*x[i]); 1318 fjac(i,2) = exp(-b[4]*x[i]); 1319 fjac(i,3) = -x[i]*b[1]*exp(-b[3]*x[i]); 1320 fjac(i,4) = -x[i]*b[2]*exp(-b[4]*x[i]); 1321 } 1322 return 0; 1323 } 1324 }; 1325 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 }; 1326 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 }; 1327 1328 // http://www.itl.nist.gov/div898/strd/nls/data/mgh17.shtml 1329 void testNistMGH17(void) 1330 { 1331 const int n=5; 1332 int info; 1333 1334 VectorXd x(n); 1335 1336 /* 1337 * First try 1338 */ 1339 x<< 50., 150., -100., 1., 2.; 1340 // do the computation 1341 MGH17_functor functor; 1342 LevenbergMarquardt<MGH17_functor> lm(functor); 1343 lm.parameters.ftol = NumTraits<double>::epsilon(); 1344 lm.parameters.xtol = NumTraits<double>::epsilon(); 1345 lm.parameters.maxfev = 1000; 1346 info = lm.minimize(x); 1347 1348 // check norm^2 1349 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.4648946975E-05); 1350 // check x 1351 VERIFY_IS_APPROX(x[0], 3.7541005211E-01); 1352 VERIFY_IS_APPROX(x[1], 1.9358469127E+00); 1353 VERIFY_IS_APPROX(x[2], -1.4646871366E+00); 1354 VERIFY_IS_APPROX(x[3], 1.2867534640E-02); 1355 VERIFY_IS_APPROX(x[4], 2.2122699662E-02); 1356 1357 // check return value 1358 VERIFY_IS_EQUAL(info, 2); 1359 ++g_test_level; 1360 VERIFY_IS_EQUAL(lm.nfev, 602); // 602 1361 VERIFY_IS_EQUAL(lm.njev, 545); // 545 1362 --g_test_level; 1363 VERIFY(lm.nfev < 602 * LM_EVAL_COUNT_TOL); 1364 VERIFY(lm.njev < 545 * LM_EVAL_COUNT_TOL); 1365 1366 /* 1367 * Second try 1368 */ 1369 x<< 0.5 ,1.5 ,-1 ,0.01 ,0.02; 1370 // do the computation 1371 lm.resetParameters(); 1372 info = lm.minimize(x); 1373 1374 // check return value 1375 VERIFY_IS_EQUAL(info, 1); 1376 VERIFY_IS_EQUAL(lm.nfev, 18); 1377 VERIFY_IS_EQUAL(lm.njev, 15); 1378 // check norm^2 1379 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.4648946975E-05); 1380 // check x 1381 VERIFY_IS_APPROX(x[0], 3.7541005211E-01); 1382 VERIFY_IS_APPROX(x[1], 1.9358469127E+00); 1383 VERIFY_IS_APPROX(x[2], -1.4646871366E+00); 1384 VERIFY_IS_APPROX(x[3], 1.2867534640E-02); 1385 VERIFY_IS_APPROX(x[4], 2.2122699662E-02); 1386 } 1387 1388 struct MGH09_functor : Functor<double> 1389 { 1390 MGH09_functor(void) : Functor<double>(4,11) {} 1391 static const double _x[11]; 1392 static const double y[11]; 1393 int operator()(const VectorXd &b, VectorXd &fvec) 1394 { 1395 assert(b.size()==4); 1396 assert(fvec.size()==11); 1397 for(int i=0; i<11; i++) { 1398 double x = _x[i], xx=x*x; 1399 fvec[i] = b[0]*(xx+x*b[1])/(xx+x*b[2]+b[3]) - y[i]; 1400 } 1401 return 0; 1402 } 1403 int df(const VectorXd &b, MatrixXd &fjac) 1404 { 1405 assert(b.size()==4); 1406 assert(fjac.rows()==11); 1407 assert(fjac.cols()==4); 1408 for(int i=0; i<11; i++) { 1409 double x = _x[i], xx=x*x; 1410 double factor = 1./(xx+x*b[2]+b[3]); 1411 fjac(i,0) = (xx+x*b[1]) * factor; 1412 fjac(i,1) = b[0]*x* factor; 1413 fjac(i,2) = - b[0]*(xx+x*b[1]) * x * factor * factor; 1414 fjac(i,3) = - b[0]*(xx+x*b[1]) * factor * factor; 1415 } 1416 return 0; 1417 } 1418 }; 1419 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 }; 1420 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 }; 1421 1422 // http://www.itl.nist.gov/div898/strd/nls/data/mgh09.shtml 1423 void testNistMGH09(void) 1424 { 1425 const int n=4; 1426 int info; 1427 1428 VectorXd x(n); 1429 1430 /* 1431 * First try 1432 */ 1433 x<< 25., 39, 41.5, 39.; 1434 // do the computation 1435 MGH09_functor functor; 1436 LevenbergMarquardt<MGH09_functor> lm(functor); 1437 lm.parameters.maxfev = 1000; 1438 info = lm.minimize(x); 1439 1440 // check return value 1441 VERIFY_IS_EQUAL(info, 1); 1442 VERIFY_IS_EQUAL(lm.nfev, 490 ); 1443 VERIFY_IS_EQUAL(lm.njev, 376 ); 1444 // check norm^2 1445 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 3.0750560385E-04); 1446 // check x 1447 VERIFY_IS_APPROX(x[0], 0.1928077089); // should be 1.9280693458E-01 1448 VERIFY_IS_APPROX(x[1], 0.19126423573); // should be 1.9128232873E-01 1449 VERIFY_IS_APPROX(x[2], 0.12305309914); // should be 1.2305650693E-01 1450 VERIFY_IS_APPROX(x[3], 0.13605395375); // should be 1.3606233068E-01 1451 1452 /* 1453 * Second try 1454 */ 1455 x<< 0.25, 0.39, 0.415, 0.39; 1456 // do the computation 1457 lm.resetParameters(); 1458 info = lm.minimize(x); 1459 1460 // check return value 1461 VERIFY_IS_EQUAL(info, 1); 1462 VERIFY_IS_EQUAL(lm.nfev, 18); 1463 VERIFY_IS_EQUAL(lm.njev, 16); 1464 // check norm^2 1465 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 3.0750560385E-04); 1466 // check x 1467 VERIFY_IS_APPROX(x[0], 0.19280781); // should be 1.9280693458E-01 1468 VERIFY_IS_APPROX(x[1], 0.19126265); // should be 1.9128232873E-01 1469 VERIFY_IS_APPROX(x[2], 0.12305280); // should be 1.2305650693E-01 1470 VERIFY_IS_APPROX(x[3], 0.13605322); // should be 1.3606233068E-01 1471 } 1472 1473 1474 1475 struct Bennett5_functor : Functor<double> 1476 { 1477 Bennett5_functor(void) : Functor<double>(3,154) {} 1478 static const double x[154]; 1479 static const double y[154]; 1480 int operator()(const VectorXd &b, VectorXd &fvec) 1481 { 1482 assert(b.size()==3); 1483 assert(fvec.size()==154); 1484 for(int i=0; i<154; i++) 1485 fvec[i] = b[0]* pow(b[1]+x[i],-1./b[2]) - y[i]; 1486 return 0; 1487 } 1488 int df(const VectorXd &b, MatrixXd &fjac) 1489 { 1490 assert(b.size()==3); 1491 assert(fjac.rows()==154); 1492 assert(fjac.cols()==3); 1493 for(int i=0; i<154; i++) { 1494 double e = pow(b[1]+x[i],-1./b[2]); 1495 fjac(i,0) = e; 1496 fjac(i,1) = - b[0]*e/b[2]/(b[1]+x[i]); 1497 fjac(i,2) = b[0]*e*log(b[1]+x[i])/b[2]/b[2]; 1498 } 1499 return 0; 1500 } 1501 }; 1502 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, 1503 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 }; 1504 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 1505 ,-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 , 1506 -31.827299E0 ,-31.821600E0 ,-31.818701E0 ,-31.812901E0 ,-31.809999E0 ,-31.807100E0 ,-31.801300E0 ,-31.798401E0 ,-31.795500E0 ,-31.789700E0 ,-31.786800E0 }; 1507 1508 // http://www.itl.nist.gov/div898/strd/nls/data/bennett5.shtml 1509 void testNistBennett5(void) 1510 { 1511 const int n=3; 1512 int info; 1513 1514 VectorXd x(n); 1515 1516 /* 1517 * First try 1518 */ 1519 x<< -2000., 50., 0.8; 1520 // do the computation 1521 Bennett5_functor functor; 1522 LevenbergMarquardt<Bennett5_functor> lm(functor); 1523 lm.parameters.maxfev = 1000; 1524 info = lm.minimize(x); 1525 1526 // check return value 1527 VERIFY_IS_EQUAL(info, 1); 1528 VERIFY_IS_EQUAL(lm.nfev, 758); 1529 VERIFY_IS_EQUAL(lm.njev, 744); 1530 // check norm^2 1531 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.2404744073E-04); 1532 // check x 1533 VERIFY_IS_APPROX(x[0], -2.5235058043E+03); 1534 VERIFY_IS_APPROX(x[1], 4.6736564644E+01); 1535 VERIFY_IS_APPROX(x[2], 9.3218483193E-01); 1536 /* 1537 * Second try 1538 */ 1539 x<< -1500., 45., 0.85; 1540 // do the computation 1541 lm.resetParameters(); 1542 info = lm.minimize(x); 1543 1544 // check return value 1545 VERIFY_IS_EQUAL(info, 1); 1546 VERIFY_IS_EQUAL(lm.nfev, 203); 1547 VERIFY_IS_EQUAL(lm.njev, 192); 1548 // check norm^2 1549 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.2404744073E-04); 1550 // check x 1551 VERIFY_IS_APPROX(x[0], -2523.3007865); // should be -2.5235058043E+03 1552 VERIFY_IS_APPROX(x[1], 46.735705771); // should be 4.6736564644E+01); 1553 VERIFY_IS_APPROX(x[2], 0.93219881891); // should be 9.3218483193E-01); 1554 } 1555 1556 struct thurber_functor : Functor<double> 1557 { 1558 thurber_functor(void) : Functor<double>(7,37) {} 1559 static const double _x[37]; 1560 static const double _y[37]; 1561 int operator()(const VectorXd &b, VectorXd &fvec) 1562 { 1563 // int called=0; printf("call hahn1_functor with iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++; 1564 assert(b.size()==7); 1565 assert(fvec.size()==37); 1566 for(int i=0; i<37; i++) { 1567 double x=_x[i], xx=x*x, xxx=xx*x; 1568 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]; 1569 } 1570 return 0; 1571 } 1572 int df(const VectorXd &b, MatrixXd &fjac) 1573 { 1574 assert(b.size()==7); 1575 assert(fjac.rows()==37); 1576 assert(fjac.cols()==7); 1577 for(int i=0; i<37; i++) { 1578 double x=_x[i], xx=x*x, xxx=xx*x; 1579 double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx); 1580 fjac(i,0) = 1.*fact; 1581 fjac(i,1) = x*fact; 1582 fjac(i,2) = xx*fact; 1583 fjac(i,3) = xxx*fact; 1584 fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact; 1585 fjac(i,4) = x*fact; 1586 fjac(i,5) = xx*fact; 1587 fjac(i,6) = xxx*fact; 1588 } 1589 return 0; 1590 } 1591 }; 1592 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 }; 1593 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}; 1594 1595 // http://www.itl.nist.gov/div898/strd/nls/data/thurber.shtml 1596 void testNistThurber(void) 1597 { 1598 const int n=7; 1599 int info; 1600 1601 VectorXd x(n); 1602 1603 /* 1604 * First try 1605 */ 1606 x<< 1000 ,1000 ,400 ,40 ,0.7,0.3,0.0 ; 1607 // do the computation 1608 thurber_functor functor; 1609 LevenbergMarquardt<thurber_functor> lm(functor); 1610 lm.parameters.ftol = 1.E4*NumTraits<double>::epsilon(); 1611 lm.parameters.xtol = 1.E4*NumTraits<double>::epsilon(); 1612 info = lm.minimize(x); 1613 1614 // check return value 1615 VERIFY_IS_EQUAL(info, 1); 1616 VERIFY_IS_EQUAL(lm.nfev, 39); 1617 VERIFY_IS_EQUAL(lm.njev, 36); 1618 // check norm^2 1619 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6427082397E+03); 1620 // check x 1621 VERIFY_IS_APPROX(x[0], 1.2881396800E+03); 1622 VERIFY_IS_APPROX(x[1], 1.4910792535E+03); 1623 VERIFY_IS_APPROX(x[2], 5.8323836877E+02); 1624 VERIFY_IS_APPROX(x[3], 7.5416644291E+01); 1625 VERIFY_IS_APPROX(x[4], 9.6629502864E-01); 1626 VERIFY_IS_APPROX(x[5], 3.9797285797E-01); 1627 VERIFY_IS_APPROX(x[6], 4.9727297349E-02); 1628 1629 /* 1630 * Second try 1631 */ 1632 x<< 1300 ,1500 ,500 ,75 ,1 ,0.4 ,0.05 ; 1633 // do the computation 1634 lm.resetParameters(); 1635 lm.parameters.ftol = 1.E4*NumTraits<double>::epsilon(); 1636 lm.parameters.xtol = 1.E4*NumTraits<double>::epsilon(); 1637 info = lm.minimize(x); 1638 1639 // check return value 1640 VERIFY_IS_EQUAL(info, 1); 1641 VERIFY_IS_EQUAL(lm.nfev, 29); 1642 VERIFY_IS_EQUAL(lm.njev, 28); 1643 // check norm^2 1644 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6427082397E+03); 1645 // check x 1646 VERIFY_IS_APPROX(x[0], 1.2881396800E+03); 1647 VERIFY_IS_APPROX(x[1], 1.4910792535E+03); 1648 VERIFY_IS_APPROX(x[2], 5.8323836877E+02); 1649 VERIFY_IS_APPROX(x[3], 7.5416644291E+01); 1650 VERIFY_IS_APPROX(x[4], 9.6629502864E-01); 1651 VERIFY_IS_APPROX(x[5], 3.9797285797E-01); 1652 VERIFY_IS_APPROX(x[6], 4.9727297349E-02); 1653 } 1654 1655 struct rat43_functor : Functor<double> 1656 { 1657 rat43_functor(void) : Functor<double>(4,15) {} 1658 static const double x[15]; 1659 static const double y[15]; 1660 int operator()(const VectorXd &b, VectorXd &fvec) 1661 { 1662 assert(b.size()==4); 1663 assert(fvec.size()==15); 1664 for(int i=0; i<15; i++) 1665 fvec[i] = b[0] * pow(1.+exp(b[1]-b[2]*x[i]),-1./b[3]) - y[i]; 1666 return 0; 1667 } 1668 int df(const VectorXd &b, MatrixXd &fjac) 1669 { 1670 assert(b.size()==4); 1671 assert(fjac.rows()==15); 1672 assert(fjac.cols()==4); 1673 for(int i=0; i<15; i++) { 1674 double e = exp(b[1]-b[2]*x[i]); 1675 double power = -1./b[3]; 1676 fjac(i,0) = pow(1.+e, power); 1677 fjac(i,1) = power*b[0]*e*pow(1.+e, power-1.); 1678 fjac(i,2) = -power*b[0]*e*x[i]*pow(1.+e, power-1.); 1679 fjac(i,3) = b[0]*power*power*log(1.+e)*pow(1.+e, power); 1680 } 1681 return 0; 1682 } 1683 }; 1684 const double rat43_functor::x[15] = { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15. }; 1685 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 }; 1686 1687 // http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky3.shtml 1688 void testNistRat43(void) 1689 { 1690 const int n=4; 1691 int info; 1692 1693 VectorXd x(n); 1694 1695 /* 1696 * First try 1697 */ 1698 x<< 100., 10., 1., 1.; 1699 // do the computation 1700 rat43_functor functor; 1701 LevenbergMarquardt<rat43_functor> lm(functor); 1702 lm.parameters.ftol = 1.E6*NumTraits<double>::epsilon(); 1703 lm.parameters.xtol = 1.E6*NumTraits<double>::epsilon(); 1704 info = lm.minimize(x); 1705 1706 // check return value 1707 VERIFY_IS_EQUAL(info, 1); 1708 VERIFY_IS_EQUAL(lm.nfev, 27); 1709 VERIFY_IS_EQUAL(lm.njev, 20); 1710 // check norm^2 1711 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7864049080E+03); 1712 // check x 1713 VERIFY_IS_APPROX(x[0], 6.9964151270E+02); 1714 VERIFY_IS_APPROX(x[1], 5.2771253025E+00); 1715 VERIFY_IS_APPROX(x[2], 7.5962938329E-01); 1716 VERIFY_IS_APPROX(x[3], 1.2792483859E+00); 1717 1718 /* 1719 * Second try 1720 */ 1721 x<< 700., 5., 0.75, 1.3; 1722 // do the computation 1723 lm.resetParameters(); 1724 lm.parameters.ftol = 1.E5*NumTraits<double>::epsilon(); 1725 lm.parameters.xtol = 1.E5*NumTraits<double>::epsilon(); 1726 info = lm.minimize(x); 1727 1728 // check return value 1729 VERIFY_IS_EQUAL(info, 1); 1730 VERIFY_IS_EQUAL(lm.nfev, 9); 1731 VERIFY_IS_EQUAL(lm.njev, 8); 1732 // check norm^2 1733 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7864049080E+03); 1734 // check x 1735 VERIFY_IS_APPROX(x[0], 6.9964151270E+02); 1736 VERIFY_IS_APPROX(x[1], 5.2771253025E+00); 1737 VERIFY_IS_APPROX(x[2], 7.5962938329E-01); 1738 VERIFY_IS_APPROX(x[3], 1.2792483859E+00); 1739 } 1740 1741 1742 1743 struct eckerle4_functor : Functor<double> 1744 { 1745 eckerle4_functor(void) : Functor<double>(3,35) {} 1746 static const double x[35]; 1747 static const double y[35]; 1748 int operator()(const VectorXd &b, VectorXd &fvec) 1749 { 1750 assert(b.size()==3); 1751 assert(fvec.size()==35); 1752 for(int i=0; i<35; i++) 1753 fvec[i] = b[0]/b[1] * exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/(b[1]*b[1])) - y[i]; 1754 return 0; 1755 } 1756 int df(const VectorXd &b, MatrixXd &fjac) 1757 { 1758 assert(b.size()==3); 1759 assert(fjac.rows()==35); 1760 assert(fjac.cols()==3); 1761 for(int i=0; i<35; i++) { 1762 double b12 = b[1]*b[1]; 1763 double e = exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/b12); 1764 fjac(i,0) = e / b[1]; 1765 fjac(i,1) = ((x[i]-b[2])*(x[i]-b[2])/b12-1.) * b[0]*e/b12; 1766 fjac(i,2) = (x[i]-b[2])*e*b[0]/b[1]/b12; 1767 } 1768 return 0; 1769 } 1770 }; 1771 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}; 1772 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 }; 1773 1774 // http://www.itl.nist.gov/div898/strd/nls/data/eckerle4.shtml 1775 void testNistEckerle4(void) 1776 { 1777 const int n=3; 1778 int info; 1779 1780 VectorXd x(n); 1781 1782 /* 1783 * First try 1784 */ 1785 x<< 1., 10., 500.; 1786 // do the computation 1787 eckerle4_functor functor; 1788 LevenbergMarquardt<eckerle4_functor> lm(functor); 1789 info = lm.minimize(x); 1790 1791 // check return value 1792 VERIFY_IS_EQUAL(info, 1); 1793 VERIFY_IS_EQUAL(lm.nfev, 18); 1794 VERIFY_IS_EQUAL(lm.njev, 15); 1795 // check norm^2 1796 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.4635887487E-03); 1797 // check x 1798 VERIFY_IS_APPROX(x[0], 1.5543827178); 1799 VERIFY_IS_APPROX(x[1], 4.0888321754); 1800 VERIFY_IS_APPROX(x[2], 4.5154121844E+02); 1801 1802 /* 1803 * Second try 1804 */ 1805 x<< 1.5, 5., 450.; 1806 // do the computation 1807 info = lm.minimize(x); 1808 1809 // check return value 1810 VERIFY_IS_EQUAL(info, 1); 1811 VERIFY_IS_EQUAL(lm.nfev, 7); 1812 VERIFY_IS_EQUAL(lm.njev, 6); 1813 // check norm^2 1814 VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.4635887487E-03); 1815 // check x 1816 VERIFY_IS_APPROX(x[0], 1.5543827178); 1817 VERIFY_IS_APPROX(x[1], 4.0888321754); 1818 VERIFY_IS_APPROX(x[2], 4.5154121844E+02); 1819 } 1820 1821 void test_NonLinearOptimization() 1822 { 1823 // Tests using the examples provided by (c)minpack 1824 CALL_SUBTEST/*_1*/(testChkder()); 1825 CALL_SUBTEST/*_1*/(testLmder1()); 1826 CALL_SUBTEST/*_1*/(testLmder()); 1827 CALL_SUBTEST/*_2*/(testHybrj1()); 1828 CALL_SUBTEST/*_2*/(testHybrj()); 1829 CALL_SUBTEST/*_2*/(testHybrd1()); 1830 CALL_SUBTEST/*_2*/(testHybrd()); 1831 CALL_SUBTEST/*_3*/(testLmstr1()); 1832 CALL_SUBTEST/*_3*/(testLmstr()); 1833 CALL_SUBTEST/*_3*/(testLmdif1()); 1834 CALL_SUBTEST/*_3*/(testLmdif()); 1835 1836 // NIST tests, level of difficulty = "Lower" 1837 CALL_SUBTEST/*_4*/(testNistMisra1a()); 1838 CALL_SUBTEST/*_4*/(testNistChwirut2()); 1839 1840 // NIST tests, level of difficulty = "Average" 1841 CALL_SUBTEST/*_5*/(testNistHahn1()); 1842 CALL_SUBTEST/*_6*/(testNistMisra1d()); 1843 CALL_SUBTEST/*_7*/(testNistMGH17()); 1844 CALL_SUBTEST/*_8*/(testNistLanczos1()); 1845 1846 // // NIST tests, level of difficulty = "Higher" 1847 CALL_SUBTEST/*_9*/(testNistRat42()); 1848 // CALL_SUBTEST/*_10*/(testNistMGH10()); 1849 CALL_SUBTEST/*_11*/(testNistBoxBOD()); 1850 // CALL_SUBTEST/*_12*/(testNistMGH09()); 1851 CALL_SUBTEST/*_13*/(testNistBennett5()); 1852 CALL_SUBTEST/*_14*/(testNistThurber()); 1853 CALL_SUBTEST/*_15*/(testNistRat43()); 1854 CALL_SUBTEST/*_16*/(testNistEckerle4()); 1855 } 1856 1857 /* 1858 * Can be useful for debugging... 1859 printf("info, nfev : %d, %d\n", info, lm.nfev); 1860 printf("info, nfev, njev : %d, %d, %d\n", info, solver.nfev, solver.njev); 1861 printf("info, nfev : %d, %d\n", info, solver.nfev); 1862 printf("x[0] : %.32g\n", x[0]); 1863 printf("x[1] : %.32g\n", x[1]); 1864 printf("x[2] : %.32g\n", x[2]); 1865 printf("x[3] : %.32g\n", x[3]); 1866 printf("fvec.blueNorm() : %.32g\n", solver.fvec.blueNorm()); 1867 printf("fvec.blueNorm() : %.32g\n", lm.fvec.blueNorm()); 1868 1869 printf("info, nfev, njev : %d, %d, %d\n", info, lm.nfev, lm.njev); 1870 printf("fvec.squaredNorm() : %.13g\n", lm.fvec.squaredNorm()); 1871 std::cout << x << std::endl; 1872 std::cout.precision(9); 1873 std::cout << x[0] << std::endl; 1874 std::cout << x[1] << std::endl; 1875 std::cout << x[2] << std::endl; 1876 std::cout << x[3] << std::endl; 1877 */ 1878 1879