RandomSamplerFromPDF.cc
Go to the documentation of this file.
1 #include <utl/RandomSamplerFromPDF.h>
2 #include <utl/RandomSamplerFromCDF.h>
3 #include <utl/ErrorLogger.h>
4 #include <utl/AugerUnits.h>
5 #include <utl/AugerException.h>
6 #include <utl/Function.h>
7 #include <utl/TabulatedFunction.h>
8 
9 #include <cmath>
10 
11 using namespace std;
12 using namespace utl;
13 
14 
15 RandomSamplerFromPDF::RandomSamplerFromPDF(const TabulatedFunction& pdf,
16  const InterpolationType intType)
17 {
18  const vector<double> x(pdf.XBegin(), pdf.XEnd());
19  const vector<double> y(pdf.YBegin(), pdf.YEnd());
20  Init(x, y, intType);
21 }
22 
23 
24 RandomSamplerFromPDF::RandomSamplerFromPDF(const map<double, double>& pdf,
25  const InterpolationType intType)
26 {
27  vector<double> x;
28  vector<double> y;
29  for (map<double, double>::const_iterator it = pdf.begin();
30  it != pdf.end(); ++it) {
31  x.push_back(it->first);
32  y.push_back(it->second);
33  }
34  Init(x, y, intType);
35 }
36 
37 
38 RandomSamplerFromPDF::~RandomSamplerFromPDF()
39 {
40  delete fCDF;
41 }
42 
43 
44 double
45 RandomSamplerFromPDF::GetInverseCDF(const double y)
46  const
47 {
48  if (!fPDF)
49  return fCDF->GetInverseCDF(y);
50 
51  if (y <= 0)
52  return fCDF->GetMinX();
53  if (y >= 1)
54  return fCDF->GetMaxX();
55 
56  const int i2 = fCDF->GetIndex(y);
57  const int i1 = i2 - 1;
58  const vector<double>& cdfx = fCDF->GetCDFX();
59  const vector<double>& cdfy = fCDF->GetCDFY();
60  const vector<double>& pdf = *fPDF;
61  const double x1 = cdfx[i1];
62  const double y1 = pdf[i1];
63  const double w = y - cdfy[i1];
64  const double k = (pdf[i2] - y1) / (cdfx[i2] - x1);
65  const double r = sqrt(y1*y1 + 2*k*w);
66  return x1 + 2*w / (r + y1);
67 }
68 
69 
70 void
71 RandomSamplerFromPDF::SetFunction(const string& function,
72  const string& independentVariableName,
73  const double min, const double max, const int bins)
74 {
75  vector<double> x;
76  x.resize(bins);
77  vector<double> y;
78  y.resize(bins);
79  utl::Function func(function, independentVariableName);
80  const double step = (max - min) / (bins - 1);
81  for (int i = 0; i < bins; ++i) {
82  const double xx = min + i * step;
83  x[i] = xx;
84  y[i] = func(xx);
85  }
86  InitLinear(x, y);
87 }
88 
89 
90 void
91 RandomSamplerFromPDF::Init(const vector<double>& x, const vector<double>& y,
92  const InterpolationType intType)
93 {
94  switch (intType) {
95  case eLinear:
96  InitLinear(x, y);
97  break;
98  case eDiscrete:
99  InitDiscrete(x, y);
100  break;
101  case eStep:
102  InitStep(x, y);
103  break;
104  }
105 }
106 
107 
108 inline
109 void
110 UniformFill(vector<double>& x, const unsigned int n, const unsigned int m)
111 {
112  const double step = 1. / m;
113  for (unsigned int i = 0; i < n; ++i)
114  x[i] = step * i;
115 }
116 
117 
118 void
119 RandomSamplerFromPDF::Init(const vector<double>& y,
120  const InterpolationType intType)
121 {
122  const unsigned int n = y.size();
123  vector<double> x;
124  switch (intType) {
125  case eLinear:
126  x.resize(n);
127  UniformFill(x, n, n-1);
128  Init(x, y, intType);
129  break;
130  case eDiscrete:
131  x.resize(n);
132  UniformFill(x, n, n);
133  Init(x, y, intType);
134  break;
135  case eStep:
136  {
137  x.resize(n+1);
138  UniformFill(x, n+1, n);
139  vector<double> yy(y);
140  yy.push_back(0);
141  Init(x, yy, intType);
142  break;
143  }
144  }
145 }
146 
147 
148 inline
149 void
150 Normalize(vector<double>& v, const double fact)
151 {
152  for (vector<double>::iterator it = v.begin();
153  it != v.end(); ++it)
154  *it *= fact;
155 }
156 
157 
158 void
159 RandomSamplerFromPDF::InitDiscrete(const vector<double>& x, const vector<double>& y)
160 {
161  const unsigned int n = x.size();
162  if (n < 1 || n != y.size())
163  throw InvalidConfigurationException("Not enough points in PDF");
164  const unsigned int n2 = 2*n;
165  vector<double> xv;
166  xv.resize(n2);
167  vector<double> yv;
168  yv.resize(n2);
169  double sum = 0;
170  for (unsigned int i = 0; i < n; ++i) {
171  unsigned int i2 = 2*i;
172  const double xx = x[i];
173  xv[i2] = xx;
174  yv[i2] = sum;
175  ++i2;
176  sum += y[i];
177  xv[i2] = xx;
178  yv[i2] = sum;
179  }
180  if (sum != 1)
181  Normalize(yv, 1/sum);
182  fCDF = new RandomSamplerFromCDF(xv, yv);
183 }
184 
185 
186 void
187 RandomSamplerFromPDF::InitStep(const vector<double>& x, const vector<double>& y)
188 {
189  const unsigned int n = x.size();
190  if (n < 2 || n != y.size())
191  throw InvalidConfigurationException("Not enough points in PDF");
192  vector<double> xv;
193  xv.resize(n);
194  vector<double> yv;
195  yv.resize(n);
196  xv[0] = x.front();
197  yv[0] = 0;
198  double sum = 0;
199  for (unsigned int i = 1; i < n; ++i) {
200  xv[i] = x[i];
201  sum += y[i-1];
202  yv[i] = sum;
203  }
204  if (sum != 1)
205  Normalize(yv, 1/sum);
206  fCDF = new RandomSamplerFromCDF(xv, yv);
207 }
208 
209 
210 void
211 RandomSamplerFromPDF::InitLinear(const vector<double>& x, const vector<double>& y)
212 {
213  const unsigned int n = x.size();
214  if (n < 2 || n != y.size())
215  throw InvalidConfigurationException("Not enough points in PDF");
216  vector<double> xv;
217  xv.resize(n);
218  vector<double> yv;
219  yv.resize(n);
220  fPDF = new vector<double>;
221  fPDF->resize(n);
222  vector<double>& pdf2 = *fPDF;
223  double sum = 0;
224  double x1 = x.front();
225  xv[0] = x1;
226  yv[0] = 0;
227  double y1 = y.front();
228  pdf2[0] = y1;
229  for (unsigned int i = 1; i < n; ++i) {
230  const double x2 = x[i];
231  xv[i] = x2;
232  const double y2 = y[i];
233  pdf2[i] = y2;
234  sum += 0.5 * (x2 - x1) * (y1 + y2);
235  yv[i] = sum;
236  x1 = x2;
237  y1 = y2;
238  }
239  if (sum != 1) {
240  if (sum == 0)
241  throw InvalidConfigurationException("Sum of samples in PDF is zero, "
242  "impossible to normalize");
243  const double fact = 1 / sum;
244  Normalize(yv, fact);
245  Normalize(pdf2, fact);
246  }
247  fCDF = new RandomSamplerFromCDF(xv, yv);
248 }
void Normalize(vector< double > &v, const double fact)
ArrayIterator XEnd()
end of array of X
Base class for exceptions arising because configuration data are not valid.
Class to hold collection (x,y) points and provide interpolation between them.
void Init()
Initialise the registry.
#define max(a, b)
Evaluate functions given in a string. The real work is done by the ExpressionParser class...
Definition: Function.h:27
ArrayIterator YBegin()
begin of array of Y
void UniformFill(vector< double > &x, const unsigned int n, const unsigned int m)
ArrayIterator XBegin()
begin of array of X
ArrayIterator YEnd()
end of array of Y
constexpr double m
Definition: AugerUnits.h:121

, generated on Tue Sep 26 2023.