ROL
ROL_Distribution.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Rapid Optimization Library (ROL) Package
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 // Drew Kouri (dpkouri@sandia.gov) and
39 // Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #ifndef ROL_DISTRIBUTION_HPP
45 #define ROL_DISTRIBUTION_HPP
46 
47 #include "ROL_Types.hpp"
48 
49 #include <cmath>
50 #include <iostream>
51 
52 namespace ROL {
53 
69 };
70 
71 template<class Real>
72 class Distribution {
73 private:
75  std::vector<Real> data_;
76 
77 public:
78 
80  switch(ed) {
81  case DISTRIBUTION_DIRAC:
82  data_.resize(1,0.0);
83  data_[0] = 0.0;
84  break;
86  data_.resize(2,0.0);
87  data_[0] = 0.0; // Mean
88  data_[1] = 1.0; // Standard Deviation
89  break;
91  data_.resize(2,0.0);
92  data_[0] = -1.0; // Lower bound
93  data_[1] = 1.0; // Upper bound
94  data_[2] = 0.0; // Mean
95  data_[3] = 1.0; // Standard Deviation
96  break;
98  data_.resize(2,0.0);
99  data_[0] = 0.0; // Lower Bound
100  data_[1] = 1.0; // Upper Bound
101  break;
103  data_[0] = 0.0; // Mean
104  data_[1] = 1.0; // Variance Parameter
105  break;
107  data_.resize(3,0.0);
108  data_[0] = 0.0; // Lower Bound
109  data_[1] = 0.5; // Mid Point
110  data_[2] = 1.0; // Upper Bound
111  break;
113  data_.resize(2,0.0);
114  data_[0] = 0.0; // Upper Bound
115  data_[1] = 1.0; // Lower Bound
116  break;
118  data_.resize(2,0.0);
119  data_[0] = 0.5; // Mean
120  data_[1] = 0.5; // Variance Parameter
121  break;
123  data_.resize(2,0.0);
124  data_[0] = 0.0;
125  data_[1] = 1.0;
126  break;
127  case DISTRIBUTION_CAUCHY:
128  data_.resize(2,0.0);
129  data_[0] = 0.0;
130  data_[1] = 1.0;
131  break;
132  case DISTRIBUTION_SMALE:
133  data_.resize(2,0.0);
134  data_[0] = 0.0;
135  data_[1] = 1.0;
136  break;
138  data_.resize(2,0.0);
139  data_[0] = 0.0;
140  data_[1] = 1.0;
141  break;
143  data_.resize(4,0.0);
144  data_[0] = 0.0; // Lower Bound
145  data_[1] = 1.0; // Upper Bound
146  data_[2] = 0.5; // Exponent 1
147  data_[3] = 0.5; // Exponent 2
148  break;
149  default:
150  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument,
151  ">>> ERROR (ROL::Distribution): Distribution not defined!");
152  }
153  }
154 
155  Distribution(EDistribution ed, std::vector<Real> &data) : ed_(ed), data_(data) {}
156 
157  Real pdf(Real input) {
158  Real val = 0.0;
159  switch(ed_) {
160  case DISTRIBUTION_DIRAC: val = dirac_pdf(input); break;
161  case DISTRIBUTION_GAUSSIAN: val = gaussian_pdf(input); break;
162  case DISTRIBUTION_TRUNCATEDGAUSSIAN: val = truncatedgaussian_pdf(input); break;
163  case DISTRIBUTION_UNIFORM: val = uniform_pdf(input); break;
164  case DISTRIBUTION_LOGISTIC: val = logistic_pdf(input); break;
165  case DISTRIBUTION_TRIANGLE: val = triangle_pdf(input); break;
166  case DISTRIBUTION_PARABOLIC: val = parabolic_pdf(input); break;
167  case DISTRIBUTION_RAISEDCOSINE: val = raisedcosine_pdf(input); break;
168  case DISTRIBUTION_LAPLACE: val = laplace_pdf(input); break;
169  case DISTRIBUTION_CAUCHY: val = cauchy_pdf(input); break;
170  case DISTRIBUTION_SMALE: val = smale_pdf(input); break;
171  case DISTRIBUTION_ARCSINE: val = arcsine_pdf(input); break;
172  case DISTRIBUTION_KUMARASWAMY: val = kumaraswamy_pdf(input); break;
173  default:
174  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument,
175  ">>> ERROR (ROL::Distribution): Distribution not defined!");
176  }
177  return val;
178  }
179 
180  Real cdf(Real input) {
181  Real val = 0.0;
182  switch(ed_) {
183  case DISTRIBUTION_DIRAC: val = dirac_cdf(input); break;
184  case DISTRIBUTION_GAUSSIAN: val = gaussian_cdf(input); break;
185  case DISTRIBUTION_TRUNCATEDGAUSSIAN: val = truncatedgaussian_cdf(input); break;
186  case DISTRIBUTION_UNIFORM: val = uniform_cdf(input); break;
187  case DISTRIBUTION_LOGISTIC: val = logistic_cdf(input); break;
188  case DISTRIBUTION_TRIANGLE: val = triangle_cdf(input); break;
189  case DISTRIBUTION_PARABOLIC: val = parabolic_cdf(input); break;
190  case DISTRIBUTION_RAISEDCOSINE: val = raisedcosine_cdf(input); break;
191  case DISTRIBUTION_LAPLACE: val = laplace_cdf(input); break;
192  case DISTRIBUTION_CAUCHY: val = cauchy_cdf(input); break;
193  case DISTRIBUTION_SMALE: val = smale_cdf(input); break;
194  case DISTRIBUTION_ARCSINE: val = arcsine_cdf(input); break;
195  case DISTRIBUTION_KUMARASWAMY: val = kumaraswamy_cdf(input); break;
196  default:
197  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument,
198  ">>> ERROR (ROL::Distribution): Distribution not defined!");
199  }
200  return val;
201  }
202 
203  Real intcdf(Real input) {
204  Real val = 0.0;
205  switch(ed_) {
206  case DISTRIBUTION_DIRAC: val = dirac_intcdf(input); break;
207  case DISTRIBUTION_GAUSSIAN: val = gaussian_intcdf(input); break;
209  case DISTRIBUTION_UNIFORM: val = uniform_intcdf(input); break;
210  case DISTRIBUTION_LOGISTIC: val = logistic_intcdf(input); break;
211  case DISTRIBUTION_TRIANGLE: val = triangle_intcdf(input); break;
212  case DISTRIBUTION_PARABOLIC: val = parabolic_intcdf(input); break;
213  case DISTRIBUTION_RAISEDCOSINE: val = raisedcosine_intcdf(input); break;
214  case DISTRIBUTION_LAPLACE: val = laplace_intcdf(input); break;
215  case DISTRIBUTION_CAUCHY: val = cauchy_intcdf(input); break;
216  case DISTRIBUTION_SMALE: val = smale_intcdf(input); break;
217  case DISTRIBUTION_ARCSINE: val = arcsine_intcdf(input); break;
218  case DISTRIBUTION_KUMARASWAMY: val = kumaraswamy_intcdf(input); break;
219  default:
220  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument,
221  ">>> ERROR (ROL::Distribution): Distribution not defined!");
222  }
223  return val;
224  }
225 
226  Real invcdf(Real input) {
227  Real val = 0.0;
228  switch(ed_) {
229  case DISTRIBUTION_DIRAC: val = dirac_invcdf(input); break;
230  case DISTRIBUTION_GAUSSIAN: val = gaussian_invcdf(input); break;
232  case DISTRIBUTION_UNIFORM: val = uniform_invcdf(input); break;
233  case DISTRIBUTION_LOGISTIC: val = logistic_invcdf(input); break;
234  case DISTRIBUTION_TRIANGLE: val = triangle_invcdf(input); break;
235  case DISTRIBUTION_PARABOLIC: val = parabolic_invcdf(input); break;
236  case DISTRIBUTION_RAISEDCOSINE: val = raisedcosine_invcdf(input); break;
237  case DISTRIBUTION_LAPLACE: val = laplace_invcdf(input); break;
238  case DISTRIBUTION_CAUCHY: val = cauchy_invcdf(input); break;
239  case DISTRIBUTION_SMALE: val = smale_invcdf(input); break;
240  case DISTRIBUTION_ARCSINE: val = arcsine_invcdf(input); break;
241  case DISTRIBUTION_KUMARASWAMY: val = kumaraswamy_invcdf(input); break;
242  default:
243  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument,
244  ">>> ERROR (ROL::Distribution): Distribution not defined!");
245  }
246  return val;
247  }
248 
249  void test(std::ostream &outStream = std::cout ) {
250  int size;
251  std::vector<Real> X;
252  std::vector<int> T;
253  switch (ed_) {
254  case DISTRIBUTION_DIRAC:
258  case DISTRIBUTION_CAUCHY:
259  case DISTRIBUTION_SMALE:
260  size = 1;
261  X.resize(size,0.0);
262  T.resize(size,0);
263  X[0] = 4.0*(Real)rand()/(Real)RAND_MAX - 2.0;
264  break;
270  size = 5;
271  X.resize(size,0.0);
272  T.resize(size,0);
273  X[0] = data_[0]-4.0*(Real)rand()/(Real)RAND_MAX;
274  T[0] = 0;
275  X[1] = data_[0];
276  T[1] = 1;
277  X[2] = (data_[1]-data_[0])*(Real)rand()/(Real)RAND_MAX + data_[0];
278  T[2] = 0;
279  X[3] = data_[1];
280  T[3] = 1;
281  X[4] = data_[1]+4.0*(Real)rand()/(Real)RAND_MAX;
282  T[4] = 0;
283  break;
285  size = 5;
286  X.resize(size,0.0);
287  T.resize(size,0);
288  X[0] = data_[0]-data_[1]-4.0*(Real)rand()/(Real)RAND_MAX;
289  T[0] = 0;
290  X[1] = data_[0]-data_[1];
291  T[1] = 1;
292  X[2] = (2.0*data_[1])*(Real)rand()/(Real)RAND_MAX + (data_[0]-data_[1]);
293  T[2] = 0;
294  X[3] = data_[0]+data_[1];
295  T[3] = 1;
296  X[4] = data_[0]+data_[1]+4.0*(Real)rand()/(Real)RAND_MAX;
297  T[4] = 0;
298  break;
300  size = 7;
301  X.resize(size,0.0);
302  T.resize(size,0);
303  X[0] = data_[0]-4.0*(Real)rand()/(Real)RAND_MAX;
304  T[0] = 0;
305  X[1] = data_[0];
306  T[1] = 1;
307  X[2] = (data_[1]-data_[0])*(Real)rand()/(Real)RAND_MAX + data_[0];
308  T[2] = 0;
309  X[3] = data_[1];
310  T[3] = 1;
311  X[4] = (data_[2]-data_[1])*(Real)rand()/(Real)RAND_MAX + data_[1];
312  T[4] = 0;
313  X[5] = data_[2];
314  T[5] = 1;
315  X[6] = data_[2]+4.0*(Real)rand()/(Real)RAND_MAX;
316  T[6] = 0;
317  break;
318  default:
319  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument,
320  ">>> ERROR (ROL::Distribution): Distribution not defined!");
321  }
322  for ( int k = 0; k < size; k++ ) {
323  if ( T[k] == 0 ) {
324  test_onesided(X[k],outStream);
325  }
326  else {
327  test_centered(X[k],outStream);
328  }
329  }
330  }
331 
332 private:
333 
334  // Dirac Distribution
335  Real dirac_pdf(Real input) {
336  return ((input==data_[0]) ? 1.0 : 0.0);
337  }
338  Real dirac_cdf(Real input) {
339  return ((input >= data_[0]) ? 1.0 : 0.0);
340  }
341  Real dirac_intcdf(Real input) {
342  return ((input < data_[0]) ? 0.0 : input);
343  }
344  Real dirac_invcdf(Real input) {
345  return data_[0];
346  }
347  // Gaussian Distribution
348  Real gaussian_pdf(Real input) {
349  return std::exp(-std::pow(input-data_[0],2.0)/(2.0*data_[1]))/(std::sqrt(2.0*M_PI*data_[1]));
350  }
351  Real gaussian_cdf(Real input) {
352  return 0.5*(1.0+erf((input-data_[0])/std::sqrt(2.0*data_[1])));
353  }
354  Real gaussian_intcdf(Real input) {
355  // NOT IMPLEMENTED
356  return ((input < data_[0]) ? 0.0 : input);
357  }
358  Real gaussian_invcdf(Real input) {
359  std::vector<Real> coeff;
360  Real x = 2.0*input - 1.0;
361  Real c = 1.0;
362  Real tmp = c * (std::sqrt(M_PI)/2.0 * x);
363  Real val = tmp;
364  coeff.push_back(c);
365  int cnt = 1;
366  while (std::abs(tmp) > std::sqrt(ROL_EPSILON)*std::abs(val)) {
367  c = 0.0;
368  for ( unsigned i = 0; i < coeff.size(); i++ ) {
369  c += coeff[i]*coeff[coeff.size()-1-i]/((i+1)*(2*i+1));
370  }
371  tmp = c/(2.0*(Real)cnt+1.0) * std::pow(std::sqrt(M_PI)/2.0 * x,2.0*(Real)cnt+1.0);
372  val += tmp;
373  coeff.push_back(c);
374  cnt++;
375  }
376  return std::sqrt(2*data_[1])*val + data_[0];
377  }
378  // Truncated Gaussian
379  Real truncatedgaussian_pdf(Real input) {
380  Real xi = (input-data_[2])/data_[3];
381  Real alpha = (data_[0]-data_[2])/data_[3];
382  Real beta = (data_[1]-data_[2])/data_[3];
383  Real Z = gaussian_cdf(beta)-gaussian_cdf(alpha);
384  return ((input <= data_[0]) ? 0.0 : ((input >= data_[1]) ? 0.0 : gaussian_pdf(xi)/(data_[3]*Z)));
385  }
386  Real truncatedgaussian_cdf(Real input) {
387  Real xi = (input-data_[2])/data_[3];
388  Real alpha = (data_[0]-data_[2])/data_[3];
389  Real beta = (data_[1]-data_[2])/data_[3];
390  Real Z = gaussian_cdf(beta)-gaussian_cdf(alpha);
391  return ((input <= data_[0]) ? 0.0 : ((input >= data_[1]) ? 1.0 :
392  (gaussian_cdf(xi)-gaussian_cdf(alpha))/Z));
393  }
394  Real truncatedgaussian_intcdf(Real input) {
395  // NOT IMPLEMENTED
396  return ((input < data_[0]) ? 0.0 : input);
397  }
398  Real truncatedgaussian_invcdf(Real input) {
399  Real alpha = (data_[0]-data_[2])/data_[3];
400  Real beta = (data_[1]-data_[2])/data_[3];
401  Real Z = gaussian_cdf(beta)-gaussian_cdf(alpha);
402  Real x = gaussian_invcdf(Z*input+gaussian_cdf(alpha));
403  return data_[3]*x + data_[2];
404  }
405  // Uniform Distribution
406  Real uniform_pdf(Real input) {
407  return ((input >= data_[0] && input <= data_[1]) ? 1.0/(data_[1]-data_[0]) : 0.0);
408  }
409  Real uniform_cdf(Real input) {
410  return ((input < data_[0]) ? 0.0 : ((input > data_[1]) ? 1.0 :
411  (input-data_[0])/(data_[1]-data_[0])));
412  }
413  Real uniform_intcdf(Real input) {
414  return ((input < data_[0]) ? 0.0 : ((input > data_[1]) ? input - 0.5*(data_[0]+data_[1]) :
415  0.5*std::pow(input-data_[0],2.0)/(data_[1]-data_[0])));
416  }
417  Real uniform_invcdf(Real input) {
418  return data_[0] + input*(data_[1]-data_[0]);
419  }
420  // Logistic Distribution
421  Real logistic_pdf(Real input) {
422  Real val = std::exp(-(input-data_[0])/data_[1]);
423  return val/(data_[1]*std::pow(1.0+val,2.0));
424  }
425  Real logistic_cdf(Real input) {
426  Real val = std::exp(-(input-data_[0])/data_[1]);
427  return 1.0/(1.0+val);
428  }
429  Real logistic_intcdf(Real input) {
430  Real val = std::exp(-(input-data_[0])/data_[1]);
431  return (input-data_[0]) + data_[1]*std::log(1.0+val);
432  }
433  Real logistic_invcdf(Real input) {
434  return data_[0] + data_[1]*std::log(input/(1.0-input));
435  }
436  // Triangle Distribution
437  Real triangle_pdf(Real input) {
438  Real a = data_[0], b = data_[1], c = data_[2];
439  Real d1 = b-a, d2 = c-b, d = c-a;
440  return ((input >= a && input < b) ? 2.0*(input-a)/(d*d1) :
441  ((input >= b && input < c) ? 2.0*(c-input)/(d*d2) :
442  0.0));
443  }
444  Real triangle_cdf(Real input) {
445  Real a = data_[0], b = data_[1], c = data_[2];
446  Real d1 = b-a, d2 = c-b, d = c-a;
447  return ((input < a) ? 0.0 :
448  ((input >= a && input < b) ?
449  std::pow(input-a,2.0)/(d*d1) :
450  ((input >= b && input < c) ?
451  1.0-std::pow(c-input,2.0)/(d*d2) :
452  1.0)));
453  }
454  Real triangle_intcdf(Real input) {
455  Real a = data_[0], b = data_[1], c = data_[2];
456  Real d1 = b-a, d2 = c-b, d = c-a;
457  return ((input < a) ? 0.0 :
458  ((input >= a && input < b) ?
459  std::pow(input-a,3.0)/(3.0*d*d1) :
460  ((input >= b && input < c) ?
461  d1*d1/(3.0*d)+(input-b)+(std::pow(c-input,3.0)-d2*d2*d2)/(3.0*d*d2) :
462  d1*d1/(3.0*d)+(input-b)-d2*d2/(3.0*d))));
463  }
464  Real triangle_invcdf(Real input) {
465  Real a = data_[0], b = data_[1], c = data_[2];
466  Real d1 = b-a, d2 = c-b, d = c-a;
467  return ((input <= d1/d) ? a + std::sqrt(input*d1*d) :
468  c - std::sqrt((1.0-input)*d2*d));
469  }
470  // Parabolic Distribution
471  Real parabolic_pdf(Real input) {
472  Real scale = 6.0/std::pow(data_[1]-data_[0],3.0);
473  return ((input >= data_[0] && input <= data_[1]) ? scale*(input-data_[0])*(data_[1]-input) : 0.0);
474  }
475  Real parabolic_cdf(Real input) {
476  Real d1 = data_[1]-data_[0];
477  Real d2 = d1*d1;
478  Real d3 = d2*d1;
479  Real v1 = input-data_[0];
480  Real v2 = v1*v1;
481  Real v3 = v1*v2;
482  return ((input < data_[0]) ? 0.0 : ((input > data_[1]) ? 1.0 :
483  3.0*v2/d2 - 2.0*v3/d3));
484  }
485  Real parabolic_intcdf(Real input) {
486  Real d0 = data_[1]+data_[0];
487  Real d1 = data_[1]-data_[0];
488  Real d2 = d1*d1;
489  Real d3 = d2*d1;
490  Real v1 = input-data_[0];
491  Real v2 = v1*v1;
492  Real v3 = v1*v2;
493  Real v4 = v1*v3;
494  return ((input < data_[0]) ? 0.0 :
495  ((input > data_[1]) ? input - 0.5*d0 :
496  v3/d2 - 0.5*v4/d3));
497  }
498  Real parabolic_invcdf(Real input) {
499  Real a = data_[0] - data_[1];
500  Real b = data_[0] + data_[1];
501  Real c = 0.0;
502  Real fa = parabolic_cdf(a) - input;
503  //Real fb = parabolic_cdf(b) - input;
504  Real fc = 0.0;
505  Real sa = ((fa < 0.0) ? -1.0 : ((fa > 0.0) ? 1.0 : 0.0));
506  //Real sb = ((fb < 0.0) ? -1.0 : ((fb > 0.0) ? 1.0 : 0.0));
507  Real sc = 0.0;
508  for (int i = 0; i < 100; i++) {
509  c = (a+b)*0.5;
510  fc = parabolic_cdf(c) - input;
511  sc = ((fc < 0.0) ? -1.0 : ((fc > 0.0) ? 1.0 : 0.0));
512  if ( fc == 0.0 || (b-a)*0.5 < ROL_EPSILON ) {
513  break;
514  }
515  if ( sc == sa ) { a = c; fa = fc; sa = sc; }
516  else { b = c; } // fb = fc; sb = sc; }
517  }
518  return c;
519  }
520  // Raised Cosine Distribution
521  Real raisedcosine_pdf(Real input) {
522  Real a = data_[0]-data_[1];
523  Real b = data_[0]+data_[1];
524  return ((input >= a && input <= b) ? (1.0+std::cos(M_PI*(input-data_[0])/data_[1]))/(2.0*data_[1]) : 0.0);
525  }
526  Real raisedcosine_cdf(Real input) {
527  Real a = data_[0]-data_[1];
528  Real b = data_[0]+data_[1];
529  return ((input < a) ? 0.0 : ((input > b) ? 1.0 :
530  0.5*(1.0+(input-data_[0])/data_[1]+std::sin(M_PI*(input-data_[0])/data_[1])/M_PI)));
531  }
532  Real raisedcosine_intcdf(Real input) {
533  Real a = data_[0]-data_[1];
534  Real b = data_[0]+data_[1];
535  Real v = input-data_[0];
536  return ((input < a) ? 0.0 : ((input > b) ? input - data_[1] :
537  0.5*(v+0.5*v*v/data_[1]-data_[1]*((std::cos(M_PI*v/data_[1])+1.0)/(M_PI*M_PI)-0.5))));
538  }
539  Real raisedcosine_invcdf(Real input) {
540  Real a = data_[0] - data_[1];
541  Real b = data_[0] + data_[1];
542  Real c = 0.0;
543  Real fa = raisedcosine_cdf(a) - input;
544  //Real fb = raisedcosine_cdf(b) - input;
545  Real fc = 0.0;
546  Real sa = ((fa < 0.0) ? -1.0 : ((fa > 0.0) ? 1.0 : 0.0));
547  //Real sb = ((fb < 0.0) ? -1.0 : ((fb > 0.0) ? 1.0 : 0.0));
548  Real sc = 0.0;
549  for (int i = 0; i < 100; i++) {
550  c = (a+b)*0.5;
551  fc = raisedcosine_cdf(c) - input;
552  sc = ((fc < 0.0) ? -1.0 : ((fc > 0.0) ? 1.0 : 0.0));
553  if ( fc == 0.0 || (b-a)*0.5 < ROL_EPSILON ) {
554  break;
555  }
556  if ( sc == sa ) { a = c; fa = fc; sa = sc; }
557  else { b = c; } // fb = fc; sb = sc; }
558  }
559  return c;
560  }
561  // Laplace Distribution
562  Real laplace_pdf(Real input) {
563  return 0.5*std::exp(-std::abs(input-data_[0])/data_[1])/data_[1];
564  }
565  Real laplace_cdf(Real input) {
566  return ((input < data_[0]) ? 0.5*std::exp((input-data_[0])/data_[1]) :
567  1.0-0.5*std::exp(-(input-data_[0])/data_[1]));
568  }
569  Real laplace_intcdf(Real input) {
570  return ((input < data_[0]) ? 0.5*data_[1]*std::exp((input-data_[0])/data_[1]) :
571  (input-data_[0])+0.5*data_[1]*std::exp(-(input-data_[0])/data_[1]));
572  }
573  Real laplace_invcdf(Real input) {
574  Real sgn = ((input < 0.5) ? -1.0 : ((input > 0.5) ? 1.0 : 0.0));
575  return data_[0] - data_[1]*sgn*std::log(1.0-2.0*std::abs(input-0.5));
576  }
577  // Cauchy Distribution
578  Real cauchy_pdf(Real input) {
579  return 1.0/(M_PI*data_[1]*(1.0+std::pow((input-data_[0])/data_[1],2.0)));
580  }
581  Real cauchy_cdf(Real input) {
582  return 0.5+atan((input-data_[0])/data_[1])/M_PI;
583  }
584  Real cauchy_intcdf(Real input) {
585  Real v = input-data_[0];
586  return 0.5*input + (v*atan(v/data_[1]) - 0.5*data_[1]*std::log(v*v+data_[1]*data_[1]))/M_PI;
587  }
588  Real cauchy_invcdf(Real input) {
589  return data_[0]+data_[1]*tan(M_PI*(input-0.5));
590  }
591  // Smale Distribution
592  Real smale_pdf(Real input) {
593  Real val = std::pow(input-data_[0],2.0)+4.0*data_[1]*data_[1];
594  Real root = std::sqrt(val);
595  return 2.0*data_[1]*data_[1]/(val*root);
596  }
597  Real smale_cdf(Real input) {
598  Real val = std::pow(input-data_[0],2.0)+4.0*data_[1]*data_[1];
599  Real root = std::sqrt(val);
600  return 0.5*(1.0+input/root);
601  }
602  Real smale_intcdf(Real input) {
603  Real val = std::pow(input-data_[0],2.0)+4.0*data_[1]*data_[1];
604  Real root = std::sqrt(val);
605  return 0.5*(input+root);
606  }
607  Real smale_invcdf(Real input) {
608  Real x = data_[0];
609  Real fx = smale_cdf(x)-input;
610  Real s = 0.0;
611  Real xs = 0.0;
612  Real a = 1.0;
613  Real tmp = 0.0;
614  for (int i = 0; i < 100; i++) {
615  if ( std::abs(fx) < ROL_EPSILON ) { break; }
616  s = -fx/smale_pdf(x);
617  a = 1.0;
618  xs = x + a*s;
619  tmp = fx;
620  fx = smale_cdf(xs)-input;
621  while ( std::abs(fx) > (1.0 - 1.e-4*a)*std::abs(tmp) ) {
622  a *= 0.5;
623  xs = x + a*s;
624  fx = smale_cdf(xs)-input;
625  }
626  x = xs;
627  }
628  return x;
629  }
630  // Arcsine Distribution
631  Real arcsine_pdf(Real input) {
632  return ((input <= data_[0]) ? 0.0 : ((input >= data_[1]) ? 0.0 :
633  1.0/(M_PI*std::sqrt((input-data_[0])*(data_[1]-input)))));
634  }
635  Real arcsine_cdf(Real input) {
636  return ((input <= data_[0]) ? 0.0 : ((input >= data_[1]) ? 1.0 :
637  2.0/M_PI * asin(std::sqrt((input-data_[0])/(data_[1]-data_[0])))));
638  }
639  Real arcsine_intcdf(Real input) {
640  // NOT IMPLEMENTED
641  return ((input < data_[0]) ? 0.0 : input);
642  }
643  Real arcsine_invcdf(Real input) {
644  Real x = std::pow(std::sin(0.5*M_PI*input),2.0);
645  return x*(data_[1]-data_[0]) + data_[0];
646  }
647  // Kumaraswamy Distribution
648  Real kumaraswamy_pdf(Real input) {
649  Real x = (input - data_[0])/(data_[1]-data_[0]);
650  return ((x <= 0.0) ? 0.0 : ((x >= 1.0) ? 0.0 :
651  data_[2]*data_[3]*std::pow(x,data_[2]-1)*std::pow(1.0-std::pow(x,data_[2]),data_[3]-1)));
652  }
653  Real kumaraswamy_cdf(Real input) {
654  Real x = (input - data_[0])/(data_[1]-data_[0]);
655  return ((x <= 0.0) ? 0.0 : ((x >= 1.0) ? 1.0 : 1.0-std::pow(1.0-std::pow(x,data_[2]),data_[3])));
656  }
657  Real kumaraswamy_intcdf(Real input) {
658  // NOT IMPLEMENTED
659  return ((input < data_[0]) ? 0.0 : input);
660  }
661  Real kumaraswamy_invcdf(Real input) {
662  Real x = std::pow(1.0-std::pow(1.0-input,1.0/data_[3]),1.0/data_[2]);
663  return x*(data_[1]-data_[0]) + data_[0];
664  }
665 
666  void test_onesided(Real x, std::ostream &outStream = std::cout) {
667  Real vx = cdf(x);
668  Real vy = 0.0;
669  Real dv = pdf(x);
670  Real t = 1.0;
671  Real diff = 0.0;
672  Real err = 0.0;
673  outStream << std::scientific << std::setprecision(11);
674  outStream << std::right << std::setw(20) << "CHECK DENSITY: f(x) = cdf(x) with x = "
675  << x << " is correct?\n";
676  outStream << std::right << std::setw(20) << "t"
677  << std::setw(20) << "f'(x)"
678  << std::setw(20) << "(f(x+t)-f(x))/t"
679  << std::setw(20) << "Error"
680  << "\n";
681  for (int i = 0; i < 13; i++) {
682  vy = cdf(x+t);
683  diff = (vy-vx)/t;
684  err = std::abs(diff-dv);
685  outStream << std::scientific << std::setprecision(11) << std::right
686  << std::setw(20) << t
687  << std::setw(20) << dv
688  << std::setw(20) << diff
689  << std::setw(20) << err
690  << "\n";
691  t *= 0.1;
692  }
693  outStream << "\n";
694  // CHECK INTCDF
695  vx = intcdf(x);
696  vy = 0.0;
697  dv = cdf(x);
698  t = 1.0;
699  diff = 0.0;
700  err = 0.0;
701  outStream << std::scientific << std::setprecision(11);
702  outStream << std::right << std::setw(20) << "CHECK DENSITY: f(x) = intcdf(x) with x = "
703  << x << " is correct?\n";
704  outStream << std::right << std::setw(20) << "t"
705  << std::setw(20) << "f'(x)"
706  << std::setw(20) << "(f(x+t)-f(x))/t"
707  << std::setw(20) << "Error"
708  << "\n";
709  for (int i = 0; i < 13; i++) {
710  vy = intcdf(x+t);
711  diff = (vy-vx)/t;
712  err = std::abs(diff-dv);
713  outStream << std::scientific << std::setprecision(11) << std::right
714  << std::setw(20) << t
715  << std::setw(20) << dv
716  << std::setw(20) << diff
717  << std::setw(20) << err
718  << "\n";
719  t *= 0.1;
720  }
721  outStream << "\n";
722  // CHECK INVCDF
723  vx = cdf(x);
724  vy = invcdf(vx);
725  err = std::abs(x-vy);
726  outStream << std::scientific << std::setprecision(11);
727  outStream << std::right << std::setw(20) << "CHECK DENSITY: f(x) = invcdf(x) with x = "
728  << x << " is correct?\n";
729  outStream << std::right << std::setw(20) << "cdf(x)"
730  << std::setw(20) << "invcdf(cdf(x))"
731  << std::setw(20) << "Error"
732  << "\n";
733  outStream << std::scientific << std::setprecision(11) << std::right
734  << std::setw(20) << vx
735  << std::setw(20) << vy
736  << std::setw(20) << err
737  << "\n\n";
738  }
739 
740  void test_centered(Real x, std::ostream &outStream = std::cout) {
741  Real vx = 0.0;
742  Real vy = 0.0;
743  Real dv = pdf(x);
744  Real t = 1.0;
745  Real diff = 0.0;
746  Real err = 0.0;
747  outStream << std::scientific << std::setprecision(11);
748  outStream << std::right << std::setw(20) << "CHECK DENSITY: f(x) = cdf(x) with x = "
749  << x << " is correct?\n";
750  outStream << std::right << std::setw(20) << "t"
751  << std::setw(20) << "f'(x)"
752  << std::setw(20) << "(f(x+t)-f(x-t))/2t"
753  << std::setw(20) << "Error"
754  << "\n";
755  for (int i = 0; i < 13; i++) {
756  vx = cdf(x+t);
757  vy = cdf(x-t);
758  diff = 0.5*(vx-vy)/t;
759  err = std::abs(diff-dv);
760  outStream << std::scientific << std::setprecision(11) << std::right
761  << std::setw(20) << t
762  << std::setw(20) << dv
763  << std::setw(20) << diff
764  << std::setw(20) << err
765  << "\n";
766  t *= 0.1;
767  }
768  outStream << "\n";
769  // CHECK INTCDF
770  vx = 0.0;
771  vy = 0.0;
772  dv = cdf(x);
773  t = 1.0;
774  diff = 0.0;
775  err = 0.0;
776  outStream << std::scientific << std::setprecision(11);
777  outStream << std::right << std::setw(20) << "CHECK DENSITY: f(x) = intcdf(x) with x = "
778  << x << " is correct?\n";
779  outStream << std::right << std::setw(20) << "t"
780  << std::setw(20) << "f'(x)"
781  << std::setw(20) << "(f(x+t)-f(x-t))/2t"
782  << std::setw(20) << "Error"
783  << "\n";
784  for (int i = 0; i < 13; i++) {
785  vx = intcdf(x+t);
786  vy = intcdf(x-t);
787  diff = 0.5*(vx-vy)/t;
788  err = std::abs(diff-dv);
789  outStream << std::scientific << std::setprecision(11) << std::right
790  << std::setw(20) << t
791  << std::setw(20) << dv
792  << std::setw(20) << diff
793  << std::setw(20) << err
794  << "\n";
795  t *= 0.1;
796  }
797  outStream << "\n";
798  // CHECK INVCDF
799  vx = cdf(x);
800  vy = invcdf(vx);
801  err = std::abs(x-vy);
802  outStream << std::scientific << std::setprecision(11);
803  outStream << std::right << std::setw(20) << "CHECK DENSITY: f(x) = invcdf(x) with x = "
804  << x << " is correct?\n";
805  outStream << std::right << std::setw(20) << "cdf(x)"
806  << std::setw(20) << "invcdf(cdf(x))"
807  << std::setw(20) << "Error"
808  << "\n";
809  outStream << std::scientific << std::setprecision(11) << std::right
810  << std::setw(20) << vx
811  << std::setw(20) << vy
812  << std::setw(20) << err
813  << "\n\n";
814  }
815 };
816 
817 }
818 
819 #endif
Real parabolic_intcdf(Real input)
Real triangle_pdf(Real input)
Real laplace_intcdf(Real input)
Real invcdf(Real input)
Real laplace_cdf(Real input)
void test_centered(Real x, std::ostream &outStream=std::cout)
Real gaussian_intcdf(Real input)
Real logistic_invcdf(Real input)
Real truncatedgaussian_pdf(Real input)
Real smale_pdf(Real input)
Real parabolic_invcdf(Real input)
Real laplace_pdf(Real input)
Real logistic_pdf(Real input)
Contains definitions of custom data types in ROL.
Real cdf(Real input)
Real cauchy_pdf(Real input)
Real smale_cdf(Real input)
Real dirac_invcdf(Real input)
Real kumaraswamy_cdf(Real input)
Real dirac_intcdf(Real input)
Real arcsine_invcdf(Real input)
Real arcsine_cdf(Real input)
Real raisedcosine_pdf(Real input)
Real kumaraswamy_invcdf(Real input)
Real triangle_invcdf(Real input)
Real dirac_pdf(Real input)
void test(std::ostream &outStream=std::cout)
Real cauchy_intcdf(Real input)
Real raisedcosine_cdf(Real input)
Real gaussian_cdf(Real input)
Real uniform_pdf(Real input)
Real truncatedgaussian_invcdf(Real input)
Real cauchy_invcdf(Real input)
Real parabolic_pdf(Real input)
Real logistic_intcdf(Real input)
void test_onesided(Real x, std::ostream &outStream=std::cout)
Real kumaraswamy_intcdf(Real input)
std::vector< Real > data_
Real triangle_cdf(Real input)
Real kumaraswamy_pdf(Real input)
Distribution(EDistribution ed)
Real smale_invcdf(Real input)
Real gaussian_invcdf(Real input)
Real arcsine_intcdf(Real input)
Real logistic_cdf(Real input)
Real uniform_cdf(Real input)
Real laplace_invcdf(Real input)
Real intcdf(Real input)
Real pdf(Real input)
Real truncatedgaussian_cdf(Real input)
Real dirac_cdf(Real input)
Real truncatedgaussian_intcdf(Real input)
Real cauchy_cdf(Real input)
Real raisedcosine_invcdf(Real input)
Distribution(EDistribution ed, std::vector< Real > &data)
Real gaussian_pdf(Real input)
Real triangle_intcdf(Real input)
Real smale_intcdf(Real input)
Real raisedcosine_intcdf(Real input)
Real uniform_intcdf(Real input)
Real parabolic_cdf(Real input)
Real arcsine_pdf(Real input)
Real uniform_invcdf(Real input)
static const double ROL_EPSILON
Platform-dependent machine epsilon.
Definition: ROL_Types.hpp:115