Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooGrid.cxx
Go to the documentation of this file.
1/// \cond ROOFIT_INTERNAL
2
3/*****************************************************************************
4 * Project: RooFit *
5 * Package: RooFitCore *
6 * @(#)root/roofitcore:$Id$
7 * Authors: *
8 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
9 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
10 * *
11 * Copyright (c) 2000-2005, Regents of the University of California *
12 * and Stanford University. All rights reserved. *
13 * *
14 * Redistribution and use in source and binary forms, *
15 * with or without modification, are permitted according to the terms *
16 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
17 *****************************************************************************/
18
19/**
20\file RooGrid.cxx
21\class RooGrid
22\ingroup Roofitcore
23
24Utility class for RooMCIntegrator which
25implements an adaptive multi-dimensional Monte Carlo numerical
26integration, following the VEGAS algorithm.
27**/
28
29#include "RooGrid.h"
30#include "RooAbsFunc.h"
31#include "RooNumber.h"
32#include "RooRandom.h"
33#include "RooMsgService.h"
34
35#include <cmath>
36#include <iomanip>
37#include <ostream>
38
39////////////////////////////////////////////////////////////////////////////////
40/// Constructor with given function binding
41
42RooGrid::RooGrid(const RooAbsFunc &function)
43 : _valid(true)
44{
45 // check that the input function is valid
46 if(!(_valid= function.isValid())) {
47 oocoutE(nullptr,InputArguments) << "RooGrid: cannot initialize using an invalid function" << std::endl;
48 return;
49 }
50
51 // allocate workspace memory
52 _dim= function.getDimension();
53 _xl.resize(_dim);
54 _xu.resize(_dim);
55 _delx.resize(_dim);
56 _d.resize(_dim*maxBins);
57 _xi.resize(_dim*(maxBins+1));
58 _xin.resize(maxBins+1);
59 _weight.resize(maxBins);
60
61 // initialize the grid
62 _valid= initialize(function);
63}
64
65
66////////////////////////////////////////////////////////////////////////////////
67/// Calculate and store the grid dimensions and volume using the
68/// specified function, and initialize the grid using a single bin.
69/// Return true, or else false if the range is not valid.
70
71bool RooGrid::initialize(const RooAbsFunc &function)
72{
73 _vol= 1;
74 _bins= 1;
75 for(UInt_t index= 0; index < _dim; index++) {
76 _xl[index]= function.getMinLimit(index);
78 oocoutE(nullptr,Integration) << "RooGrid: lower limit of dimension " << index << " is infinite" << std::endl;
79 return false;
80 }
81 _xu[index]= function.getMaxLimit(index);
83 oocoutE(nullptr,Integration) << "RooGrid: upper limit of dimension " << index << " is infinite" << std::endl;
84 return false;
85 }
86 double dx= _xu[index] - _xl[index];
87 if(dx <= 0) {
88 oocoutE(nullptr,Integration) << "RooGrid: bad range for dimension " << index << ": [" << _xl[index]
89 << "," << _xu[index] << "]" << std::endl;
90 return false;
91 }
92 _delx[index]= dx;
93 _vol*= dx;
94 coord(0,index) = 0;
95 coord(1,index) = 1;
96 }
97 return true;
98}
99
100
101////////////////////////////////////////////////////////////////////////////////
102/// Adjust the subdivision of each axis to give the specified
103/// number of bins, using an algorithm that preserves relative
104/// bin density. The new binning can be finer or coarser than
105/// the original binning.
106
107void RooGrid::resize(UInt_t bins)
108{
109 // is there anything to do?
110 if(bins == _bins) return;
111
112 // weight is ratio of bin sizes
113 double pts_per_bin = (double) _bins / (double) bins;
114
115 // loop over grid dimensions
116 for (UInt_t j = 0; j < _dim; j++) {
117 double xold;
118 double xnew(0);
119 double dw(0);
120 Int_t i = 1;
121 // loop over bins in this dimension and load _xin[] with new bin edges
122
123 UInt_t k;
124 for(k = 1; k <= _bins; k++) {
125 dw += 1.0;
126 xold = xnew;
127 xnew = coord(k,j);
128 while(dw > pts_per_bin) {
129 dw -= pts_per_bin;
130 newCoord(i++)= xnew - (xnew - xold) * dw;
131 }
132 }
133 // copy the new edges into _xi[j]
134 for(k = 1 ; k < bins; k++) {
135 coord(k, j) = newCoord(k);
136 }
137 coord(bins, j) = 1;
138 }
139 _bins = bins;
140}
141
142
143////////////////////////////////////////////////////////////////////////////////
144/// Reset the values associated with each grid cell.
145
146void RooGrid::resetValues()
147{
148 for(UInt_t i = 0; i < _bins; i++) {
149 for (UInt_t j = 0; j < _dim; j++) {
150 value(i,j)= 0.0;
151 }
152 }
153}
154
155
156////////////////////////////////////////////////////////////////////////////////
157/// Generate a random vector in the specified box and store its
158/// coordinates in the x[] array provided, the corresponding bin
159/// indices in the bin[] array, and the volume of this bin in vol.
160/// The box is specified by the array box[] of box integer indices
161/// that each range from 0 to getNBoxes()-1.
162
163void RooGrid::generatePoint(const UInt_t box[], double x[], UInt_t bin[], double &vol,
164 bool useQuasiRandom) const
165{
166 vol= 1;
167
168 // generate a vector of quasi-random numbers to use
169 if(useQuasiRandom) {
171 }
172 else {
174 }
175
176 // loop over coordinate axes
177 for(UInt_t j= 0; j < _dim; ++j) {
178
179 // generate a random point uniformly distributed (in box space)
180 // within the box[j]-th box of coordinate axis j.
181 double z= ((box[j] + x[j])/_boxes)*_bins;
182
183 // store the bin in which this point lies along the j-th
184 // coordinate axis and calculate its width and position y
185 // in normalized bin coordinates.
186 Int_t k= static_cast<Int_t>(z);
187 bin[j] = k;
188 double y;
189 double bin_width;
190 if(k == 0) {
191 bin_width= coord(1,j);
192 y= z * bin_width;
193 }
194 else {
195 bin_width= coord(k+1,j) - coord(k,j);
196 y= coord(k,j) + (z-k)*bin_width;
197 }
198 // transform from normalized bin coordinates to x space.
199 x[j] = _xl[j] + y*_delx[j];
200
201 // update this bin's calculated volume
202 vol *= bin_width;
203 }
204}
205
206
207
208////////////////////////////////////////////////////////////////////////////////
209/// Reset the specified array of box indices to refer to the first box
210/// in the standard traversal order.
211
212void RooGrid::firstBox(UInt_t box[]) const
213{
214 for(UInt_t i= 0; i < _dim; i++) box[i]= 0;
215}
216
217
218
219////////////////////////////////////////////////////////////////////////////////
220/// Update the specified array of box indices to refer to the next box
221/// in the standard traversal order and return true, or else return
222/// false if we the indices already refer to the last box.
223
224bool RooGrid::nextBox(UInt_t box[]) const
225{
226 // try incrementing each index until we find one that does not roll
227 // over, starting from the last index.
228 Int_t j(_dim-1);
229 while (j >= 0) {
230 box[j]= (box[j] + 1) % _boxes;
231 if (0 != box[j]) return true;
232 j--;
233 }
234 // if we get here, then there are no more boxes
235 return false;
236}
237
238
239
240////////////////////////////////////////////////////////////////////////////////
241/// Print info about this object to the specified stream.
242
243void RooGrid::print(std::ostream& os, bool verbose, std::string const& indent) const
244{
245 os << "RooGrid: volume = " << getVolume() << std::endl;
246 os << indent << " Has " << getDimension() << " dimension(s) each subdivided into "
247 << getNBins() << " bin(s) and sampled with " << _boxes << " box(es)" << std::endl;
248 for(std::size_t index= 0; index < getDimension(); index++) {
249 os << indent << " (" << index << ") ["
250 << std::setw(10) << _xl[index] << "," << std::setw(10) << _xu[index] << "]" << std::endl;
251 if(!verbose) continue;
252 for(std::size_t bin= 0; bin < _bins; bin++) {
253 os << indent << " bin-" << bin << " : x = " << coord(bin,index) << " , y = "
254 << value(bin,index) << std::endl;
255 }
256 }
257}
258
259
260////////////////////////////////////////////////////////////////////////////////
261/// Add the specified amount to bin[j] of the 1D histograms associated
262/// with each axis j.
263
264void RooGrid::accumulate(const UInt_t bin[], double amount)
265{
266 for(UInt_t j = 0; j < _dim; j++) value(bin[j],j) += amount;
267}
268
269
270////////////////////////////////////////////////////////////////////////////////
271/// Refine the grid using the values that have been accumulated so far.
272/// The parameter alpha controls the stiffness of the rebinning and should
273/// usually be between 1 (stiffer) and 2 (more flexible). A value of zero
274/// prevents any rebinning.
275
276void RooGrid::refine(double alpha)
277{
278 for (UInt_t j = 0; j < _dim; j++) {
279
280 // smooth this dimension's histogram of grid values and calculate the
281 // new sum of the histogram contents as grid_tot_j
282 double oldg = value(0,j);
283 double newg = value(1,j);
284 value(0,j)= (oldg + newg)/2;
285 double grid_tot_j = value(0,j);
286 // this loop implements value(i,j) = ( value(i-1,j)+value(i,j)+value(i+1,j) ) / 3
287
288 UInt_t i;
289 for (i = 1; i < _bins - 1; i++) {
290 double rc = oldg + newg;
291 oldg = newg;
292 newg = value(i+1,j);
293 value(i,j)= (rc + newg)/3;
294 grid_tot_j+= value(i,j);
295 }
296 value(_bins-1,j)= (newg + oldg)/2;
297 grid_tot_j+= value(_bins-1,j);
298
299 // calculate the weights for each bin of this dimension's histogram of values
300 // and their sum
301 double tot_weight(0);
302 for (i = 0; i < _bins; i++) {
303 _weight[i] = 0;
304 if (value(i,j) > 0) {
305 oldg = grid_tot_j/value(i,j);
306 /* damped change */
307 _weight[i] = std::pow(((oldg-1.0)/oldg/log(oldg)), alpha);
308 }
309 tot_weight += _weight[i];
310 }
311
312 double pts_per_bin = tot_weight / _bins;
313
314 double xold;
315 double xnew = 0;
316 double dw = 0;
317
318 i = 1;
319 for (UInt_t k = 0; k < _bins; k++) {
320 dw += _weight[k];
321 xold = xnew;
322 xnew = coord(k+1,j);
323
324 while(dw > pts_per_bin) {
325 dw -= pts_per_bin;
326 newCoord(i++) = xnew - (xnew - xold) * dw / _weight[k];
327 }
328 }
329
330 for (UInt_t k = 1 ; k < _bins ; k++) {
331 coord( k, j) = newCoord(k);
332 }
333
334 coord(_bins, j) = 1;
335 }
336}
337
338/// \endcond
#define oocoutE(o, a)
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Abstract interface for evaluating a real-valued function of one real variable and performing numerica...
Definition RooAbsFunc.h:27
bool isValid() const
Definition RooAbsFunc.h:37
virtual double getMaxLimit(UInt_t dimension) const =0
virtual double getMinLimit(UInt_t dimension) const =0
UInt_t getDimension() const
Definition RooAbsFunc.h:33
static constexpr int isInfinite(double x)
Return true if x is infinite by RooNumber internal specification.
Definition RooNumber.h:27
static double uniform(TRandom *generator=randomGenerator())
Return a number uniformly distributed from (0,1)
Definition RooRandom.cxx:77
static bool quasi(UInt_t dimension, double vector[], RooQuasiRandomGenerator *generator=quasiGenerator())
Return a quasi-random number in the range (0,1) using the Niederreiter base 2 generator described in ...
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
RVec< PromoteType< T > > log(const RVec< T > &v)
Definition RVec.hxx:1821
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
void initialize(typename Architecture_t::Matrix_t &A, EInitialization m)
Definition Functions.h:282