|
Packit |
67cb25 |
/* multifit/lmpar.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
|
|
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 |
#include <gsl/gsl_permute_vector_double.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include "qrsolv.c"
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static size_t
|
|
Packit |
67cb25 |
count_nsing (const gsl_matrix * r)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Count the number of nonsingular entries. Returns the index of the
|
|
Packit |
67cb25 |
first entry which is singular. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t n = r->size2;
|
|
Packit |
67cb25 |
size_t i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < n; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double rii = gsl_matrix_get (r, i, i);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (rii == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
break;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return i;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
compute_newton_direction (const gsl_matrix * r, const gsl_permutation * perm,
|
|
Packit |
67cb25 |
const gsl_vector * qtf, gsl_vector * x)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Compute and store in x the Gauss-Newton direction. If the
|
|
Packit |
67cb25 |
Jacobian is rank-deficient then obtain a least squares
|
|
Packit |
67cb25 |
solution. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
const size_t n = r->size2;
|
|
Packit |
67cb25 |
size_t i, j, nsing;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0 ; i < n ; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double qtfi = gsl_vector_get (qtf, i);
|
|
Packit |
67cb25 |
gsl_vector_set (x, i, qtfi);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
nsing = count_nsing (r);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("nsing = %d\n", nsing);
|
|
Packit |
67cb25 |
printf("r = "); gsl_matrix_fprintf(stdout, r, "%g"); printf("\n");
|
|
Packit |
67cb25 |
printf("qtf = "); gsl_vector_fprintf(stdout, x, "%g"); printf("\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = nsing; i < n; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_vector_set (x, i, 0.0);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (nsing > 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
for (j = nsing; j > 0 && j--;)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double rjj = gsl_matrix_get (r, j, j);
|
|
Packit |
67cb25 |
double temp = gsl_vector_get (x, j) / rjj;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (x, j, temp);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < j; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double rij = gsl_matrix_get (r, i, j);
|
|
Packit |
67cb25 |
double xi = gsl_vector_get (x, i);
|
|
Packit |
67cb25 |
gsl_vector_set (x, i, xi - rij * temp);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_permute_vector_inverse (perm, x);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
compute_newton_correction (const gsl_matrix * r, const gsl_vector * sdiag,
|
|
Packit |
67cb25 |
const gsl_permutation * p, gsl_vector * x,
|
|
Packit |
67cb25 |
double dxnorm,
|
|
Packit |
67cb25 |
const gsl_vector * diag, gsl_vector * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t n = r->size2;
|
|
Packit |
67cb25 |
size_t i, j;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < n; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t pi = gsl_permutation_get (p, i);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double dpi = gsl_vector_get (diag, pi);
|
|
Packit |
67cb25 |
double xpi = gsl_vector_get (x, pi);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (w, i, dpi * (dpi * xpi) / dxnorm);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (j = 0; j < n; j++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double sj = gsl_vector_get (sdiag, j);
|
|
Packit |
67cb25 |
double wj = gsl_vector_get (w, j);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double tj = wj / sj;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (w, j, tj);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = j + 1; i < n; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double rij = gsl_matrix_get (r, i, j);
|
|
Packit |
67cb25 |
double wi = gsl_vector_get (w, i);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (w, i, wi - rij * tj);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
compute_newton_bound (const gsl_matrix * r, const gsl_vector * x,
|
|
Packit |
67cb25 |
double dxnorm, const gsl_permutation * perm,
|
|
Packit |
67cb25 |
const gsl_vector * diag, gsl_vector * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* If the jacobian is not rank-deficient then the Newton step
|
|
Packit |
67cb25 |
provides a lower bound for the zero of the function. Otherwise
|
|
Packit |
67cb25 |
set this bound to zero. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t n = r->size2;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t i, j;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t nsing = count_nsing (r);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (nsing < n)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_vector_set_zero (w);
|
|
Packit |
67cb25 |
return;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < n; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t pi = gsl_permutation_get (perm, i);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double dpi = gsl_vector_get (diag, pi);
|
|
Packit |
67cb25 |
double xpi = gsl_vector_get (x, pi);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (w, i, dpi * (dpi * xpi / dxnorm));
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (j = 0; j < n; j++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double sum = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < j; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
sum += gsl_matrix_get (r, i, j) * gsl_vector_get (w, i);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double rjj = gsl_matrix_get (r, j, j);
|
|
Packit |
67cb25 |
double wj = gsl_vector_get (w, j);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (w, j, (wj - sum) / rjj);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* compute scaled gradient g = D^{-1} J^T f (see More' eq 7.2) */
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
compute_gradient_direction (const gsl_matrix * r, const gsl_permutation * p,
|
|
Packit |
67cb25 |
const gsl_vector * qtf, const gsl_vector * diag,
|
|
Packit |
67cb25 |
gsl_vector * g)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = r->size2;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t i, j;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (j = 0; j < n; j++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double sum = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i <= j; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
sum += gsl_matrix_get (r, i, j) * gsl_vector_get (qtf, i);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t pj = gsl_permutation_get (p, j);
|
|
Packit |
67cb25 |
double dpj = gsl_vector_get (diag, pj);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (g, j, sum / dpj);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* compute gradient g = J^T f */
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
compute_gradient (const gsl_matrix * r, const gsl_vector * qtf,
|
|
Packit |
67cb25 |
gsl_vector * g)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = r->size2;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t i, j;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (j = 0; j < n; j++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double sum = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i <= j; i++)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
sum += gsl_matrix_get (r, i, j) * gsl_vector_get (qtf, i);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_set (g, j, sum);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
lmpar (gsl_matrix * r, const gsl_permutation * perm, const gsl_vector * qtf,
|
|
Packit |
67cb25 |
const gsl_vector * diag, double delta, double * par_inout,
|
|
Packit |
67cb25 |
gsl_vector * newton, gsl_vector * gradient, gsl_vector * sdiag,
|
|
Packit |
67cb25 |
gsl_vector * x, gsl_vector * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double dxnorm, gnorm, fp, fp_old, par_lower, par_upper, par_c;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double par = *par_inout;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t iter = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("ENTERING lmpar\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
compute_newton_direction (r, perm, qtf, newton);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf ("newton = ");
|
|
Packit |
67cb25 |
gsl_vector_fprintf (stdout, newton, "%g");
|
|
Packit |
67cb25 |
printf ("\n");
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
printf ("diag = ");
|
|
Packit |
67cb25 |
gsl_vector_fprintf (stdout, diag, "%g");
|
|
Packit |
67cb25 |
printf ("\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate the function at the origin and test for acceptance of
|
|
Packit |
67cb25 |
the Gauss-Newton direction. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
dxnorm = scaled_enorm (diag, newton);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
fp = dxnorm - delta;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf ("dxnorm = %g, delta = %g, fp = %g\n", dxnorm, delta, fp);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (fp <= 0.1 * delta)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_vector_memcpy (x, newton);
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf ("took newton (fp = %g, delta = %g)\n", fp, delta);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
*par_inout = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf ("r = ");
|
|
Packit |
67cb25 |
gsl_matrix_fprintf (stdout, r, "%g");
|
|
Packit |
67cb25 |
printf ("\n");
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
printf ("newton = ");
|
|
Packit |
67cb25 |
gsl_vector_fprintf (stdout, newton, "%g");
|
|
Packit |
67cb25 |
printf ("\n");
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
printf ("dxnorm = %g\n", dxnorm);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
compute_newton_bound (r, newton, dxnorm, perm, diag, w);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("perm = "); gsl_permutation_fprintf(stdout, perm, "%d");
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
printf ("diag = ");
|
|
Packit |
67cb25 |
gsl_vector_fprintf (stdout, diag, "%g");
|
|
Packit |
67cb25 |
printf ("\n");
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
printf ("w = ");
|
|
Packit |
67cb25 |
gsl_vector_fprintf (stdout, w, "%g");
|
|
Packit |
67cb25 |
printf ("\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double wnorm = enorm (w);
|
|
Packit |
67cb25 |
double phider = wnorm * wnorm;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* w == zero if r rank-deficient,
|
|
Packit |
67cb25 |
then set lower bound to zero form MINPACK, lmder.f
|
|
Packit |
67cb25 |
Hans E. Plesser 2002-02-25 (hans.plesser@itf.nlh.no) */
|
|
Packit |
67cb25 |
if ( wnorm > 0 )
|
|
Packit |
67cb25 |
par_lower = fp / (delta * phider);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
par_lower = 0.0;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("par = %g\n", par );
|
|
Packit |
67cb25 |
printf("par_lower = %g\n", par_lower);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
compute_gradient_direction (r, perm, qtf, diag, gradient);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gnorm = enorm (gradient);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("gradient = "); gsl_vector_fprintf(stdout, gradient, "%g"); printf("\n");
|
|
Packit |
67cb25 |
printf("gnorm = %g\n", gnorm);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
par_upper = gnorm / delta;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (par_upper == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
par_upper = GSL_DBL_MIN / GSL_MIN_DBL(delta, 0.1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("par_upper = %g\n", par_upper);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (par > par_upper)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("set par to par_upper\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
par = par_upper;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (par < par_lower)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("set par to par_lower\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
par = par_lower;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (par == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
par = gnorm / dxnorm;
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("set par to gnorm/dxnorm = %g\n", par);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Beginning of iteration */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
iteration:
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
iter++;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("lmpar iteration = %d\n", iter);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef BRIANSFIX
|
|
Packit |
67cb25 |
/* Seems like this is described in the paper but not in the MINPACK code */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (par < par_lower || par > par_upper)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
par = GSL_MAX_DBL (0.001 * par_upper, sqrt(par_lower * par_upper));
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate the function at the current value of par */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (par == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
par = GSL_MAX_DBL (0.001 * par_upper, GSL_DBL_MIN);
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("par = 0, set par to = %g\n", par);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Compute the least squares solution of [ R P x - Q^T f, sqrt(par) D x]
|
|
Packit |
67cb25 |
for A = Q R P^T */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf ("calling qrsolv with par = %g\n", par);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double sqrt_par = sqrt(par);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
qrsolv (r, perm, sqrt_par, diag, qtf, x, sdiag, w);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
dxnorm = scaled_enorm (diag, x);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
fp_old = fp;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
fp = dxnorm - delta;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf ("After qrsolv dxnorm = %g, delta = %g, fp = %g\n", dxnorm, delta, fp);
|
|
Packit |
67cb25 |
printf ("sdiag = ") ; gsl_vector_fprintf(stdout, sdiag, "%g"); printf("\n");
|
|
Packit |
67cb25 |
printf ("x = ") ; gsl_vector_fprintf(stdout, x, "%g"); printf("\n");
|
|
Packit |
67cb25 |
printf ("r = ") ; gsl_matrix_fprintf(stdout, r, "%g"); printf("\nXXX\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* If the function is small enough, accept the current value of par */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (fabs (fp) <= 0.1 * delta)
|
|
Packit |
67cb25 |
goto line220;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (par_lower == 0 && fp <= fp_old && fp_old < 0)
|
|
Packit |
67cb25 |
goto line220;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Check for maximum number of iterations */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (iter == 10)
|
|
Packit |
67cb25 |
goto line220;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Compute the Newton correction */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
compute_newton_correction (r, sdiag, perm, x, dxnorm, diag, w);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf ("newton_correction = ");
|
|
Packit |
67cb25 |
gsl_vector_fprintf(stdout, w, "%g"); printf("\n");
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double wnorm = enorm (w);
|
|
Packit |
67cb25 |
par_c = fp / (delta * wnorm * wnorm);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("fp = %g\n", fp);
|
|
Packit |
67cb25 |
printf("par_lower = %g\n", par_lower);
|
|
Packit |
67cb25 |
printf("par_upper = %g\n", par_upper);
|
|
Packit |
67cb25 |
printf("par_c = %g\n", par_c);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Depending on the sign of the function, update par_lower or par_upper */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (fp > 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (par > par_lower)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
par_lower = par;
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("fp > 0: set par_lower = par = %g\n", par);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (fp < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (par < par_upper)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("fp < 0: set par_upper = par = %g\n", par);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
par_upper = par;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Compute an improved estimate for par */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("improved estimate par = MAX(%g, %g) \n", par_lower, par+par_c);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
par = GSL_MAX_DBL (par_lower, par + par_c);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("improved estimate par = %g \n", par);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
goto iteration;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
line220:
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifdef DEBUG
|
|
Packit |
67cb25 |
printf("LEAVING lmpar, par = %g\n", par);
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
*par_inout = par;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|