1 /*  _______________________________________________________________________
2 
3     PECOS: Parallel Environment for Creation Of Stochastics
4     Copyright (c) 2011, Sandia National Laboratories.
5     This software is distributed under the GNU Lesser General Public License.
6     For more information, see the README file in the top Pecos directory.
7     _______________________________________________________________________ */
8 
9 //- Class:	 RandomVariable
10 //- Description:
11 //- Owner:       Mike Eldred
12 //- Revised by:
13 //- Version:
14 
15 #ifndef RANDOM_VARIABLE_HPP
16 #define RANDOM_VARIABLE_HPP
17 
18 #include "pecos_stat_util.hpp"
19 
20 namespace Pecos {
21 
22 
23 /// base class for random variable hierarchy
24 
25 /** This class enables cdf(), ccdf(), inverse_cdf(), inverse_ccdf(),
26     pdf(), pdf_gradient(), pdf_hessian(), and related random variable
27     utilities from contained distribution parameters. */
28 
29 // ExtremeValueBase: Gumbel, Frechet, Weibull -> alpha, beta, no bounds
30 // EmpiricalBase: histogram bin, KDE, ...
31 
32 class RandomVariable
33 {
34 public:
35 
36   //
37   //- Heading: Constructors, destructor, and operator=
38   //
39 
40   /// default constructor
41   RandomVariable();
42   /// standard constructor for envelope
43   RandomVariable(short ran_var_type);
44   /// copy constructor
45   RandomVariable(const RandomVariable& ran_var);
46 
47   /// destructor
48   virtual ~RandomVariable();
49 
50   /// assignment operator
51   RandomVariable operator=(const RandomVariable& ran_var);
52 
53   //
54   //- Heading: Virtual functions
55   //
56 
57   /// return the cumulative distribution function value of the random
58   /// variable at x
59   virtual Real cdf(Real x) const;
60   /// return the x value corresponding to a cumulative probability
61   virtual Real inverse_cdf(Real p_cdf) const;
62 
63   /// return the complementary cumulative distribution function value
64   /// of the random variable at x
65   virtual Real ccdf(Real x) const;
66   /// return the x value corresponding to a complementary cumulative probability
67   virtual Real inverse_ccdf(Real p_ccdf) const;
68 
69   /// return the value of the random variable's probability density
70   /// function at x
71   virtual Real pdf(Real x) const;
72   /// return the gradient of the random variable's probability density
73   /// function at x
74   virtual Real pdf_gradient(Real x) const;
75   /// return the hessian of the random variable's probability density
76   /// function at x
77   virtual Real pdf_hessian(Real x) const;
78   /// return the value of the natural log of the random variable's probability
79   /// density function at x (useful for calculations of log density in Bayesian
80   /// methods)
81   virtual Real log_pdf(Real x) const;
82   /// return the gradient of the natural log of the random variable's
83   /// probability density function at x (useful for defining MCMC proposal
84   /// distributions in Bayesian methods)
85   virtual Real log_pdf_gradient(Real x) const;
86   /// return the Hessian of the natural log of the random variable's probability
87   /// density function at x (useful for defining MCMC proposal distributions in
88   /// Bayesian methods)
89   virtual Real log_pdf_hessian(Real x) const;
90 
91   /// return the x value for a standardized probability distribution
92   /// corresponding to a cumulative probability
93   virtual Real inverse_standard_cdf(Real p_cdf) const;
94 
95   /// return the value of a standardized random variable's probability density
96   /// function at x
97   virtual Real standard_pdf(Real z) const;
98   /// return the natural log of a standardized random variable's probability
99   /// density function at x (useful for calculations of log density in
100   /// Bayesian methods)
101   virtual Real log_standard_pdf(Real z) const;
102   /// return the gradient of the natural log of a standardized random
103   /// variable's probability density function at x (useful for
104   /// calculations of log density in Bayesian methods)
105   virtual Real log_standard_pdf_gradient(Real z) const;
106   /// return the Hessian of the natural log of a standardized random
107   /// variable's probability density function at x (useful for
108   /// calculations of log density in Bayesian methods)
109   virtual Real log_standard_pdf_hessian(Real z) const;
110 
111   /// scale variable value x from current to standardized distribution
112   virtual Real to_standard(Real x) const;
113   /// scale variable value z from standardized to current distribution
114   virtual Real from_standard(Real z) const;
115 
116   /// return the value of the named distribution parameter
117   virtual void pull_parameter(short dist_param, Real& val) const;
118   /// return the value of the named distribution parameter
119   virtual void pull_parameter(short dist_param, int& val) const;
120   /// return the value of the named distribution parameter
121   virtual void pull_parameter(short dist_param, unsigned int& val) const;
122   /// return the value of the named distribution parameter
123   virtual void pull_parameter(short dist_param, IntSet& val) const;
124   /// return the value of the named distribution parameter
125   virtual void pull_parameter(short dist_param, StringSet& val) const;
126   /// return the value of the named distribution parameter
127   virtual void pull_parameter(short dist_param, RealSet& val) const;
128   /// return the value of the named distribution parameter
129   virtual void pull_parameter(short dist_param, IntRealMap& val) const;
130   /// return the value of the named distribution parameter
131   virtual void pull_parameter(short dist_param, StringRealMap& val) const;
132   /// return the value of the named distribution parameter
133   virtual void pull_parameter(short dist_param, RealRealMap& val) const;
134   /// return the value of the named distribution parameter
135   virtual void pull_parameter(short dist_param, IntIntPairRealMap& val) const;
136   /// return the value of the named distribution parameter
137   virtual void pull_parameter(short dist_param, RealRealPairRealMap& val) const;
138 
139   /// update the value of the named distribution parameter
140   virtual void push_parameter(short dist_param, Real val);
141   /// update the value of the named distribution parameter
142   virtual void push_parameter(short dist_param, int val);
143   /// update the value of the named distribution parameter
144   virtual void push_parameter(short dist_param, unsigned int val);
145   /// update the value of the named distribution parameter
146   virtual void push_parameter(short dist_param, const IntSet& val);
147   /// update the value of the named distribution parameter
148   virtual void push_parameter(short dist_param, const StringSet& val);
149   /// update the value of the named distribution parameter
150   virtual void push_parameter(short dist_param, const RealSet& val);
151   /// update the value of the named distribution parameter
152   virtual void push_parameter(short dist_param, const IntRealMap& val);
153   /// update the value of the named distribution parameter
154   virtual void push_parameter(short dist_param, const StringRealMap& val);
155   /// update the value of the named distribution parameter
156   virtual void push_parameter(short dist_param, const RealRealMap& val);
157   /// update the value of the named distribution parameter
158   virtual void push_parameter(short dist_param, const IntIntPairRealMap& val);
159   /// update the value of the named distribution parameter
160   virtual void push_parameter(short dist_param, const RealRealPairRealMap& val);
161 
162   /// copy the distribution parameter values from rv into *this
163   virtual void copy_parameters(const RandomVariable& rv);
164 
165   /// return the distribution mean
166   virtual Real mean() const;
167   /// return the distribution mode
168   virtual Real median() const;
169   /// return the distribution mode
170   virtual Real mode() const;
171   /// return the distribution variance
172   virtual Real standard_deviation() const;
173   /// return the distribution variance
174   virtual Real variance() const;
175 
176   /// return the distribution mean and standard deviation as a pair
177   /** default is only overridden when more efficient to compute together */
178   virtual RealRealPair moments() const;
179 
180   /// return the distribution lower and upper bounds as a pair
181   virtual RealRealPair distribution_bounds() const;
182 
183   //virtual Real pull_lower_bound() const;
184   //virtual int  pull_lower_bound() const;
185   //virtual void push_lower_bound(Real l_bnd);
186   //virtual void push_lower_bound(int  l_bnd);
187   virtual void lower_bound(Real l_bnd);
188   virtual void lower_bound(int  l_bnd);
189   virtual void upper_bound(Real l_bnd);
190   virtual void upper_bound(int  l_bnd);
191 
192   /// compute the coefficient of variation (used to compute selected
193   /// correlation warping factors); defined for semi-infinite distributions
194   /// with nonzero mean (lognormal, exponential, gamma, frechet, weibull)
195   /** default is only overridden when more efficient to compute together */
196   virtual Real coefficient_of_variation() const;
197   /// compute the warping factor for correlation between the current
198   /// variable and the one passed in (used in NatafTransformation)
199   virtual Real correlation_warping_factor(const RandomVariable& rv,
200 					  Real corr) const;
201 
202   /// compute the design Jacobian from differentiating the X->Z mapping with
203   /// respect to the distibution parameter s
204   virtual Real dx_ds(short dist_param, short u_type, Real x, Real z) const;
205   /// compute the mapping-specific factor that is multiplied by dz/ds for
206   /// contributions to the dx/ds design Jacobian in the case of correlated
207   /// random variables (dz/ds is evaluated numerically and multiplied by
208   /// this analytic factor)
209   virtual Real dz_ds_factor(short u_type, Real x, Real z) const;
210 
211   //
212   //- Heading: Member functions
213   //
214 
215   // Invoke virtual pull_parameter(short, T) and return result
216   //template <typename T>
217   //T return_parameter(short dist_param) const;
218 
219   /// Draw a sample from the distribution using inverse_cdf on uniform[0,1]
220   template <typename Engine>
221   Real draw_sample(Engine& rng) const;
222   /// Draw a sample from the distribution using inverse_cdf on uniform[0,1]
223   template <typename Engine>
224   Real draw_standard_sample(Engine& rng) const;
225 
226   /// set ranVarType
227   void type(short ran_var_type);
228   /// get ranVarType
229   short type() const;
230 
231   /// returns ranVarRep for access to derived class member functions
232   /// that are not mapped to the base level
233   std::shared_ptr<RandomVariable> random_variable_rep() const;
234   /// function to check modelRep (does this envelope contain a letter)
235   bool is_null() const;
236 
237 protected:
238 
239   //
240   //- Heading: Constructors
241   //
242 
243   /// constructor initializes the base class part of letter classes
244   /// (BaseConstructor overloading avoids infinite recursion in the
245   /// derived class constructors - Coplien, p. 139)
246   RandomVariable(BaseConstructor);
247 
248   //
249   //- Heading: Member functions
250   //
251 
252   //
253   //- Heading: Data
254   //
255 
256   /// enumeration value indicating type of random variable
257   short ranVarType;
258 
259 private:
260 
261   //
262   //- Heading: Member functions
263   //
264 
265   /// Used only by the standard envelope constructor to initialize
266   /// ranVarRep to the appropriate derived type.
267   std::shared_ptr<RandomVariable> get_random_variable(short ran_var_type);
268 
269   //
270   //- Heading: Data members
271   //
272 
273   /// draws real samples on [0,1]
274   boost::uniform_real<Real> uniformSampler;
275 
276   /// pointer to the letter (initialized only for the envelope)
277   std::shared_ptr<RandomVariable> ranVarRep;
278 };
279 
280 
281 /*
282 template <typename T>
283 T RandomVariable::return_parameter(short dist_param) const
284 {
285   T val;
286   pull_parameter(dist_param, val);
287   return val;
288 }
289 */
290 
291 
292 template <typename Engine>
draw_sample(Engine & rng) const293 Real RandomVariable::draw_sample(Engine& rng) const
294 {
295   if (ranVarRep)
296     return ranVarRep->draw_sample(rng);
297   else {
298     // draw random number on [0,1] from a persistent RNG sequence
299     Real u01 = uniformSampler(rng);
300     return inverse_cdf(u01);
301   }
302 }
303 
304 
305 template <typename Engine>
draw_standard_sample(Engine & rng) const306 Real RandomVariable::draw_standard_sample(Engine& rng) const
307 {
308   if (ranVarRep)
309     return ranVarRep->draw_standard_sample(rng);
310   else {
311     // draw random number on [0,1] from a persistent RNG sequence
312     Real u01 = uniformSampler(rng);
313     return inverse_standard_cdf(u01);
314   }
315 }
316 
317 
type(short ran_var_type)318 inline void RandomVariable::type(short ran_var_type)
319 {
320   if (ranVarRep) ranVarRep->ranVarType = ran_var_type;
321   else           ranVarType = ran_var_type;
322 }
323 
324 
type() const325 inline short RandomVariable::type() const
326 { return (ranVarRep) ? ranVarRep->ranVarType : ranVarType; }
327 
328 
329 inline std::shared_ptr<RandomVariable>
random_variable_rep() const330 RandomVariable::random_variable_rep() const
331 { return ranVarRep; }
332 
333 
is_null() const334 inline bool RandomVariable::is_null() const
335 { return (ranVarRep) ? false : true; }
336 
337 } // namespace Pecos
338 
339 #endif
340