3 * Copyright (C) 2007 Brian Gough
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 /* These tests are based on the NIST Statistical Reference Datasets
21 See http://www.nist.gov/itl/div898/strd/index.html for more
26 #include <gsl/gsl_math.h>
27 #include <gsl/gsl_test.h>
28 #include <gsl/gsl_multifit.h>
29 #include <gsl/gsl_multifit_nlin.h>
30 #include <gsl/gsl_blas.h>
32 #include <gsl/gsl_ieee_utils.h>
34 #include "test_longley.c"
35 #include "test_filip.c"
36 #include "test_pontius.c"
37 #include "test_brown.c"
38 #include "test_enso.c"
39 #include "test_kirby2.c"
40 #include "test_hahn1.c"
41 #include "test_nelson.c"
43 #include "test_estimator.c"
46 test_lmder (gsl_multifit_function_fdf * f, double x0[],
47 double * X, double F[], double * cov);
50 test_fdf (const char * name, gsl_multifit_function_fdf * f,
51 double x0[], double x[], double sumsq,
65 gsl_multifit_function_fdf f = make_fdf (&brown_f, &brown_df, &brown_fdf,
68 test_lmder(&f, brown_x0, &brown_X[0][0], brown_F, &brown_cov[0][0]);
72 gsl_multifit_function_fdf f = make_fdf (&enso_f, &enso_df, &enso_fdf,
75 test_fdf("nist-ENSO", &f, enso_x0, enso_x, enso_sumsq, enso_sigma);
79 gsl_multifit_function_fdf f = make_fdf (&kirby2_f, &kirby2_df, &kirby2_fdf,
80 kirby2_N, kirby2_P, 0);
82 test_fdf("nist-kirby2", &f, kirby2_x0, kirby2_x, kirby2_sumsq, kirby2_sigma);
86 gsl_multifit_function_fdf f = make_fdf (&hahn1_f, &hahn1_df, &hahn1_fdf,
89 test_fdf("nist-hahn1", &f, hahn1_x0, hahn1_x, hahn1_sumsq, hahn1_sigma);
94 gsl_multifit_function_fdf f = make_fdf (&nelson_f, &nelson_df, &nelson_fdf,
95 nelson_N, nelson_P, 0);
97 test_fdf("nist-nelson", &f, nelson_x0, nelson_x, nelson_sumsq, nelson_sigma);
101 /* now summarize the results */
103 exit (gsl_test_summary ());
108 test_lmder (gsl_multifit_function_fdf * f, double x0[],
109 double * X, double F[], double * cov)
111 const gsl_multifit_fdfsolver_type *T;
112 gsl_multifit_fdfsolver *s;
114 const size_t n = f->n;
115 const size_t p = f->p;
120 gsl_vector_view x = gsl_vector_view_array (x0, p);
122 T = gsl_multifit_fdfsolver_lmsder;
123 s = gsl_multifit_fdfsolver_alloc (T, n, p);
124 gsl_multifit_fdfsolver_set (s, f, &x.vector);
128 status = gsl_multifit_fdfsolver_iterate (s);
130 for (i = 0 ; i < p; i++)
132 gsl_test_rel (gsl_vector_get (s->x, i), X[p*iter+i], 1e-5,
133 "lmsder, iter=%u, x%u", iter, i);
136 gsl_test_rel (gsl_blas_dnrm2 (s->f), F[iter], 1e-5,
137 "lmsder, iter=%u, f", iter);
145 gsl_matrix * covar = gsl_matrix_alloc (4, 4);
146 gsl_multifit_covar (s->J, 0.0, covar);
148 for (i = 0; i < 4; i++)
150 for (j = 0; j < 4; j++)
152 gsl_test_rel (gsl_matrix_get(covar,i,j), cov[i*p + j], 1e-7,
153 "gsl_multifit_covar cov(%d,%d)", i, j) ;
157 gsl_matrix_free (covar);
160 gsl_multifit_fdfsolver_free (s);
165 test_fdf (const char * name, gsl_multifit_function_fdf * f,
166 double x0[], double x_final[],
167 double f_sumsq, double sigma[])
169 const gsl_multifit_fdfsolver_type *T;
170 gsl_multifit_fdfsolver *s;
172 const size_t n = f->n;
173 const size_t p = f->p;
178 gsl_vector_view x = gsl_vector_view_array (x0, p);
180 T = gsl_multifit_fdfsolver_lmsder;
181 s = gsl_multifit_fdfsolver_alloc (T, n, p);
182 gsl_multifit_fdfsolver_set (s, f, &x.vector);
186 status = gsl_multifit_fdfsolver_iterate (s);
189 printf("iter = %d status = %d |f| = %.18e x = \n",
190 iter, status, gsl_blas_dnrm2 (s->f));
192 gsl_vector_fprintf(stdout, s->x, "%.8e");
194 status = gsl_multifit_test_delta (s->dx, s->x, 0.0, 1e-7);
198 while (status == GSL_CONTINUE && iter < 1000);
202 gsl_matrix * covar = gsl_matrix_alloc (p, p);
203 gsl_multifit_covar (s->J, 0.0, covar);
205 for (i = 0 ; i < p; i++)
207 gsl_test_rel (gsl_vector_get (s->x, i), x_final[i], 1e-5,
208 "%s, lmsder, x%u", name, i);
213 double s2 = pow(gsl_blas_dnrm2 (s->f), 2.0);
215 gsl_test_rel (s2, f_sumsq, 1e-5, "%s, lmsder, |f|^2", name);
217 for (i = 0; i < p; i++)
219 double ei = sqrt(s2/(n-p))*sqrt(gsl_matrix_get(covar,i,i));
220 gsl_test_rel (ei, sigma[i], 1e-4,
221 "%s, sigma(%d)", name, i) ;
225 gsl_matrix_free (covar);
228 /* Check that there is no hidden state, restarting should
229 produce identical results. */
232 int status0, status1;
234 gsl_multifit_fdfsolver *t = gsl_multifit_fdfsolver_alloc (T, n, p);
235 gsl_multifit_fdfsolver_set (t, f, &x.vector);
237 /* do a few extra iterations to stir things up */
239 gsl_multifit_fdfsolver_set (s, f, &x.vector);
241 for (i = 0; i < 3; i++)
243 gsl_multifit_fdfsolver_iterate (s);
246 gsl_multifit_fdfsolver_set (s, f, &x.vector);
250 status0 = gsl_multifit_fdfsolver_iterate (s);
251 status1 = gsl_multifit_fdfsolver_iterate (t);
253 gsl_test_int(status0, status1, "%s, lmsder status after set iter=%u", name, iter);
255 for (i = 0; i < p; i++) {
256 double sxi = gsl_vector_get(s->x,i);
257 double txi = gsl_vector_get(t->x,i);
259 printf("%d %g %g\n", i, sxi, txi);
261 gsl_test_rel(sxi, txi, 1e-15, "%s, lmsder after set, %u/%u", name, iter, i);
265 printf("iter = %d status = %d |f| = %.18e x = \n",
266 iter, status, gsl_blas_dnrm2 (s->f));
268 gsl_vector_fprintf(stdout, s->x, "%.8e");
270 status0 = gsl_multifit_test_delta (s->dx, s->x, 0.0, 1e-7);
271 status1 = gsl_multifit_test_delta (t->dx, s->x, 0.0, 1e-7);
273 gsl_test_int(status0, status1, "%s, lmsder test delta status after set iter=%u", name, iter);
277 while (status1 == GSL_CONTINUE && iter < 1000);
279 gsl_multifit_fdfsolver_free (t);
282 gsl_multifit_fdfsolver_free (s);