Object-oriented Scientific Computing Library: Version 0.910
gsl_vegas.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 /* monte/vegas.c
00024  * 
00025  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Michael Booth
00026  * 
00027  * This program is free software; you can redistribute it and/or modify
00028  * it under the terms of the GNU General Public License as published by
00029  * the Free Software Foundation; either version 3 of the License, or (at
00030  * your option) any later version.
00031  * 
00032  * This program is distributed in the hope that it will be useful, but
00033  * WITHOUT ANY WARRANTY; without even the implied warranty of
00034  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00035  * General Public License for more details.
00036  * 
00037  * You should have received a copy of the GNU General Public License
00038  * along with this program; if not, write to the Free Software
00039  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
00040  * 02110-1301, USA.
00041  */
00042 
00043 #ifndef O2SCL_GSL_VEGAS_H
00044 #define O2SCL_GSL_VEGAS_H
00045 
00046 #include <iostream>
00047 #include <o2scl/mcarlo_inte.h>
00048 #include <o2scl/gsl_rnga.h>
00049 #include <gsl/gsl_math.h>
00050 #include <gsl/gsl_monte.h>
00051 #include <gsl/gsl_machine.h>
00052 #include <gsl/gsl_monte_vegas.h>
00053 
00054 #ifndef DOXYGENP
00055 namespace o2scl {
00056 #endif
00057   
00058   /** \brief Multidimensional integration using Vegas Monte Carlo (GSL)
00059 
00060       The output options are a little different than the original GSL
00061       routine. The default setting of \ref mcarlo_inte::verbose is 0,
00062       which turns off all output. A verbose value of 1 prints summary
00063       information about the weighted average and final result, while a
00064       value of 2 also displays the grid coordinates. A value of 3
00065       prints information from the rebinning procedure for each
00066       iteration.
00067 
00068       Some original documentation from GSL:
00069 
00070       \verbatim 
00071       The input coordinates are x[j], with upper and lower limits
00072       xu[j] and xl[j]. The integration length in the j-th direction is
00073       delx[j]. Each coordinate x[j] is rescaled to a variable y[j] in
00074       the range 0 to 1. The range is divided into bins with boundaries
00075       xi[i][j], where i=0 corresponds to y=0 and i=bins to y=1. The
00076       grid is refined (ie, bins are adjusted) using d[i][j] which is
00077       some variation on the squared sum. A third parameter used in
00078       defining the real coordinate using random numbers is called z.
00079       It ranges from 0 to bins. Its integer part gives the lower index
00080       of the bin into which a call is to be placed, and the remainder
00081       gives the location inside the bin.
00082 
00083       When stratified sampling is used the bins are grouped into
00084       boxes, and the algorithm allocates an equal number of function
00085       calls to each box.
00086 
00087       The variable alpha controls how "stiff" the rebinning algorithm
00088       is. alpha = 0 means never change the grid. Alpha is typically
00089       set between 1 and 2. 
00090       \endverbatim
00091 
00092       \todo Mode = importance only doesn't give the same answer
00093       as GSL yet.
00094 
00095       \future Prettify the verbose output
00096 
00097       \future Allow the user to get information about the how
00098       the sampling was done, possibly by converting the bins
00099       and boxes into a structure or class.
00100 
00101       \future Allow the user to change the maximum number of bins.
00102 
00103       Based on \ref Lepage78 . The current version of the algorithm
00104       was described in the Cornell preprint CLNS-80/447 of March,
00105       1980. The GSL code follows most closely the C version by D. R.
00106       Yennie, coded in 1984.
00107   */
00108   template<class func_t=multi_funct<>, class rng_t=gsl_rnga, 
00109     class vec_t=ovector_base, class alloc_vec_t=ovector,
00110     class alloc_t=ovector_alloc> class gsl_vegas : 
00111   public mcarlo_inte<func_t,rng_t,vec_t> {
00112 
00113     public:
00114     
00115     /// \name Integration mode (default is mode_importance)
00116     //@{
00117     int mode;
00118     static const int mode_importance=1;
00119     static const int mode_importance_only=0;
00120     static const int mode_stratified=-1;
00121     //@}
00122 
00123     /// Result from last iteration
00124     double result;
00125 
00126     /// Uncertainty from last iteration
00127     double sigma;
00128 
00129     /** \brief The stiffness of the rebinning algorithm (default 1.5)
00130 
00131         This usual range is between 1 and 2.
00132     */
00133     double alpha;
00134 
00135     /// Set the number of iterations (default 5)
00136     unsigned int iterations;
00137 
00138     /** \brief The chi-squared per degree of freedom for the weighted
00139         estimate of the integral
00140         
00141         After an integration, this should be close to 1. If it is not,
00142         then this indicates that the values of the integral from
00143         different iterations are inconsistent, and the error may be
00144         underestimated. Further iterations of the algorithm may enable
00145         one to obtain more reliable results.
00146     */
00147     double chisq;
00148     
00149     /// The output stream to send output information (default \c std::cout)
00150     std::ostream *outs;
00151 
00152 #ifndef DOXYGEN_INTERNAL
00153 
00154     protected:
00155 
00156     /// Maximum number of bins
00157     static const size_t bins_max=50;
00158     
00159     /// Number of dimensions
00160     size_t dim;
00161     /// Number of bins
00162     unsigned int bins;
00163     /// Number of boxes
00164     unsigned int boxes; 
00165     /// Boundaries for each bin
00166     uvector xi;
00167     /// Storage for grid refinement
00168     uvector xin;
00169     /// The iteration length in each direction
00170     uvector delx;
00171     /// The weight for each bin
00172     uvector weight;
00173     /// The volume of the current bin
00174     double vol;
00175 
00176     /// The bins for each direction
00177     uvector_int bin;
00178     /// The boxes for each direction
00179     uvector_int box;
00180 
00181     /// Distribution 
00182     uvector d;
00183 
00184     /** \name Scratch variables preserved between calls to 
00185         vegas_minteg_err()
00186     */
00187     //@{
00188     double jac;
00189     double wtd_int_sum;
00190     double sum_wgts;
00191     double chi_sum;
00192     //@}
00193     
00194     /// The starting iteration number
00195     unsigned int it_start;
00196     /// The total number of iterations
00197     unsigned int it_num;
00198     /// Number of samples for computing chi squared
00199     unsigned int samples;
00200     /// Number of function calls per box
00201     unsigned int calls_per_box;
00202     
00203     /// Initialize box coordinates
00204     virtual void init_box_coord(uvector_int &boxt) {
00205       size_t i;
00206       for (i=0;i<dim;i++) {
00207         boxt[i]=0;
00208       }
00209       return;
00210     }
00211   
00212     /** \brief Change box coordinates
00213         
00214         Steps through the box coordinates, e.g.
00215         \verbatim
00216         {0,0}, {0,1}, {0,2}, {0,3}, {1,0}, {1,1}, {1,2}, ...
00217         \endverbatim
00218         
00219         This is among the member functions that is not virtual
00220         because it is part of the innermost loop.
00221     */
00222     int change_box_coord(uvector_int &boxt) {
00223       int j=dim-1;
00224       int ng=boxes;
00225       
00226       while (j >= 0) {
00227 
00228         boxt[j]=(boxt[j]+1) % ng;
00229         if (boxt[j] != 0) {
00230           return 1;
00231         }
00232         j--;
00233 
00234       }
00235       
00236       return 0;
00237     }
00238  
00239     /// Initialize grid
00240     virtual void init_grid(const vec_t &xl, const vec_t &xu, size_t ldim) {
00241       size_t j;
00242       vol=1.0;
00243       bins=1;
00244       
00245       for (j=0;j<ldim;j++) {
00246         double dx=xu[j]-xl[j];
00247         delx[j]=dx;
00248         vol *= dx;
00249         
00250         xi[j]=0.0;
00251         xi[dim+j]=1.0;
00252       }
00253       
00254       return;
00255     }
00256 
00257     /// Reset grid values
00258     virtual void reset_grid_values() {
00259       size_t i, j;
00260       
00261       for (i=0;i<bins;i++) {
00262         for (j=0;j<dim;j++) {
00263           d[i*dim+j]=0.0;
00264         }
00265       }
00266       return;
00267     }
00268 
00269     /** \brief Add the most recently generated result to the distribution
00270 
00271         This is among the member functions that is not virtual
00272         because it is part of the innermost loop.
00273     */
00274     void accumulate_distribution(uvector_int &lbin, double y) {
00275       size_t j;
00276       
00277       for (j=0;j<dim;j++) {
00278         int i=lbin[j];
00279         d[i*dim+j]+=y;
00280       }
00281       return;
00282     }
00283     
00284     /** \brief Generate a random position in a given box
00285         
00286         Use the random number generator \ref mcarlo_inte::def_rng to
00287         return a random position x in a given box. The value of bin
00288         gives the bin location of the random position (there may be
00289         several bins within a given box)
00290         
00291         This is among the member functions that is not virtual
00292         because it is part of the innermost loop.
00293     */
00294     void random_point(vec_t &lx, uvector_int &lbin, double &bin_vol,
00295                       const uvector_int &lbox, const vec_t &xl, 
00296                       const vec_t &xu) {
00297 
00298       double lvol=1.0;
00299 
00300       size_t j;
00301 
00302       for (j=0;j<dim;++j) {
00303 
00304         // The equivalent of gsl_rng_uniform_pos()
00305         double rdn;
00306         do { rdn=this->def_rng.random(); } while (rdn==0);
00307         
00308         /* lbox[j] + ran gives the position in the box units, while z
00309            is the position in bin units.  */
00310         double z=((lbox[j]+rdn)/boxes)*bins;
00311         
00312         int k=(int)z;
00313         
00314         double y, bin_width;
00315         
00316         lbin[j]=k;
00317 
00318         if (k == 0) {
00319           bin_width=xi[dim+j];
00320           y=z*bin_width;
00321         } else {
00322           bin_width=xi[(k+1)*dim+j]-xi[k*dim+j];
00323           y=xi[k*dim+j]+(z-k)*bin_width;
00324         }
00325         
00326         lx[j]=xl[j]+y*delx[j];
00327         
00328         lvol *= bin_width;
00329       }
00330       
00331       bin_vol=lvol;
00332 
00333       return;
00334     }
00335 
00336     /// Resize the grid
00337     virtual void resize_grid(unsigned int lbins) {
00338       size_t j, k;
00339 
00340       /* weight is ratio of bin sizes */
00341 
00342       double pts_per_bin=(double) bins/(double) lbins;
00343 
00344       for (j=0;j<dim;j++) {
00345         double xold;
00346         double xnew=0;
00347         double dw=0;
00348         int i=1;
00349 
00350         for (k=1;k <= bins;k++) {
00351           dw+=1.0;
00352           xold=xnew;
00353           xnew=xi[k*dim+j];
00354 
00355           for (;dw > pts_per_bin;i++) {
00356             dw -= pts_per_bin;
00357             (xin[i])=xnew-(xnew-xold)*dw;
00358           }
00359         }
00360 
00361         for (k=1 ;k<lbins;k++) {
00362           xi[k*dim+j]=xin[k];
00363         }
00364 
00365         xi[lbins*dim+j]=1;
00366       }
00367       
00368       bins=lbins;
00369 
00370       return;
00371     }
00372 
00373     /// Refine the grid
00374     virtual void refine_grid() {
00375 
00376       size_t i, j, k;
00377 
00378       for (j=0;j<dim;j++) {
00379         double grid_tot_j, tot_weight;
00380 
00381         double oldg=d[j];
00382         double newg=d[dim+j];
00383 
00384         d[j]=(oldg+newg)/2;
00385         grid_tot_j=d[j];
00386 
00387         /* This implements gs[i][j]=(gs[i-1][j]+gs[i][j]+gs[i+1][j])/3 */
00388 
00389         for (i=1;i<bins-1;i++) {
00390           double rc=oldg+newg;
00391           oldg=newg;
00392           newg=d[(i+1)*dim+j];
00393           d[i*dim+j]=(rc+newg)/3;
00394           grid_tot_j+=d[i*dim+j];
00395         }
00396         d[(bins-1)*dim+j]=(newg+oldg)/2;
00397 
00398         grid_tot_j+=d[(bins-1)*dim+j];
00399 
00400         tot_weight=0;
00401 
00402         for (i=0;i<bins;i++) {
00403           weight[i]=0;
00404 
00405           if (d[i*dim+j] > 0) {
00406             oldg=grid_tot_j/d[i*dim+j];
00407             /* damped change */
00408             weight[i]=pow (((oldg-1)/oldg/log (oldg)), alpha);
00409           }
00410               
00411           tot_weight+=weight[i];
00412         }
00413 
00414         {
00415           double pts_per_bin=tot_weight/bins;
00416 
00417           double xold;
00418           double xnew=0;
00419           double dw=0;
00420           i=1;
00421 
00422           for (k=0;k<bins;k++) {
00423             dw+=weight[k];
00424             xold=xnew;
00425             xnew=xi[(k+1)*dim+j];
00426 
00427             for (;dw > pts_per_bin;i++) {
00428               dw -= pts_per_bin;
00429               (xin[i])=xnew-(xnew-xold)*dw/weight[k];
00430             }
00431           }
00432 
00433           for (k=1 ;k<bins ;k++) {
00434             xi[k*dim+j]=xin[k];
00435           }
00436             
00437           xi[bins*dim+j]=1;
00438         }
00439       }
00440       return;
00441     }
00442 
00443     /// Print limits of integration
00444     virtual void print_lim(const vec_t &xl, const vec_t &xu, 
00445                            unsigned long ldim) {
00446                    
00447       unsigned long j;
00448       
00449       (*outs) << "The limits of integration are:\n" << std::endl;
00450       for (j=0;j<ldim;++j) {
00451         (*outs) << "xl[" << j << "]=" << xl[j] << "    xu[" << j 
00452                 <<  "]=" << xu[j] << std::endl;
00453       }
00454       (*outs) << std::endl;
00455 
00456       return;
00457     }
00458 
00459     /// Print header
00460     virtual void print_head(unsigned long num_dim, unsigned long calls,
00461                             unsigned int lit_num, unsigned int lbins, 
00462                             unsigned int lboxes)  {
00463 
00464       (*outs) << "num_dim=" << num_dim << ", calls=" << calls 
00465       << ", it_num=" << lit_num << ", max_it_num=" 
00466       << iterations << ", verb=" << this->verbose << ", alph=" << alpha 
00467       << ",\n mode=" << mode << ", boxes=" << lboxes
00468       << "\n\n    single.......iteration               "
00469       << "accumulated......results\n"
00470       << "iter   integral     sigma            integral   "
00471       << "  sigma        chi-sq/it" << std::endl;
00472       
00473       return;
00474     }
00475     
00476     /// Print results
00477     virtual void print_res(unsigned int itr, double res, 
00478                            double err, double cum_res, double cum_err,
00479                            double chi_sq) {
00480       (*outs).precision(5);
00481       (*outs) << itr << "     ";
00482       outs->setf(std::ios::showpos);
00483       (*outs) << res << "  ";
00484       outs->unsetf(std::ios::showpos);
00485       (*outs) << err << "     ";
00486       outs->setf(std::ios::showpos);
00487       (*outs) << cum_res << "  ";
00488       outs->unsetf(std::ios::showpos);
00489       (*outs) << cum_err << "  " << chi_sq << std::endl;
00490       (*outs).precision(6);
00491       return;
00492     }
00493  
00494     /// Print distribution
00495     virtual void print_dist(unsigned long ldim) {
00496       unsigned long i, j;
00497 
00498       if (this->verbose<2) {
00499         return;
00500       }
00501       
00502       for (j=0;j<ldim;++j) {
00503         (*outs) << "\n Axis " << j << std::endl;
00504         (*outs) << "       x     g" << std::endl;
00505         outs->setf(std::ios::showpos);
00506         for (i=0;i<bins;i++) {
00507           (*outs) << "weight [ " << (xi[(i)*dim+(j)]) << " , " 
00508                   << xi[(i+1)*dim+j] << " ] = ";
00509           (*outs) << " " << (d[(i)*dim+(j)]) << std::endl;
00510         }
00511         outs->unsetf(std::ios::showpos);
00512         (*outs) << std::endl;
00513       }
00514       (*outs) << std::endl;
00515       return;
00516     }
00517  
00518     /// Print grid
00519     virtual void print_grid(unsigned long ldim) {
00520 
00521       if (this->verbose<2) {
00522         return;
00523       }
00524       
00525       unsigned long i, j;
00526       for (j=0;j<ldim;++j) {
00527         (*outs) << "\n Axis " << j << std::endl;
00528         (*outs) << "      x     " << std::endl;
00529         outs->setf(std::ios::showpos);
00530         for (i=0;i <= bins;i++)  {
00531           (*outs) << (xi[(i)*dim+(j)]) << " ";
00532           if (i % 5 == 4) {
00533             (*outs) << std::endl;
00534           }
00535         }
00536         (*outs) << std::endl;
00537         outs->unsetf(std::ios::showpos);
00538       }
00539       (*outs) << std::endl;
00540       return;
00541     }
00542 
00543     /// Memory allocation object
00544     alloc_t ao;
00545 
00546     /// Point for function evaluation
00547     alloc_vec_t x;
00548 
00549 #endif
00550 
00551     public:
00552 
00553     gsl_vegas() {
00554       this->verbose=0;
00555       outs=&std::cout;
00556       alpha=1.5;
00557       iterations=5;
00558       mode=mode_importance;
00559       chisq=0;
00560       bins=bins_max;
00561       dim=0;
00562     }
00563     
00564     /// Allocate memory
00565     virtual int allocate(size_t ldim) {
00566 
00567       delx.allocate(ldim);
00568       d.allocate(bins_max*ldim);
00569       xi.allocate((bins_max+1)*ldim);
00570       xin.allocate(bins_max+1);
00571       weight.allocate(bins_max);
00572       box.allocate(ldim);
00573       bin.allocate(ldim);
00574       ao.allocate(x,ldim);
00575 
00576       dim=ldim;
00577 
00578       return 0;
00579     }
00580 
00581     /// Free allocated memory
00582     virtual int free() {
00583       if (dim>0) {
00584         delx.free();
00585         d.free();
00586         xi.free();
00587         xin.free();
00588         weight.free();
00589         box.free();
00590         bin.free();
00591         ao.free(x);
00592         dim=0;
00593       }
00594       return 0;
00595     }
00596 
00597     /** \brief Integrate function \c func from x=a to x=b.
00598 
00599         Original documentation from GSL:
00600         
00601         Normally, <tt>stage = 0</tt> which begins with a new uniform
00602         grid and empty weighted average. Calling vegas with <tt>stage
00603         = 1</tt> retains the grid from the previous run but discards
00604         the weighted average, so that one can "tune" the grid using a
00605         relatively small number of points and then do a large run with
00606         <tt>stage = 1</tt> on the optimized grid. Setting <tt>stage =
00607         2</tt> keeps the grid and the weighted average from the
00608         previous run, but may increase (or decrease) the number of
00609         histogram bins in the grid depending on the number of calls
00610         available. Choosing <tt>stage = 3</tt> enters at the main
00611         loop, so that nothing is changed, and is equivalent to
00612         performing additional iterations in a previous call.
00613 
00614         \todo Should stage be passed by reference?
00615         \todo There was an update between gsl-1.12 and 1.15 which
00616         has not been implemented here yet.
00617     */
00618     virtual int vegas_minteg_err(int stage, func_t &func, size_t ndim, 
00619                                  const vec_t &xl, const vec_t &xu, 
00620                                  double &res, double &err) {
00621 
00622       size_t calls=this->n_points;
00623 
00624       double cum_int, cum_sig;
00625       size_t i, k, it;
00626         
00627       for (i=0;i<dim;i++) {
00628         if (xu[i] <= xl[i]) {
00629           std::string serr="Upper limit, "+dtos(xu[i])+", must be greater "+
00630             "than lower limit, "+dtos(xl[i])+", in gsl_vegas::"+
00631             "vegas_minteg_err().";
00632           O2SCL_ERR_RET(serr.c_str(),gsl_einval);
00633         }
00634 
00635         if (xu[i]-xl[i] > GSL_DBL_MAX) {
00636           O2SCL_ERR2_RET("Range of integration is too large, please rescale ",
00637                          "in gsl_vegas::vegas_minteg_err().",gsl_einval);
00638         }
00639       }
00640 
00641       if (stage == 0) {
00642         init_grid(xl,xu,dim);
00643         if (this->verbose>=1) {
00644           print_lim(xl,xu,dim);
00645         }
00646       }
00647       
00648       if (stage<=1) {
00649         wtd_int_sum=0;
00650         sum_wgts=0;
00651         chi_sum=0;
00652         it_num=1;
00653         samples=0;
00654         chisq=0;
00655       }
00656       
00657       if (stage <= 2) {
00658 
00659         unsigned int lbins=bins_max;
00660         unsigned int lboxes=1;
00661 
00662         if (mode != mode_importance_only) {
00663 
00664           /* shooting for 2 calls/box */
00665           
00666           // The original GSL code was:
00667           // boxes=floor (pow (calls/2.0, 1.0/dim));
00668           // but floor returns double on my machine, so 
00669           // we explicitly typecast here
00670           
00671           lboxes=((unsigned int)(floor(pow(calls/2.0,1.0/dim))));
00672           mode=mode_importance;
00673 
00674           if (2*lboxes >=  bins_max) {
00675             /* if bins/box < 2 */
00676             int box_per_bin=GSL_MAX(lboxes/bins_max,1);
00677 
00678             lbins=GSL_MIN(lboxes/box_per_bin,bins_max);
00679             lboxes=box_per_bin*lbins;
00680 
00681             mode=mode_stratified;
00682           }
00683 
00684         }
00685 
00686         //double tot_boxes=gsl_pow_int((double)boxes,dim);
00687         double tot_boxes=pow((double)lboxes,(double)dim);
00688         calls_per_box=((unsigned int)(GSL_MAX(calls/tot_boxes,2)));
00689         calls=((size_t)( calls_per_box*tot_boxes));
00690         
00691         /* total volume of x-space/(avg num of calls/bin) */
00692         jac=vol*pow((double) lbins, (double) dim)/calls;
00693          
00694         boxes=lboxes;
00695 
00696         /* If the number of bins changes from the previous invocation, bins
00697            are expanded or contracted accordingly, while preserving bin
00698            density */
00699         
00700         if (lbins!=bins) {
00701           resize_grid(lbins);
00702           if (this->verbose > 2) print_grid(dim);
00703         }
00704         if (this->verbose >= 1) {
00705           print_head(dim,calls,it_num,bins,boxes);
00706         }
00707       }
00708 
00709       it_start=it_num;
00710 
00711       cum_int=0.0;
00712       cum_sig=0.0;
00713 
00714       for (it=0;it<iterations;it++) {
00715 
00716         double intgrl=0.0, intgrl_sq=0.0;
00717         double tss=0.0;
00718         double wgt, var, sig;
00719         size_t lcalls_per_box=calls_per_box;
00720         double jacbin=jac;
00721 
00722         it_num=it_start+it;
00723 
00724         reset_grid_values();
00725         init_box_coord(box);
00726 
00727         do {
00728           volatile double m=0, q=0;
00729           double f_sq_sum=0.0;
00730 
00731           for (k=0;k<lcalls_per_box;k++) {
00732             double fval, bin_vol;
00733             
00734             random_point(x,bin,bin_vol,box,xl,xu);
00735             
00736             fval=func(dim,x);
00737             fval*=jacbin*bin_vol;
00738 
00739             /* recurrence for mean and variance (sum of squares) */
00740 
00741             {
00742               double dt=fval-m;
00743               m+=dt/(k+1.0);
00744               q+=dt*dt*(k/(k+1.0));
00745             }
00746 
00747             if (mode != mode_stratified) {
00748               double f_sq=fval*fval;
00749               accumulate_distribution(bin,f_sq);
00750             }
00751           }
00752 
00753           intgrl+=m*lcalls_per_box;
00754 
00755           f_sq_sum=q*lcalls_per_box;
00756 
00757           tss+=f_sq_sum;
00758 
00759           if (mode == mode_stratified) {
00760             accumulate_distribution (bin, f_sq_sum);
00761           }
00762 
00763         } while (change_box_coord(box));
00764 
00765         /* Compute final results for this iteration   */
00766         
00767         var=tss/(lcalls_per_box-1.0);
00768         
00769         if (var>0) {
00770           wgt=1.0/var;
00771         } else if (sum_wgts>0) {
00772           wgt=sum_wgts/samples;
00773         } else {
00774           wgt=0.0;
00775         }
00776         
00777         intgrl_sq=intgrl*intgrl;
00778 
00779         sig=sqrt(var);
00780 
00781         result=intgrl;
00782         sigma=sig;
00783         
00784         if (wgt > 0.0) {
00785           double lsum_wgts=sum_wgts;
00786           double m=(sum_wgts > 0) ? (wtd_int_sum/sum_wgts) : 0;
00787           double q=intgrl-m;
00788           
00789           samples++;
00790           sum_wgts+=wgt;
00791           wtd_int_sum+=intgrl*wgt;
00792           chi_sum+=intgrl_sq*wgt;
00793 
00794           cum_int= wtd_int_sum/sum_wgts;
00795           cum_sig=sqrt(1/sum_wgts);
00796 
00797           /* The original chisq formula from the Lepage paper is
00798              
00799              if ( samples > 1) {
00800              chisq=(chi_sum-wtd_int_sum*cum_int)/(samples-1.0);
00801              }
00802              
00803              This can suffer from cancellations and return a negative
00804              value of chi squared. We use the new formula from 
00805              GSL-1.12 instead
00806            */
00807           if (samples==1) {
00808             chisq=0;
00809           } else {
00810             chisq*=(samples-2.0);
00811             chisq+=(wgt/(1+(wgt/lsum_wgts)))*q*q;
00812             chisq/=(samples-1.0);
00813           }
00814 
00815         } else {
00816           cum_int+=(intgrl-cum_int)/(it+1.0);
00817           cum_sig=0.0;
00818         }         
00819         
00820         if (this->verbose >= 1) {
00821           print_res(it_num,intgrl,sig,cum_int,cum_sig,chisq);
00822           if (it+1 ==  iterations &&  this->verbose > 1) {
00823             print_grid(dim);
00824           }
00825         }
00826 
00827         if (this->verbose > 2) {
00828           print_dist(dim);
00829         }
00830 
00831         refine_grid ();
00832 
00833         if (this->verbose > 2) {
00834           print_grid(dim);
00835         }
00836 
00837       }
00838 
00839       /* 
00840          By setting stage to 1 further calls will generate independent
00841          estimates based on the same grid, although it may be rebinned. 
00842       */
00843       stage=1;
00844 
00845       res=cum_int;
00846       err=cum_sig;
00847 
00848       return GSL_SUCCESS;
00849     }
00850 
00851     virtual ~gsl_vegas() {}
00852   
00853     /// Integrate function \c func from x=a to x=b.
00854     virtual int minteg_err(func_t &func, size_t ndim, const vec_t &a, 
00855                            const vec_t &b, double &res, double &err) {
00856       allocate(ndim);
00857       chisq=0;
00858       bins=bins_max;
00859       int ret=vegas_minteg_err(0,func,ndim,a,b,res,err);
00860       free();
00861       return ret;
00862     }
00863     
00864     /** \brief Integrate function \c func over the hypercube from
00865         \f$ x_i=a_i \f$ to \f$ x_i=b_i \f$ for
00866         \f$ 0<i< \f$ ndim-1
00867     */
00868     virtual double minteg(func_t &func, size_t ndim, const vec_t &a, 
00869                           const vec_t &b) {
00870       double res;
00871       minteg_err(func,ndim,a,b,res,this->interror);
00872       return res;
00873     }
00874     
00875     /// Return string denoting type ("gsl_vegas")
00876     virtual const char *type() { return "gsl_vegas"; }
00877       
00878   };
00879 
00880 #ifndef DOXYGENP
00881 }
00882 #endif
00883 
00884 #endif
00885 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.