|
Packit |
67cb25 |
/* multifit/fdfridge.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 2014 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 |
#include <config.h>
|
|
Packit |
67cb25 |
#include <stdlib.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_math.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_vector.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_matrix.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_multifit_nlin.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_blas.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int fdfridge_f(const gsl_vector * x, void * params, gsl_vector * f);
|
|
Packit |
67cb25 |
static int fdfridge_df(const gsl_vector * x, void * params, gsl_matrix * J);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge *
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_alloc (const gsl_multifit_fdfsolver_type * T,
|
|
Packit |
67cb25 |
const size_t n, const size_t p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge * work;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
work = calloc(1, sizeof(gsl_multifit_fdfridge));
|
|
Packit |
67cb25 |
if (work == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_VAL("failed to allocate workspace",
|
|
Packit |
67cb25 |
GSL_ENOMEM, 0);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
work->s = gsl_multifit_fdfsolver_alloc (T, n + p, p);
|
|
Packit |
67cb25 |
if (work->s == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_free(work);
|
|
Packit |
67cb25 |
GSL_ERROR_VAL("failed to allocate space for fdfsolver",
|
|
Packit |
67cb25 |
GSL_ENOMEM, 0);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
work->wts = gsl_vector_alloc(n + p);
|
|
Packit |
67cb25 |
if (work->wts == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_free(work);
|
|
Packit |
67cb25 |
GSL_ERROR_VAL("failed to allocate space for weight vector",
|
|
Packit |
67cb25 |
GSL_ENOMEM, 0);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
work->f = gsl_vector_alloc(n);
|
|
Packit |
67cb25 |
if (work->f == NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_free(work);
|
|
Packit |
67cb25 |
GSL_ERROR_VAL("failed to allocate space for f vector",
|
|
Packit |
67cb25 |
GSL_ENOMEM, 0);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
work->n = n;
|
|
Packit |
67cb25 |
work->p = p;
|
|
Packit |
67cb25 |
work->lambda = 0.0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* initialize weights to 1 (for augmented portion of vector) */
|
|
Packit |
67cb25 |
gsl_vector_set_all(work->wts, 1.0);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return work;
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_alloc() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
void
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_free(gsl_multifit_fdfridge *work)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (work->s)
|
|
Packit |
67cb25 |
gsl_multifit_fdfsolver_free(work->s);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (work->wts)
|
|
Packit |
67cb25 |
gsl_vector_free(work->wts);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (work->f)
|
|
Packit |
67cb25 |
gsl_vector_free(work->f);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
free(work);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
const char *
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_name(const gsl_multifit_fdfridge * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return gsl_multifit_fdfsolver_name(w->s);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector *
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_position (const gsl_multifit_fdfridge * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return gsl_multifit_fdfsolver_position(w->s);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector *
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_residual (const gsl_multifit_fdfridge * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return gsl_multifit_fdfsolver_residual(w->s);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
size_t
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_niter (const gsl_multifit_fdfridge * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return w->s->niter;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_set (gsl_multifit_fdfridge * w,
|
|
Packit |
67cb25 |
gsl_multifit_function_fdf * f,
|
|
Packit |
67cb25 |
const gsl_vector * x,
|
|
Packit |
67cb25 |
const double lambda)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return gsl_multifit_fdfridge_wset(w, f, x, lambda, NULL);
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_set() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_wset (gsl_multifit_fdfridge * w,
|
|
Packit |
67cb25 |
gsl_multifit_function_fdf * f,
|
|
Packit |
67cb25 |
const gsl_vector * x,
|
|
Packit |
67cb25 |
const double lambda,
|
|
Packit |
67cb25 |
const gsl_vector * wts)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = w->n;
|
|
Packit |
67cb25 |
const size_t p = w->p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (n != f->n || p != f->p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("function size does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (p != x->size)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("vector length does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (wts != NULL && n != wts->size)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("weight vector length does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
gsl_vector_view wv = gsl_vector_subvector(w->wts, 0, n);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* save user defined fdf */
|
|
Packit |
67cb25 |
w->fdf = f;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* build modified fdf for Tikhonov terms */
|
|
Packit |
67cb25 |
w->fdftik.f = &fdfridge_f;
|
|
Packit |
67cb25 |
w->fdftik.df = &fdfridge_df;
|
|
Packit |
67cb25 |
w->fdftik.n = n + p; /* add p for Tikhonov terms */
|
|
Packit |
67cb25 |
w->fdftik.p = p;
|
|
Packit |
67cb25 |
w->fdftik.params = (void *) w;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* store damping parameter */
|
|
Packit |
67cb25 |
w->lambda = lambda;
|
|
Packit |
67cb25 |
w->L = NULL;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (wts)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* copy weight vector into user portion of w->wts */
|
|
Packit |
67cb25 |
gsl_vector_memcpy(&wv.vector, wts);
|
|
Packit |
67cb25 |
status = gsl_multifit_fdfsolver_wset(w->s, &(w->fdftik), x, w->wts);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
status = gsl_multifit_fdfsolver_wset(w->s, &(w->fdftik), x, NULL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* update function/Jacobian evaluations */
|
|
Packit |
67cb25 |
f->nevalf = w->fdftik.nevalf;
|
|
Packit |
67cb25 |
f->nevaldf = w->fdftik.nevaldf;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_wset() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_set2 (gsl_multifit_fdfridge * w,
|
|
Packit |
67cb25 |
gsl_multifit_function_fdf * f,
|
|
Packit |
67cb25 |
const gsl_vector * x,
|
|
Packit |
67cb25 |
const gsl_vector * lambda)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return gsl_multifit_fdfridge_wset2(w, f, x, lambda, NULL);
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_set2() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_wset2 (gsl_multifit_fdfridge * w,
|
|
Packit |
67cb25 |
gsl_multifit_function_fdf * f,
|
|
Packit |
67cb25 |
const gsl_vector * x,
|
|
Packit |
67cb25 |
const gsl_vector * lambda,
|
|
Packit |
67cb25 |
const gsl_vector * wts)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = w->n;
|
|
Packit |
67cb25 |
const size_t p = w->p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (n != f->n || p != f->p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("function size does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (p != x->size)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("vector length does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (lambda->size != p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("lambda vector size does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (wts != NULL && n != wts->size)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("weight vector length does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
gsl_vector_view wv = gsl_vector_subvector(w->wts, 0, n);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* save user defined fdf */
|
|
Packit |
67cb25 |
w->fdf = f;
|
|
Packit |
67cb25 |
w->fdf->nevalf = 0;
|
|
Packit |
67cb25 |
w->fdf->nevaldf = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* build modified fdf for Tikhonov terms */
|
|
Packit |
67cb25 |
w->fdftik.f = &fdfridge_f;
|
|
Packit |
67cb25 |
w->fdftik.df = &fdfridge_df;
|
|
Packit |
67cb25 |
w->fdftik.n = n + p; /* add p for Tikhonov terms */
|
|
Packit |
67cb25 |
w->fdftik.p = p;
|
|
Packit |
67cb25 |
w->fdftik.params = (void *) w;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* store damping matrix */
|
|
Packit |
67cb25 |
w->lambda = 0.0;
|
|
Packit |
67cb25 |
w->L_diag = lambda;
|
|
Packit |
67cb25 |
w->L = NULL;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (wts)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* copy weight vector into user portion */
|
|
Packit |
67cb25 |
gsl_vector_memcpy(&wv.vector, wts);
|
|
Packit |
67cb25 |
status = gsl_multifit_fdfsolver_wset(w->s, &(w->fdftik), x, w->wts);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
status = gsl_multifit_fdfsolver_wset(w->s, &(w->fdftik), x, NULL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* update function/Jacobian evaluations */
|
|
Packit |
67cb25 |
f->nevalf = w->fdftik.nevalf;
|
|
Packit |
67cb25 |
f->nevaldf = w->fdftik.nevaldf;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_wset2() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_set3 (gsl_multifit_fdfridge * w,
|
|
Packit |
67cb25 |
gsl_multifit_function_fdf * f,
|
|
Packit |
67cb25 |
const gsl_vector * x,
|
|
Packit |
67cb25 |
const gsl_matrix * L)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return gsl_multifit_fdfridge_wset3(w, f, x, L, NULL);
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_set3() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_wset3 (gsl_multifit_fdfridge * w,
|
|
Packit |
67cb25 |
gsl_multifit_function_fdf * f,
|
|
Packit |
67cb25 |
const gsl_vector * x,
|
|
Packit |
67cb25 |
const gsl_matrix * L,
|
|
Packit |
67cb25 |
const gsl_vector * wts)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = w->n;
|
|
Packit |
67cb25 |
const size_t p = w->p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (n != f->n || p != f->p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("function size does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (p != x->size)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("vector length does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (L->size2 != p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("L matrix size2 does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (wts != NULL && n != wts->size)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR ("weight vector length does not match solver", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
gsl_vector_view wv = gsl_vector_subvector(w->wts, 0, n);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* save user defined fdf */
|
|
Packit |
67cb25 |
w->fdf = f;
|
|
Packit |
67cb25 |
w->fdf->nevalf = 0;
|
|
Packit |
67cb25 |
w->fdf->nevaldf = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* build modified fdf for Tikhonov terms */
|
|
Packit |
67cb25 |
w->fdftik.f = &fdfridge_f;
|
|
Packit |
67cb25 |
w->fdftik.df = &fdfridge_df;
|
|
Packit |
67cb25 |
w->fdftik.n = n + p; /* add p for Tikhonov terms */
|
|
Packit |
67cb25 |
w->fdftik.p = p;
|
|
Packit |
67cb25 |
w->fdftik.params = (void *) w;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* store damping matrix */
|
|
Packit |
67cb25 |
w->lambda = 0.0;
|
|
Packit |
67cb25 |
w->L_diag = NULL;
|
|
Packit |
67cb25 |
w->L = L;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (wts)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* copy weight vector into user portion */
|
|
Packit |
67cb25 |
gsl_vector_memcpy(&wv.vector, wts);
|
|
Packit |
67cb25 |
status = gsl_multifit_fdfsolver_wset(w->s, &(w->fdftik), x, w->wts);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
status = gsl_multifit_fdfsolver_wset(w->s, &(w->fdftik), x, NULL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* update function/Jacobian evaluations */
|
|
Packit |
67cb25 |
f->nevalf = w->fdftik.nevalf;
|
|
Packit |
67cb25 |
f->nevaldf = w->fdftik.nevaldf;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_wset3() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_iterate (gsl_multifit_fdfridge * w)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status = gsl_multifit_fdfsolver_iterate(w->s);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* update function/Jacobian evaluations */
|
|
Packit |
67cb25 |
w->fdf->nevalf = w->fdftik.nevalf;
|
|
Packit |
67cb25 |
w->fdf->nevaldf = w->fdftik.nevaldf;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge_driver (gsl_multifit_fdfridge * w,
|
|
Packit |
67cb25 |
const size_t maxiter,
|
|
Packit |
67cb25 |
const double xtol,
|
|
Packit |
67cb25 |
const double gtol,
|
|
Packit |
67cb25 |
const double ftol,
|
|
Packit |
67cb25 |
int *info)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status = gsl_multifit_fdfsolver_driver(w->s, maxiter, xtol,
|
|
Packit |
67cb25 |
gtol, ftol, info);
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
} /* gsl_multifit_fdfridge_driver() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
fdfridge_f()
|
|
Packit |
67cb25 |
Callback function to provide residuals, including extra p
|
|
Packit |
67cb25 |
Tikhonov terms. The residual vector will have the form:
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
f~ = [ f ]
|
|
Packit |
67cb25 |
[ \lambda x ]
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
where f is the user supplied residuals, x are the model
|
|
Packit |
67cb25 |
parameters, and \lambda is the Tikhonov damping parameter
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: x - model parameters (size p)
|
|
Packit |
67cb25 |
params - pointer to fdfridge workspace
|
|
Packit |
67cb25 |
f - (output) (n+p) vector to store f~
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
fdfridge_f(const gsl_vector * x, void * params, gsl_vector * f)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge *w = (gsl_multifit_fdfridge *) params;
|
|
Packit |
67cb25 |
const size_t n = w->n;
|
|
Packit |
67cb25 |
const size_t p = w->p;
|
|
Packit |
67cb25 |
gsl_vector_view f_user = gsl_vector_subvector(f, 0, n);
|
|
Packit |
67cb25 |
gsl_vector_view f_tik = gsl_vector_subvector(f, n, p);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* call user callback function to get residual vector f */
|
|
Packit |
67cb25 |
status = gsl_multifit_eval_wf(w->fdf, x, NULL, &f_user.vector);
|
|
Packit |
67cb25 |
if (status)
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (w->L_diag)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* store diag(L_diag) x in Tikhonov portion of f~ */
|
|
Packit |
67cb25 |
gsl_vector_memcpy(&f_tik.vector, x);
|
|
Packit |
67cb25 |
gsl_vector_mul(&f_tik.vector, w->L_diag);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (w->L)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* store Lx in Tikhonov portion of f~ */
|
|
Packit |
67cb25 |
gsl_blas_dgemv(CblasNoTrans, 1.0, w->L, x, 0.0, &f_tik.vector);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* store \lambda x in Tikhonov portion of f~ */
|
|
Packit |
67cb25 |
gsl_vector_memcpy(&f_tik.vector, x);
|
|
Packit |
67cb25 |
gsl_vector_scale(&f_tik.vector, w->lambda);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
} /* fdfridge_f() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
fdfridge_df(const gsl_vector * x, void * params, gsl_matrix * J)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
gsl_multifit_fdfridge *w = (gsl_multifit_fdfridge *) params;
|
|
Packit |
67cb25 |
const size_t n = w->n;
|
|
Packit |
67cb25 |
const size_t p = w->p;
|
|
Packit |
67cb25 |
gsl_matrix_view J_user = gsl_matrix_submatrix(J, 0, 0, n, p);
|
|
Packit |
67cb25 |
gsl_matrix_view J_tik = gsl_matrix_submatrix(J, n, 0, p, p);
|
|
Packit |
67cb25 |
gsl_vector_view diag = gsl_matrix_diagonal(&J_tik.matrix);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* compute Jacobian */
|
|
Packit |
67cb25 |
if (w->fdf->df)
|
|
Packit |
67cb25 |
status = gsl_multifit_eval_wdf(w->fdf, x, NULL, &J_user.matrix);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* compute f(x) and then finite difference Jacobian */
|
|
Packit |
67cb25 |
status = gsl_multifit_eval_wf(w->fdf, x, NULL, w->f);
|
|
Packit |
67cb25 |
status += gsl_multifit_fdfsolver_dif_df(x, NULL, w->fdf, w->f,
|
|
Packit |
67cb25 |
&J_user.matrix);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (status)
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (w->L_diag)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* store diag(L_diag) in Tikhonov portion of J */
|
|
Packit |
67cb25 |
gsl_matrix_set_zero(&J_tik.matrix);
|
|
Packit |
67cb25 |
gsl_vector_memcpy(&diag.vector, w->L_diag);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (w->L)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* store L in Tikhonov portion of J */
|
|
Packit |
67cb25 |
gsl_matrix_memcpy(&J_tik.matrix, w->L);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* store \lambda I_p in Tikhonov portion of J */
|
|
Packit |
67cb25 |
gsl_matrix_set_zero(&J_tik.matrix);
|
|
Packit |
67cb25 |
gsl_vector_set_all(&diag.vector, w->lambda);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
} /* fdfridge_df() */
|