Home | History | Annotate | Download | only in test
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2009 Thomas Capricelli <orzel (at) freehackers.org>
      5 // Copyright (C) 2012 desire Nuentsa <desire.nuentsa_wakam (at) inria.fr
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 
     12 #include <stdio.h>
     13 
     14 #include "main.h"
     15 #include <unsupported/Eigen/LevenbergMarquardt>
     16 
     17 // This disables some useless Warnings on MSVC.
     18 // It is intended to be done for this test only.
     19 #include <Eigen/src/Core/util/DisableStupidWarnings.h>
     20 
     21 using std::sqrt;
     22 
     23 struct lmder_functor : DenseFunctor<double>
     24 {
     25     lmder_functor(void): DenseFunctor<double>(3,15) {}
     26     int operator()(const VectorXd &x, VectorXd &fvec) const
     27     {
     28         double tmp1, tmp2, tmp3;
     29         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,
     30             3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39};
     31 
     32         for (int i = 0; i < values(); i++)
     33         {
     34             tmp1 = i+1;
     35             tmp2 = 16 - i - 1;
     36             tmp3 = (i>=8)? tmp2 : tmp1;
     37             fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
     38         }
     39         return 0;
     40     }
     41 
     42     int df(const VectorXd &x, MatrixXd &fjac) const
     43     {
     44         double tmp1, tmp2, tmp3, tmp4;
     45         for (int i = 0; i < values(); i++)
     46         {
     47             tmp1 = i+1;
     48             tmp2 = 16 - i - 1;
     49             tmp3 = (i>=8)? tmp2 : tmp1;
     50             tmp4 = (x[1]*tmp2 + x[2]*tmp3); tmp4 = tmp4*tmp4;
     51             fjac(i,0) = -1;
     52             fjac(i,1) = tmp1*tmp2/tmp4;
     53             fjac(i,2) = tmp1*tmp3/tmp4;
     54         }
     55         return 0;
     56     }
     57 };
     58 
     59 void testLmder1()
     60 {
     61   int n=3, info;
     62 
     63   VectorXd x;
     64 
     65   /* the following starting values provide a rough fit. */
     66   x.setConstant(n, 1.);
     67 
     68   // do the computation
     69   lmder_functor functor;
     70   LevenbergMarquardt<lmder_functor> lm(functor);
     71   info = lm.lmder1(x);
     72 
     73   // check return value
     74   VERIFY_IS_EQUAL(info, 1);
     75   VERIFY_IS_EQUAL(lm.nfev(), 6);
     76   VERIFY_IS_EQUAL(lm.njev(), 5);
     77 
     78   // check norm
     79   VERIFY_IS_APPROX(lm.fvec().blueNorm(), 0.09063596);
     80 
     81   // check x
     82   VectorXd x_ref(n);
     83   x_ref << 0.08241058, 1.133037, 2.343695;
     84   VERIFY_IS_APPROX(x, x_ref);
     85 }
     86 
     87 void testLmder()
     88 {
     89   const int m=15, n=3;
     90   int info;
     91   double fnorm, covfac;
     92   VectorXd x;
     93 
     94   /* the following starting values provide a rough fit. */
     95   x.setConstant(n, 1.);
     96 
     97   // do the computation
     98   lmder_functor functor;
     99   LevenbergMarquardt<lmder_functor> lm(functor);
    100   info = lm.minimize(x);
    101 
    102   // check return values
    103   VERIFY_IS_EQUAL(info, 1);
    104   VERIFY_IS_EQUAL(lm.nfev(), 6);
    105   VERIFY_IS_EQUAL(lm.njev(), 5);
    106 
    107   // check norm
    108   fnorm = lm.fvec().blueNorm();
    109   VERIFY_IS_APPROX(fnorm, 0.09063596);
    110 
    111   // check x
    112   VectorXd x_ref(n);
    113   x_ref << 0.08241058, 1.133037, 2.343695;
    114   VERIFY_IS_APPROX(x, x_ref);
    115 
    116   // check covariance
    117   covfac = fnorm*fnorm/(m-n);
    118   internal::covar(lm.matrixR(), lm.permutation().indices()); // TODO : move this as a function of lm
    119 
    120   MatrixXd cov_ref(n,n);
    121   cov_ref <<
    122       0.0001531202,   0.002869941,  -0.002656662,
    123       0.002869941,    0.09480935,   -0.09098995,
    124       -0.002656662,   -0.09098995,    0.08778727;
    125 
    126 //  std::cout << fjac*covfac << std::endl;
    127 
    128   MatrixXd cov;
    129   cov =  covfac*lm.matrixR().topLeftCorner<n,n>();
    130   VERIFY_IS_APPROX( cov, cov_ref);
    131   // TODO: why isn't this allowed ? :
    132   // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref);
    133 }
    134 
    135 struct lmdif_functor : DenseFunctor<double>
    136 {
    137     lmdif_functor(void) : DenseFunctor<double>(3,15) {}
    138     int operator()(const VectorXd &x, VectorXd &fvec) const
    139     {
    140         int i;
    141         double tmp1,tmp2,tmp3;
    142         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,
    143             3.7e-1,5.8e-1,7.3e-1,9.6e-1,1.34e0,2.1e0,4.39e0};
    144 
    145         assert(x.size()==3);
    146         assert(fvec.size()==15);
    147         for (i=0; i<15; i++)
    148         {
    149             tmp1 = i+1;
    150             tmp2 = 15 - i;
    151             tmp3 = tmp1;
    152 
    153             if (i >= 8) tmp3 = tmp2;
    154             fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
    155         }
    156         return 0;
    157     }
    158 };
    159 
    160 void testLmdif1()
    161 {
    162   const int n=3;
    163   int info;
    164 
    165   VectorXd x(n), fvec(15);
    166 
    167   /* the following starting values provide a rough fit. */
    168   x.setConstant(n, 1.);
    169 
    170   // do the computation
    171   lmdif_functor functor;
    172   DenseIndex nfev;
    173   info = LevenbergMarquardt<lmdif_functor>::lmdif1(functor, x, &nfev);
    174 
    175   // check return value
    176   VERIFY_IS_EQUAL(info, 1);
    177 //   VERIFY_IS_EQUAL(nfev, 26);
    178 
    179   // check norm
    180   functor(x, fvec);
    181   VERIFY_IS_APPROX(fvec.blueNorm(), 0.09063596);
    182 
    183   // check x
    184   VectorXd x_ref(n);
    185   x_ref << 0.0824106, 1.1330366, 2.3436947;
    186   VERIFY_IS_APPROX(x, x_ref);
    187 
    188 }
    189 
    190 void testLmdif()
    191 {
    192   const int m=15, n=3;
    193   int info;
    194   double fnorm, covfac;
    195   VectorXd x(n);
    196 
    197   /* the following starting values provide a rough fit. */
    198   x.setConstant(n, 1.);
    199 
    200   // do the computation
    201   lmdif_functor functor;
    202   NumericalDiff<lmdif_functor> numDiff(functor);
    203   LevenbergMarquardt<NumericalDiff<lmdif_functor> > lm(numDiff);
    204   info = lm.minimize(x);
    205 
    206   // check return values
    207   VERIFY_IS_EQUAL(info, 1);
    208 //   VERIFY_IS_EQUAL(lm.nfev(), 26);
    209 
    210   // check norm
    211   fnorm = lm.fvec().blueNorm();
    212   VERIFY_IS_APPROX(fnorm, 0.09063596);
    213 
    214   // check x
    215   VectorXd x_ref(n);
    216   x_ref << 0.08241058, 1.133037, 2.343695;
    217   VERIFY_IS_APPROX(x, x_ref);
    218 
    219   // check covariance
    220   covfac = fnorm*fnorm/(m-n);
    221   internal::covar(lm.matrixR(), lm.permutation().indices()); // TODO : move this as a function of lm
    222 
    223   MatrixXd cov_ref(n,n);
    224   cov_ref <<
    225       0.0001531202,   0.002869942,  -0.002656662,
    226       0.002869942,    0.09480937,   -0.09098997,
    227       -0.002656662,   -0.09098997,    0.08778729;
    228 
    229 //  std::cout << fjac*covfac << std::endl;
    230 
    231   MatrixXd cov;
    232   cov =  covfac*lm.matrixR().topLeftCorner<n,n>();
    233   VERIFY_IS_APPROX( cov, cov_ref);
    234   // TODO: why isn't this allowed ? :
    235   // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref);
    236 }
    237 
    238 struct chwirut2_functor : DenseFunctor<double>
    239 {
    240     chwirut2_functor(void) : DenseFunctor<double>(3,54) {}
    241     static const double m_x[54];
    242     static const double m_y[54];
    243     int operator()(const VectorXd &b, VectorXd &fvec)
    244     {
    245         int i;
    246 
    247         assert(b.size()==3);
    248         assert(fvec.size()==54);
    249         for(i=0; i<54; i++) {
    250             double x = m_x[i];
    251             fvec[i] = exp(-b[0]*x)/(b[1]+b[2]*x) - m_y[i];
    252         }
    253         return 0;
    254     }
    255     int df(const VectorXd &b, MatrixXd &fjac)
    256     {
    257         assert(b.size()==3);
    258         assert(fjac.rows()==54);
    259         assert(fjac.cols()==3);
    260         for(int i=0; i<54; i++) {
    261             double x = m_x[i];
    262             double factor = 1./(b[1]+b[2]*x);
    263             double e = exp(-b[0]*x);
    264             fjac(i,0) = -x*e*factor;
    265             fjac(i,1) = -e*factor*factor;
    266             fjac(i,2) = -x*e*factor*factor;
    267         }
    268         return 0;
    269     }
    270 };
    271 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};
    272 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  };
    273 
    274 // http://www.itl.nist.gov/div898/strd/nls/data/chwirut2.shtml
    275 void testNistChwirut2(void)
    276 {
    277   const int n=3;
    278   int info;
    279 
    280   VectorXd x(n);
    281 
    282   /*
    283    * First try
    284    */
    285   x<< 0.1, 0.01, 0.02;
    286   // do the computation
    287   chwirut2_functor functor;
    288   LevenbergMarquardt<chwirut2_functor> lm(functor);
    289   info = lm.minimize(x);
    290 
    291   // check return value
    292   VERIFY_IS_EQUAL(info, 1);
    293 //   VERIFY_IS_EQUAL(lm.nfev(), 10);
    294   VERIFY_IS_EQUAL(lm.njev(), 8);
    295   // check norm^2
    296   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.1304802941E+02);
    297   // check x
    298   VERIFY_IS_APPROX(x[0], 1.6657666537E-01);
    299   VERIFY_IS_APPROX(x[1], 5.1653291286E-03);
    300   VERIFY_IS_APPROX(x[2], 1.2150007096E-02);
    301 
    302   /*
    303    * Second try
    304    */
    305   x<< 0.15, 0.008, 0.010;
    306   // do the computation
    307   lm.resetParameters();
    308   lm.setFtol(1.E6*NumTraits<double>::epsilon());
    309   lm.setXtol(1.E6*NumTraits<double>::epsilon());
    310   info = lm.minimize(x);
    311 
    312   // check return value
    313   VERIFY_IS_EQUAL(info, 1);
    314 //   VERIFY_IS_EQUAL(lm.nfev(), 7);
    315   VERIFY_IS_EQUAL(lm.njev(), 6);
    316   // check norm^2
    317   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.1304802941E+02);
    318   // check x
    319   VERIFY_IS_APPROX(x[0], 1.6657666537E-01);
    320   VERIFY_IS_APPROX(x[1], 5.1653291286E-03);
    321   VERIFY_IS_APPROX(x[2], 1.2150007096E-02);
    322 }
    323 
    324 
    325 struct misra1a_functor : DenseFunctor<double>
    326 {
    327     misra1a_functor(void) : DenseFunctor<double>(2,14) {}
    328     static const double m_x[14];
    329     static const double m_y[14];
    330     int operator()(const VectorXd &b, VectorXd &fvec)
    331     {
    332         assert(b.size()==2);
    333         assert(fvec.size()==14);
    334         for(int i=0; i<14; i++) {
    335             fvec[i] = b[0]*(1.-exp(-b[1]*m_x[i])) - m_y[i] ;
    336         }
    337         return 0;
    338     }
    339     int df(const VectorXd &b, MatrixXd &fjac)
    340     {
    341         assert(b.size()==2);
    342         assert(fjac.rows()==14);
    343         assert(fjac.cols()==2);
    344         for(int i=0; i<14; i++) {
    345             fjac(i,0) = (1.-exp(-b[1]*m_x[i]));
    346             fjac(i,1) = (b[0]*m_x[i]*exp(-b[1]*m_x[i]));
    347         }
    348         return 0;
    349     }
    350 };
    351 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};
    352 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};
    353 
    354 // http://www.itl.nist.gov/div898/strd/nls/data/misra1a.shtml
    355 void testNistMisra1a(void)
    356 {
    357   const int n=2;
    358   int info;
    359 
    360   VectorXd x(n);
    361 
    362   /*
    363    * First try
    364    */
    365   x<< 500., 0.0001;
    366   // do the computation
    367   misra1a_functor functor;
    368   LevenbergMarquardt<misra1a_functor> lm(functor);
    369   info = lm.minimize(x);
    370 
    371   // check return value
    372   VERIFY_IS_EQUAL(info, 1);
    373   VERIFY_IS_EQUAL(lm.nfev(), 19);
    374   VERIFY_IS_EQUAL(lm.njev(), 15);
    375   // check norm^2
    376   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.2455138894E-01);
    377   // check x
    378   VERIFY_IS_APPROX(x[0], 2.3894212918E+02);
    379   VERIFY_IS_APPROX(x[1], 5.5015643181E-04);
    380 
    381   /*
    382    * Second try
    383    */
    384   x<< 250., 0.0005;
    385   // do the computation
    386   info = lm.minimize(x);
    387 
    388   // check return value
    389   VERIFY_IS_EQUAL(info, 1);
    390   VERIFY_IS_EQUAL(lm.nfev(), 5);
    391   VERIFY_IS_EQUAL(lm.njev(), 4);
    392   // check norm^2
    393   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.2455138894E-01);
    394   // check x
    395   VERIFY_IS_APPROX(x[0], 2.3894212918E+02);
    396   VERIFY_IS_APPROX(x[1], 5.5015643181E-04);
    397 }
    398 
    399 struct hahn1_functor : DenseFunctor<double>
    400 {
    401     hahn1_functor(void) : DenseFunctor<double>(7,236) {}
    402     static const double m_x[236];
    403     int operator()(const VectorXd &b, VectorXd &fvec)
    404     {
    405         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 ,
    406         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 ,
    407 12.596E0 ,
    408 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 };
    409 
    410         //        int called=0; printf("call hahn1_functor with  iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++;
    411 
    412         assert(b.size()==7);
    413         assert(fvec.size()==236);
    414         for(int i=0; i<236; i++) {
    415             double x=m_x[i], xx=x*x, xxx=xx*x;
    416             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];
    417         }
    418         return 0;
    419     }
    420 
    421     int df(const VectorXd &b, MatrixXd &fjac)
    422     {
    423         assert(b.size()==7);
    424         assert(fjac.rows()==236);
    425         assert(fjac.cols()==7);
    426         for(int i=0; i<236; i++) {
    427             double x=m_x[i], xx=x*x, xxx=xx*x;
    428             double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx);
    429             fjac(i,0) = 1.*fact;
    430             fjac(i,1) = x*fact;
    431             fjac(i,2) = xx*fact;
    432             fjac(i,3) = xxx*fact;
    433             fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact;
    434             fjac(i,4) = x*fact;
    435             fjac(i,5) = xx*fact;
    436             fjac(i,6) = xxx*fact;
    437         }
    438         return 0;
    439     }
    440 };
    441 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 ,
    442 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 ,
    443 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};
    444 
    445 // http://www.itl.nist.gov/div898/strd/nls/data/hahn1.shtml
    446 void testNistHahn1(void)
    447 {
    448   const int  n=7;
    449   int info;
    450 
    451   VectorXd x(n);
    452 
    453   /*
    454    * First try
    455    */
    456   x<< 10., -1., .05, -.00001, -.05, .001, -.000001;
    457   // do the computation
    458   hahn1_functor functor;
    459   LevenbergMarquardt<hahn1_functor> lm(functor);
    460   info = lm.minimize(x);
    461 
    462   // check return value
    463   VERIFY_IS_EQUAL(info, 1);
    464   VERIFY_IS_EQUAL(lm.nfev(), 11);
    465   VERIFY_IS_EQUAL(lm.njev(), 10);
    466   // check norm^2
    467   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.5324382854E+00);
    468   // check x
    469   VERIFY_IS_APPROX(x[0], 1.0776351733E+00);
    470   VERIFY_IS_APPROX(x[1],-1.2269296921E-01);
    471   VERIFY_IS_APPROX(x[2], 4.0863750610E-03);
    472   VERIFY_IS_APPROX(x[3],-1.426264e-06); // shoulde be : -1.4262662514E-06
    473   VERIFY_IS_APPROX(x[4],-5.7609940901E-03);
    474   VERIFY_IS_APPROX(x[5], 2.4053735503E-04);
    475   VERIFY_IS_APPROX(x[6],-1.2314450199E-07);
    476 
    477   /*
    478    * Second try
    479    */
    480   x<< .1, -.1, .005, -.000001, -.005, .0001, -.0000001;
    481   // do the computation
    482   info = lm.minimize(x);
    483 
    484   // check return value
    485   VERIFY_IS_EQUAL(info, 1);
    486 //   VERIFY_IS_EQUAL(lm.nfev(), 11);
    487   VERIFY_IS_EQUAL(lm.njev(), 10);
    488   // check norm^2
    489   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.5324382854E+00);
    490   // check x
    491   VERIFY_IS_APPROX(x[0], 1.077640); // should be :  1.0776351733E+00
    492   VERIFY_IS_APPROX(x[1], -0.1226933); // should be : -1.2269296921E-01
    493   VERIFY_IS_APPROX(x[2], 0.004086383); // should be : 4.0863750610E-03
    494   VERIFY_IS_APPROX(x[3], -1.426277e-06); // shoulde be : -1.4262662514E-06
    495   VERIFY_IS_APPROX(x[4],-5.7609940901E-03);
    496   VERIFY_IS_APPROX(x[5], 0.00024053772); // should be : 2.4053735503E-04
    497   VERIFY_IS_APPROX(x[6], -1.231450e-07); // should be : -1.2314450199E-07
    498 
    499 }
    500 
    501 struct misra1d_functor : DenseFunctor<double>
    502 {
    503     misra1d_functor(void) : DenseFunctor<double>(2,14) {}
    504     static const double x[14];
    505     static const double y[14];
    506     int operator()(const VectorXd &b, VectorXd &fvec)
    507     {
    508         assert(b.size()==2);
    509         assert(fvec.size()==14);
    510         for(int i=0; i<14; i++) {
    511             fvec[i] = b[0]*b[1]*x[i]/(1.+b[1]*x[i]) - y[i];
    512         }
    513         return 0;
    514     }
    515     int df(const VectorXd &b, MatrixXd &fjac)
    516     {
    517         assert(b.size()==2);
    518         assert(fjac.rows()==14);
    519         assert(fjac.cols()==2);
    520         for(int i=0; i<14; i++) {
    521             double den = 1.+b[1]*x[i];
    522             fjac(i,0) = b[1]*x[i] / den;
    523             fjac(i,1) = b[0]*x[i]*(den-b[1]*x[i])/den/den;
    524         }
    525         return 0;
    526     }
    527 };
    528 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};
    529 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};
    530 
    531 // http://www.itl.nist.gov/div898/strd/nls/data/misra1d.shtml
    532 void testNistMisra1d(void)
    533 {
    534   const int n=2;
    535   int info;
    536 
    537   VectorXd x(n);
    538 
    539   /*
    540    * First try
    541    */
    542   x<< 500., 0.0001;
    543   // do the computation
    544   misra1d_functor functor;
    545   LevenbergMarquardt<misra1d_functor> lm(functor);
    546   info = lm.minimize(x);
    547 
    548   // check return value
    549   VERIFY_IS_EQUAL(info, 1);
    550   VERIFY_IS_EQUAL(lm.nfev(), 9);
    551   VERIFY_IS_EQUAL(lm.njev(), 7);
    552   // check norm^2
    553   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6419295283E-02);
    554   // check x
    555   VERIFY_IS_APPROX(x[0], 4.3736970754E+02);
    556   VERIFY_IS_APPROX(x[1], 3.0227324449E-04);
    557 
    558   /*
    559    * Second try
    560    */
    561   x<< 450., 0.0003;
    562   // do the computation
    563   info = lm.minimize(x);
    564 
    565   // check return value
    566   VERIFY_IS_EQUAL(info, 1);
    567   VERIFY_IS_EQUAL(lm.nfev(), 4);
    568   VERIFY_IS_EQUAL(lm.njev(), 3);
    569   // check norm^2
    570   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6419295283E-02);
    571   // check x
    572   VERIFY_IS_APPROX(x[0], 4.3736970754E+02);
    573   VERIFY_IS_APPROX(x[1], 3.0227324449E-04);
    574 }
    575 
    576 
    577 struct lanczos1_functor : DenseFunctor<double>
    578 {
    579     lanczos1_functor(void) : DenseFunctor<double>(6,24) {}
    580     static const double x[24];
    581     static const double y[24];
    582     int operator()(const VectorXd &b, VectorXd &fvec)
    583     {
    584         assert(b.size()==6);
    585         assert(fvec.size()==24);
    586         for(int i=0; i<24; i++)
    587             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];
    588         return 0;
    589     }
    590     int df(const VectorXd &b, MatrixXd &fjac)
    591     {
    592         assert(b.size()==6);
    593         assert(fjac.rows()==24);
    594         assert(fjac.cols()==6);
    595         for(int i=0; i<24; i++) {
    596             fjac(i,0) = exp(-b[1]*x[i]);
    597             fjac(i,1) = -b[0]*x[i]*exp(-b[1]*x[i]);
    598             fjac(i,2) = exp(-b[3]*x[i]);
    599             fjac(i,3) = -b[2]*x[i]*exp(-b[3]*x[i]);
    600             fjac(i,4) = exp(-b[5]*x[i]);
    601             fjac(i,5) = -b[4]*x[i]*exp(-b[5]*x[i]);
    602         }
    603         return 0;
    604     }
    605 };
    606 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 };
    607 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 };
    608 
    609 // http://www.itl.nist.gov/div898/strd/nls/data/lanczos1.shtml
    610 void testNistLanczos1(void)
    611 {
    612   const int n=6;
    613   int info;
    614 
    615   VectorXd x(n);
    616 
    617   /*
    618    * First try
    619    */
    620   x<< 1.2, 0.3, 5.6, 5.5, 6.5, 7.6;
    621   // do the computation
    622   lanczos1_functor functor;
    623   LevenbergMarquardt<lanczos1_functor> lm(functor);
    624   info = lm.minimize(x);
    625 
    626   // check return value
    627   VERIFY_IS_EQUAL(info, 2);
    628   VERIFY_IS_EQUAL(lm.nfev(), 79);
    629   VERIFY_IS_EQUAL(lm.njev(), 72);
    630   // check norm^2
    631 //   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.430899764097e-25);  // should be 1.4307867721E-25, but nist results are on 128-bit floats
    632   // check x
    633   VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
    634   VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
    635   VERIFY_IS_APPROX(x[2], 8.6070000013E-01);
    636   VERIFY_IS_APPROX(x[3], 3.0000000002E+00);
    637   VERIFY_IS_APPROX(x[4], 1.5575999998E+00);
    638   VERIFY_IS_APPROX(x[5], 5.0000000001E+00);
    639 
    640   /*
    641    * Second try
    642    */
    643   x<< 0.5, 0.7, 3.6, 4.2, 4., 6.3;
    644   // do the computation
    645   info = lm.minimize(x);
    646 
    647   // check return value
    648   VERIFY_IS_EQUAL(info, 2);
    649   VERIFY_IS_EQUAL(lm.nfev(), 9);
    650   VERIFY_IS_EQUAL(lm.njev(), 8);
    651   // check norm^2
    652 //   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.428595533845e-25);  // should be 1.4307867721E-25, but nist results are on 128-bit floats
    653   // check x
    654   VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
    655   VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
    656   VERIFY_IS_APPROX(x[2], 8.6070000013E-01);
    657   VERIFY_IS_APPROX(x[3], 3.0000000002E+00);
    658   VERIFY_IS_APPROX(x[4], 1.5575999998E+00);
    659   VERIFY_IS_APPROX(x[5], 5.0000000001E+00);
    660 
    661 }
    662 
    663 struct rat42_functor : DenseFunctor<double>
    664 {
    665     rat42_functor(void) : DenseFunctor<double>(3,9) {}
    666     static const double x[9];
    667     static const double y[9];
    668     int operator()(const VectorXd &b, VectorXd &fvec)
    669     {
    670         assert(b.size()==3);
    671         assert(fvec.size()==9);
    672         for(int i=0; i<9; i++) {
    673             fvec[i] = b[0] / (1.+exp(b[1]-b[2]*x[i])) - y[i];
    674         }
    675         return 0;
    676     }
    677 
    678     int df(const VectorXd &b, MatrixXd &fjac)
    679     {
    680         assert(b.size()==3);
    681         assert(fjac.rows()==9);
    682         assert(fjac.cols()==3);
    683         for(int i=0; i<9; i++) {
    684             double e = exp(b[1]-b[2]*x[i]);
    685             fjac(i,0) = 1./(1.+e);
    686             fjac(i,1) = -b[0]*e/(1.+e)/(1.+e);
    687             fjac(i,2) = +b[0]*e*x[i]/(1.+e)/(1.+e);
    688         }
    689         return 0;
    690     }
    691 };
    692 const double rat42_functor::x[9] = { 9.000E0, 14.000E0, 21.000E0, 28.000E0, 42.000E0, 57.000E0, 63.000E0, 70.000E0, 79.000E0 };
    693 const double rat42_functor::y[9] = { 8.930E0 ,10.800E0 ,18.590E0 ,22.330E0 ,39.350E0 ,56.110E0 ,61.730E0 ,64.620E0 ,67.080E0 };
    694 
    695 // http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky2.shtml
    696 void testNistRat42(void)
    697 {
    698   const int n=3;
    699   int info;
    700 
    701   VectorXd x(n);
    702 
    703   /*
    704    * First try
    705    */
    706   x<< 100., 1., 0.1;
    707   // do the computation
    708   rat42_functor functor;
    709   LevenbergMarquardt<rat42_functor> lm(functor);
    710   info = lm.minimize(x);
    711 
    712   // check return value
    713   VERIFY_IS_EQUAL(info, 1);
    714   VERIFY_IS_EQUAL(lm.nfev(), 10);
    715   VERIFY_IS_EQUAL(lm.njev(), 8);
    716   // check norm^2
    717   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.0565229338E+00);
    718   // check x
    719   VERIFY_IS_APPROX(x[0], 7.2462237576E+01);
    720   VERIFY_IS_APPROX(x[1], 2.6180768402E+00);
    721   VERIFY_IS_APPROX(x[2], 6.7359200066E-02);
    722 
    723   /*
    724    * Second try
    725    */
    726   x<< 75., 2.5, 0.07;
    727   // do the computation
    728   info = lm.minimize(x);
    729 
    730   // check return value
    731   VERIFY_IS_EQUAL(info, 1);
    732   VERIFY_IS_EQUAL(lm.nfev(), 6);
    733   VERIFY_IS_EQUAL(lm.njev(), 5);
    734   // check norm^2
    735   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.0565229338E+00);
    736   // check x
    737   VERIFY_IS_APPROX(x[0], 7.2462237576E+01);
    738   VERIFY_IS_APPROX(x[1], 2.6180768402E+00);
    739   VERIFY_IS_APPROX(x[2], 6.7359200066E-02);
    740 }
    741 
    742 struct MGH10_functor : DenseFunctor<double>
    743 {
    744     MGH10_functor(void) : DenseFunctor<double>(3,16) {}
    745     static const double x[16];
    746     static const double y[16];
    747     int operator()(const VectorXd &b, VectorXd &fvec)
    748     {
    749         assert(b.size()==3);
    750         assert(fvec.size()==16);
    751         for(int i=0; i<16; i++)
    752             fvec[i] =  b[0] * exp(b[1]/(x[i]+b[2])) - y[i];
    753         return 0;
    754     }
    755     int df(const VectorXd &b, MatrixXd &fjac)
    756     {
    757         assert(b.size()==3);
    758         assert(fjac.rows()==16);
    759         assert(fjac.cols()==3);
    760         for(int i=0; i<16; i++) {
    761             double factor = 1./(x[i]+b[2]);
    762             double e = exp(b[1]*factor);
    763             fjac(i,0) = e;
    764             fjac(i,1) = b[0]*factor*e;
    765             fjac(i,2) = -b[1]*b[0]*factor*factor*e;
    766         }
    767         return 0;
    768     }
    769 };
    770 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 };
    771 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 };
    772 
    773 // http://www.itl.nist.gov/div898/strd/nls/data/mgh10.shtml
    774 void testNistMGH10(void)
    775 {
    776   const int n=3;
    777   int info;
    778 
    779   VectorXd x(n);
    780 
    781   /*
    782    * First try
    783    */
    784   x<< 2., 400000., 25000.;
    785   // do the computation
    786   MGH10_functor functor;
    787   LevenbergMarquardt<MGH10_functor> lm(functor);
    788   info = lm.minimize(x);
    789 
    790   // check return value
    791   VERIFY_IS_EQUAL(info, 1);
    792   VERIFY_IS_EQUAL(lm.nfev(), 284 );
    793   VERIFY_IS_EQUAL(lm.njev(), 249 );
    794   // check norm^2
    795   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7945855171E+01);
    796   // check x
    797   VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
    798   VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
    799   VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
    800 
    801   /*
    802    * Second try
    803    */
    804   x<< 0.02, 4000., 250.;
    805   // do the computation
    806   info = lm.minimize(x);
    807 
    808   // check return value
    809   VERIFY_IS_EQUAL(info, 1);
    810   VERIFY_IS_EQUAL(lm.nfev(), 126);
    811   VERIFY_IS_EQUAL(lm.njev(), 116);
    812   // check norm^2
    813   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7945855171E+01);
    814   // check x
    815   VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
    816   VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
    817   VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
    818 }
    819 
    820 
    821 struct BoxBOD_functor : DenseFunctor<double>
    822 {
    823     BoxBOD_functor(void) : DenseFunctor<double>(2,6) {}
    824     static const double x[6];
    825     int operator()(const VectorXd &b, VectorXd &fvec)
    826     {
    827         static const double y[6] = { 109., 149., 149., 191., 213., 224. };
    828         assert(b.size()==2);
    829         assert(fvec.size()==6);
    830         for(int i=0; i<6; i++)
    831             fvec[i] =  b[0]*(1.-exp(-b[1]*x[i])) - y[i];
    832         return 0;
    833     }
    834     int df(const VectorXd &b, MatrixXd &fjac)
    835     {
    836         assert(b.size()==2);
    837         assert(fjac.rows()==6);
    838         assert(fjac.cols()==2);
    839         for(int i=0; i<6; i++) {
    840             double e = exp(-b[1]*x[i]);
    841             fjac(i,0) = 1.-e;
    842             fjac(i,1) = b[0]*x[i]*e;
    843         }
    844         return 0;
    845     }
    846 };
    847 const double BoxBOD_functor::x[6] = { 1., 2., 3., 5., 7., 10. };
    848 
    849 // http://www.itl.nist.gov/div898/strd/nls/data/boxbod.shtml
    850 void testNistBoxBOD(void)
    851 {
    852   const int n=2;
    853   int info;
    854 
    855   VectorXd x(n);
    856 
    857   /*
    858    * First try
    859    */
    860   x<< 1., 1.;
    861   // do the computation
    862   BoxBOD_functor functor;
    863   LevenbergMarquardt<BoxBOD_functor> lm(functor);
    864   lm.setFtol(1.E6*NumTraits<double>::epsilon());
    865   lm.setXtol(1.E6*NumTraits<double>::epsilon());
    866   lm.setFactor(10);
    867   info = lm.minimize(x);
    868 
    869   // check return value
    870   VERIFY_IS_EQUAL(info, 1);
    871   VERIFY_IS_EQUAL(lm.nfev(), 31);
    872   VERIFY_IS_EQUAL(lm.njev(), 25);
    873   // check norm^2
    874   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.1680088766E+03);
    875   // check x
    876   VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
    877   VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
    878 
    879   /*
    880    * Second try
    881    */
    882   x<< 100., 0.75;
    883   // do the computation
    884   lm.resetParameters();
    885   lm.setFtol(NumTraits<double>::epsilon());
    886   lm.setXtol( NumTraits<double>::epsilon());
    887   info = lm.minimize(x);
    888 
    889   // check return value
    890   VERIFY_IS_EQUAL(info, 1);
    891   VERIFY_IS_EQUAL(lm.nfev(), 15 );
    892   VERIFY_IS_EQUAL(lm.njev(), 14 );
    893   // check norm^2
    894   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.1680088766E+03);
    895   // check x
    896   VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
    897   VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
    898 }
    899 
    900 struct MGH17_functor : DenseFunctor<double>
    901 {
    902     MGH17_functor(void) : DenseFunctor<double>(5,33) {}
    903     static const double x[33];
    904     static const double y[33];
    905     int operator()(const VectorXd &b, VectorXd &fvec)
    906     {
    907         assert(b.size()==5);
    908         assert(fvec.size()==33);
    909         for(int i=0; i<33; i++)
    910             fvec[i] =  b[0] + b[1]*exp(-b[3]*x[i]) +  b[2]*exp(-b[4]*x[i]) - y[i];
    911         return 0;
    912     }
    913     int df(const VectorXd &b, MatrixXd &fjac)
    914     {
    915         assert(b.size()==5);
    916         assert(fjac.rows()==33);
    917         assert(fjac.cols()==5);
    918         for(int i=0; i<33; i++) {
    919             fjac(i,0) = 1.;
    920             fjac(i,1) = exp(-b[3]*x[i]);
    921             fjac(i,2) = exp(-b[4]*x[i]);
    922             fjac(i,3) = -x[i]*b[1]*exp(-b[3]*x[i]);
    923             fjac(i,4) = -x[i]*b[2]*exp(-b[4]*x[i]);
    924         }
    925         return 0;
    926     }
    927 };
    928 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 };
    929 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 };
    930 
    931 // http://www.itl.nist.gov/div898/strd/nls/data/mgh17.shtml
    932 void testNistMGH17(void)
    933 {
    934   const int n=5;
    935   int info;
    936 
    937   VectorXd x(n);
    938 
    939   /*
    940    * First try
    941    */
    942   x<< 50., 150., -100., 1., 2.;
    943   // do the computation
    944   MGH17_functor functor;
    945   LevenbergMarquardt<MGH17_functor> lm(functor);
    946   lm.setFtol(NumTraits<double>::epsilon());
    947   lm.setXtol(NumTraits<double>::epsilon());
    948   lm.setMaxfev(1000);
    949   info = lm.minimize(x);
    950 
    951   // check return value
    952 //   VERIFY_IS_EQUAL(info, 2);  //FIXME Use (lm.info() == Success)
    953 //   VERIFY_IS_EQUAL(lm.nfev(), 602 );
    954   VERIFY_IS_EQUAL(lm.njev(), 545 );
    955   // check norm^2
    956   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.4648946975E-05);
    957   // check x
    958   VERIFY_IS_APPROX(x[0], 3.7541005211E-01);
    959   VERIFY_IS_APPROX(x[1], 1.9358469127E+00);
    960   VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
    961   VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
    962   VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
    963 
    964   /*
    965    * Second try
    966    */
    967   x<< 0.5  ,1.5  ,-1   ,0.01 ,0.02;
    968   // do the computation
    969   lm.resetParameters();
    970   info = lm.minimize(x);
    971 
    972   // check return value
    973   VERIFY_IS_EQUAL(info, 1);
    974   VERIFY_IS_EQUAL(lm.nfev(), 18);
    975   VERIFY_IS_EQUAL(lm.njev(), 15);
    976   // check norm^2
    977   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.4648946975E-05);
    978   // check x
    979   VERIFY_IS_APPROX(x[0], 3.7541005211E-01);
    980   VERIFY_IS_APPROX(x[1], 1.9358469127E+00);
    981   VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
    982   VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
    983   VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
    984 }
    985 
    986 struct MGH09_functor : DenseFunctor<double>
    987 {
    988     MGH09_functor(void) : DenseFunctor<double>(4,11) {}
    989     static const double _x[11];
    990     static const double y[11];
    991     int operator()(const VectorXd &b, VectorXd &fvec)
    992     {
    993         assert(b.size()==4);
    994         assert(fvec.size()==11);
    995         for(int i=0; i<11; i++) {
    996             double x = _x[i], xx=x*x;
    997             fvec[i] = b[0]*(xx+x*b[1])/(xx+x*b[2]+b[3]) - y[i];
    998         }
    999         return 0;
   1000     }
   1001     int df(const VectorXd &b, MatrixXd &fjac)
   1002     {
   1003         assert(b.size()==4);
   1004         assert(fjac.rows()==11);
   1005         assert(fjac.cols()==4);
   1006         for(int i=0; i<11; i++) {
   1007             double x = _x[i], xx=x*x;
   1008             double factor = 1./(xx+x*b[2]+b[3]);
   1009             fjac(i,0) = (xx+x*b[1]) * factor;
   1010             fjac(i,1) = b[0]*x* factor;
   1011             fjac(i,2) = - b[0]*(xx+x*b[1]) * x * factor * factor;
   1012             fjac(i,3) = - b[0]*(xx+x*b[1]) * factor * factor;
   1013         }
   1014         return 0;
   1015     }
   1016 };
   1017 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 };
   1018 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 };
   1019 
   1020 // http://www.itl.nist.gov/div898/strd/nls/data/mgh09.shtml
   1021 void testNistMGH09(void)
   1022 {
   1023   const int n=4;
   1024   int info;
   1025 
   1026   VectorXd x(n);
   1027 
   1028   /*
   1029    * First try
   1030    */
   1031   x<< 25., 39, 41.5, 39.;
   1032   // do the computation
   1033   MGH09_functor functor;
   1034   LevenbergMarquardt<MGH09_functor> lm(functor);
   1035   lm.setMaxfev(1000);
   1036   info = lm.minimize(x);
   1037 
   1038   // check return value
   1039   VERIFY_IS_EQUAL(info, 1);
   1040   VERIFY_IS_EQUAL(lm.nfev(), 490 );
   1041   VERIFY_IS_EQUAL(lm.njev(), 376 );
   1042   // check norm^2
   1043   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 3.0750560385E-04);
   1044   // check x
   1045   VERIFY_IS_APPROX(x[0], 0.1928077089); // should be 1.9280693458E-01
   1046   VERIFY_IS_APPROX(x[1], 0.19126423573); // should be 1.9128232873E-01
   1047   VERIFY_IS_APPROX(x[2], 0.12305309914); // should be 1.2305650693E-01
   1048   VERIFY_IS_APPROX(x[3], 0.13605395375); // should be 1.3606233068E-01
   1049 
   1050   /*
   1051    * Second try
   1052    */
   1053   x<< 0.25, 0.39, 0.415, 0.39;
   1054   // do the computation
   1055   lm.resetParameters();
   1056   info = lm.minimize(x);
   1057 
   1058   // check return value
   1059   VERIFY_IS_EQUAL(info, 1);
   1060   VERIFY_IS_EQUAL(lm.nfev(), 18);
   1061   VERIFY_IS_EQUAL(lm.njev(), 16);
   1062   // check norm^2
   1063   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 3.0750560385E-04);
   1064   // check x
   1065   VERIFY_IS_APPROX(x[0], 0.19280781); // should be 1.9280693458E-01
   1066   VERIFY_IS_APPROX(x[1], 0.19126265); // should be 1.9128232873E-01
   1067   VERIFY_IS_APPROX(x[2], 0.12305280); // should be 1.2305650693E-01
   1068   VERIFY_IS_APPROX(x[3], 0.13605322); // should be 1.3606233068E-01
   1069 }
   1070 
   1071 
   1072 
   1073 struct Bennett5_functor : DenseFunctor<double>
   1074 {
   1075     Bennett5_functor(void) : DenseFunctor<double>(3,154) {}
   1076     static const double x[154];
   1077     static const double y[154];
   1078     int operator()(const VectorXd &b, VectorXd &fvec)
   1079     {
   1080         assert(b.size()==3);
   1081         assert(fvec.size()==154);
   1082         for(int i=0; i<154; i++)
   1083             fvec[i] = b[0]* pow(b[1]+x[i],-1./b[2]) - y[i];
   1084         return 0;
   1085     }
   1086     int df(const VectorXd &b, MatrixXd &fjac)
   1087     {
   1088         assert(b.size()==3);
   1089         assert(fjac.rows()==154);
   1090         assert(fjac.cols()==3);
   1091         for(int i=0; i<154; i++) {
   1092             double e = pow(b[1]+x[i],-1./b[2]);
   1093             fjac(i,0) = e;
   1094             fjac(i,1) = - b[0]*e/b[2]/(b[1]+x[i]);
   1095             fjac(i,2) = b[0]*e*log(b[1]+x[i])/b[2]/b[2];
   1096         }
   1097         return 0;
   1098     }
   1099 };
   1100 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,
   1101 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 };
   1102 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
   1103 ,-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 ,
   1104 -31.827299E0 ,-31.821600E0 ,-31.818701E0 ,-31.812901E0 ,-31.809999E0 ,-31.807100E0 ,-31.801300E0 ,-31.798401E0 ,-31.795500E0 ,-31.789700E0 ,-31.786800E0 };
   1105 
   1106 // http://www.itl.nist.gov/div898/strd/nls/data/bennett5.shtml
   1107 void testNistBennett5(void)
   1108 {
   1109   const int  n=3;
   1110   int info;
   1111 
   1112   VectorXd x(n);
   1113 
   1114   /*
   1115    * First try
   1116    */
   1117   x<< -2000., 50., 0.8;
   1118   // do the computation
   1119   Bennett5_functor functor;
   1120   LevenbergMarquardt<Bennett5_functor> lm(functor);
   1121   lm.setMaxfev(1000);
   1122   info = lm.minimize(x);
   1123 
   1124   // check return value
   1125   VERIFY_IS_EQUAL(info, 1);
   1126   VERIFY_IS_EQUAL(lm.nfev(), 758);
   1127   VERIFY_IS_EQUAL(lm.njev(), 744);
   1128   // check norm^2
   1129   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.2404744073E-04);
   1130   // check x
   1131   VERIFY_IS_APPROX(x[0], -2.5235058043E+03);
   1132   VERIFY_IS_APPROX(x[1], 4.6736564644E+01);
   1133   VERIFY_IS_APPROX(x[2], 9.3218483193E-01);
   1134   /*
   1135    * Second try
   1136    */
   1137   x<< -1500., 45., 0.85;
   1138   // do the computation
   1139   lm.resetParameters();
   1140   info = lm.minimize(x);
   1141 
   1142   // check return value
   1143   VERIFY_IS_EQUAL(info, 1);
   1144   VERIFY_IS_EQUAL(lm.nfev(), 203);
   1145   VERIFY_IS_EQUAL(lm.njev(), 192);
   1146   // check norm^2
   1147   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.2404744073E-04);
   1148   // check x
   1149   VERIFY_IS_APPROX(x[0], -2523.3007865); // should be -2.5235058043E+03
   1150   VERIFY_IS_APPROX(x[1], 46.735705771); // should be 4.6736564644E+01);
   1151   VERIFY_IS_APPROX(x[2], 0.93219881891); // should be 9.3218483193E-01);
   1152 }
   1153 
   1154 struct thurber_functor : DenseFunctor<double>
   1155 {
   1156     thurber_functor(void) : DenseFunctor<double>(7,37) {}
   1157     static const double _x[37];
   1158     static const double _y[37];
   1159     int operator()(const VectorXd &b, VectorXd &fvec)
   1160     {
   1161         //        int called=0; printf("call hahn1_functor with  iflag=%d, called=%d\n", iflag, called); if (iflag==1) called++;
   1162         assert(b.size()==7);
   1163         assert(fvec.size()==37);
   1164         for(int i=0; i<37; i++) {
   1165             double x=_x[i], xx=x*x, xxx=xx*x;
   1166             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];
   1167         }
   1168         return 0;
   1169     }
   1170     int df(const VectorXd &b, MatrixXd &fjac)
   1171     {
   1172         assert(b.size()==7);
   1173         assert(fjac.rows()==37);
   1174         assert(fjac.cols()==7);
   1175         for(int i=0; i<37; i++) {
   1176             double x=_x[i], xx=x*x, xxx=xx*x;
   1177             double fact = 1./(1.+b[4]*x+b[5]*xx+b[6]*xxx);
   1178             fjac(i,0) = 1.*fact;
   1179             fjac(i,1) = x*fact;
   1180             fjac(i,2) = xx*fact;
   1181             fjac(i,3) = xxx*fact;
   1182             fact = - (b[0]+b[1]*x+b[2]*xx+b[3]*xxx) * fact * fact;
   1183             fjac(i,4) = x*fact;
   1184             fjac(i,5) = xx*fact;
   1185             fjac(i,6) = xxx*fact;
   1186         }
   1187         return 0;
   1188     }
   1189 };
   1190 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 };
   1191 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};
   1192 
   1193 // http://www.itl.nist.gov/div898/strd/nls/data/thurber.shtml
   1194 void testNistThurber(void)
   1195 {
   1196   const int n=7;
   1197   int info;
   1198 
   1199   VectorXd x(n);
   1200 
   1201   /*
   1202    * First try
   1203    */
   1204   x<< 1000 ,1000 ,400 ,40 ,0.7,0.3,0.0 ;
   1205   // do the computation
   1206   thurber_functor functor;
   1207   LevenbergMarquardt<thurber_functor> lm(functor);
   1208   lm.setFtol(1.E4*NumTraits<double>::epsilon());
   1209   lm.setXtol(1.E4*NumTraits<double>::epsilon());
   1210   info = lm.minimize(x);
   1211 
   1212   // check return value
   1213   VERIFY_IS_EQUAL(info, 1);
   1214   VERIFY_IS_EQUAL(lm.nfev(), 39);
   1215   VERIFY_IS_EQUAL(lm.njev(), 36);
   1216   // check norm^2
   1217   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6427082397E+03);
   1218   // check x
   1219   VERIFY_IS_APPROX(x[0], 1.2881396800E+03);
   1220   VERIFY_IS_APPROX(x[1], 1.4910792535E+03);
   1221   VERIFY_IS_APPROX(x[2], 5.8323836877E+02);
   1222   VERIFY_IS_APPROX(x[3], 7.5416644291E+01);
   1223   VERIFY_IS_APPROX(x[4], 9.6629502864E-01);
   1224   VERIFY_IS_APPROX(x[5], 3.9797285797E-01);
   1225   VERIFY_IS_APPROX(x[6], 4.9727297349E-02);
   1226 
   1227   /*
   1228    * Second try
   1229    */
   1230   x<< 1300 ,1500 ,500  ,75   ,1    ,0.4  ,0.05  ;
   1231   // do the computation
   1232   lm.resetParameters();
   1233   lm.setFtol(1.E4*NumTraits<double>::epsilon());
   1234   lm.setXtol(1.E4*NumTraits<double>::epsilon());
   1235   info = lm.minimize(x);
   1236 
   1237   // check return value
   1238   VERIFY_IS_EQUAL(info, 1);
   1239   VERIFY_IS_EQUAL(lm.nfev(), 29);
   1240   VERIFY_IS_EQUAL(lm.njev(), 28);
   1241   // check norm^2
   1242   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.6427082397E+03);
   1243   // check x
   1244   VERIFY_IS_APPROX(x[0], 1.2881396800E+03);
   1245   VERIFY_IS_APPROX(x[1], 1.4910792535E+03);
   1246   VERIFY_IS_APPROX(x[2], 5.8323836877E+02);
   1247   VERIFY_IS_APPROX(x[3], 7.5416644291E+01);
   1248   VERIFY_IS_APPROX(x[4], 9.6629502864E-01);
   1249   VERIFY_IS_APPROX(x[5], 3.9797285797E-01);
   1250   VERIFY_IS_APPROX(x[6], 4.9727297349E-02);
   1251 }
   1252 
   1253 struct rat43_functor : DenseFunctor<double>
   1254 {
   1255     rat43_functor(void) : DenseFunctor<double>(4,15) {}
   1256     static const double x[15];
   1257     static const double y[15];
   1258     int operator()(const VectorXd &b, VectorXd &fvec)
   1259     {
   1260         assert(b.size()==4);
   1261         assert(fvec.size()==15);
   1262         for(int i=0; i<15; i++)
   1263             fvec[i] = b[0] * pow(1.+exp(b[1]-b[2]*x[i]),-1./b[3]) - y[i];
   1264         return 0;
   1265     }
   1266     int df(const VectorXd &b, MatrixXd &fjac)
   1267     {
   1268         assert(b.size()==4);
   1269         assert(fjac.rows()==15);
   1270         assert(fjac.cols()==4);
   1271         for(int i=0; i<15; i++) {
   1272             double e = exp(b[1]-b[2]*x[i]);
   1273             double power = -1./b[3];
   1274             fjac(i,0) = pow(1.+e, power);
   1275             fjac(i,1) = power*b[0]*e*pow(1.+e, power-1.);
   1276             fjac(i,2) = -power*b[0]*e*x[i]*pow(1.+e, power-1.);
   1277             fjac(i,3) = b[0]*power*power*log(1.+e)*pow(1.+e, power);
   1278         }
   1279         return 0;
   1280     }
   1281 };
   1282 const double rat43_functor::x[15] = { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15. };
   1283 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 };
   1284 
   1285 // http://www.itl.nist.gov/div898/strd/nls/data/ratkowsky3.shtml
   1286 void testNistRat43(void)
   1287 {
   1288   const int n=4;
   1289   int info;
   1290 
   1291   VectorXd x(n);
   1292 
   1293   /*
   1294    * First try
   1295    */
   1296   x<< 100., 10., 1., 1.;
   1297   // do the computation
   1298   rat43_functor functor;
   1299   LevenbergMarquardt<rat43_functor> lm(functor);
   1300   lm.setFtol(1.E6*NumTraits<double>::epsilon());
   1301   lm.setXtol(1.E6*NumTraits<double>::epsilon());
   1302   info = lm.minimize(x);
   1303 
   1304   // check return value
   1305   VERIFY_IS_EQUAL(info, 1);
   1306   VERIFY_IS_EQUAL(lm.nfev(), 27);
   1307   VERIFY_IS_EQUAL(lm.njev(), 20);
   1308   // check norm^2
   1309   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7864049080E+03);
   1310   // check x
   1311   VERIFY_IS_APPROX(x[0], 6.9964151270E+02);
   1312   VERIFY_IS_APPROX(x[1], 5.2771253025E+00);
   1313   VERIFY_IS_APPROX(x[2], 7.5962938329E-01);
   1314   VERIFY_IS_APPROX(x[3], 1.2792483859E+00);
   1315 
   1316   /*
   1317    * Second try
   1318    */
   1319   x<< 700., 5., 0.75, 1.3;
   1320   // do the computation
   1321   lm.resetParameters();
   1322   lm.setFtol(1.E5*NumTraits<double>::epsilon());
   1323   lm.setXtol(1.E5*NumTraits<double>::epsilon());
   1324   info = lm.minimize(x);
   1325 
   1326   // check return value
   1327   VERIFY_IS_EQUAL(info, 1);
   1328   VERIFY_IS_EQUAL(lm.nfev(), 9);
   1329   VERIFY_IS_EQUAL(lm.njev(), 8);
   1330   // check norm^2
   1331   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7864049080E+03);
   1332   // check x
   1333   VERIFY_IS_APPROX(x[0], 6.9964151270E+02);
   1334   VERIFY_IS_APPROX(x[1], 5.2771253025E+00);
   1335   VERIFY_IS_APPROX(x[2], 7.5962938329E-01);
   1336   VERIFY_IS_APPROX(x[3], 1.2792483859E+00);
   1337 }
   1338 
   1339 
   1340 
   1341 struct eckerle4_functor : DenseFunctor<double>
   1342 {
   1343     eckerle4_functor(void) : DenseFunctor<double>(3,35) {}
   1344     static const double x[35];
   1345     static const double y[35];
   1346     int operator()(const VectorXd &b, VectorXd &fvec)
   1347     {
   1348         assert(b.size()==3);
   1349         assert(fvec.size()==35);
   1350         for(int i=0; i<35; i++)
   1351             fvec[i] = b[0]/b[1] * exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/(b[1]*b[1])) - y[i];
   1352         return 0;
   1353     }
   1354     int df(const VectorXd &b, MatrixXd &fjac)
   1355     {
   1356         assert(b.size()==3);
   1357         assert(fjac.rows()==35);
   1358         assert(fjac.cols()==3);
   1359         for(int i=0; i<35; i++) {
   1360             double b12 = b[1]*b[1];
   1361             double e = exp(-0.5*(x[i]-b[2])*(x[i]-b[2])/b12);
   1362             fjac(i,0) = e / b[1];
   1363             fjac(i,1) = ((x[i]-b[2])*(x[i]-b[2])/b12-1.) * b[0]*e/b12;
   1364             fjac(i,2) = (x[i]-b[2])*e*b[0]/b[1]/b12;
   1365         }
   1366         return 0;
   1367     }
   1368 };
   1369 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};
   1370 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 };
   1371 
   1372 // http://www.itl.nist.gov/div898/strd/nls/data/eckerle4.shtml
   1373 void testNistEckerle4(void)
   1374 {
   1375   const int n=3;
   1376   int info;
   1377 
   1378   VectorXd x(n);
   1379 
   1380   /*
   1381    * First try
   1382    */
   1383   x<< 1., 10., 500.;
   1384   // do the computation
   1385   eckerle4_functor functor;
   1386   LevenbergMarquardt<eckerle4_functor> lm(functor);
   1387   info = lm.minimize(x);
   1388 
   1389   // check return value
   1390   VERIFY_IS_EQUAL(info, 1);
   1391   VERIFY_IS_EQUAL(lm.nfev(), 18);
   1392   VERIFY_IS_EQUAL(lm.njev(), 15);
   1393   // check norm^2
   1394   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.4635887487E-03);
   1395   // check x
   1396   VERIFY_IS_APPROX(x[0], 1.5543827178);
   1397   VERIFY_IS_APPROX(x[1], 4.0888321754);
   1398   VERIFY_IS_APPROX(x[2], 4.5154121844E+02);
   1399 
   1400   /*
   1401    * Second try
   1402    */
   1403   x<< 1.5, 5., 450.;
   1404   // do the computation
   1405   info = lm.minimize(x);
   1406 
   1407   // check return value
   1408   VERIFY_IS_EQUAL(info, 1);
   1409   VERIFY_IS_EQUAL(lm.nfev(), 7);
   1410   VERIFY_IS_EQUAL(lm.njev(), 6);
   1411   // check norm^2
   1412   VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.4635887487E-03);
   1413   // check x
   1414   VERIFY_IS_APPROX(x[0], 1.5543827178);
   1415   VERIFY_IS_APPROX(x[1], 4.0888321754);
   1416   VERIFY_IS_APPROX(x[2], 4.5154121844E+02);
   1417 }
   1418 
   1419 void test_levenberg_marquardt()
   1420 {
   1421     // Tests using the examples provided by (c)minpack
   1422     CALL_SUBTEST(testLmder1());
   1423     CALL_SUBTEST(testLmder());
   1424     CALL_SUBTEST(testLmdif1());
   1425 //     CALL_SUBTEST(testLmstr1());
   1426 //     CALL_SUBTEST(testLmstr());
   1427     CALL_SUBTEST(testLmdif());
   1428 
   1429     // NIST tests, level of difficulty = "Lower"
   1430     CALL_SUBTEST(testNistMisra1a());
   1431     CALL_SUBTEST(testNistChwirut2());
   1432 
   1433     // NIST tests, level of difficulty = "Average"
   1434     CALL_SUBTEST(testNistHahn1());
   1435     CALL_SUBTEST(testNistMisra1d());
   1436     CALL_SUBTEST(testNistMGH17());
   1437     CALL_SUBTEST(testNistLanczos1());
   1438 
   1439 //     // NIST tests, level of difficulty = "Higher"
   1440     CALL_SUBTEST(testNistRat42());
   1441     CALL_SUBTEST(testNistMGH10());
   1442     CALL_SUBTEST(testNistBoxBOD());
   1443 //     CALL_SUBTEST(testNistMGH09());
   1444     CALL_SUBTEST(testNistBennett5());
   1445     CALL_SUBTEST(testNistThurber());
   1446     CALL_SUBTEST(testNistRat43());
   1447     CALL_SUBTEST(testNistEckerle4());
   1448 }
   1449