Blame multifit_nlinear/test_fdf.c

Packit 67cb25
/* multifit_nlinear/test_fdf.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 2007, 2013, 2014, 2015, 2016 Brian Gough, Patrick Alken
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
typedef struct
Packit 67cb25
{
Packit 67cb25
  const char *name;
Packit 67cb25
  double *x0;       /* initial parameters (size p) */
Packit 67cb25
  double *weights;  /* data weights */
Packit 67cb25
  double *sigma;
Packit 67cb25
  double *epsrel;   /* relative tolerance for solution checking */
Packit 67cb25
  void (*checksol) (const double x[], const double sumsq,
Packit 67cb25
                    const double epsrel, const char *sname,
Packit 67cb25
                    const char *pname);
Packit 67cb25
  gsl_multifit_nlinear_fdf *fdf;
Packit 67cb25
} test_fdf_problem;
Packit 67cb25
Packit 67cb25
#include "test_bard.c"
Packit 67cb25
#include "test_beale.c"
Packit 67cb25
#include "test_biggs.c"
Packit 67cb25
#include "test_box.c"
Packit 67cb25
#include "test_boxbod.c"
Packit 67cb25
#include "test_brown1.c"
Packit 67cb25
#include "test_brown2.c"
Packit 67cb25
#include "test_brown3.c"
Packit 67cb25
#include "test_eckerle.c"
Packit 67cb25
#include "test_enso.c"
Packit 67cb25
#include "test_exp1.c"
Packit 67cb25
#include "test_gaussian.c"
Packit 67cb25
#include "test_hahn1.c"
Packit 67cb25
#include "test_helical.c"
Packit 67cb25
#include "test_jennrich.c"
Packit 67cb25
#include "test_kirby2.c"
Packit 67cb25
#include "test_kowalik.c"
Packit 67cb25
#include "test_lin1.c"
Packit 67cb25
#include "test_lin2.c"
Packit 67cb25
#include "test_lin3.c"
Packit 67cb25
#include "test_meyer.c"
Packit 67cb25
#include "test_meyerscal.c"
Packit 67cb25
#include "test_osborne.c"
Packit 67cb25
#include "test_penalty1.c"
Packit 67cb25
#include "test_penalty2.c"
Packit 67cb25
#include "test_powell1.c"
Packit 67cb25
#include "test_powell2.c"
Packit 67cb25
#include "test_powell3.c"
Packit 67cb25
#include "test_rat42.c"
Packit 67cb25
#include "test_rat43.c"
Packit 67cb25
#include "test_rosenbrock.c"
Packit 67cb25
#include "test_rosenbrocke.c"
Packit 67cb25
#include "test_roth.c"
Packit 67cb25
#include "test_thurber.c"
Packit 67cb25
#include "test_vardim.c"
Packit 67cb25
#include "test_watson.c"
Packit 67cb25
#include "test_wood.c"
Packit 67cb25
Packit 67cb25
#include "test_wnlin.c"
Packit 67cb25
Packit 67cb25
static void test_fdf(const gsl_multifit_nlinear_type * T,
Packit 67cb25
                     const gsl_multifit_nlinear_parameters * params,
Packit 67cb25
                     const double xtol, const double gtol,
Packit 67cb25
                     const double ftol,
Packit 67cb25
                     const double epsrel,
Packit 67cb25
                     test_fdf_problem *problem);
Packit 67cb25
static void test_fdf_checksol(const char *sname, const char *pname,
Packit 67cb25
                              const double epsrel,
Packit 67cb25
                              gsl_multifit_nlinear_workspace *s,
Packit 67cb25
                              test_fdf_problem *problem);
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 * FIXME: some test problems are disabled since they fail on certain
Packit 67cb25
 * solvers. Known failures are:
Packit 67cb25
 *
Packit 67cb25
 * Method     test-problem
Packit 67cb25
 * ======     ============
Packit 67cb25
 * dogleg     thurbera
Packit 67cb25
 * dogleg     rat43a
Packit 67cb25
 * all        boxboda
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
static test_fdf_problem *test_problems[] = {
Packit 67cb25
  /*
Packit 67cb25
   * These test problems are taken from
Packit 67cb25
   *
Packit 67cb25
   * H. B. Nielsen, UCTP test problems for unconstrained optimization,
Packit 67cb25
   * IMM Department of Mathematical Modeling, Tech. Report
Packit 67cb25
   * IMM-REP-2000-17, 2000.
Packit 67cb25
   */
Packit 67cb25
  &lin1_problem,       /* 1 */
Packit 67cb25
  &lin2_problem,       /* 2 */
Packit 67cb25
  &lin3_problem,       /* 3 */
Packit 67cb25
  &rosenbrock_problem, /* 4 */
Packit 67cb25
  &helical_problem,    /* 5 */
Packit 67cb25
  &powell1_problem,    /* 6 */
Packit 67cb25
  &roth_problem,       /* 7 */
Packit 67cb25
  &bard_problem,       /* 8 */
Packit 67cb25
  &kowalik_problem,    /* 9 */
Packit 67cb25
  &meyer_problem,      /* 10 */
Packit 67cb25
  &watson_problem,     /* 11 */
Packit 67cb25
  &box_problem,        /* 12 */
Packit 67cb25
  &jennrich_problem,   /* 13 */
Packit 67cb25
  &brown1_problem,     /* 14 */
Packit 67cb25
  &brown2_problem,     /* 16 */
Packit 67cb25
  &osborne_problem,    /* 17 */
Packit 67cb25
  &exp1_problem,       /* 18 */
Packit 67cb25
  &meyerscal_problem,  /* 20 */
Packit 67cb25
Packit 67cb25
  &powell2_problem,
Packit 67cb25
Packit 67cb25
  /*
Packit 67cb25
   * These tests are from
Packit 67cb25
   *
Packit 67cb25
   * J. J. More, B. S. Garbow and K. E. Hillstrom, Testing
Packit 67cb25
   * Unconstrained Optimization Software, ACM Trans. Math. Soft.
Packit 67cb25
   * Vol 7, No 1, 1981.
Packit 67cb25
   *
Packit 67cb25
   * Many of these overlap with the Nielsen tests
Packit 67cb25
   */
Packit 67cb25
  &rosenbrock_problem,   /* 1 */
Packit 67cb25
  &roth_problem,         /* 2 */
Packit 67cb25
  &powell3_problem,      /* 3 */
Packit 67cb25
  &brown3_problem,       /* 4 */
Packit 67cb25
  &beale_problem,        /* 5 */
Packit 67cb25
  &jennrich_problem,     /* 6 */
Packit 67cb25
  &helical_problem,      /* 7 */
Packit 67cb25
  &bard_problem,         /* 8 */
Packit 67cb25
  &gaussian_problem,     /* 9 */
Packit 67cb25
  &meyer_problem,        /* 10 */
Packit 67cb25
  &box_problem,          /* 12 */
Packit 67cb25
  &powell1_problem,      /* 13 */
Packit 67cb25
  &wood_problem,         /* 14 */
Packit 67cb25
  &kowalik_problem,      /* 15 */
Packit 67cb25
  &brown1_problem,       /* 16 */
Packit 67cb25
  &osborne_problem,      /* 17 */
Packit 67cb25
  &biggs_problem,        /* 18 */
Packit 67cb25
  &watson_problem,       /* 20 */
Packit 67cb25
  &rosenbrocke_problem,  /* 21 */
Packit 67cb25
  &penalty1_problem,     /* 23 */
Packit 67cb25
  &penalty2_problem,     /* 24 */
Packit 67cb25
  &vardim_problem,       /* 25 */
Packit 67cb25
  &brown2_problem,       /* 27 */
Packit 67cb25
  &lin1_problem,         /* 32 */
Packit 67cb25
  &lin2_problem,         /* 33 */
Packit 67cb25
  &lin3_problem,         /* 34 */
Packit 67cb25
Packit 67cb25
  /* NIST test cases */
Packit 67cb25
  &kirby2a_problem,
Packit 67cb25
  &kirby2b_problem,
Packit 67cb25
  &hahn1a_problem,
Packit 67cb25
  &hahn1b_problem,
Packit 67cb25
  &ensoa_problem,
Packit 67cb25
  &ensob_problem,
Packit 67cb25
  /*&thurbera_problem,*/
Packit 67cb25
  &thurberb_problem,
Packit 67cb25
  /*&boxboda_problem,*/
Packit 67cb25
  &boxbodb_problem,
Packit 67cb25
  &rat42a_problem,
Packit 67cb25
  &rat42b_problem,
Packit 67cb25
  &eckerlea_problem,
Packit 67cb25
  &eckerleb_problem,
Packit 67cb25
  /*&rat43a_problem,*/
Packit 67cb25
  &rat43b_problem,
Packit 67cb25
Packit 67cb25
  /* weighted test cases */
Packit 67cb25
  &wnlin_problem1,
Packit 67cb25
  &wnlin_problem2,
Packit 67cb25
Packit 67cb25
  NULL
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
test_fdf_main(const gsl_multifit_nlinear_parameters * params)
Packit 67cb25
{
Packit 67cb25
  const double xtol = pow(GSL_DBL_EPSILON, 0.9);
Packit 67cb25
  const double gtol = pow(GSL_DBL_EPSILON, 0.9);
Packit 67cb25
  const double ftol = 0.0;
Packit 67cb25
  size_t i;
Packit 67cb25
Packit 67cb25
  for (i = 0; test_problems[i] != NULL; ++i)
Packit 67cb25
    {
Packit 67cb25
      test_fdf_problem *problem = test_problems[i];
Packit 67cb25
      double epsrel = *(problem->epsrel);
Packit 67cb25
      gsl_multifit_nlinear_fdf fdf;
Packit 67cb25
Packit 67cb25
      test_fdf(gsl_multifit_nlinear_trust, params, xtol, gtol, ftol,
Packit 67cb25
               epsrel, problem);
Packit 67cb25
Packit 67cb25
      /* test finite difference Jacobian
Packit 67cb25
       * XXX: watson problem doesn't work with forward differences */
Packit 67cb25
      if (problem != &watson_problem)
Packit 67cb25
        {
Packit 67cb25
          fdf.df = problem->fdf->df;
Packit 67cb25
          problem->fdf->df = NULL;
Packit 67cb25
Packit 67cb25
          test_fdf(gsl_multifit_nlinear_trust, params, xtol, gtol, ftol,
Packit 67cb25
                   1.0e3 * epsrel, problem);
Packit 67cb25
Packit 67cb25
          problem->fdf->df = fdf.df;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
#if 0 /*XXX: box3d test fails on MacOS here */
Packit 67cb25
      if (params->trs == gsl_multifit_nlinear_trs_lmaccel && problem->fdf->fvv != NULL)
Packit 67cb25
        {
Packit 67cb25
          /* test finite difference second directional derivative */
Packit 67cb25
          fdf.fvv = problem->fdf->fvv;
Packit 67cb25
          problem->fdf->fvv = NULL;
Packit 67cb25
Packit 67cb25
          test_fdf(gsl_multifit_nlinear_trust, params, xtol, gtol, ftol,
Packit 67cb25
                   epsrel / params->h_fvv, problem);
Packit 67cb25
Packit 67cb25
          problem->fdf->fvv = fdf.fvv;
Packit 67cb25
        }
Packit 67cb25
#endif
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
test_fdf()
Packit 67cb25
  Test a weighted nonlinear least squares problem
Packit 67cb25
Packit 67cb25
Inputs: T        - solver to use
Packit 67cb25
        params   - solver parameters
Packit 67cb25
        xtol     - tolerance in x
Packit 67cb25
        gtol     - tolerance in gradient
Packit 67cb25
        ftol     - tolerance in residual vector
Packit 67cb25
        epsrel   - relative error tolerance in solution
Packit 67cb25
        problem  - contains the nonlinear problem and solution point
Packit 67cb25
*/
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
test_fdf(const gsl_multifit_nlinear_type * T,
Packit 67cb25
         const gsl_multifit_nlinear_parameters * params,
Packit 67cb25
         const double xtol, const double gtol, const double ftol,
Packit 67cb25
         const double epsrel,
Packit 67cb25
         test_fdf_problem *problem)
Packit 67cb25
{
Packit 67cb25
  gsl_multifit_nlinear_fdf *fdf = problem->fdf;
Packit 67cb25
  const size_t n = fdf->n;
Packit 67cb25
  const size_t p = fdf->p;
Packit 67cb25
  const size_t max_iter = 2500;
Packit 67cb25
  gsl_vector *x0 = gsl_vector_alloc(p);
Packit 67cb25
  gsl_vector_view x0v = gsl_vector_view_array(problem->x0, p);
Packit 67cb25
  gsl_multifit_nlinear_workspace *w =
Packit 67cb25
    gsl_multifit_nlinear_alloc (T, params, n, p);
Packit 67cb25
  const char *pname = problem->name;
Packit 67cb25
  char buf[2048];
Packit 67cb25
  char sname[2048];
Packit 67cb25
  int status, info;
Packit 67cb25
Packit 67cb25
  sprintf(buf, "%s/%s/scale=%s/solver=%s",
Packit 67cb25
    gsl_multifit_nlinear_name(w),
Packit 67cb25
    params->trs->name,
Packit 67cb25
    params->scale->name,
Packit 67cb25
    params->solver->name);
Packit 67cb25
Packit 67cb25
  if (problem->fdf->df == NULL)
Packit 67cb25
    {
Packit 67cb25
      if (params->fdtype == GSL_MULTIFIT_NLINEAR_FWDIFF)
Packit 67cb25
        strcat(buf, "/fdjac,forward");
Packit 67cb25
      else
Packit 67cb25
        strcat(buf, "/fdjac,center");
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (problem->fdf->fvv == NULL)
Packit 67cb25
    {
Packit 67cb25
      strcat(buf, "/fdfvv");
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  strcpy(sname, buf);
Packit 67cb25
Packit 67cb25
  gsl_vector_memcpy(x0, &x0v.vector);
Packit 67cb25
Packit 67cb25
  if (problem->weights != NULL)
Packit 67cb25
    {
Packit 67cb25
      gsl_vector_const_view wv = gsl_vector_const_view_array(problem->weights, n);
Packit 67cb25
      gsl_multifit_nlinear_winit(x0, &wv.vector, fdf, w);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    gsl_multifit_nlinear_init(x0, fdf, w);
Packit 67cb25
Packit 67cb25
  status = gsl_multifit_nlinear_driver(max_iter, xtol, gtol, ftol,
Packit 67cb25
                                       NULL, NULL, &info, w);
Packit 67cb25
  gsl_test(status, "%s/%s did not converge, status=%s",
Packit 67cb25
           sname, pname, gsl_strerror(status));
Packit 67cb25
Packit 67cb25
  /* check solution */
Packit 67cb25
  test_fdf_checksol(sname, pname, epsrel, w, problem);
Packit 67cb25
Packit 67cb25
  if (problem->weights == NULL)
Packit 67cb25
    {
Packit 67cb25
      /* test again with weighting matrix W = I */
Packit 67cb25
      gsl_vector *wv = gsl_vector_alloc(n);
Packit 67cb25
Packit 67cb25
      sprintf(sname, "%s/weighted", buf);
Packit 67cb25
Packit 67cb25
      gsl_vector_memcpy(x0, &x0v.vector);
Packit 67cb25
Packit 67cb25
      gsl_vector_set_all(wv, 1.0);
Packit 67cb25
      gsl_multifit_nlinear_winit(x0, wv, fdf, w);
Packit 67cb25
  
Packit 67cb25
      status = gsl_multifit_nlinear_driver(max_iter, xtol, gtol, ftol,
Packit 67cb25
                                           NULL, NULL, &info, w);
Packit 67cb25
      gsl_test(status, "%s/%s did not converge, status=%s",
Packit 67cb25
               sname, pname, gsl_strerror(status));
Packit 67cb25
Packit 67cb25
      test_fdf_checksol(sname, pname, epsrel, w, problem);
Packit 67cb25
Packit 67cb25
      gsl_vector_free(wv);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  gsl_multifit_nlinear_free(w);
Packit 67cb25
  gsl_vector_free(x0);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
test_fdf_checksol(const char *sname, const char *pname,
Packit 67cb25
                  const double epsrel,
Packit 67cb25
                  gsl_multifit_nlinear_workspace *w,
Packit 67cb25
                  test_fdf_problem *problem)
Packit 67cb25
{
Packit 67cb25
  gsl_multifit_nlinear_fdf *fdf = problem->fdf;
Packit 67cb25
  const double *sigma = problem->sigma;
Packit 67cb25
  gsl_vector *f = gsl_multifit_nlinear_residual(w);
Packit 67cb25
  gsl_vector *x = gsl_multifit_nlinear_position(w);
Packit 67cb25
  double sumsq;
Packit 67cb25
Packit 67cb25
  /* check solution vector x and sumsq = ||f||^2 */
Packit 67cb25
  gsl_blas_ddot(f, f, &sumsq);
Packit 67cb25
  (problem->checksol)(x->data, sumsq, epsrel, sname, pname);
Packit 67cb25
Packit 67cb25
  /* check variances */
Packit 67cb25
  if (sigma)
Packit 67cb25
    {
Packit 67cb25
      const size_t n = fdf->n;
Packit 67cb25
      const size_t p = fdf->p;
Packit 67cb25
      size_t i;
Packit 67cb25
      gsl_matrix * covar = gsl_matrix_alloc (p, p);
Packit 67cb25
      gsl_matrix *J = gsl_multifit_nlinear_jac (w);
Packit 67cb25
Packit 67cb25
      gsl_multifit_nlinear_covar (J, 0.0, covar);
Packit 67cb25
Packit 67cb25
      for (i = 0; i < p; i++) 
Packit 67cb25
        {
Packit 67cb25
          double ei = sqrt(sumsq/(n-p))*sqrt(gsl_matrix_get(covar,i,i));
Packit 67cb25
          gsl_test_rel (ei, sigma[i], epsrel, 
Packit 67cb25
                        "%s/%s, sigma(%d)", sname, pname, i) ;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      gsl_matrix_free (covar);
Packit 67cb25
    }
Packit 67cb25
}