Blame monte/vegas.c

Packit 67cb25
/* monte/vegas.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Michael Booth
Packit 67cb25
 * Copyright (C) 2009 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
/* Author: MJB */
Packit 67cb25
/* Modified by: Brian Gough, 12/2000 */
Packit 67cb25
Packit 67cb25
/* This is an implementation of the adaptive Monte-Carlo algorithm
Packit 67cb25
   of G. P. Lepage, originally described in J. Comp. Phys. 27, 192(1978).
Packit 67cb25
   The current version of the algorithm was described in the Cornell
Packit 67cb25
   preprint CLNS-80/447 of March, 1980.
Packit 67cb25
Packit 67cb25
   This code follows most closely the c version by D.R.Yennie, coded
Packit 67cb25
   in 1984.
Packit 67cb25
Packit 67cb25
   The input coordinates are x[j], with upper and lower limits xu[j]
Packit 67cb25
   and xl[j].  The integration length in the j-th direction is
Packit 67cb25
   delx[j].  Each coordinate x[j] is rescaled to a variable y[j] in
Packit 67cb25
   the range 0 to 1.  The range is divided into bins with boundaries
Packit 67cb25
   xi[i][j], where i=0 corresponds to y=0 and i=bins to y=1.  The grid
Packit 67cb25
   is refined (ie, bins are adjusted) using d[i][j] which is some
Packit 67cb25
   variation on the squared sum.  A third parameter used in defining
Packit 67cb25
   the real coordinate using random numbers is called z.  It ranges
Packit 67cb25
   from 0 to bins.  Its integer part gives the lower index of the bin
Packit 67cb25
   into which a call is to be placed, and the remainder gives the
Packit 67cb25
   location inside the bin.
Packit 67cb25
Packit 67cb25
   When stratified sampling is used the bins are grouped into boxes,
Packit 67cb25
   and the algorithm allocates an equal number of function calls to
Packit 67cb25
   each box.
Packit 67cb25
Packit 67cb25
   The variable alpha controls how "stiff" the rebinning algorithm is.  
Packit 67cb25
   alpha = 0 means never change the grid.  Alpha is typically set between
Packit 67cb25
   1 and 2.
Packit 67cb25
Packit 67cb25
   */
Packit 67cb25
Packit 67cb25
/* configuration headers */
Packit 67cb25
#include <config.h>
Packit 67cb25
Packit 67cb25
/* standard headers */
Packit 67cb25
#include <math.h>
Packit 67cb25
#include <stdio.h>
Packit 67cb25
Packit 67cb25
/* gsl headers */
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_rng.h>
Packit 67cb25
#include <gsl/gsl_monte_vegas.h>
Packit 67cb25
Packit 67cb25
/* lib-specific headers */
Packit 67cb25
#define BINS_MAX 50             /* even integer, will be divided by two */
Packit 67cb25
Packit 67cb25
/* A separable grid with coordinates and values */
Packit 67cb25
#define COORD(s,i,j) ((s)->xi[(i)*(s)->dim + (j)])
Packit 67cb25
#define NEW_COORD(s,i) ((s)->xin[(i)])
Packit 67cb25
#define VALUE(s,i,j) ((s)->d[(i)*(s)->dim + (j)])
Packit 67cb25
Packit 67cb25
#define USE_ORIGINAL_CHISQ_FORMULA 0
Packit 67cb25
Packit 67cb25
/* predeclare functions */
Packit 67cb25
Packit 67cb25
typedef int coord;
Packit 67cb25
Packit 67cb25
static void init_grid (gsl_monte_vegas_state * s, double xl[], double xu[],
Packit 67cb25
                size_t dim);
Packit 67cb25
static void reset_grid_values (gsl_monte_vegas_state * s);
Packit 67cb25
static void init_box_coord (gsl_monte_vegas_state * s, coord box[]);
Packit 67cb25
static int change_box_coord (gsl_monte_vegas_state * s, coord box[]);
Packit 67cb25
static void accumulate_distribution (gsl_monte_vegas_state * s, coord bin[],
Packit 67cb25
                                     double y);
Packit 67cb25
static void random_point (double x[], coord bin[], double *bin_vol,
Packit 67cb25
                          const coord box[], 
Packit 67cb25
                          const double xl[], const double xu[],
Packit 67cb25
                          gsl_monte_vegas_state * s, gsl_rng * r);
Packit 67cb25
static void resize_grid (gsl_monte_vegas_state * s, unsigned int bins);
Packit 67cb25
static void refine_grid (gsl_monte_vegas_state * s);
Packit 67cb25
Packit 67cb25
static void print_lim (gsl_monte_vegas_state * state,
Packit 67cb25
                       double xl[], double xu[], unsigned long dim);
Packit 67cb25
static void print_head (gsl_monte_vegas_state * state,
Packit 67cb25
                        unsigned long num_dim, unsigned long calls,
Packit 67cb25
                        unsigned int it_num, 
Packit 67cb25
                        unsigned int bins, unsigned int boxes);
Packit 67cb25
static void print_res (gsl_monte_vegas_state * state,
Packit 67cb25
                       unsigned int itr, double res, double err, 
Packit 67cb25
                       double cum_res, double cum_err,
Packit 67cb25
                       double chi_sq);
Packit 67cb25
static void print_dist (gsl_monte_vegas_state * state, unsigned long dim);
Packit 67cb25
static void print_grid (gsl_monte_vegas_state * state, unsigned long dim);
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_monte_vegas_integrate (gsl_monte_function * f,
Packit 67cb25
                           double xl[], double xu[],
Packit 67cb25
                           size_t dim, size_t calls,
Packit 67cb25
                           gsl_rng * r,
Packit 67cb25
                           gsl_monte_vegas_state * state,
Packit 67cb25
                           double *result, double *abserr)
Packit 67cb25
{
Packit 67cb25
  double cum_int, cum_sig;
Packit 67cb25
  size_t i, k, it;
Packit 67cb25
Packit 67cb25
  if (dim != state->dim)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("number of dimensions must match allocated size", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      if (xu[i] <= xl[i])
Packit 67cb25
        {
Packit 67cb25
          GSL_ERROR ("xu must be greater than xl", GSL_EINVAL);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (xu[i] - xl[i] > GSL_DBL_MAX)
Packit 67cb25
        {
Packit 67cb25
          GSL_ERROR ("Range of integration is too large, please rescale",
Packit 67cb25
                     GSL_EINVAL);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (state->stage == 0)
Packit 67cb25
    {
Packit 67cb25
      init_grid (state, xl, xu, dim);
Packit 67cb25
Packit 67cb25
      if (state->verbose >= 0)
Packit 67cb25
        {
Packit 67cb25
          print_lim (state, xl, xu, dim);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (state->stage <= 1)
Packit 67cb25
    {
Packit 67cb25
      state->wtd_int_sum = 0;
Packit 67cb25
      state->sum_wgts = 0;
Packit 67cb25
      state->chi_sum = 0;
Packit 67cb25
      state->it_num = 1;
Packit 67cb25
      state->samples = 0;
Packit 67cb25
      state->chisq = 0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (state->stage <= 2)
Packit 67cb25
    {
Packit 67cb25
      unsigned int bins = state->bins_max;
Packit 67cb25
      unsigned int boxes = 1;
Packit 67cb25
Packit 67cb25
      if (state->mode != GSL_VEGAS_MODE_IMPORTANCE_ONLY)
Packit 67cb25
        {
Packit 67cb25
          /* shooting for 2 calls/box */
Packit 67cb25
Packit 67cb25
          boxes = floor (pow (calls / 2.0, 1.0 / dim));
Packit 67cb25
          state->mode = GSL_VEGAS_MODE_IMPORTANCE;
Packit 67cb25
Packit 67cb25
          if (2 * boxes >= state->bins_max)
Packit 67cb25
            {
Packit 67cb25
              /* if bins/box < 2 */
Packit 67cb25
              int box_per_bin = GSL_MAX (boxes / state->bins_max, 1);
Packit 67cb25
Packit 67cb25
              bins = GSL_MIN(boxes / box_per_bin, state->bins_max);
Packit 67cb25
              boxes = box_per_bin * bins;
Packit 67cb25
Packit 67cb25
              state->mode = GSL_VEGAS_MODE_STRATIFIED;
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      {
Packit 67cb25
        double tot_boxes = gsl_pow_int ((double) boxes, dim);
Packit 67cb25
        state->calls_per_box = GSL_MAX (calls / tot_boxes, 2);
Packit 67cb25
        calls = state->calls_per_box * tot_boxes;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      /* total volume of x-space/(avg num of calls/bin) */
Packit 67cb25
      state->jac = state->vol * pow ((double) bins, (double) dim) / calls;
Packit 67cb25
Packit 67cb25
      state->boxes = boxes;
Packit 67cb25
Packit 67cb25
      /* If the number of bins changes from the previous invocation, bins
Packit 67cb25
         are expanded or contracted accordingly, while preserving bin
Packit 67cb25
         density */
Packit 67cb25
Packit 67cb25
      if (bins != state->bins)
Packit 67cb25
        {
Packit 67cb25
          resize_grid (state, bins);
Packit 67cb25
Packit 67cb25
          if (state->verbose > 1)
Packit 67cb25
            {
Packit 67cb25
              print_grid (state, dim);
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (state->verbose >= 0)
Packit 67cb25
        {
Packit 67cb25
          print_head (state,
Packit 67cb25
                      dim, calls, state->it_num, state->bins, state->boxes);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  state->it_start = state->it_num;
Packit 67cb25
Packit 67cb25
  cum_int = 0.0;
Packit 67cb25
  cum_sig = 0.0;
Packit 67cb25
Packit 67cb25
  for (it = 0; it < state->iterations; it++)
Packit 67cb25
    {
Packit 67cb25
      double intgrl = 0.0, intgrl_sq = 0.0;
Packit 67cb25
      double tss = 0.0;
Packit 67cb25
      double wgt, var, sig;
Packit 67cb25
      size_t calls_per_box = state->calls_per_box;
Packit 67cb25
      double jacbin = state->jac;
Packit 67cb25
      double *x = state->x;
Packit 67cb25
      coord *bin = state->bin;
Packit 67cb25
Packit 67cb25
      state->it_num = state->it_start + it;
Packit 67cb25
Packit 67cb25
      reset_grid_values (state);
Packit 67cb25
      init_box_coord (state, state->box);
Packit 67cb25
      
Packit 67cb25
      do
Packit 67cb25
        {
Packit 67cb25
          volatile double m = 0, q = 0;
Packit 67cb25
          double f_sq_sum = 0.0;
Packit 67cb25
Packit 67cb25
          for (k = 0; k < calls_per_box; k++)
Packit 67cb25
            {
Packit 67cb25
              volatile double fval;
Packit 67cb25
              double bin_vol;
Packit 67cb25
Packit 67cb25
              random_point (x, bin, &bin_vol, state->box, xl, xu, state, r);
Packit 67cb25
Packit 67cb25
              fval = jacbin * bin_vol * GSL_MONTE_FN_EVAL (f, x);
Packit 67cb25
Packit 67cb25
              /* recurrence for mean and variance (sum of squares) */
Packit 67cb25
Packit 67cb25
              {
Packit 67cb25
                double d = fval - m;
Packit 67cb25
                m += d / (k + 1.0);
Packit 67cb25
                q += d * d * (k / (k + 1.0));
Packit 67cb25
              }
Packit 67cb25
Packit 67cb25
              if (state->mode != GSL_VEGAS_MODE_STRATIFIED)
Packit 67cb25
                {
Packit 67cb25
                  double f_sq = fval * fval;
Packit 67cb25
                  accumulate_distribution (state, bin, f_sq);
Packit 67cb25
                }
Packit 67cb25
            }
Packit 67cb25
Packit 67cb25
          intgrl += m * calls_per_box;
Packit 67cb25
Packit 67cb25
          f_sq_sum = q * calls_per_box;
Packit 67cb25
Packit 67cb25
          tss += f_sq_sum;
Packit 67cb25
Packit 67cb25
          if (state->mode == GSL_VEGAS_MODE_STRATIFIED)
Packit 67cb25
            {
Packit 67cb25
              accumulate_distribution (state, bin, f_sq_sum);
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
      while (change_box_coord (state, state->box));
Packit 67cb25
Packit 67cb25
      /* Compute final results for this iteration   */
Packit 67cb25
Packit 67cb25
      var = tss / (calls_per_box - 1.0)  ;
Packit 67cb25
Packit 67cb25
      if (var > 0) 
Packit 67cb25
        {
Packit 67cb25
          wgt = 1.0 / var;
Packit 67cb25
        }
Packit 67cb25
      else if (state->sum_wgts > 0) 
Packit 67cb25
        {
Packit 67cb25
          wgt = state->sum_wgts / state->samples;
Packit 67cb25
        }
Packit 67cb25
      else 
Packit 67cb25
        {
Packit 67cb25
          wgt = 0.0;
Packit 67cb25
        }
Packit 67cb25
        
Packit 67cb25
     intgrl_sq = intgrl * intgrl;
Packit 67cb25
Packit 67cb25
     sig = sqrt (var);
Packit 67cb25
Packit 67cb25
     state->result = intgrl;
Packit 67cb25
     state->sigma  = sig;
Packit 67cb25
Packit 67cb25
     if (wgt > 0.0)
Packit 67cb25
       {
Packit 67cb25
         double sum_wgts = state->sum_wgts;
Packit 67cb25
         double wtd_int_sum = state->wtd_int_sum;
Packit 67cb25
         double m = (sum_wgts > 0) ? (wtd_int_sum / sum_wgts) : 0;
Packit 67cb25
         double q = intgrl - m;
Packit 67cb25
Packit 67cb25
         state->samples++ ;
Packit 67cb25
         state->sum_wgts += wgt;
Packit 67cb25
         state->wtd_int_sum += intgrl * wgt;
Packit 67cb25
         state->chi_sum += intgrl_sq * wgt;
Packit 67cb25
Packit 67cb25
         cum_int = state->wtd_int_sum / state->sum_wgts;
Packit 67cb25
         cum_sig = sqrt (1 / state->sum_wgts);
Packit 67cb25
Packit 67cb25
#if USE_ORIGINAL_CHISQ_FORMULA
Packit 67cb25
/* This is the chisq formula from the original Lepage paper.  It
Packit 67cb25
   computes the variance from <x^2> - <x>^2 and can suffer from
Packit 67cb25
   catastrophic cancellations, e.g. returning negative chisq. */
Packit 67cb25
         if (state->samples > 1)
Packit 67cb25
           {
Packit 67cb25
             state->chisq = (state->chi_sum - state->wtd_int_sum * cum_int) /
Packit 67cb25
               (state->samples - 1.0);
Packit 67cb25
           }
Packit 67cb25
#else
Packit 67cb25
/* The new formula below computes exactly the same quantity as above
Packit 67cb25
   but using a stable recurrence */
Packit 67cb25
         if (state->samples == 1) {
Packit 67cb25
           state->chisq = 0;
Packit 67cb25
         } else {
Packit 67cb25
           state->chisq *= (state->samples - 2.0);
Packit 67cb25
           state->chisq += (wgt / (1 + (wgt / sum_wgts))) * q * q;
Packit 67cb25
           state->chisq /= (state->samples - 1.0);
Packit 67cb25
         }
Packit 67cb25
#endif
Packit 67cb25
       }
Packit 67cb25
     else
Packit 67cb25
       {
Packit 67cb25
         cum_int += (intgrl - cum_int) / (it + 1.0);
Packit 67cb25
         cum_sig = 0.0;
Packit 67cb25
       }         
Packit 67cb25
Packit 67cb25
Packit 67cb25
      if (state->verbose >= 0)
Packit 67cb25
        {
Packit 67cb25
          print_res (state,
Packit 67cb25
                     state->it_num, intgrl, sig, cum_int, cum_sig,
Packit 67cb25
                     state->chisq);
Packit 67cb25
          if (it + 1 == state->iterations && state->verbose > 0)
Packit 67cb25
            {
Packit 67cb25
              print_grid (state, dim);
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (state->verbose > 1)
Packit 67cb25
        {
Packit 67cb25
          print_dist (state, dim);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      refine_grid (state);
Packit 67cb25
Packit 67cb25
      if (state->verbose > 1)
Packit 67cb25
        {
Packit 67cb25
          print_grid (state, dim);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* By setting stage to 1 further calls will generate independent
Packit 67cb25
     estimates based on the same grid, although it may be rebinned. */
Packit 67cb25
Packit 67cb25
  state->stage = 1;  
Packit 67cb25
Packit 67cb25
  *result = cum_int;
Packit 67cb25
  *abserr = cum_sig;
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
Packit 67cb25
gsl_monte_vegas_state *
Packit 67cb25
gsl_monte_vegas_alloc (size_t dim)
Packit 67cb25
{
Packit 67cb25
  gsl_monte_vegas_state *s =
Packit 67cb25
    (gsl_monte_vegas_state *) malloc (sizeof (gsl_monte_vegas_state));
Packit 67cb25
Packit 67cb25
  if (s == 0)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for vegas state struct",
Packit 67cb25
                     GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->delx = (double *) malloc (dim * sizeof (double));
Packit 67cb25
Packit 67cb25
  if (s->delx == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for delx", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->d = (double *) malloc (BINS_MAX * dim * sizeof (double));
Packit 67cb25
Packit 67cb25
  if (s->d == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s->delx);
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for d", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->xi = (double *) malloc ((BINS_MAX + 1) * dim * sizeof (double));
Packit 67cb25
Packit 67cb25
  if (s->xi == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s->d);
Packit 67cb25
      free (s->delx);
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for xi", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->xin = (double *) malloc ((BINS_MAX + 1) * sizeof (double));
Packit 67cb25
Packit 67cb25
  if (s->xin == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s->xi);
Packit 67cb25
      free (s->d);
Packit 67cb25
      free (s->delx);
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for xin", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->weight = (double *) malloc (BINS_MAX * sizeof (double));
Packit 67cb25
Packit 67cb25
  if (s->weight == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s->xin);
Packit 67cb25
      free (s->xi);
Packit 67cb25
      free (s->d);
Packit 67cb25
      free (s->delx);
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for xin", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->box = (coord *) malloc (dim * sizeof (coord));
Packit 67cb25
Packit 67cb25
  if (s->box == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s->weight);
Packit 67cb25
      free (s->xin);
Packit 67cb25
      free (s->xi);
Packit 67cb25
      free (s->d);
Packit 67cb25
      free (s->delx);
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for box", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->bin = (coord *) malloc (dim * sizeof (coord));
Packit 67cb25
Packit 67cb25
  if (s->bin == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s->box);
Packit 67cb25
      free (s->weight);
Packit 67cb25
      free (s->xin);
Packit 67cb25
      free (s->xi);
Packit 67cb25
      free (s->d);
Packit 67cb25
      free (s->delx);
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for bin", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->x = (double *) malloc (dim * sizeof (double));
Packit 67cb25
Packit 67cb25
  if (s->x == 0)
Packit 67cb25
    {
Packit 67cb25
      free (s->bin);
Packit 67cb25
      free (s->box);
Packit 67cb25
      free (s->weight);
Packit 67cb25
      free (s->xin);
Packit 67cb25
      free (s->xi);
Packit 67cb25
      free (s->d);
Packit 67cb25
      free (s->delx);
Packit 67cb25
      free (s);
Packit 67cb25
      GSL_ERROR_VAL ("failed to allocate space for x", GSL_ENOMEM, 0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->dim = dim;
Packit 67cb25
  s->bins_max = BINS_MAX;
Packit 67cb25
Packit 67cb25
  gsl_monte_vegas_init (s);
Packit 67cb25
Packit 67cb25
  return s;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Set some default values and whatever */
Packit 67cb25
int
Packit 67cb25
gsl_monte_vegas_init (gsl_monte_vegas_state * state)
Packit 67cb25
{
Packit 67cb25
  state->stage = 0;
Packit 67cb25
  state->alpha = 1.5;
Packit 67cb25
  state->verbose = -1;
Packit 67cb25
  state->iterations = 5;
Packit 67cb25
  state->mode = GSL_VEGAS_MODE_IMPORTANCE;
Packit 67cb25
  state->chisq = 0;
Packit 67cb25
  state->bins = state->bins_max;
Packit 67cb25
  state->ostream = stdout;
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
void
Packit 67cb25
gsl_monte_vegas_free (gsl_monte_vegas_state * s)
Packit 67cb25
{
Packit 67cb25
  RETURN_IF_NULL (s);
Packit 67cb25
  free (s->x);
Packit 67cb25
  free (s->delx);
Packit 67cb25
  free (s->d);
Packit 67cb25
  free (s->xi);
Packit 67cb25
  free (s->xin);
Packit 67cb25
  free (s->weight);
Packit 67cb25
  free (s->box);
Packit 67cb25
  free (s->bin);
Packit 67cb25
  free (s);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_monte_vegas_chisq (const gsl_monte_vegas_state * s)
Packit 67cb25
{
Packit 67cb25
  return s->chisq;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
void
Packit 67cb25
gsl_monte_vegas_runval (const gsl_monte_vegas_state * s, double * result, double * sigma)
Packit 67cb25
{
Packit 67cb25
  *result = s->result;
Packit 67cb25
  *sigma = s->sigma;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
void 
Packit 67cb25
gsl_monte_vegas_params_get (const gsl_monte_vegas_state * s, gsl_monte_vegas_params * p)
Packit 67cb25
{
Packit 67cb25
  p->alpha = s->alpha;
Packit 67cb25
  p->iterations = s->iterations;
Packit 67cb25
  p->stage = s->stage;
Packit 67cb25
  p->mode = s->mode;
Packit 67cb25
  p->verbose = s->verbose;
Packit 67cb25
  p->ostream = s->ostream;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
void 
Packit 67cb25
gsl_monte_vegas_params_set (gsl_monte_vegas_state * s, const gsl_monte_vegas_params * p)
Packit 67cb25
{
Packit 67cb25
  s->alpha = p->alpha;
Packit 67cb25
  s->iterations = p->iterations;
Packit 67cb25
  s->stage = p->stage;
Packit 67cb25
  s->mode = p->mode;
Packit 67cb25
  s->verbose = p->verbose;
Packit 67cb25
  s->ostream = p->ostream;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
init_box_coord (gsl_monte_vegas_state * s, coord box[])
Packit 67cb25
{
Packit 67cb25
  size_t i;
Packit 67cb25
Packit 67cb25
  size_t dim = s->dim;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < dim; i++)
Packit 67cb25
    {
Packit 67cb25
      box[i] = 0;
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* change_box_coord steps through the box coord like
Packit 67cb25
   {0,0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}, {1, 2}, ...
Packit 67cb25
*/
Packit 67cb25
static int
Packit 67cb25
change_box_coord (gsl_monte_vegas_state * s, coord box[])
Packit 67cb25
{
Packit 67cb25
  int j = s->dim - 1;
Packit 67cb25
Packit 67cb25
  int ng = s->boxes;
Packit 67cb25
Packit 67cb25
  while (j >= 0)
Packit 67cb25
    {
Packit 67cb25
      box[j] = (box[j] + 1) % ng;
Packit 67cb25
Packit 67cb25
      if (box[j] != 0)
Packit 67cb25
        {
Packit 67cb25
          return 1;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      j--;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return 0;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
init_grid (gsl_monte_vegas_state * s, double xl[], double xu[], size_t dim)
Packit 67cb25
{
Packit 67cb25
  size_t j;
Packit 67cb25
Packit 67cb25
  double vol = 1.0;
Packit 67cb25
Packit 67cb25
  s->bins = 1;
Packit 67cb25
Packit 67cb25
  for (j = 0; j < dim; j++)
Packit 67cb25
    {
Packit 67cb25
      double dx = xu[j] - xl[j];
Packit 67cb25
      s->delx[j] = dx;
Packit 67cb25
      vol *= dx;
Packit 67cb25
Packit 67cb25
      COORD (s, 0, j) = 0.0;
Packit 67cb25
      COORD (s, 1, j) = 1.0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->vol = vol;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
reset_grid_values (gsl_monte_vegas_state * s)
Packit 67cb25
{
Packit 67cb25
  size_t i, j;
Packit 67cb25
Packit 67cb25
  size_t dim = s->dim;
Packit 67cb25
  size_t bins = s->bins;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < bins; i++)
Packit 67cb25
    {
Packit 67cb25
      for (j = 0; j < dim; j++)
Packit 67cb25
        {
Packit 67cb25
          VALUE (s, i, j) = 0.0;
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
accumulate_distribution (gsl_monte_vegas_state * s, coord bin[], double y)
Packit 67cb25
{
Packit 67cb25
  size_t j;
Packit 67cb25
  size_t dim = s->dim;
Packit 67cb25
Packit 67cb25
  for (j = 0; j < dim; j++)
Packit 67cb25
    {
Packit 67cb25
      int i = bin[j];
Packit 67cb25
      VALUE (s, i, j) += y;
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
random_point (double x[], coord bin[], double *bin_vol,
Packit 67cb25
              const coord box[], const double xl[], const double xu[],
Packit 67cb25
              gsl_monte_vegas_state * s, gsl_rng * r)
Packit 67cb25
{
Packit 67cb25
  /* Use the random number generator r to return a random position x
Packit 67cb25
     in a given box.  The value of bin gives the bin location of the
Packit 67cb25
     random position (there may be several bins within a given box) */
Packit 67cb25
Packit 67cb25
  double vol = 1.0;
Packit 67cb25
Packit 67cb25
  size_t j;
Packit 67cb25
Packit 67cb25
  size_t dim = s->dim;
Packit 67cb25
  size_t bins = s->bins;
Packit 67cb25
  size_t boxes = s->boxes;
Packit 67cb25
Packit 67cb25
  DISCARD_POINTER(xu); /* prevent warning about unused parameter */
Packit 67cb25
Packit 67cb25
  for (j = 0; j < dim; ++j)
Packit 67cb25
    {
Packit 67cb25
      /* box[j] + ran gives the position in the box units, while z
Packit 67cb25
         is the position in bin units.  */
Packit 67cb25
Packit 67cb25
      double z = ((box[j] + gsl_rng_uniform_pos (r)) / boxes) * bins;
Packit 67cb25
Packit 67cb25
      int k = z;
Packit 67cb25
Packit 67cb25
      double y, bin_width;
Packit 67cb25
Packit 67cb25
      bin[j] = k;
Packit 67cb25
Packit 67cb25
      if (k == 0)
Packit 67cb25
        {
Packit 67cb25
          bin_width = COORD (s, 1, j);
Packit 67cb25
          y = z * bin_width;
Packit 67cb25
        }
Packit 67cb25
      else
Packit 67cb25
        {
Packit 67cb25
          bin_width = COORD (s, k + 1, j) - COORD (s, k, j);
Packit 67cb25
          y = COORD (s, k, j) + (z - k) * bin_width;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      x[j] = xl[j] + y * s->delx[j];
Packit 67cb25
Packit 67cb25
      vol *= bin_width;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  *bin_vol = vol;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
resize_grid (gsl_monte_vegas_state * s, unsigned int bins)
Packit 67cb25
{
Packit 67cb25
  size_t j, k;
Packit 67cb25
  size_t dim = s->dim;
Packit 67cb25
Packit 67cb25
  /* weight is ratio of bin sizes */
Packit 67cb25
Packit 67cb25
  double pts_per_bin = (double) s->bins / (double) bins;
Packit 67cb25
Packit 67cb25
  for (j = 0; j < dim; j++)
Packit 67cb25
    {
Packit 67cb25
      double xold;
Packit 67cb25
      double xnew = 0;
Packit 67cb25
      double dw = 0;
Packit 67cb25
      int i = 1;
Packit 67cb25
Packit 67cb25
      for (k = 1; k <= s->bins; k++)
Packit 67cb25
        {
Packit 67cb25
          dw += 1.0;
Packit 67cb25
          xold = xnew;
Packit 67cb25
          xnew = COORD (s, k, j);
Packit 67cb25
Packit 67cb25
          for (; dw > pts_per_bin; i++)
Packit 67cb25
            {
Packit 67cb25
              dw -= pts_per_bin;
Packit 67cb25
              NEW_COORD (s, i) = xnew - (xnew - xold) * dw;
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      for (k = 1 ; k < bins; k++)
Packit 67cb25
        {
Packit 67cb25
          COORD(s, k, j) = NEW_COORD(s, k);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      COORD (s, bins, j) = 1;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  s->bins = bins;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
refine_grid (gsl_monte_vegas_state * s)
Packit 67cb25
{
Packit 67cb25
  size_t i, j, k;
Packit 67cb25
  size_t dim = s->dim;
Packit 67cb25
  size_t bins = s->bins;
Packit 67cb25
Packit 67cb25
  for (j = 0; j < dim; j++)
Packit 67cb25
    {
Packit 67cb25
      double grid_tot_j, tot_weight;
Packit 67cb25
      double * weight = s->weight;
Packit 67cb25
Packit 67cb25
      double oldg = VALUE (s, 0, j);
Packit 67cb25
      double newg = VALUE (s, 1, j);
Packit 67cb25
Packit 67cb25
      VALUE (s, 0, j) = (oldg + newg) / 2;
Packit 67cb25
      grid_tot_j = VALUE (s, 0, j);
Packit 67cb25
Packit 67cb25
      /* This implements gs[i][j] = (gs[i-1][j]+gs[i][j]+gs[i+1][j])/3 */
Packit 67cb25
Packit 67cb25
      for (i = 1; i < bins - 1; i++)
Packit 67cb25
        {
Packit 67cb25
          double rc = oldg + newg;
Packit 67cb25
          oldg = newg;
Packit 67cb25
          newg = VALUE (s, i + 1, j);
Packit 67cb25
          VALUE (s, i, j) = (rc + newg) / 3;
Packit 67cb25
          grid_tot_j += VALUE (s, i, j);
Packit 67cb25
        }
Packit 67cb25
      VALUE (s, bins - 1, j) = (newg + oldg) / 2;
Packit 67cb25
Packit 67cb25
      grid_tot_j += VALUE (s, bins - 1, j);
Packit 67cb25
Packit 67cb25
      tot_weight = 0;
Packit 67cb25
Packit 67cb25
      for (i = 0; i < bins; i++)
Packit 67cb25
        {
Packit 67cb25
          weight[i] = 0;
Packit 67cb25
Packit 67cb25
          if (VALUE (s, i, j) > 0)
Packit 67cb25
            {
Packit 67cb25
              oldg = grid_tot_j / VALUE (s, i, j);
Packit 67cb25
              /* damped change */
Packit 67cb25
              weight[i] = pow (((oldg - 1) / oldg / log (oldg)), s->alpha);
Packit 67cb25
            }
Packit 67cb25
Packit 67cb25
          tot_weight += weight[i];
Packit 67cb25
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
          printf("weight[%d] = %g\n", i, weight[i]);
Packit 67cb25
#endif
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      {
Packit 67cb25
        double pts_per_bin = tot_weight / bins;
Packit 67cb25
Packit 67cb25
        double xold;
Packit 67cb25
        double xnew = 0;
Packit 67cb25
        double dw = 0;
Packit 67cb25
        i = 1;
Packit 67cb25
Packit 67cb25
        for (k = 0; k < bins; k++)
Packit 67cb25
          {
Packit 67cb25
            dw += weight[k];
Packit 67cb25
            xold = xnew;
Packit 67cb25
            xnew = COORD (s, k + 1, j);
Packit 67cb25
Packit 67cb25
            for (; dw > pts_per_bin; i++)
Packit 67cb25
              {
Packit 67cb25
                dw -= pts_per_bin;
Packit 67cb25
                NEW_COORD (s, i) = xnew - (xnew - xold) * dw / weight[k];
Packit 67cb25
              }
Packit 67cb25
          }
Packit 67cb25
Packit 67cb25
        for (k = 1 ; k < bins ; k++)
Packit 67cb25
          {
Packit 67cb25
            COORD(s, k, j) = NEW_COORD(s, k);
Packit 67cb25
          }
Packit 67cb25
Packit 67cb25
        COORD (s, bins, j) = 1;
Packit 67cb25
      }
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
print_lim (gsl_monte_vegas_state * state,
Packit 67cb25
           double xl[], double xu[], unsigned long dim)
Packit 67cb25
{
Packit 67cb25
  unsigned long j;
Packit 67cb25
Packit 67cb25
  fprintf (state->ostream, "The limits of integration are:\n");
Packit 67cb25
  for (j = 0; j < dim; ++j)
Packit 67cb25
    fprintf (state->ostream, "\nxl[%lu]=%f    xu[%lu]=%f", j, xl[j], j, xu[j]);
Packit 67cb25
  fprintf (state->ostream, "\n");
Packit 67cb25
  fflush (state->ostream);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
print_head (gsl_monte_vegas_state * state,
Packit 67cb25
            unsigned long num_dim, unsigned long calls,
Packit 67cb25
            unsigned int it_num, unsigned int bins, unsigned int boxes)
Packit 67cb25
{
Packit 67cb25
  fprintf (state->ostream,
Packit 67cb25
           "\nnum_dim=%lu, calls=%lu, it_num=%d, max_it_num=%d ",
Packit 67cb25
           num_dim, calls, it_num, state->iterations);
Packit 67cb25
  fprintf (state->ostream,
Packit 67cb25
           "verb=%d, alph=%.2f,\nmode=%d, bins=%d, boxes=%d\n",
Packit 67cb25
           state->verbose, state->alpha, state->mode, bins, boxes);
Packit 67cb25
  fprintf (state->ostream,
Packit 67cb25
           "\n       single.......iteration                   ");
Packit 67cb25
  fprintf (state->ostream, "accumulated......results   \n");
Packit 67cb25
Packit 67cb25
  fprintf (state->ostream,
Packit 67cb25
           "iteration     integral    sigma             integral   ");
Packit 67cb25
  fprintf (state->ostream, "      sigma     chi-sq/it\n\n");
Packit 67cb25
  fflush (state->ostream);
Packit 67cb25
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
print_res (gsl_monte_vegas_state * state,
Packit 67cb25
           unsigned int itr, 
Packit 67cb25
           double res, double err, 
Packit 67cb25
           double cum_res, double cum_err,
Packit 67cb25
           double chi_sq)
Packit 67cb25
{
Packit 67cb25
  fprintf (state->ostream,
Packit 67cb25
           "%4d        %6.4e %10.2e          %6.4e      %8.2e  %10.2e\n",
Packit 67cb25
           itr, res, err, cum_res, cum_err, chi_sq);
Packit 67cb25
  fflush (state->ostream);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
print_dist (gsl_monte_vegas_state * state, unsigned long dim)
Packit 67cb25
{
Packit 67cb25
  unsigned long i, j;
Packit 67cb25
  int p = state->verbose;
Packit 67cb25
  if (p < 1)
Packit 67cb25
    return;
Packit 67cb25
Packit 67cb25
  for (j = 0; j < dim; ++j)
Packit 67cb25
    {
Packit 67cb25
      fprintf (state->ostream, "\n axis %lu \n", j);
Packit 67cb25
      fprintf (state->ostream, "      x   g\n");
Packit 67cb25
      for (i = 0; i < state->bins; i++)
Packit 67cb25
        {
Packit 67cb25
          fprintf (state->ostream, "weight [%11.2e , %11.2e] = ", 
Packit 67cb25
                   COORD (state, i, j), COORD(state,i+1,j));
Packit 67cb25
          fprintf (state->ostream, " %11.2e\n", VALUE (state, i, j));
Packit 67cb25
Packit 67cb25
        }
Packit 67cb25
      fprintf (state->ostream, "\n");
Packit 67cb25
    }
Packit 67cb25
  fprintf (state->ostream, "\n");
Packit 67cb25
  fflush (state->ostream);
Packit 67cb25
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
print_grid (gsl_monte_vegas_state * state, unsigned long dim)
Packit 67cb25
{
Packit 67cb25
  unsigned long i, j;
Packit 67cb25
  int p = state->verbose;
Packit 67cb25
  if (p < 1)
Packit 67cb25
    return;
Packit 67cb25
Packit 67cb25
  for (j = 0; j < dim; ++j)
Packit 67cb25
    {
Packit 67cb25
      fprintf (state->ostream, "\n axis %lu \n", j);
Packit 67cb25
      fprintf (state->ostream, "      x   \n");
Packit 67cb25
      for (i = 0; i <= state->bins; i++)
Packit 67cb25
        {
Packit 67cb25
          fprintf (state->ostream, "%11.2e", COORD (state, i, j));
Packit 67cb25
          if (i % 5 == 4)
Packit 67cb25
            fprintf (state->ostream, "\n");
Packit 67cb25
        }
Packit 67cb25
      fprintf (state->ostream, "\n");
Packit 67cb25
    }
Packit 67cb25
  fprintf (state->ostream, "\n");
Packit 67cb25
  fflush (state->ostream);
Packit 67cb25
Packit 67cb25
}
Packit 67cb25