|
Packit |
67cb25 |
#include <gsl/gsl_math.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_vector.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_matrix.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_rng.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_randist.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_multifit.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_multilarge.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_blas.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* function to be fitted */
|
|
Packit |
67cb25 |
double
|
|
Packit |
67cb25 |
func(const double t)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double x = sin(10.0 * t);
|
|
Packit |
67cb25 |
return exp(x*x*x);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* construct a row of the least squares matrix */
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
build_row(const double t, gsl_vector *row)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t p = row->size;
|
|
Packit |
67cb25 |
double Xj = 1.0;
|
|
Packit |
67cb25 |
size_t j;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (j = 0; j < p; ++j)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_vector_set(row, j, Xj);
|
|
Packit |
67cb25 |
Xj *= t;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return 0;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
solve_system(const int print_data, const gsl_multilarge_linear_type * T,
|
|
Packit |
67cb25 |
const double lambda, const size_t n, const size_t p,
|
|
Packit |
67cb25 |
gsl_vector * c)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t nblock = 5; /* number of blocks to accumulate */
|
|
Packit |
67cb25 |
const size_t nrows = n / nblock; /* number of rows per block */
|
|
Packit |
67cb25 |
gsl_multilarge_linear_workspace * w =
|
|
Packit |
67cb25 |
gsl_multilarge_linear_alloc(T, p);
|
|
Packit |
67cb25 |
gsl_matrix *X = gsl_matrix_alloc(nrows, p);
|
|
Packit |
67cb25 |
gsl_vector *y = gsl_vector_alloc(nrows);
|
|
Packit |
67cb25 |
gsl_rng *r = gsl_rng_alloc(gsl_rng_default);
|
|
Packit |
67cb25 |
const size_t nlcurve = 200;
|
|
Packit |
67cb25 |
gsl_vector *reg_param = gsl_vector_alloc(nlcurve);
|
|
Packit |
67cb25 |
gsl_vector *rho = gsl_vector_alloc(nlcurve);
|
|
Packit |
67cb25 |
gsl_vector *eta = gsl_vector_alloc(nlcurve);
|
|
Packit |
67cb25 |
size_t rowidx = 0;
|
|
Packit |
67cb25 |
double rnorm, snorm, rcond;
|
|
Packit |
67cb25 |
double t = 0.0;
|
|
Packit |
67cb25 |
double dt = 1.0 / (n - 1.0);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
while (rowidx < n)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t nleft = n - rowidx; /* number of rows left to accumulate */
|
|
Packit |
67cb25 |
size_t nr = GSL_MIN(nrows, nleft); /* number of rows in this block */
|
|
Packit |
67cb25 |
gsl_matrix_view Xv = gsl_matrix_submatrix(X, 0, 0, nr, p);
|
|
Packit |
67cb25 |
gsl_vector_view yv = gsl_vector_subvector(y, 0, nr);
|
|
Packit |
67cb25 |
size_t i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* build (X,y) block with 'nr' rows */
|
|
Packit |
67cb25 |
for (i = 0; i < nr; ++i)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_vector_view row = gsl_matrix_row(&Xv.matrix, i);
|
|
Packit |
67cb25 |
double fi = func(t);
|
|
Packit |
67cb25 |
double ei = gsl_ran_gaussian (r, 0.1 * fi); /* noise */
|
|
Packit |
67cb25 |
double yi = fi + ei;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* construct this row of LS matrix */
|
|
Packit |
67cb25 |
build_row(t, &row.vector);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* set right hand side value with added noise */
|
|
Packit |
67cb25 |
gsl_vector_set(&yv.vector, i, yi);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (print_data && (i % 100 == 0))
|
|
Packit |
67cb25 |
printf("%f %f\n", t, yi);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
t += dt;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* accumulate (X,y) block into LS system */
|
|
Packit |
67cb25 |
gsl_multilarge_linear_accumulate(&Xv.matrix, &yv.vector, w);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
rowidx += nr;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (print_data)
|
|
Packit |
67cb25 |
printf("\n\n");
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* compute L-curve */
|
|
Packit |
67cb25 |
gsl_multilarge_linear_lcurve(reg_param, rho, eta, w);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* solve large LS system and store solution in c */
|
|
Packit |
67cb25 |
gsl_multilarge_linear_solve(lambda, c, &rnorm, &snorm, w);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* compute reciprocal condition number */
|
|
Packit |
67cb25 |
gsl_multilarge_linear_rcond(&rcond, w);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
fprintf(stderr, "=== Method %s ===\n", gsl_multilarge_linear_name(w));
|
|
Packit |
67cb25 |
fprintf(stderr, "condition number = %e\n", 1.0 / rcond);
|
|
Packit |
67cb25 |
fprintf(stderr, "residual norm = %e\n", rnorm);
|
|
Packit |
67cb25 |
fprintf(stderr, "solution norm = %e\n", snorm);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* output L-curve */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t i;
|
|
Packit |
67cb25 |
for (i = 0; i < nlcurve; ++i)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
printf("%.12e %.12e %.12e\n",
|
|
Packit |
67cb25 |
gsl_vector_get(reg_param, i),
|
|
Packit |
67cb25 |
gsl_vector_get(rho, i),
|
|
Packit |
67cb25 |
gsl_vector_get(eta, i));
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
printf("\n\n");
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_matrix_free(X);
|
|
Packit |
67cb25 |
gsl_vector_free(y);
|
|
Packit |
67cb25 |
gsl_multilarge_linear_free(w);
|
|
Packit |
67cb25 |
gsl_rng_free(r);
|
|
Packit |
67cb25 |
gsl_vector_free(reg_param);
|
|
Packit |
67cb25 |
gsl_vector_free(rho);
|
|
Packit |
67cb25 |
gsl_vector_free(eta);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return 0;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
main(int argc, char *argv[])
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t n = 50000; /* number of observations */
|
|
Packit |
67cb25 |
const size_t p = 16; /* polynomial order + 1 */
|
|
Packit |
67cb25 |
double lambda = 0.0; /* regularization parameter */
|
|
Packit |
67cb25 |
gsl_vector *c_tsqr = gsl_vector_alloc(p);
|
|
Packit |
67cb25 |
gsl_vector *c_normal = gsl_vector_alloc(p);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (argc > 1)
|
|
Packit |
67cb25 |
lambda = atof(argv[1]);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* solve system with TSQR method */
|
|
Packit |
67cb25 |
solve_system(1, gsl_multilarge_linear_tsqr, lambda, n, p, c_tsqr);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* solve system with Normal equations method */
|
|
Packit |
67cb25 |
solve_system(0, gsl_multilarge_linear_normal, lambda, n, p, c_normal);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* output solutions */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_vector *v = gsl_vector_alloc(p);
|
|
Packit |
67cb25 |
double t;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (t = 0.0; t <= 1.0; t += 0.01)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double f_exact = func(t);
|
|
Packit |
67cb25 |
double f_tsqr, f_normal;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
build_row(t, v);
|
|
Packit |
67cb25 |
gsl_blas_ddot(v, c_tsqr, &f_tsqr);
|
|
Packit |
67cb25 |
gsl_blas_ddot(v, c_normal, &f_normal);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
printf("%f %e %e %e\n", t, f_exact, f_tsqr, f_normal);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_free(v);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_vector_free(c_tsqr);
|
|
Packit |
67cb25 |
gsl_vector_free(c_normal);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return 0;
|
|
Packit |
67cb25 |
}
|