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