Indian Ocean Skipjack
distributions.hpp
1 #pragma once
2 
3 namespace Utilities {
4 namespace Distributions {
5 
9 struct Generator : boost::mt19937 {
10  Generator(void){
11  seed(static_cast<unsigned int>(std::time(0)));
12  }
13 } Generator;
14 
18 template<
19  typename Derived
20 >
21 class Distribution : public Polymorph<Derived> {
22 public:
23 
24  using Polymorph<Derived>::derived;
25 
26  void reset(void){
27  }
28 
29  double minimum(void) const {
30  return -INFINITY;
31  }
32 
33  double maximum(void) const {
34  return INFINITY;
35  }
36 
37  double mean(void) const {
38  return boost::math::mean(derived().boost_dist());
39  }
40 
41  double median(void) const {
42  return boost::math::median(derived().boost_dist());
43  }
44 
45  double mode(void) const {
46  return boost::math::mode(derived().boost_dist());
47  }
48 
49  double sd(void) const {
50  return boost::math::standard_deviation(derived().boost_dist());
51  }
52 
53  double variance(void) const {
54  return boost::math::variance(derived().boost_dist());
55  }
56 
57  double skewness(void) const {
58  return boost::math::skewness(derived().boost_dist());
59  }
60 
61  double kurtosis(void) const {
62  return boost::math::kurtosis(derived().boost_dist());
63  }
64 
65  double kurtosis_excess(void) const {
66  return boost::math::kurtosis_excess(derived().boost_dist());
67  }
68 
69  bool valid(void) const {
70  return true;
71  }
72 
73  double loglike(const double& x) const {
74  return std::log(derived().pdf(x));
75  }
76 
77  double pdf(const double& x) const {
78  if(derived().valid()) return boost::math::pdf(derived().boost_dist(),x);
79  else return NAN;
80  }
81 
82  double cdf(const double& x) const {
83  if(derived().valid()) return boost::math::cdf(derived().boost_dist(),x);
84  else return NAN;
85  }
86 
87  double quantile(const double& p) const {
88  if(derived().valid()) return boost::math::quantile(derived().boost_dist(),p);
89  else return NAN;
90  }
91 
92  double integral(const double& from,const double& to) const {
93  return cdf(to)-cdf(from);
94  }
95 
96  double random(void) const {
97  auto boost_rand = derived().boost_rand();
98  boost::variate_generator<boost::mt19937&,decltype(boost_rand)> random(Generator,boost_rand);
99  return random();
100  }
101 };
102 
103 
104 class Fixed {
105 public:
106 
107  double value = NAN;
108 
109  bool valid(void) const {
110  return std::isfinite(value);
111  }
112 
113  double minimum(void) const {
114  return value;
115  }
116 
117  double maximum(void) const {
118  return value;
119  }
120 
121  double mean(void) const {
122  return value;
123  }
124 
125  double sd(void) const {
126  return 0;
127  }
128 
129  double random(void) const {
130  return value;
131  };
132 
133  double likelihood(const double& x) const {
134  return (x==value)?0:-INFINITY;
135  }
136 
137  double pdf(const double& x) const {
138  return (x==value)?1:0;
139  }
140 
141  double quantile(const double& p) const {
142  return value;
143  }
144 
145  template<class Mirror>
146  void reflect(Mirror& mirror) {
147  mirror
148  .data(value,"value")
149  ;
150  }
151 };
152 
153 class Beta : public Distribution<Beta> {
154 public:
155 
156  double alpha = NAN;
157  double beta = NAN;
158 
159  Beta(const double& alpha = NAN, const double& beta = NAN):
160  alpha(alpha),
161  beta(beta){
162  }
163 
164  Beta& mean_sd(const double& mean, const double& sd){
165  double var = sd*sd;
166  alpha = boost::math::beta_distribution<>::find_alpha(mean,var);
167  beta = boost::math::beta_distribution<>::find_beta(mean,var);
168  return *this;
169  }
170 
171  boost::math::beta_distribution<> boost_dist(void) const {
172  return boost::math::beta_distribution<>(alpha,beta);
173  }
174 
175  boost::random::beta_distribution<> boost_rand(void) const {
176  return boost::random::beta_distribution<>(alpha,beta);
177  }
178 
179  template<class Mirror>
180  void reflect(Mirror& mirror) {
181  mirror
182  .data(alpha,"alpha")
183  .data(beta,"beta")
184  ;
185  }
186 };
187 
188 class Normal : public Distribution<Normal> {
189 public:
190 
191  double mean = NAN;
192  double sd = NAN;
193 
194  Normal(double mean = NAN, double sd = NAN): mean(mean),sd(sd){}
195 
196  bool valid(void) const {
197  return std::isfinite(mean) and sd>0;
198  }
199 
200  boost::math::normal boost_dist(void) const {
201  return boost::math::normal(mean,sd);
202  }
203 
204  boost::normal_distribution<> boost_rand(void) const {
205  return boost::random::normal_distribution<>(mean,sd);
206  }
207 
208  template<class Mirror>
209  void reflect(Mirror& mirror) {
210  mirror
211  .data(mean,"mean")
212  .data(sd,"sd")
213  ;
214  }
215 };
216 
217 class TruncatedNormal : public Distribution<TruncatedNormal> {
218 public:
219 
220  double mean;
221  double sd;
222  double min;
223  double max;
224 
225  TruncatedNormal(double mean = NAN,double sd = NAN,double min_ = -INFINITY, double max_ = INFINITY):
226  mean(mean),sd(sd),min(min_),max(max_){}
227 
228  double minimum(void) const {
229  return min;
230  }
231 
232  double maximum(void) const {
233  return max;
234  }
235 
236  double random(void) const {
237  boost::random::normal_distribution<> dist(mean,sd);
238  boost::variate_generator<boost::mt19937&,decltype(dist)> random(Generator,dist);
239  auto trial = random();
240  if(trial<min or trial>max) trial = random();
241  return trial;
242  };
243 
244  double pdf(const double& x) const {
245  boost::math::normal norm(mean,sd);
246  if(x<min or x>max) return std::numeric_limits<double>::epsilon();
247  else return boost::math::pdf(norm,x);
248  }
249 
250  template<class Mirror>
251  void reflect(Mirror& mirror) {
252  mirror
253  .data(mean,"mean")
254  .data(sd,"sd")
255  .data(min,"min")
256  .data(max,"max")
257  ;
258  }
259 };
260 
261 
262 class Lognormal : public Distribution<Lognormal> {
263 public:
264 
265  double location = NAN;
266  double dispersion = NAN;
267 
268  Lognormal(double location = NAN, double dispersion = NAN): location(location),dispersion(dispersion){}
269 
270  double minimum(void) const {
271  return std::numeric_limits<double>::epsilon();
272  }
273 
274  bool valid(void) const {
275  return location>0 and dispersion>0;
276  }
277 
278  boost::math::lognormal boost_dist(void) const {
279  return boost::math::lognormal(location,dispersion);
280  }
281 
282  boost::lognormal_distribution<> boost_rand(void) const {
283  // Note that `boost::lognormal_distribution` is depreciated in favour
284  // of `boost::random::lognormal_distribution`. However, the latter
285  // does not produce random variates with mean of one so the
286  // older version is used for now.
287  return boost::lognormal_distribution<>(location,dispersion);
288  }
289 
290  template<class Mirror>
291  void reflect(Mirror& mirror) {
292  mirror
293  .data(location,"location")
294  .data(dispersion,"dispersion")
295  ;
296  }
297 };
298 
299 
300 class Uniform : public Distribution<Uniform> {
301 public:
302 
303  double lower = NAN;
304  double upper = NAN;
305 
306  Uniform(double lower = NAN,double upper = NAN):
307  lower(lower),
308  upper(upper){
309  }
310 
311  bool valid(void) const {
312  return std::isfinite(lower) and std::isfinite(upper) and lower<upper;
313  }
314 
315  double minimum(void) const {
316  return lower;
317  }
318 
319  double maximum(void) const {
320  return upper;
321  }
322 
323  boost::math::uniform boost_dist(void) const {
324  return boost::math::uniform(lower,upper);
325  }
326 
327  double random(void) const {
328  // If lower and upper are equal then boost random number generator
329  // will loop endlessly attempting to create a valid value. So escape that condition...
330  if(lower==upper) return lower;
331  else{
332  boost::uniform_real<> distr(lower,upper);
333  boost::variate_generator<boost::mt19937&,decltype(distr)> randomVariate(Generator,distr);
334  return randomVariate();
335  }
336  }
337 
338  template<class Mirror>
339  void reflect(Mirror& mirror) {
340  mirror
341  .data(lower,"lower")
342  .data(upper,"upper")
343  ;
344  }
345 };
346 
347 
348 class FournierRobustifiedMultivariateNormal : public Distribution<FournierRobustifiedMultivariateNormal> {
349 public:
350 
351  double proportion;
352  double size;
353  static double max_size;
354 
355  FournierRobustifiedMultivariateNormal(const double& proportion = NAN, const double& size = NAN):
356  proportion(proportion),
357  size(size){
358  }
359 
360  bool valid(void) const {
361  return std::isfinite(proportion) and size>0;
362  }
363 
364  double minimum(void) const {
365  return 0;
366  }
367 
368  double maximum(void) const {
369  return 1;
370  }
371 
372  double mean(void) const {
373  return proportion;
374  }
375 
376  double sd(void) const {
377  return proportion * (1-proportion);
378  }
379 
380  double loglike(const double& x) const {
381  double n_apos = std::min(size,max_size);
382  double e_apos = (1-x)*x+0.1/40.0;
383  return 0.5*e_apos+std::log(std::exp(-std::pow(proportion-x,2)/(2*e_apos/n_apos))+0.01);
384  }
385 
386  template<class Mirror>
387  void reflect(Mirror& mirror) {
388  mirror
389  .data(proportion,"proportion")
390  .data(size,"size")
391  ;
392  }
393 };
394 double FournierRobustifiedMultivariateNormal::max_size = 1000;
395 
396 
397 } // namespace Distributions
398 } // namespace IOSKJ
Definition: distributions.hpp:21
Definition: distributions.hpp:188
Definition: distributions.hpp:153
Definition: distributions.hpp:9
Definition: distributions.hpp:3
Definition: distributions.hpp:217
Definition: distributions.hpp:104
Definition: distributions.hpp:300
Definition: distributions.hpp:262