RandomSamplerFromCDF.cc
Go to the documentation of this file.
1 #include <utl/RandomSamplerFromCDF.h>
2 #include <utl/ErrorLogger.h>
3 #include <utl/AugerUnits.h>
4 #include <utl/AugerException.h>
5 #include <utl/Function.h>
6 #include <utl/TabulatedFunction.h>
7 
8 #include <cmath>
9 #include <sstream>
10 
11 using namespace std;
12 using namespace utl;
13 
14 
15 RandomSamplerFromCDF::RandomSamplerFromCDF(const TabulatedFunction& cdf) :
16  fX(cdf.XBegin(), cdf.XEnd()),
17  fY(cdf.YBegin(), cdf.YEnd())
18 {
20 }
21 
22 
23 RandomSamplerFromCDF::RandomSamplerFromCDF(const vector<double>& cdf) :
24  fY(cdf.begin(), cdf.end())
25 {
26  const int size = cdf.size();
27  fX.resize(size);
28  const double step = 1. / (size - 1);
29  for (int i = 0; i < size; ++i)
30  fX[i] = i * step;
32 }
33 
34 
35 RandomSamplerFromCDF::RandomSamplerFromCDF(const map<double, double>& cdf)
36 {
37  for (map<double, double>::const_iterator it = cdf.begin();
38  it != cdf.end(); ++it) {
39  fX.push_back(it->first);
40  fY.push_back(it->second);
41  }
43 }
44 
45 
46 double
48  const
49 {
50  if (y <= 0)
51  return fX.front();
52  if (y >= 1)
53  return fX.back();
54 
55  const int i2 = GetIndex(y);
56  const int i1 = i2 - 1;
57  const double x1 = fX[i1];
58  const double y1 = fY[i1];
59  return x1 + (fX[i2] - x1)*(y - y1)/(fY[i2] - y1);
60 }
61 
62 
63 void
64 RandomSamplerFromCDF::SetFunction(const string& function, const string& independentVariableName,
65  const double min, const double max, const int bins)
66 {
67  fX.resize(bins);
68  fY.resize(bins);
69  const vector<string> vars = {independentVariableName};
70  utl::Function func(function, vars);
71  const double step = (max - min) / (bins - 1);
72  for (int i = 0; i < bins; ++i) {
73  const double x = min + i * step;
74  const double y = func(x);
75  fX[i] = x;
76  fY[i] = y;
77  }
79 }
80 
81 
82 void
84 {
85  const unsigned int n = fX.size();
86  if (n < 2 || n != fY.size())
87  throw InvalidConfigurationException("Not enough points.");
88  if (fY.front() != 0) {
89  ostringstream err;
90  err << "CDF starts with " << fY.front() << " instead of 0.";
91  throw InvalidConfigurationException(err.str());
92  }
93  vector<double>::iterator it = fY.begin();
94  double y1 = *it;
95  for (++it; it != fY.end(); ++it) {
96  const double y2 = *it;
97  if (y1 > y2) {
98  cerr << "CDF is not monotonously increasing: " << y1 << " > " << y2 << endl;
99  Dump();
100  throw InvalidConfigurationException("CDF is not monotonously increasing.");
101  }
102  y1 = y2;
103  }
104  if (y1 != 1) {
105  const double fac = 1 / y1;
106  for (it = fY.begin(); it != fY.end(); ++it)
107  *it *= fac;
108  }
109 }
110 
111 
112 void
114  const
115 {
116  cerr << "CDF (x,y) dump:" << endl;
117  const size_t n = fX.size();
118  for (size_t i = 0; i < n; ++i)
119  cerr << fX.at(i) << ' ' << fY.at(i) << endl;
120 }
Base class for exceptions arising because configuration data are not valid.
Class to hold collection (x,y) points and provide interpolation between them.
int GetIndex(const double y) const
#define max(a, b)
std::vector< double > fY
double GetInverseCDF(const double y) const
Evaluate functions given in a string. The real work is done by the ExpressionParser class...
Definition: Function.h:27
std::vector< double > fX
void SetFunction(const std::string &function, const std::string &independentVariableName, const double min, const double max, const int bins)
RandomSamplerFromCDF(const std::vector< double > &x, const std::vector< double > &y)
Construct using a CDF defined by X and Y vectors.

, generated on Tue Sep 26 2023.