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