Blame doc/examples/largefit.c

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
}