|
Packit |
f2184d |
/* multifit/test_nonlinear.c
|
|
Packit |
f2184d |
*
|
|
Packit |
f2184d |
* Copyright (C) 2007, 2013, 2014 Brian Gough, Patrick Alken
|
|
Packit |
f2184d |
*
|
|
Packit |
f2184d |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
f2184d |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
f2184d |
* the Free Software Foundation; either version 3 of the License, or (at
|
|
Packit |
f2184d |
* your option) any later version.
|
|
Packit |
f2184d |
*
|
|
Packit |
f2184d |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
f2184d |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
f2184d |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
f2184d |
* General Public License for more details.
|
|
Packit |
f2184d |
*
|
|
Packit |
f2184d |
* You should have received a copy of the GNU General Public License
|
|
Packit |
f2184d |
* along with this program; if not, write to the Free Software
|
|
Packit |
f2184d |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
f2184d |
*/
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
typedef struct
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
const char *name;
|
|
Packit |
f2184d |
double *x0; /* initial parameters (size p) */
|
|
Packit |
f2184d |
double *sigma;
|
|
Packit |
f2184d |
double *epsrel; /* relative tolerance for solution checking */
|
|
Packit |
f2184d |
size_t ntries;
|
|
Packit |
f2184d |
void (*checksol) (const double x[], const double sumsq,
|
|
Packit |
f2184d |
const double epsrel, const char *sname,
|
|
Packit |
f2184d |
const char *pname);
|
|
Packit |
f2184d |
gsl_multifit_function_fdf *fdf;
|
|
Packit |
f2184d |
} test_fdf_problem;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
#include "test_bard.c"
|
|
Packit |
f2184d |
#include "test_beale.c"
|
|
Packit |
f2184d |
#include "test_biggs.c"
|
|
Packit |
f2184d |
#include "test_box.c"
|
|
Packit |
f2184d |
#include "test_boxbod.c"
|
|
Packit |
f2184d |
#include "test_brown1.c"
|
|
Packit |
f2184d |
#include "test_brown2.c"
|
|
Packit |
f2184d |
#include "test_brown3.c"
|
|
Packit |
f2184d |
#include "test_eckerle.c"
|
|
Packit |
f2184d |
#include "test_enso.c"
|
|
Packit |
f2184d |
#include "test_exp1.c"
|
|
Packit |
f2184d |
#include "test_gaussian.c"
|
|
Packit |
f2184d |
#include "test_hahn1.c"
|
|
Packit |
f2184d |
#include "test_helical.c"
|
|
Packit |
f2184d |
#include "test_jennrich.c"
|
|
Packit |
f2184d |
#include "test_kirby2.c"
|
|
Packit |
f2184d |
#include "test_kowalik.c"
|
|
Packit |
f2184d |
#include "test_lin1.c"
|
|
Packit |
f2184d |
#include "test_lin2.c"
|
|
Packit |
f2184d |
#include "test_lin3.c"
|
|
Packit |
f2184d |
#include "test_meyer.c"
|
|
Packit |
f2184d |
#include "test_meyerscal.c"
|
|
Packit |
f2184d |
#include "test_osborne.c"
|
|
Packit |
f2184d |
#include "test_penalty1.c"
|
|
Packit |
f2184d |
#include "test_penalty2.c"
|
|
Packit |
f2184d |
#include "test_powell1.c"
|
|
Packit |
f2184d |
#include "test_powell2.c"
|
|
Packit |
f2184d |
#include "test_powell3.c"
|
|
Packit |
f2184d |
#include "test_rat42.c"
|
|
Packit |
f2184d |
#include "test_rat43.c"
|
|
Packit |
f2184d |
#include "test_rosenbrock.c"
|
|
Packit |
f2184d |
#include "test_rosenbrocke.c"
|
|
Packit |
f2184d |
#include "test_roth.c"
|
|
Packit |
f2184d |
#include "test_thurber.c"
|
|
Packit |
f2184d |
#include "test_vardim.c"
|
|
Packit |
f2184d |
#include "test_watson.c"
|
|
Packit |
f2184d |
#include "test_wood.c"
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
#include "test_wnlin.c"
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
static void test_fdf(const gsl_multifit_fdfsolver_type * T,
|
|
Packit |
f2184d |
const double xtol, const double gtol,
|
|
Packit |
f2184d |
const double ftol, const double epsrel,
|
|
Packit |
f2184d |
const double x0_scale, test_fdf_problem *problem,
|
|
Packit |
f2184d |
const double *wts);
|
|
Packit |
f2184d |
static void test_fdfridge(const gsl_multifit_fdfsolver_type * T,
|
|
Packit |
f2184d |
const double xtol, const double gtol,
|
|
Packit |
f2184d |
const double ftol, const double epsrel,
|
|
Packit |
f2184d |
const double x0_scale, test_fdf_problem *problem,
|
|
Packit |
f2184d |
const double *wts);
|
|
Packit |
f2184d |
static void test_fdf_checksol(const char *sname, const char *pname,
|
|
Packit |
f2184d |
const double epsrel,
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver *s,
|
|
Packit |
f2184d |
test_fdf_problem *problem);
|
|
Packit |
f2184d |
static void test_scale_x0(gsl_vector *x0, const double scale);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/*
|
|
Packit |
f2184d |
* These test problems are taken from
|
|
Packit |
f2184d |
*
|
|
Packit |
f2184d |
* H. B. Nielsen, UCTP test problems for unconstrained optimization,
|
|
Packit |
f2184d |
* IMM Department of Mathematical Modeling, Tech. Report IMM-REP-2000-17,
|
|
Packit |
f2184d |
* 2000.
|
|
Packit |
f2184d |
*/
|
|
Packit |
f2184d |
static test_fdf_problem *test_fdf_nielsen[] = {
|
|
Packit |
f2184d |
&lin1_problem, /* 1 */
|
|
Packit |
f2184d |
&lin2_problem, /* 2 */
|
|
Packit |
f2184d |
&lin3_problem, /* 3 */
|
|
Packit |
f2184d |
&rosenbrock_problem, /* 4 */
|
|
Packit |
f2184d |
&helical_problem, /* 5 */
|
|
Packit |
f2184d |
&powell1_problem, /* 6 */
|
|
Packit |
f2184d |
&roth_problem, /* 7 */
|
|
Packit |
f2184d |
&bard_problem, /* 8 */
|
|
Packit |
f2184d |
&kowalik_problem, /* 9 */
|
|
Packit |
f2184d |
&meyer_problem, /* 10 */
|
|
Packit |
f2184d |
&watson_problem, /* 11 */
|
|
Packit |
f2184d |
&box_problem, /* 12 */
|
|
Packit |
f2184d |
&jennrich_problem, /* 13 */
|
|
Packit |
f2184d |
&brown1_problem, /* 14 */
|
|
Packit |
f2184d |
&brown2_problem, /* 16 */
|
|
Packit |
f2184d |
&osborne_problem, /* 17 */
|
|
Packit |
f2184d |
&exp1_problem, /* 18 */
|
|
Packit |
f2184d |
&meyerscal_problem, /* 20 */
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
&powell2_problem,
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
NULL
|
|
Packit |
f2184d |
};
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/*
|
|
Packit |
f2184d |
* These tests are from
|
|
Packit |
f2184d |
*
|
|
Packit |
f2184d |
* J. J. More, B. S. Garbow and K. E. Hillstrom, Testing
|
|
Packit |
f2184d |
* Unconstrained Optimization Software, ACM Trans. Math. Soft.
|
|
Packit |
f2184d |
* Vol 7, No 1, 1981.
|
|
Packit |
f2184d |
*
|
|
Packit |
f2184d |
* Many of these overlap with the Nielsen tests
|
|
Packit |
f2184d |
*/
|
|
Packit |
f2184d |
static test_fdf_problem *test_fdf_more[] = {
|
|
Packit |
f2184d |
&rosenbrock_problem, /* 1 */
|
|
Packit |
f2184d |
&roth_problem, /* 2 */
|
|
Packit |
f2184d |
&powell3_problem, /* 3 */
|
|
Packit |
f2184d |
&brown3_problem, /* 4 */
|
|
Packit |
f2184d |
&beale_problem, /* 5 */
|
|
Packit |
f2184d |
&jennrich_problem, /* 6 */
|
|
Packit |
f2184d |
&helical_problem, /* 7 */
|
|
Packit |
f2184d |
&bard_problem, /* 8 */
|
|
Packit |
f2184d |
&gaussian_problem, /* 9 */
|
|
Packit |
f2184d |
&meyer_problem, /* 10 */
|
|
Packit |
f2184d |
&box_problem, /* 12 */
|
|
Packit |
f2184d |
&powell1_problem, /* 13 */
|
|
Packit |
f2184d |
&wood_problem, /* 14 */
|
|
Packit |
f2184d |
&kowalik_problem, /* 15 */
|
|
Packit |
f2184d |
&brown1_problem, /* 16 */
|
|
Packit |
f2184d |
&osborne_problem, /* 17 */
|
|
Packit |
f2184d |
&biggs_problem, /* 18 */
|
|
Packit |
f2184d |
&watson_problem, /* 20 */
|
|
Packit |
f2184d |
&rosenbrocke_problem, /* 21 */
|
|
Packit |
f2184d |
&penalty1_problem, /* 23 */
|
|
Packit |
f2184d |
&penalty2_problem, /* 24 */
|
|
Packit |
f2184d |
&vardim_problem, /* 25 */
|
|
Packit |
f2184d |
&brown2_problem, /* 27 */
|
|
Packit |
f2184d |
&lin1_problem, /* 32 */
|
|
Packit |
f2184d |
&lin2_problem, /* 33 */
|
|
Packit |
f2184d |
&lin3_problem, /* 34 */
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
NULL
|
|
Packit |
f2184d |
};
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* NIST test cases */
|
|
Packit |
f2184d |
static test_fdf_problem *test_fdf_nist[] = {
|
|
Packit |
f2184d |
&kirby2_problem,
|
|
Packit |
f2184d |
&hahn1_problem,
|
|
Packit |
f2184d |
&enso_problem,
|
|
Packit |
f2184d |
&thurber_problem,
|
|
Packit |
f2184d |
&boxbod_problem,
|
|
Packit |
f2184d |
&rat42_problem,
|
|
Packit |
f2184d |
&eckerle_problem,
|
|
Packit |
f2184d |
&rat43_problem,
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
NULL
|
|
Packit |
f2184d |
};
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
static void
|
|
Packit |
f2184d |
test_nonlinear(void)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
const double xtol = pow(GSL_DBL_EPSILON, 0.9);
|
|
Packit |
f2184d |
const double gtol = pow(GSL_DBL_EPSILON, 0.9);
|
|
Packit |
f2184d |
const double ftol = 0.0;
|
|
Packit |
f2184d |
size_t i, j;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* Nielsen tests */
|
|
Packit |
f2184d |
for (i = 0; test_fdf_nielsen[i] != NULL; ++i)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
test_fdf_problem *problem = test_fdf_nielsen[i];
|
|
Packit |
f2184d |
double epsrel = *(problem->epsrel);
|
|
Packit |
f2184d |
double scale = 1.0;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
for (j = 0; j < problem->ntries; ++j)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
double eps_scale = epsrel * scale;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, scale, problem, NULL);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, scale, problem, NULL);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* test finite difference Jacobian */
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_multifit_function_fdf fdf;
|
|
Packit |
f2184d |
fdf.df = problem->fdf->df;
|
|
Packit |
f2184d |
problem->fdf->df = NULL;
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
1.0e5 * eps_scale, 1.0, problem, NULL);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
1.0e5 * eps_scale, 1.0, problem, NULL);
|
|
Packit |
f2184d |
problem->fdf->df = fdf.df;
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
scale *= 10.0;
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmniel, xtol, gtol, ftol,
|
|
Packit |
f2184d |
10.0 * epsrel, 1.0, problem, NULL);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* More tests */
|
|
Packit |
f2184d |
for (i = 0; test_fdf_more[i] != NULL; ++i)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
test_fdf_problem *problem = test_fdf_more[i];
|
|
Packit |
f2184d |
double epsrel = *(problem->epsrel);
|
|
Packit |
f2184d |
double scale = 1.0;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
for (j = 0; j < problem->ntries; ++j)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
double eps_scale = epsrel * scale;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, scale, problem, NULL);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, scale, problem, NULL);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* test finite difference Jacobian */
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_multifit_function_fdf fdf;
|
|
Packit |
f2184d |
fdf.df = problem->fdf->df;
|
|
Packit |
f2184d |
problem->fdf->df = NULL;
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
1.0e5 * eps_scale, 1.0, problem, NULL);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
1.0e5 * eps_scale, 1.0, problem, NULL);
|
|
Packit |
f2184d |
problem->fdf->df = fdf.df;
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
scale *= 10.0;
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmniel, xtol, gtol, ftol,
|
|
Packit |
f2184d |
10.0 * epsrel, 1.0, problem, NULL);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* NIST tests */
|
|
Packit |
f2184d |
for (i = 0; test_fdf_nist[i] != NULL; ++i)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
test_fdf_problem *problem = test_fdf_nist[i];
|
|
Packit |
f2184d |
double epsrel = *(problem->epsrel);
|
|
Packit |
f2184d |
double scale = 1.0;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
for (j = 0; j < problem->ntries; ++j)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
double eps_scale = epsrel * scale;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, scale, problem, NULL);
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, scale, problem, NULL);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* test finite difference Jacobian */
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_multifit_function_fdf fdf;
|
|
Packit |
f2184d |
fdf.df = problem->fdf->df;
|
|
Packit |
f2184d |
problem->fdf->df = NULL;
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, 1.0, problem, NULL);
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
eps_scale, scale, problem, NULL);
|
|
Packit |
f2184d |
problem->fdf->df = fdf.df;
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
scale *= 10.0;
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmniel, xtol, gtol, ftol,
|
|
Packit |
f2184d |
epsrel, 1.0, problem, NULL);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* test weighted nonlinear least squares */
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* internal weighting in _f and _df functions */
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem1, NULL);
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmniel, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem1, NULL);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem1, NULL);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmniel, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem1, NULL);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* weighting through fdfsolver_wset */
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem2, wnlin_W);
|
|
Packit |
f2184d |
test_fdf(gsl_multifit_fdfsolver_lmniel, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem2, wnlin_W);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmsder, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem2, wnlin_W);
|
|
Packit |
f2184d |
test_fdfridge(gsl_multifit_fdfsolver_lmniel, xtol, gtol, ftol,
|
|
Packit |
f2184d |
wnlin_epsrel, 1.0, &wnlin_problem2, wnlin_W);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/*
|
|
Packit |
f2184d |
test_fdf()
|
|
Packit |
f2184d |
Test a weighted nonlinear least squares problem
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
Inputs: T - solver to use
|
|
Packit |
f2184d |
xtol - tolerance in x
|
|
Packit |
f2184d |
gtol - tolerance in gradient
|
|
Packit |
f2184d |
ftol - tolerance in residual vector
|
|
Packit |
f2184d |
epsrel - relative error tolerance in solution
|
|
Packit |
f2184d |
x0_scale - to test robustness against starting points,
|
|
Packit |
f2184d |
the standard starting point in 'problem' is
|
|
Packit |
f2184d |
multiplied by this scale factor:
|
|
Packit |
f2184d |
x0 <- x0 * x0_scale
|
|
Packit |
f2184d |
If x0 = 0, then all components of x0 are set to
|
|
Packit |
f2184d |
x0_scale
|
|
Packit |
f2184d |
problem - contains the nonlinear problem and solution point
|
|
Packit |
f2184d |
wts - weight vector (NULL for unweighted)
|
|
Packit |
f2184d |
*/
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
static void
|
|
Packit |
f2184d |
test_fdf(const gsl_multifit_fdfsolver_type * T, const double xtol,
|
|
Packit |
f2184d |
const double gtol, const double ftol,
|
|
Packit |
f2184d |
const double epsrel, const double x0_scale,
|
|
Packit |
f2184d |
test_fdf_problem *problem,
|
|
Packit |
f2184d |
const double *wts)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_multifit_function_fdf *fdf = problem->fdf;
|
|
Packit |
f2184d |
const size_t n = fdf->n;
|
|
Packit |
f2184d |
const size_t p = fdf->p;
|
|
Packit |
f2184d |
const size_t max_iter = 1500;
|
|
Packit |
f2184d |
gsl_vector *x0 = gsl_vector_alloc(p);
|
|
Packit |
f2184d |
gsl_vector_view x0v = gsl_vector_view_array(problem->x0, p);
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver *s = gsl_multifit_fdfsolver_alloc (T, n, p);
|
|
Packit |
f2184d |
const char *pname = problem->name;
|
|
Packit |
f2184d |
char sname[2048];
|
|
Packit |
f2184d |
int status, info;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
sprintf(sname, "%s/scale=%g%s",
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver_name(s), x0_scale,
|
|
Packit |
f2184d |
problem->fdf->df ? "" : "/fdiff");
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* scale starting point x0 */
|
|
Packit |
f2184d |
gsl_vector_memcpy(x0, &x0v.vector);
|
|
Packit |
f2184d |
test_scale_x0(x0, x0_scale);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
if (wts)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_vector_const_view wv = gsl_vector_const_view_array(wts, n);
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver_wset(s, fdf, x0, &wv.vector);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
else
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver_set(s, fdf, x0);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
status = gsl_multifit_fdfsolver_driver(s, max_iter, xtol, gtol,
|
|
Packit |
f2184d |
ftol, &info;;
|
|
Packit |
f2184d |
gsl_test(status, "%s/%s did not converge, status=%s",
|
|
Packit |
f2184d |
sname, pname, gsl_strerror(status));
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* check solution */
|
|
Packit |
f2184d |
test_fdf_checksol(sname, pname, epsrel, s, problem);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
if (wts == NULL)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
/* test again with weighting matrix W = I */
|
|
Packit |
f2184d |
gsl_vector *wv = gsl_vector_alloc(n);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
sprintf(sname, "%s/scale=%g%s/weights",
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver_name(s), x0_scale,
|
|
Packit |
f2184d |
problem->fdf->df ? "" : "/fdiff");
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_vector_memcpy(x0, &x0v.vector);
|
|
Packit |
f2184d |
test_scale_x0(x0, x0_scale);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_vector_set_all(wv, 1.0);
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver_wset(s, fdf, x0, wv);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
status = gsl_multifit_fdfsolver_driver(s, max_iter, xtol, gtol,
|
|
Packit |
f2184d |
ftol, &info;;
|
|
Packit |
f2184d |
gsl_test(status, "%s/%s did not converge, status=%s",
|
|
Packit |
f2184d |
sname, pname, gsl_strerror(status));
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
test_fdf_checksol(sname, pname, epsrel, s, problem);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_vector_free(wv);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver_free(s);
|
|
Packit |
f2184d |
gsl_vector_free(x0);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/*
|
|
Packit |
f2184d |
test_fdfridge()
|
|
Packit |
f2184d |
Test a nonlinear least squares problem
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
Inputs: T - solver to use
|
|
Packit |
f2184d |
xtol - tolerance in x
|
|
Packit |
f2184d |
gtol - tolerance in gradient
|
|
Packit |
f2184d |
ftol - tolerance in residual vector
|
|
Packit |
f2184d |
epsrel - relative error tolerance in solution
|
|
Packit |
f2184d |
x0_scale - to test robustness against starting points,
|
|
Packit |
f2184d |
the standard starting point in 'problem' is
|
|
Packit |
f2184d |
multiplied by this scale factor:
|
|
Packit |
f2184d |
x0 <- x0 * x0_scale
|
|
Packit |
f2184d |
If x0 = 0, then all components of x0 are set to
|
|
Packit |
f2184d |
x0_scale
|
|
Packit |
f2184d |
problem - contains the nonlinear problem and solution point
|
|
Packit |
f2184d |
wts - weight vector
|
|
Packit |
f2184d |
*/
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
static void
|
|
Packit |
f2184d |
test_fdfridge(const gsl_multifit_fdfsolver_type * T, const double xtol,
|
|
Packit |
f2184d |
const double gtol, const double ftol,
|
|
Packit |
f2184d |
const double epsrel, const double x0_scale,
|
|
Packit |
f2184d |
test_fdf_problem *problem, const double *wts)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_multifit_function_fdf *fdf = problem->fdf;
|
|
Packit |
f2184d |
const size_t n = fdf->n;
|
|
Packit |
f2184d |
const size_t p = fdf->p;
|
|
Packit |
f2184d |
const size_t max_iter = 1500;
|
|
Packit |
f2184d |
gsl_vector *x0 = gsl_vector_alloc(p);
|
|
Packit |
f2184d |
gsl_vector_view x0v = gsl_vector_view_array(problem->x0, p);
|
|
Packit |
f2184d |
gsl_multifit_fdfridge *w = gsl_multifit_fdfridge_alloc (T, n, p);
|
|
Packit |
f2184d |
const char *pname = problem->name;
|
|
Packit |
f2184d |
char sname[2048];
|
|
Packit |
f2184d |
int status, info;
|
|
Packit |
f2184d |
double lambda = 0.0;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
sprintf(sname, "ridge/%s", gsl_multifit_fdfridge_name(w));
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* scale starting point x0 */
|
|
Packit |
f2184d |
gsl_vector_memcpy(x0, &x0v.vector);
|
|
Packit |
f2184d |
test_scale_x0(x0, x0_scale);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* test undamped case with lambda = 0 */
|
|
Packit |
f2184d |
if (wts)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_vector_const_view wv = gsl_vector_const_view_array(wts, n);
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_wset(w, fdf, x0, lambda, &wv.vector);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
else
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_set(w, fdf, x0, lambda);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
status = gsl_multifit_fdfridge_driver(w, max_iter, xtol, gtol,
|
|
Packit |
f2184d |
ftol, &info;;
|
|
Packit |
f2184d |
gsl_test(status, "%s/%s did not converge, status=%s",
|
|
Packit |
f2184d |
sname, pname, gsl_strerror(status));
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* check solution */
|
|
Packit |
f2184d |
test_fdf_checksol(sname, pname, epsrel, w->s, problem);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* test for self consisent solution with L = \lambda I */
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
const double eps = 1.0e-10;
|
|
Packit |
f2184d |
gsl_matrix *L = gsl_matrix_calloc(p, p);
|
|
Packit |
f2184d |
gsl_vector_view diag = gsl_matrix_diagonal(L);
|
|
Packit |
f2184d |
gsl_multifit_fdfridge *w2 = gsl_multifit_fdfridge_alloc (T, n, p);
|
|
Packit |
f2184d |
gsl_vector *y0 = gsl_vector_alloc(p);
|
|
Packit |
f2184d |
size_t i;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* pick some value for lambda and set L = \lambda I */
|
|
Packit |
f2184d |
lambda = 5.0;
|
|
Packit |
f2184d |
gsl_vector_set_all(&diag.vector, lambda);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* scale initial vector */
|
|
Packit |
f2184d |
gsl_vector_memcpy(x0, &x0v.vector);
|
|
Packit |
f2184d |
test_scale_x0(x0, x0_scale);
|
|
Packit |
f2184d |
gsl_vector_memcpy(y0, x0);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
if (wts)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_vector_const_view wv = gsl_vector_const_view_array(wts, n);
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_wset(w, fdf, x0, lambda, &wv.vector);
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_wset3(w2, fdf, y0, L, &wv.vector);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
else
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_set(w, fdf, x0, lambda);
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_set3(w2, fdf, y0, L);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* solve with scalar lambda routine */
|
|
Packit |
f2184d |
status = gsl_multifit_fdfridge_driver(w, max_iter, xtol, gtol,
|
|
Packit |
f2184d |
ftol, &info;;
|
|
Packit |
f2184d |
gsl_test(status, "%s/lambda/%s did not converge, status=%s",
|
|
Packit |
f2184d |
sname, pname, gsl_strerror(status));
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* solve with general matrix routine */
|
|
Packit |
f2184d |
status = gsl_multifit_fdfridge_driver(w2, max_iter, xtol, gtol,
|
|
Packit |
f2184d |
ftol, &info;;
|
|
Packit |
f2184d |
gsl_test(status, "%s/L/%s did not converge, status=%s",
|
|
Packit |
f2184d |
sname, pname, gsl_strerror(status));
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* test x = y */
|
|
Packit |
f2184d |
for (i = 0; i < p; ++i)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
double xi = gsl_vector_get(w->s->x, i);
|
|
Packit |
f2184d |
double yi = gsl_vector_get(w2->s->x, i);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
if (fabs(xi) < eps)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_test_abs(yi, xi, eps, "%s/%s ridge lambda=%g i=%zu",
|
|
Packit |
f2184d |
sname, pname, lambda, i);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
else
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_test_rel(yi, xi, eps, "%s/%s ridge lambda=%g i=%zu",
|
|
Packit |
f2184d |
sname, pname, lambda, i);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_matrix_free(L);
|
|
Packit |
f2184d |
gsl_vector_free(y0);
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_free(w2);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_multifit_fdfridge_free(w);
|
|
Packit |
f2184d |
gsl_vector_free(x0);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
static void
|
|
Packit |
f2184d |
test_fdf_checksol(const char *sname, const char *pname,
|
|
Packit |
f2184d |
const double epsrel, gsl_multifit_fdfsolver *s,
|
|
Packit |
f2184d |
test_fdf_problem *problem)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
gsl_multifit_function_fdf *fdf = problem->fdf;
|
|
Packit |
f2184d |
const double *sigma = problem->sigma;
|
|
Packit |
f2184d |
gsl_vector *f = gsl_multifit_fdfsolver_residual(s);
|
|
Packit |
f2184d |
gsl_vector *x = gsl_multifit_fdfsolver_position(s);
|
|
Packit |
f2184d |
double sumsq;
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
/* check solution vector x and sumsq = ||f||^2 */
|
|
Packit |
f2184d |
gsl_blas_ddot(f, f, &sumsq);
|
|
Packit |
f2184d |
(problem->checksol)(x->data, sumsq, epsrel, sname, pname);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
#if 1
|
|
Packit |
f2184d |
/* check variances */
|
|
Packit |
f2184d |
if (sigma)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
const size_t n = fdf->n;
|
|
Packit |
f2184d |
const size_t p = fdf->p;
|
|
Packit |
f2184d |
size_t i;
|
|
Packit |
f2184d |
gsl_matrix * J = gsl_matrix_alloc(n, p);
|
|
Packit |
f2184d |
gsl_matrix * covar = gsl_matrix_alloc (p, p);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_multifit_fdfsolver_jac (s, J);
|
|
Packit |
f2184d |
gsl_multifit_covar(J, 0.0, covar);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
for (i = 0; i < p; i++)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
double ei = sqrt(sumsq/(n-p))*sqrt(gsl_matrix_get(covar,i,i));
|
|
Packit |
f2184d |
gsl_test_rel (ei, sigma[i], epsrel,
|
|
Packit |
f2184d |
"%s/%s, sigma(%d)", sname, pname, i) ;
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
gsl_matrix_free (J);
|
|
Packit |
f2184d |
gsl_matrix_free (covar);
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
#endif
|
|
Packit |
f2184d |
}
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
static void
|
|
Packit |
f2184d |
test_scale_x0(gsl_vector *x0, const double scale)
|
|
Packit |
f2184d |
{
|
|
Packit |
f2184d |
double nx = gsl_blas_dnrm2(x0);
|
|
Packit |
f2184d |
|
|
Packit |
f2184d |
if (nx == 0.0)
|
|
Packit |
f2184d |
gsl_vector_set_all(x0, scale);
|
|
Packit |
f2184d |
else
|
|
Packit |
f2184d |
gsl_vector_scale(x0, scale);
|
|
Packit |
f2184d |
} /* test_scale_x0() */
|