NonLinearOptimization.cpp
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
00005 
00006 #include <stdio.h>
00007 
00008 #include "main.h"
00009 #include <unsupported/Eigen/NonLinearOptimization>
00010 
00011 // This disables some useless Warnings on MSVC.
00012 // It is intended to be done for this test only.
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     /*      subroutine fcn for chkder example. */
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             /* error introduced into next statement for illustration. */
00046             /* corrected statement should read    tmp3 = tmp1 . */
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   /*      the following values should be suitable for */
00068   /*      checking the jacobian matrix. */
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   // check those
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 // Generic functor
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   // you should define that in the subclass :
00127 //  void operator() (const InputType& x, ValueType* v, JacobianType* _j=0) const;
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   /* the following starting values provide a rough fit. */
00173   x.setConstant(n, 1.);
00174 
00175   // do the computation
00176   lmder_functor functor;
00177   LevenbergMarquardt<lmder_functor> lm(functor);
00178   info = lm.lmder1(x);
00179 
00180   // check return value
00181   VERIFY_IS_EQUAL(info, 1);
00182   VERIFY_IS_EQUAL(lm.nfev, 6);
00183   VERIFY_IS_EQUAL(lm.njev, 5);
00184 
00185   // check norm
00186   VERIFY_IS_APPROX(lm.fvec.blueNorm(), 0.09063596);
00187 
00188   // check x
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   /* the following starting values provide a rough fit. */
00202   x.setConstant(n, 1.);
00203 
00204   // do the computation
00205   lmder_functor functor;
00206   LevenbergMarquardt<lmder_functor> lm(functor);
00207   info = lm.minimize(x);
00208 
00209   // check return values
00210   VERIFY_IS_EQUAL(info, 1);
00211   VERIFY_IS_EQUAL(lm.nfev, 6);
00212   VERIFY_IS_EQUAL(lm.njev, 5);
00213 
00214   // check norm
00215   fnorm = lm.fvec.blueNorm();
00216   VERIFY_IS_APPROX(fnorm, 0.09063596);
00217 
00218   // check x
00219   VectorXd x_ref(n);
00220   x_ref << 0.08241058, 1.133037, 2.343695;
00221   VERIFY_IS_APPROX(x, x_ref);
00222 
00223   // check covariance
00224   covfac = fnorm*fnorm/(m-n);
00225   internal::covar(lm.fjac, lm.permutation.indices()); // TODO : move this as a function of lm
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 //  std::cout << fjac*covfac << std::endl;
00234 
00235   MatrixXd cov;
00236   cov =  covfac*lm.fjac.topLeftCorner<n,n>();
00237   VERIFY_IS_APPROX( cov, cov_ref);
00238   // TODO: why isn't this allowed ? :
00239   // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref);
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   /* the following starting values provide a rough fit. */
00287   x.setConstant(n, -1.);
00288 
00289   // do the computation
00290   hybrj_functor functor;
00291   HybridNonLinearSolver<hybrj_functor> solver(functor);
00292   info = solver.hybrj1(x);
00293 
00294   // check return value
00295   VERIFY_IS_EQUAL(info, 1);
00296   VERIFY_IS_EQUAL(solver.nfev, 11);
00297   VERIFY_IS_EQUAL(solver.njev, 1);
00298 
00299   // check norm
00300   VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00301 
00302 
00303 // check x
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   /* the following starting values provide a rough fit. */
00319   x.setConstant(n, -1.);
00320 
00321 
00322   // do the computation
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   // check return value
00330   VERIFY_IS_EQUAL(info, 1);
00331   VERIFY_IS_EQUAL(solver.nfev, 11);
00332   VERIFY_IS_EQUAL(solver.njev, 1);
00333 
00334   // check norm
00335   VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00336 
00337 
00338 // check x
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   /* the following starting values provide a rough solution. */
00376   x.setConstant(n, -1.);
00377 
00378   // do the computation
00379   hybrd_functor functor;
00380   HybridNonLinearSolver<hybrd_functor> solver(functor);
00381   info = solver.hybrd1(x);
00382 
00383   // check return value
00384   VERIFY_IS_EQUAL(info, 1);
00385   VERIFY_IS_EQUAL(solver.nfev, 20);
00386 
00387   // check norm
00388   VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00389 
00390   // check x
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   /* the following starting values provide a rough fit. */
00403   x.setConstant(n, -1.);
00404 
00405   // do the computation
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   // check return value
00415   VERIFY_IS_EQUAL(info, 1);
00416   VERIFY_IS_EQUAL(solver.nfev, 14);
00417 
00418   // check norm
00419   VERIFY_IS_APPROX(solver.fvec.blueNorm(), 1.192636e-08);
00420 
00421   // check x
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         /*  subroutine fcn for lmstr1 example. */
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   /* the following starting values provide a rough fit. */
00478   x.setConstant(n, 1.);
00479 
00480   // do the computation
00481   lmstr_functor functor;
00482   LevenbergMarquardt<lmstr_functor> lm(functor);
00483   info = lm.lmstr1(x);
00484 
00485   // check return value
00486   VERIFY_IS_EQUAL(info, 1);
00487   VERIFY_IS_EQUAL(lm.nfev, 6);
00488   VERIFY_IS_EQUAL(lm.njev, 5);
00489 
00490   // check norm
00491   VERIFY_IS_APPROX(lm.fvec.blueNorm(), 0.09063596);
00492 
00493   // check x
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   /* the following starting values provide a rough fit. */
00507   x.setConstant(n, 1.);
00508 
00509   // do the computation
00510   lmstr_functor functor;
00511   LevenbergMarquardt<lmstr_functor> lm(functor);
00512   info = lm.minimizeOptimumStorage(x);
00513 
00514   // check return values
00515   VERIFY_IS_EQUAL(info, 1);
00516   VERIFY_IS_EQUAL(lm.nfev, 6);
00517   VERIFY_IS_EQUAL(lm.njev, 5);
00518 
00519   // check norm
00520   fnorm = lm.fvec.blueNorm();
00521   VERIFY_IS_APPROX(fnorm, 0.09063596);
00522 
00523   // check x
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   /* the following starting values provide a rough fit. */
00563   x.setConstant(n, 1.);
00564 
00565   // do the computation
00566   lmdif_functor functor;
00567   DenseIndex nfev;
00568   info = LevenbergMarquardt<lmdif_functor>::lmdif1(functor, x, &nfev);
00569 
00570   // check return value
00571   VERIFY_IS_EQUAL(info, 1);
00572   VERIFY_IS_EQUAL(nfev, 26);
00573 
00574   // check norm
00575   functor(x, fvec);
00576   VERIFY_IS_APPROX(fvec.blueNorm(), 0.09063596);
00577 
00578   // check x
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   /* the following starting values provide a rough fit. */
00593   x.setConstant(n, 1.);
00594 
00595   // do the computation
00596   lmdif_functor functor;
00597   NumericalDiff<lmdif_functor> numDiff(functor);
00598   LevenbergMarquardt<NumericalDiff<lmdif_functor> > lm(numDiff);
00599   info = lm.minimize(x);
00600 
00601   // check return values
00602   VERIFY_IS_EQUAL(info, 1);
00603   VERIFY_IS_EQUAL(lm.nfev, 26);
00604 
00605   // check norm
00606   fnorm = lm.fvec.blueNorm();
00607   VERIFY_IS_APPROX(fnorm, 0.09063596);
00608 
00609   // check x
00610   VectorXd x_ref(n);
00611   x_ref << 0.08241058, 1.133037, 2.343695;
00612   VERIFY_IS_APPROX(x, x_ref);
00613 
00614   // check covariance
00615   covfac = fnorm*fnorm/(m-n);
00616   internal::covar(lm.fjac, lm.permutation.indices()); // TODO : move this as a function of lm
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 //  std::cout << fjac*covfac << std::endl;
00625 
00626   MatrixXd cov;
00627   cov =  covfac*lm.fjac.topLeftCorner<n,n>();
00628   VERIFY_IS_APPROX( cov, cov_ref);
00629   // TODO: why isn't this allowed ? :
00630   // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref);
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 // http://www.itl.nist.gov/div898/strd/nls/data/chwirut2.shtml
00670 void testNistChwirut2(void)
00671 {
00672   const int n=3;
00673   int info;
00674 
00675   VectorXd x(n);
00676 
00677   /*
00678    * First try
00679    */
00680   x<< 0.1, 0.01, 0.02;
00681   // do the computation
00682   chwirut2_functor functor;
00683   LevenbergMarquardt<chwirut2_functor> lm(functor);
00684   info = lm.minimize(x);
00685 
00686   // check return value
00687   VERIFY_IS_EQUAL(info, 1);
00688   VERIFY_IS_EQUAL(lm.nfev, 10);
00689   VERIFY_IS_EQUAL(lm.njev, 8);
00690   // check norm^2
00691   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.1304802941E+02);
00692   // check x
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    * Second try
00699    */
00700   x<< 0.15, 0.008, 0.010;
00701   // do the computation
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   // check return value
00708   VERIFY_IS_EQUAL(info, 1);
00709   VERIFY_IS_EQUAL(lm.nfev, 7);
00710   VERIFY_IS_EQUAL(lm.njev, 6);
00711   // check norm^2
00712   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.1304802941E+02);
00713   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/misra1a.shtml
00750 void testNistMisra1a(void)
00751 {
00752   const int n=2;
00753   int info;
00754 
00755   VectorXd x(n);
00756 
00757   /*
00758    * First try
00759    */
00760   x<< 500., 0.0001;
00761   // do the computation
00762   misra1a_functor functor;
00763   LevenbergMarquardt<misra1a_functor> lm(functor);
00764   info = lm.minimize(x);
00765 
00766   // check return value
00767   VERIFY_IS_EQUAL(info, 1);
00768   VERIFY_IS_EQUAL(lm.nfev, 19);
00769   VERIFY_IS_EQUAL(lm.njev, 15);
00770   // check norm^2
00771   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.2455138894E-01);
00772   // check x
00773   VERIFY_IS_APPROX(x[0], 2.3894212918E+02);
00774   VERIFY_IS_APPROX(x[1], 5.5015643181E-04);
00775 
00776   /*
00777    * Second try
00778    */
00779   x<< 250., 0.0005;
00780   // do the computation
00781   info = lm.minimize(x);
00782 
00783   // check return value
00784   VERIFY_IS_EQUAL(info, 1);
00785   VERIFY_IS_EQUAL(lm.nfev, 5);
00786   VERIFY_IS_EQUAL(lm.njev, 4);
00787   // check norm^2
00788   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.2455138894E-01);
00789   // check x
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         //        int called=0; printf("call hahn1_functor with  iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++;
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 // http://www.itl.nist.gov/div898/strd/nls/data/hahn1.shtml
00840 void testNistHahn1(void)
00841 {
00842   const int  n=7;
00843   int info;
00844 
00845   VectorXd x(n);
00846 
00847   /*
00848    * First try
00849    */
00850   x<< 10., -1., .05, -.00001, -.05, .001, -.000001;
00851   // do the computation
00852   hahn1_functor functor;
00853   LevenbergMarquardt<hahn1_functor> lm(functor);
00854   info = lm.minimize(x);
00855 
00856   // check return value
00857   VERIFY_IS_EQUAL(info, 1);
00858   VERIFY_IS_EQUAL(lm.nfev, 11);
00859   VERIFY_IS_EQUAL(lm.njev, 10);
00860   // check norm^2
00861   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.5324382854E+00);
00862   // check x
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); // shoulde be : -1.4262662514E-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    * Second try
00873    */
00874   x<< .1, -.1, .005, -.000001, -.005, .0001, -.0000001;
00875   // do the computation
00876   info = lm.minimize(x);
00877 
00878   // check return value
00879   VERIFY_IS_EQUAL(info, 1);
00880   VERIFY_IS_EQUAL(lm.nfev, 11);
00881   VERIFY_IS_EQUAL(lm.njev, 10);
00882   // check norm^2
00883   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.5324382854E+00);
00884   // check x
00885   VERIFY_IS_APPROX(x[0], 1.077640); // should be :  1.0776351733E+00
00886   VERIFY_IS_APPROX(x[1], -0.1226933); // should be : -1.2269296921E-01
00887   VERIFY_IS_APPROX(x[2], 0.004086383); // should be : 4.0863750610E-03
00888   VERIFY_IS_APPROX(x[3], -1.426277e-06); // shoulde be : -1.4262662514E-06
00889   VERIFY_IS_APPROX(x[4],-5.7609940901E-03);
00890   VERIFY_IS_APPROX(x[5], 0.00024053772); // should be : 2.4053735503E-04
00891   VERIFY_IS_APPROX(x[6], -1.231450e-07); // should be : -1.2314450199E-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 // http://www.itl.nist.gov/div898/strd/nls/data/misra1d.shtml
00926 void testNistMisra1d(void)
00927 {
00928   const int n=2;
00929   int info;
00930 
00931   VectorXd x(n);
00932 
00933   /*
00934    * First try
00935    */
00936   x<< 500., 0.0001;
00937   // do the computation
00938   misra1d_functor functor;
00939   LevenbergMarquardt<misra1d_functor> lm(functor);
00940   info = lm.minimize(x);
00941 
00942   // check return value
00943   VERIFY_IS_EQUAL(info, 3);
00944   VERIFY_IS_EQUAL(lm.nfev, 9);
00945   VERIFY_IS_EQUAL(lm.njev, 7);
00946   // check norm^2
00947   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6419295283E-02);
00948   // check x
00949   VERIFY_IS_APPROX(x[0], 4.3736970754E+02);
00950   VERIFY_IS_APPROX(x[1], 3.0227324449E-04);
00951 
00952   /*
00953    * Second try
00954    */
00955   x<< 450., 0.0003;
00956   // do the computation
00957   info = lm.minimize(x);
00958 
00959   // check return value
00960   VERIFY_IS_EQUAL(info, 1);
00961   VERIFY_IS_EQUAL(lm.nfev, 4);
00962   VERIFY_IS_EQUAL(lm.njev, 3);
00963   // check norm^2
00964   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6419295283E-02);
00965   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/lanczos1.shtml
01004 void testNistLanczos1(void)
01005 {
01006   const int n=6;
01007   int info;
01008 
01009   VectorXd x(n);
01010 
01011   /*
01012    * First try
01013    */
01014   x<< 1.2, 0.3, 5.6, 5.5, 6.5, 7.6;
01015   // do the computation
01016   lanczos1_functor functor;
01017   LevenbergMarquardt<lanczos1_functor> lm(functor);
01018   info = lm.minimize(x);
01019 
01020   // check return value
01021   VERIFY_IS_EQUAL(info, 2);
01022   VERIFY_IS_EQUAL(lm.nfev, 79);
01023   VERIFY_IS_EQUAL(lm.njev, 72);
01024   // check norm^2
01025   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.430899764097e-25);  // should be 1.4307867721E-25, but nist results are on 128-bit floats
01026   // check x
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    * Second try
01036    */
01037   x<< 0.5, 0.7, 3.6, 4.2, 4., 6.3;
01038   // do the computation
01039   info = lm.minimize(x);
01040 
01041   // check return value
01042   VERIFY_IS_EQUAL(info, 2);
01043   VERIFY_IS_EQUAL(lm.nfev, 9);
01044   VERIFY_IS_EQUAL(lm.njev, 8);
01045   // check norm^2
01046   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.428595533845e-25);  // should be 1.4307867721E-25, but nist results are on 128-bit floats
01047   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky2.shtml
01090 void testNistRat42(void)
01091 {
01092   const int n=3;
01093   int info;
01094 
01095   VectorXd x(n);
01096 
01097   /*
01098    * First try
01099    */
01100   x<< 100., 1., 0.1;
01101   // do the computation
01102   rat42_functor functor;
01103   LevenbergMarquardt<rat42_functor> lm(functor);
01104   info = lm.minimize(x);
01105 
01106   // check return value
01107   VERIFY_IS_EQUAL(info, 1);
01108   VERIFY_IS_EQUAL(lm.nfev, 10);
01109   VERIFY_IS_EQUAL(lm.njev, 8);
01110   // check norm^2
01111   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.0565229338E+00);
01112   // check x
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    * Second try
01119    */
01120   x<< 75., 2.5, 0.07;
01121   // do the computation
01122   info = lm.minimize(x);
01123 
01124   // check return value
01125   VERIFY_IS_EQUAL(info, 1);
01126   VERIFY_IS_EQUAL(lm.nfev, 6);
01127   VERIFY_IS_EQUAL(lm.njev, 5);
01128   // check norm^2
01129   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.0565229338E+00);
01130   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/mgh10.shtml
01168 void testNistMGH10(void)
01169 {
01170   const int n=3;
01171   int info;
01172 
01173   VectorXd x(n);
01174 
01175   /*
01176    * First try
01177    */
01178   x<< 2., 400000., 25000.;
01179   // do the computation
01180   MGH10_functor functor;
01181   LevenbergMarquardt<MGH10_functor> lm(functor);
01182   info = lm.minimize(x);
01183 
01184   // check return value
01185   VERIFY_IS_EQUAL(info, 2); 
01186   VERIFY_IS_EQUAL(lm.nfev, 284 ); 
01187   VERIFY_IS_EQUAL(lm.njev, 249 ); 
01188   // check norm^2
01189   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7945855171E+01);
01190   // check x
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    * Second try
01197    */
01198   x<< 0.02, 4000., 250.;
01199   // do the computation
01200   info = lm.minimize(x);
01201 
01202   // check return value
01203   VERIFY_IS_EQUAL(info, 3);
01204   VERIFY_IS_EQUAL(lm.nfev, 126);
01205   VERIFY_IS_EQUAL(lm.njev, 116);
01206   // check norm^2
01207   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7945855171E+01);
01208   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/boxbod.shtml
01244 void testNistBoxBOD(void)
01245 {
01246   const int n=2;
01247   int info;
01248 
01249   VectorXd x(n);
01250 
01251   /*
01252    * First try
01253    */
01254   x<< 1., 1.;
01255   // do the computation
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   // check return value
01264   VERIFY_IS_EQUAL(info, 1);
01265   VERIFY_IS_EQUAL(lm.nfev, 31);
01266   VERIFY_IS_EQUAL(lm.njev, 25);
01267   // check norm^2
01268   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.1680088766E+03);
01269   // check x
01270   VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
01271   VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
01272 
01273   /*
01274    * Second try
01275    */
01276   x<< 100., 0.75;
01277   // do the computation
01278   lm.resetParameters();
01279   lm.parameters.ftol = NumTraits<double>::epsilon();
01280   lm.parameters.xtol = NumTraits<double>::epsilon();
01281   info = lm.minimize(x);
01282 
01283   // check return value
01284   VERIFY_IS_EQUAL(info, 1); 
01285   VERIFY_IS_EQUAL(lm.nfev, 15 ); 
01286   VERIFY_IS_EQUAL(lm.njev, 14 ); 
01287   // check norm^2
01288   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.1680088766E+03);
01289   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/mgh17.shtml
01326 void testNistMGH17(void)
01327 {
01328   const int n=5;
01329   int info;
01330 
01331   VectorXd x(n);
01332 
01333   /*
01334    * First try
01335    */
01336   x<< 50., 150., -100., 1., 2.;
01337   // do the computation
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   // check return value
01346   VERIFY_IS_EQUAL(info, 2); 
01347   VERIFY_IS_EQUAL(lm.nfev, 602 ); 
01348   VERIFY_IS_EQUAL(lm.njev, 545 ); 
01349   // check norm^2
01350   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.4648946975E-05);
01351   // check x
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    * Second try
01360    */
01361   x<< 0.5  ,1.5  ,-1   ,0.01 ,0.02;
01362   // do the computation
01363   lm.resetParameters();
01364   info = lm.minimize(x);
01365 
01366   // check return value
01367   VERIFY_IS_EQUAL(info, 1);
01368   VERIFY_IS_EQUAL(lm.nfev, 18);
01369   VERIFY_IS_EQUAL(lm.njev, 15);
01370   // check norm^2
01371   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.4648946975E-05);
01372   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/mgh09.shtml
01415 void testNistMGH09(void)
01416 {
01417   const int n=4;
01418   int info;
01419 
01420   VectorXd x(n);
01421 
01422   /*
01423    * First try
01424    */
01425   x<< 25., 39, 41.5, 39.;
01426   // do the computation
01427   MGH09_functor functor;
01428   LevenbergMarquardt<MGH09_functor> lm(functor);
01429   lm.parameters.maxfev = 1000;
01430   info = lm.minimize(x);
01431 
01432   // check return value
01433   VERIFY_IS_EQUAL(info, 1); 
01434   VERIFY_IS_EQUAL(lm.nfev, 490 ); 
01435   VERIFY_IS_EQUAL(lm.njev, 376 ); 
01436   // check norm^2
01437   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 3.0750560385E-04);
01438   // check x
01439   VERIFY_IS_APPROX(x[0], 0.1928077089); // should be 1.9280693458E-01
01440   VERIFY_IS_APPROX(x[1], 0.19126423573); // should be 1.9128232873E-01
01441   VERIFY_IS_APPROX(x[2], 0.12305309914); // should be 1.2305650693E-01
01442   VERIFY_IS_APPROX(x[3], 0.13605395375); // should be 1.3606233068E-01
01443 
01444   /*
01445    * Second try
01446    */
01447   x<< 0.25, 0.39, 0.415, 0.39;
01448   // do the computation
01449   lm.resetParameters();
01450   info = lm.minimize(x);
01451 
01452   // check return value
01453   VERIFY_IS_EQUAL(info, 1);
01454   VERIFY_IS_EQUAL(lm.nfev, 18);
01455   VERIFY_IS_EQUAL(lm.njev, 16);
01456   // check norm^2
01457   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 3.0750560385E-04);
01458   // check x
01459   VERIFY_IS_APPROX(x[0], 0.19280781); // should be 1.9280693458E-01
01460   VERIFY_IS_APPROX(x[1], 0.19126265); // should be 1.9128232873E-01
01461   VERIFY_IS_APPROX(x[2], 0.12305280); // should be 1.2305650693E-01
01462   VERIFY_IS_APPROX(x[3], 0.13605322); // should be 1.3606233068E-01
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 // http://www.itl.nist.gov/div898/strd/nls/data/bennett5.shtml
01501 void testNistBennett5(void)
01502 {
01503   const int  n=3;
01504   int info;
01505 
01506   VectorXd x(n);
01507 
01508   /*
01509    * First try
01510    */
01511   x<< -2000., 50., 0.8;
01512   // do the computation
01513   Bennett5_functor functor;
01514   LevenbergMarquardt<Bennett5_functor> lm(functor);
01515   lm.parameters.maxfev = 1000;
01516   info = lm.minimize(x);
01517 
01518   // check return value
01519   VERIFY_IS_EQUAL(info, 1);
01520   VERIFY_IS_EQUAL(lm.nfev, 758);
01521   VERIFY_IS_EQUAL(lm.njev, 744);
01522   // check norm^2
01523   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.2404744073E-04);
01524   // check x
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    * Second try
01530    */
01531   x<< -1500., 45., 0.85;
01532   // do the computation
01533   lm.resetParameters();
01534   info = lm.minimize(x);
01535 
01536   // check return value
01537   VERIFY_IS_EQUAL(info, 1);
01538   VERIFY_IS_EQUAL(lm.nfev, 203);
01539   VERIFY_IS_EQUAL(lm.njev, 192);
01540   // check norm^2
01541   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.2404744073E-04);
01542   // check x
01543   VERIFY_IS_APPROX(x[0], -2523.3007865); // should be -2.5235058043E+03
01544   VERIFY_IS_APPROX(x[1], 46.735705771); // should be 4.6736564644E+01);
01545   VERIFY_IS_APPROX(x[2], 0.93219881891); // should be 9.3218483193E-01);
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         //        int called=0; printf("call hahn1_functor with  iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++;
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 // http://www.itl.nist.gov/div898/strd/nls/data/thurber.shtml
01588 void testNistThurber(void)
01589 {
01590   const int n=7;
01591   int info;
01592 
01593   VectorXd x(n);
01594 
01595   /*
01596    * First try
01597    */
01598   x<< 1000 ,1000 ,400 ,40 ,0.7,0.3,0.0 ;
01599   // do the computation
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   // check return value
01607   VERIFY_IS_EQUAL(info, 1);
01608   VERIFY_IS_EQUAL(lm.nfev, 39);
01609   VERIFY_IS_EQUAL(lm.njev, 36);
01610   // check norm^2
01611   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6427082397E+03);
01612   // check x
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    * Second try
01623    */
01624   x<< 1300 ,1500 ,500  ,75   ,1    ,0.4  ,0.05  ;
01625   // do the computation
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   // check return value
01632   VERIFY_IS_EQUAL(info, 1);
01633   VERIFY_IS_EQUAL(lm.nfev, 29);
01634   VERIFY_IS_EQUAL(lm.njev, 28);
01635   // check norm^2
01636   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.6427082397E+03);
01637   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky3.shtml
01680 void testNistRat43(void)
01681 {
01682   const int n=4;
01683   int info;
01684 
01685   VectorXd x(n);
01686 
01687   /*
01688    * First try
01689    */
01690   x<< 100., 10., 1., 1.;
01691   // do the computation
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   // check return value
01699   VERIFY_IS_EQUAL(info, 1);
01700   VERIFY_IS_EQUAL(lm.nfev, 27);
01701   VERIFY_IS_EQUAL(lm.njev, 20);
01702   // check norm^2
01703   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7864049080E+03);
01704   // check x
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    * Second try
01712    */
01713   x<< 700., 5., 0.75, 1.3;
01714   // do the computation
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   // check return value
01721   VERIFY_IS_EQUAL(info, 1);
01722   VERIFY_IS_EQUAL(lm.nfev, 9);
01723   VERIFY_IS_EQUAL(lm.njev, 8);
01724   // check norm^2
01725   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 8.7864049080E+03);
01726   // check x
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 // http://www.itl.nist.gov/div898/strd/nls/data/eckerle4.shtml
01767 void testNistEckerle4(void)
01768 {
01769   const int n=3;
01770   int info;
01771 
01772   VectorXd x(n);
01773 
01774   /*
01775    * First try
01776    */
01777   x<< 1., 10., 500.;
01778   // do the computation
01779   eckerle4_functor functor;
01780   LevenbergMarquardt<eckerle4_functor> lm(functor);
01781   info = lm.minimize(x);
01782 
01783   // check return value
01784   VERIFY_IS_EQUAL(info, 1);
01785   VERIFY_IS_EQUAL(lm.nfev, 18);
01786   VERIFY_IS_EQUAL(lm.njev, 15);
01787   // check norm^2
01788   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.4635887487E-03);
01789   // check x
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    * Second try
01796    */
01797   x<< 1.5, 5., 450.;
01798   // do the computation
01799   info = lm.minimize(x);
01800 
01801   // check return value
01802   VERIFY_IS_EQUAL(info, 1);
01803   VERIFY_IS_EQUAL(lm.nfev, 7);
01804   VERIFY_IS_EQUAL(lm.njev, 6);
01805   // check norm^2
01806   VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.4635887487E-03);
01807   // check x
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     // Tests using the examples provided by (c)minpack
01816     CALL_SUBTEST/*_1*/(testChkder());
01817     CALL_SUBTEST/*_1*/(testLmder1());
01818     CALL_SUBTEST/*_1*/(testLmder());
01819     CALL_SUBTEST/*_2*/(testHybrj1());
01820     CALL_SUBTEST/*_2*/(testHybrj());
01821     CALL_SUBTEST/*_2*/(testHybrd1());
01822     CALL_SUBTEST/*_2*/(testHybrd());
01823     CALL_SUBTEST/*_3*/(testLmstr1());
01824     CALL_SUBTEST/*_3*/(testLmstr());
01825     CALL_SUBTEST/*_3*/(testLmdif1());
01826     CALL_SUBTEST/*_3*/(testLmdif());
01827 
01828     // NIST tests, level of difficulty = "Lower"
01829     CALL_SUBTEST/*_4*/(testNistMisra1a());
01830     CALL_SUBTEST/*_4*/(testNistChwirut2());
01831 
01832     // NIST tests, level of difficulty = "Average"
01833     CALL_SUBTEST/*_5*/(testNistHahn1());
01834     CALL_SUBTEST/*_6*/(testNistMisra1d());
01835 //     CALL_SUBTEST/*_7*/(testNistMGH17());
01836 //     CALL_SUBTEST/*_8*/(testNistLanczos1());
01837 
01838 //     // NIST tests, level of difficulty = "Higher"
01839     CALL_SUBTEST/*_9*/(testNistRat42());
01840 //     CALL_SUBTEST/*_10*/(testNistMGH10());
01841     CALL_SUBTEST/*_11*/(testNistBoxBOD());
01842 //     CALL_SUBTEST/*_12*/(testNistMGH09());
01843     CALL_SUBTEST/*_13*/(testNistBennett5());
01844     CALL_SUBTEST/*_14*/(testNistThurber());
01845     CALL_SUBTEST/*_15*/(testNistRat43());
01846     CALL_SUBTEST/*_16*/(testNistEckerle4());
01847 }
01848 
01849 /*
01850  * Can be useful for debugging...
01851   printf("info, nfev : %d, %d\n", info, lm.nfev);
01852   printf("info, nfev, njev : %d, %d, %d\n", info, solver.nfev, solver.njev);
01853   printf("info, nfev : %d, %d\n", info, solver.nfev);
01854   printf("x[0] : %.32g\n", x[0]);
01855   printf("x[1] : %.32g\n", x[1]);
01856   printf("x[2] : %.32g\n", x[2]);
01857   printf("x[3] : %.32g\n", x[3]);
01858   printf("fvec.blueNorm() : %.32g\n", solver.fvec.blueNorm());
01859   printf("fvec.blueNorm() : %.32g\n", lm.fvec.blueNorm());
01860 
01861   printf("info, nfev, njev : %d, %d, %d\n", info, lm.nfev, lm.njev);
01862   printf("fvec.squaredNorm() : %.13g\n", lm.fvec.squaredNorm());
01863   std::cout << x << std::endl;
01864   std::cout.precision(9);
01865   std::cout << x[0] << std::endl;
01866   std::cout << x[1] << std::endl;
01867   std::cout << x[2] << std::endl;
01868   std::cout << x[3] << std::endl;
01869 */
01870 


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:33:28