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