CMP++: Uncertainty Quantification & Bayesian Calibration
Loading...
Searching...
No Matches
distribution.h
Go to the documentation of this file.
1#ifndef DISTRIBUTION_HPP
2#define DISTRIBUTION_HPP
3
4#include "cmp_defines.h"
5#include <cmath>
6#include <vector>
7#include <memory>
8#include <random>
9#include <stdexcept>
10#include <limits>
11#include <Eigen/Dense>
12
18
19
20// ==============================================================================
21// HELPER FUNCTIONS
22// ==============================================================================
23
24inline double erfinv(float x) {
25 double tt1, tt2, lnx, sgn;
26 sgn = (x < 0) ? -1.0f : 1.0f;
27 x = 1 - x * x;
28 lnx = std::log(x);
29 tt1 = 2 / (M_PI * 0.147) + 0.5f * lnx;
30 tt2 = 1 / (0.147) * lnx;
31 return (sgn * std::sqrt(-tt1 + std::sqrt(tt1 * tt1 - tt2)));
32}
33
34inline double CDF_normal(const double &x) {
35 return 0.5 * (1 + std::erf(x / std::sqrt(2)));
36}
37
38inline double sech(const double &x) {
39 return 1.0 / std::cosh(x);
40}
41
42// ==============================================================================
43// CRTP BASE CLASSES
44// ==============================================================================
45
61template <typename Derived>
63 public:
70 double logPDF(const double &x) const {
71 return static_cast<const Derived*>(this)->logPDF(x);
72 }
73
80 double dLogPDF(const double &x) const {
81 return static_cast<const Derived*>(this)->dLogPDF(x);
82 }
83
90 double ddLogPDF(const double &x) const {
91 return static_cast<const Derived*>(this)->ddLogPDF(x);
92 }
93
100 double CDF(const double &x) const {
101 return static_cast<const Derived*>(this)->CDF(x);
102 }
103
110 double quantile(const double &p) const {
111 return static_cast<const Derived*>(this)->quantile(p);
112 }
113
120 double sample(std::default_random_engine &rng) {
121 return static_cast<Derived*>(this)->sample(rng);
122 }
123};
124
138template <typename Derived>
140 public:
147 double logPDF(const Eigen::Ref<const Eigen::VectorXd> &x) const {
148 return static_cast<const Derived*>(this)->logPDF(x);
149 }
150
157 Eigen::VectorXd sample(std::default_random_engine &rng) {
158 return static_cast<Derived*>(this)->sample(rng);
159 }
160
167 Eigen::MatrixXd toCanonical(const Eigen::MatrixXd &x) const {
168 return static_cast<const Derived*>(this)->toCanonical(x);
169 }
170
177 Eigen::MatrixXd fromCanonical(const Eigen::MatrixXd &x) const {
178 return static_cast<const Derived*>(this)->fromCanonical(x);
179 }
180
184 size_t dimension() const {
185 return static_cast<const Derived*>(this)->dimension();
186 }
187};
188
189template <typename Derived>
191 public:
192 double logJumpPDF(const Eigen::Ref<const Eigen::VectorXd> &jump) {
193 return static_cast<Derived*>(this)->logJumpPDF(jump);
194 }
195 Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma) {
196 return static_cast<Derived*>(this)->sample(rng, gamma);
197 }
198 double squaredMahalanobis(const Eigen::Ref<const Eigen::VectorXd> &jump) const {
199 return static_cast<const Derived*>(this)->squaredMahalanobis(jump);
200 }
201 Eigen::VectorXd sample(std::default_random_engine &rng) {
202 return static_cast<Derived*>(this)->sample(rng, 1.0);
203 }
204 Eigen::VectorXd get() const {
205 return static_cast<Derived*>(this)->get();
206 }
207 void set(const Eigen::Ref<const Eigen::VectorXd> &x) {
208 static_cast<Derived*>(this)->set(x);
209 }
210};
211
212// ==============================================================================
213// UNIVARIATE DISTRIBUTIONS
214// ==============================================================================
215
216class NormalDistribution : public UnivariateDistribution<NormalDistribution> {
217 private:
218 double mean_{0.0};
219 double std_{1.0};
220 std::normal_distribution<double> distN_;
221 public:
222 NormalDistribution(double mean, double sd): mean_(mean), std_(sd), distN_(0., 1.) {}
224
225 static double logPDF(const double &res, const double &std) {
226 return -0.5 * std::log(2 * M_PI) - std::log(std) - 0.5 * std::pow(res / std, 2);
227 }
228
229 double logPDF(const double &x) const {
230 return logPDF(x - mean_, std_);
231 }
232 double dLogPDF(const double &x) const {
233 return -(x - mean_) / std::pow(std_, 2);
234 }
235 double ddLogPDF(const double &x) const {
236 return -1 / std::pow(std_, 2);
237 }
238 double CDF(const double &x) const {
239 return 0.5 * (1 + std::erf((x - mean_) / (std_ * std::sqrt(2))));
240 }
241 double quantile(const double &p) const {
242 return mean_ + std_ * std::sqrt(2) * erfinv(2 * p - 1);
243 }
244 double sample(std::default_random_engine &rng) {
245 return distN_(rng) * std_ + mean_;
246 }
247
248 void setMean(double mean) {
249 mean_ = mean;
250 }
251 void setStd(double std) {
252 std_ = std;
253 }
254 double mean() const {
255 return mean_;
256 }
257 double std() const {
258 return std_;
259 }
260};
261
262
263class UniformDistribution : public UnivariateDistribution<UniformDistribution> {
264 private:
265 double lowerBound_{0.0};
266 double upperBound_{1.0};
267 std::uniform_real_distribution<double> distU_{0., 1.};
268 public:
269 UniformDistribution(double a, double b): lowerBound_(a), upperBound_(b), distU_(0., 1.) {}
271
272 double logPDF(const double &x) const {
273 if(x < lowerBound_ || x > upperBound_) return -std::numeric_limits<double>::infinity();
274 return -std::log(upperBound_ - lowerBound_);
275 }
276 double dLogPDF(const double &x) const {
277 return 0.0;
278 }
279 double ddLogPDF(const double &x) const {
280 return 0.0;
281 }
282 double CDF(const double &x) const {
283 if(x < lowerBound_) return 0.0;
284 if(x > upperBound_) return 1.0;
285 return (x - lowerBound_) / (upperBound_ - lowerBound_);
286 }
287 double quantile(const double &p) const {
288 return lowerBound_ + p * (upperBound_ - lowerBound_);
289 }
290 double sample(std::default_random_engine &rng) {
291 return lowerBound_ + distU_(rng) * (upperBound_ - lowerBound_);
292 }
293 void setLowerBound(double a) {
294 lowerBound_ = a;
295 }
296 void setUpperBound(double b) {
297 upperBound_ = b;
298 }
299};
300
301
302class InverseGammaDistribution : public UnivariateDistribution<InverseGammaDistribution> {
303 private:
304 double alpha_;
305 double beta_;
306 std::gamma_distribution<double> distGamma_;
307 public:
308 InverseGammaDistribution(double alpha, double beta): alpha_(alpha), beta_(beta), distGamma_(alpha, 1 / beta) {}
310
311 double logPDF(const double &x) const {
312 return -(alpha_ + 1) * std::log(x) - beta_ / x + alpha_ * std::log(beta_) - std::log(std::tgamma(alpha_));
313 }
314 double dLogPDF(const double &x) const {
315 return (beta_ - (alpha_ + 1) * x) / std::pow(x, 2);
316 }
317 double ddLogPDF(const double &x) const {
318 return (-2 * beta_ + x + x * alpha_) / std::pow(x, 3);
319 }
320 double CDF(const double &x) const {
321 return 0.0; // To-do
322 }
323 double quantile(const double &p) const {
324 return 0.0; // To-do
325 }
326 double sample(std::default_random_engine &rng) {
327 return 1 / distGamma_(rng);
328 }
329 void setAlpha(double alpha) {
330 alpha_ = alpha;
331 }
332 void setBeta(double beta) {
333 beta_ = beta;
334 }
335};
336
337class GammaDistribution : public UnivariateDistribution<GammaDistribution> {
338 private:
339 double alpha_;
340 double beta_;
341 std::gamma_distribution<double> distGamma_;
342
343 public:
344 // std::gamma_distribution takes (shape, scale), so we pass (alpha, 1/beta)
345 GammaDistribution(double alpha, double beta)
346 : alpha_(alpha), beta_(beta), distGamma_(alpha, 1.0 / beta) {
347 if(alpha_ <= 0.0 || beta_ <= 0.0) {
348 throw std::invalid_argument("Gamma parameters alpha and beta must be strictly positive.");
349 }
350 }
351
352 GammaDistribution() = default;
353
354 double logPDF(const double &x) const {
355 if(x <= 0.0) return -std::numeric_limits<double>::infinity();
356
357 // Using std::lgamma is much more numerically stable than std::log(std::tgamma())
358 return alpha_ * std::log(beta_) - std::lgamma(alpha_) + (alpha_ - 1.0) * std::log(x) - beta_ * x;
359 }
360
361 double dLogPDF(const double &x) const {
362 if(x <= 0.0) return 0.0;
363 return (alpha_ - 1.0) / x - beta_;
364 }
365
366 double ddLogPDF(const double &x) const {
367 if(x <= 0.0) return 0.0;
368 return -(alpha_ - 1.0) / std::pow(x, 2);
369 }
370
371 double CDF(const double &x) const {
372 return 0.0; // To-do: Requires regularized lower incomplete gamma function
373 }
374
375 double quantile(const double &p) const {
376 return 0.0; // To-do: Requires inverse incomplete gamma function
377 }
378
379 double sample(std::default_random_engine &rng) {
380 return distGamma_(rng);
381 }
382
383 // Setters need to recreate the std::gamma_distribution to update internal state
384 void setAlpha(double alpha) {
385 alpha_ = alpha;
386 distGamma_ = std::gamma_distribution<double>(alpha_, 1.0 / beta_);
387 }
388
389 void setBeta(double beta) {
390 beta_ = beta;
391 distGamma_ = std::gamma_distribution<double>(alpha_, 1.0 / beta_);
392 }
393
394 // Getters are useful when extracting parameters in the DPMM
395 double getAlpha() const {
396 return alpha_;
397 }
398 double getBeta() const {
399 return beta_;
400 }
401};
402
403class BetaDistribution : public UnivariateDistribution<BetaDistribution> {
404 private:
405 double alpha_;
406 double beta_;
407 std::gamma_distribution<double> distGammaAlpha_;
408 std::gamma_distribution<double> distGammaBeta_;
409
410 public:
411 BetaDistribution(double alpha, double beta)
412 : alpha_(alpha), beta_(beta),
413 distGammaAlpha_(alpha, 1.0),
414 distGammaBeta_(beta, 1.0) {
415 if(alpha_ <= 0.0 || beta_ <= 0.0) {
416 throw std::invalid_argument("Beta parameters alpha and beta must be strictly positive.");
417 }
418 }
419
420 BetaDistribution() = default;
421
422 double logPDF(const double &x) const {
423 // Beta distribution is strictly defined on the interval (0, 1)
424 if(x <= 0.0 || x >= 1.0) return -std::numeric_limits<double>::infinity();
425
426 // Calculate the log Beta function: ln(B(a, b)) = ln(Gamma(a)) + ln(Gamma(b)) - ln(Gamma(a+b))
427 double logBetaFunc = std::lgamma(alpha_) + std::lgamma(beta_) - std::lgamma(alpha_ + beta_);
428
429 return (alpha_ - 1.0) * std::log(x) + (beta_ - 1.0) * std::log(1.0 - x) - logBetaFunc;
430 }
431
432 double dLogPDF(const double &x) const {
433 if(x <= 0.0 || x >= 1.0) return 0.0;
434 return (alpha_ - 1.0) / x - (beta_ - 1.0) / (1.0 - x);
435 }
436
437 double ddLogPDF(const double &x) const {
438 if(x <= 0.0 || x >= 1.0) return 0.0;
439 return -(alpha_ - 1.0) / std::pow(x, 2) - (beta_ - 1.0) / std::pow(1.0 - x, 2);
440 }
441
442 double CDF(const double &x) const {
443 return 0.0; // To-do: Requires regularized incomplete beta function
444 }
445
446 double quantile(const double &p) const {
447 return 0.0; // To-do: Requires inverse incomplete beta function
448 }
449
450 double sample(std::default_random_engine &rng) {
451 double x = distGammaAlpha_(rng);
452 double y = distGammaBeta_(rng);
453
454 // Prevent division by zero in the extremely rare case both evaluate to 0.0
455 if(x + y == 0.0) return 0.5;
456
457 return x / (x + y);
458 }
459
460 // Setters update the internal gamma generators
461 void setAlpha(double alpha) {
462 if(alpha <= 0.0) throw std::invalid_argument("Alpha must be > 0");
463 alpha_ = alpha;
464 distGammaAlpha_ = std::gamma_distribution<double>(alpha_, 1.0);
465 }
466
467 void setBeta(double beta) {
468 if(beta <= 0.0) throw std::invalid_argument("Beta must be > 0");
469 beta_ = beta;
470 distGammaBeta_ = std::gamma_distribution<double>(beta_, 1.0);
471 }
472
473 double getAlpha() const {
474 return alpha_;
475 }
476 double getBeta() const {
477 return beta_;
478 }
479};
480
481
482class LogNormalDistribution : public UnivariateDistribution<LogNormalDistribution> {
483 private:
484 double mean_{0.0};
485 double std_{1.0};
486 std::normal_distribution<double> distN_;
487 public:
488 LogNormalDistribution(double mu, double sigma): mean_(mu), std_(sigma), distN_(0, 1) {}
490
491 double logPDF(const double &x) const {
492 return -0.5 * std::pow((std::log(x) - mean_) / std_, 2) - 0.5 * std::log(2 * M_PI);
493 }
494 double dLogPDF(const double &x) const {
495 return (mean_ - std::log(x)) / (x * std::pow(std_, 2));
496 }
497 double ddLogPDF(const double &x) const {
498 return (-1 - mean_ + std::log(x)) / std::pow(x * std_, 2);
499 }
500 double CDF(const double &x) const {
501 return 0.5 * (1 + std::erf((std::log(x) - mean_) / (std_ * std::sqrt(2))));
502 }
503 double quantile(const double &p) const {
504 return std::exp(mean_ + std_ * std::sqrt(2) * erfinv(2 * p - 1));
505 }
506 double sample(std::default_random_engine &rng) {
507 return std::exp(distN_(rng) * std_ + mean_);
508 }
509 void setMean(double mu) {
510 mean_ = mu;
511 }
512 void setStd(double sigma) {
513 std_ = sigma;
514 }
515};
516
517
518class StudentDistribution : public UnivariateDistribution<StudentDistribution> {
519 private:
520 double dofs_;
521 double mean_;
522 double std_;
523 std::student_t_distribution<double> distN_;
524 std::normal_distribution<double> normDist_{0.0, 1.0};
525 public:
526 StudentDistribution(double nu, double mu, double sigma): dofs_(nu), mean_(mu), std_(sigma), distN_(nu) {}
528
529 double logPDF(const double &x) const {
530 return std::log(std::tgammal(0.5 * (dofs_ + 1)) - std::log(std::tgammal(0.5 * dofs_)) - 0.5 * std::log(M_PI * dofs_)) - std_ - 0.5 * (dofs_ + 1) * std::log(1 + std::pow(x - mean_, 2) / (dofs_ * std_ * std_));
531 }
532 double dLogPDF(const double &x) const {
533 return -(x - mean_) * (1 + dofs_) / (std_ * std_ * dofs_ + std::pow(x - mean_, 2));
534 }
535 double ddLogPDF(const double &x) const {
536 return (1 + dofs_) * (std::pow(x - mean_, 2) - dofs_ * std_ * std_) / std::pow((std::pow(x - mean_, 2) + dofs_ * std_ * std_), 2);
537 }
538 double CDF(const double &x) const {
539 return 0.0; // To-do
540 }
541 double quantile(const double &p) const {
542 return 0.0; // To-do
543 }
544 double sample(std::default_random_engine &rng) {
545 double z = normDist_(rng);
546 double chi = 0.0;
547 for(size_t j = 0; j < dofs_; j++) {
548 chi += std::pow(normDist_(rng), 2);
549 }
550 return mean_ + z * std_ / std::sqrt(chi / dofs_);
551 }
552 void setDoFs(double dofs) {
553 dofs_ = dofs;
554 }
555 void setMean(double mu) {
556 mean_ = mu;
557 }
558 void setStd(double sigma) {
559 std_ = sigma;
560 }
561};
562
563
564class PowerLawDistribution : public UnivariateDistribution<PowerLawDistribution> {
565 private:
566 double degree_;
567 double lowerBound_;
568 std::uniform_real_distribution<double> distU_;
569 public:
570 PowerLawDistribution(double alpha, double lowerBound = 1.0): degree_(alpha), distU_(0., 1.), lowerBound_(lowerBound) {}
572
573 double logPDF(const double &x) const {
574 return std::log(lowerBound_) - degree_ * std::log(x);
575 }
576 double dLogPDF(const double &x) const {
577 return -degree_ / x;
578 }
579 double ddLogPDF(const double &x) const {
580 return degree_ / std::pow(x, 2);
581 }
582 double CDF(const double &t) const {
583 return 1.0 - std::pow(lowerBound_ / t, degree_);
584 }
585 double quantile(const double &q) const {
586 return lowerBound_ / std::pow(1 - q, 1 / degree_);
587 }
588 double sample(std::default_random_engine &rng) {
589 return quantile(distU_(rng));
590 }
591 void setDegree(double degree) {
592 degree_ = degree;
593 }
594};
595
596
597class SmoothUniformDistribution : public UnivariateDistribution<SmoothUniformDistribution> {
598 private:
599 double lowerBound_;
600 double upperBound_;
601 double std_;
602 std::uniform_real_distribution<double> distU_;
603 std::normal_distribution<double> distN_;
604 public:
605 SmoothUniformDistribution(double lowerBound, double upperBound, double sigma): lowerBound_(lowerBound), upperBound_(upperBound), std_(sigma), distU_(0, 1), distN_(0, 1) {}
607
608 double logPDF(const double &x) const {
609 return std::log((CDF_normal((upperBound_ - x) / std_) - CDF_normal((lowerBound_ - x) / std_)) / (upperBound_ - lowerBound_));
610 }
611 double dLogPDF(const double &x) const {
612 return (std::pow(M_E, -std::pow(lowerBound_ - x, 2) / (2.*std::pow(std_, 2))) - std::pow(M_E, -std::pow(upperBound_ - x, 2) / (2.*std::pow(std_, 2)))) / ((-lowerBound_ + upperBound_) * std::sqrt(2 * M_PI) * std_);
613 }
614 double ddLogPDF(const double &x) const {
615 return ((lowerBound_ - x) / std::pow(M_E, std::pow(lowerBound_ - x, 2) / (2.*std::pow(std_, 2))) +
616 (-upperBound_ + x) / std::pow(M_E, std::pow(upperBound_ - x, 2) / (2.*std::pow(std_, 2)))) /
617 ((-lowerBound_ + upperBound_) * std::sqrt(2 * M_PI) * std::pow(std_, 3));
618 }
619 double CDF(const double &t) const {
620 return (lowerBound_ - upperBound_ + (-std::pow(M_E, -std::pow(lowerBound_ - t, 2) / (2.*std::pow(std_, 2))) +
621 std::pow(M_E, -std::pow(upperBound_ - t, 2) / (2.*std::pow(std_, 2)))) *
622 std::sqrt(2 / M_PI) * std_ + (-lowerBound_ + t) * std::erf((lowerBound_ - t) / (std::sqrt(2) * std_)) +
623 (upperBound_ - t) * std::erf((upperBound_ - t) / (std::sqrt(2) * std_))) / (2.*(lowerBound_ - upperBound_));
624 }
625 double quantile(const double &p) const {
626 if(p < 0 || p > 1) return std::numeric_limits<double>::quiet_NaN();
627 double x = 0.5 * (lowerBound_ + upperBound_);
628 for(size_t i = 0; i < 5; i++) {
629 double f = CDF(x) - p;
630 double df = std::exp(logPDF(x));
631 x = x - f / df;
632 }
633 return x;
634 }
635 double sample(std::default_random_engine &rng) {
636 return lowerBound_ + (upperBound_ - lowerBound_) * distU_(rng) + distN_(rng) * std_;
637 }
638
639 void setLowerBound(double a) {
640 lowerBound_ = a;
641 }
642 void setUpperBound(double b) {
643 upperBound_ = b;
644 }
645 void setStd(double sigma) {
646 std_ = sigma;
647 }
648};
649
650// ==============================================================================
651// MULTIVARIATE DISTRIBUTIONS & PROPOSALS
652// ==============================================================================
653
654class MultivariateNormalDistribution : public ProposalDistribution<MultivariateNormalDistribution> {
655 private:
656 Eigen::VectorXd mean_;
657 Eigen::LDLT<Eigen::MatrixXd> ldltDecomposition_;
658 std::normal_distribution<double> distN_;
659 public:
660
661 MultivariateNormalDistribution(const Eigen::Ref<const Eigen::VectorXd> &mean, const Eigen::Ref<const Eigen::MatrixXd> &cov)
662 : mean_(mean), distN_(0., 1.) {
663 ldltDecomposition_.compute(cov);
664 }
665 template<typename MatrixType>
666 MultivariateNormalDistribution(const Eigen::Ref<const Eigen::VectorXd> &mean, const Eigen::LDLT<MatrixType> &ldltDecomposition)
668
670
671 static double logPDF(const Eigen::Ref<const Eigen::VectorXd> &res, const Eigen::LDLT<Eigen::MatrixXd> &ldltDecomposition) {
672 Eigen::VectorXd alpha = ldltDecomposition.solve(res);
673 return -0.5 * res.dot(alpha) - 0.5 * (ldltDecomposition.vectorD().array().abs().log()).sum() - 0.5 * res.size() * std::log(2 * M_PI);
674 }
675 static double dLogPDF(const Eigen::Ref<const Eigen::VectorXd> &res, const Eigen::LDLT<Eigen::MatrixXd> &ldltDecomposition, const Eigen::Ref<const Eigen::MatrixXd> &cov_gradient, const Eigen::Ref<const Eigen::VectorXd> &mean_gradient) {
676 Eigen::VectorXd alpha = ldltDecomposition.solve(res);
677 Eigen::MatrixXd alpha_alpha_t = alpha * alpha.transpose();
678 return 0.5 * (alpha_alpha_t * cov_gradient - ldltDecomposition.solve(cov_gradient)).trace() + res.dot(ldltDecomposition.solve(mean_gradient));
679 }
680 static double ddLogPDF(const Eigen::Ref<const Eigen::VectorXd> &res, const Eigen::LDLT<Eigen::MatrixXd> &ldltDecomposition, const Eigen::Ref<const Eigen::MatrixXd> &cov_gradient_l, const Eigen::Ref<const Eigen::MatrixXd> &cov_gradient_k, const Eigen::Ref<const Eigen::MatrixXd> &cov_hessian) {
681 Eigen::VectorXd alpha = ldltDecomposition.solve(res);
682 Eigen::MatrixXd alpha_alpha_t = alpha * alpha.transpose();
683 auto a_l = ldltDecomposition.solve(cov_gradient_l);
684 auto a_k = ldltDecomposition.solve(cov_gradient_k);
685 auto sym_tens = 0.5 * ((a_l * alpha_alpha_t) + (a_l * alpha_alpha_t).transpose());
686 double H1 = (alpha_alpha_t*cov_hessian).trace();
687 double H2 = (ldltDecomposition.solve(cov_hessian)).trace();
688 double H3 = (sym_tens * cov_gradient_k).trace();
689 double H4 = (a_l * a_k).trace();
690 return 0.5 * H1 - 0.5 * H2 - H3 + 0.5 * H4;
691 }
692
693 double logPDF(const Eigen::Ref<const Eigen::VectorXd> &x) const {
694 return logPDF(mean_ - x, ldltDecomposition_);
695 }
696 double logJumpPDF(const Eigen::Ref<const Eigen::VectorXd> &jump) {
697 return logPDF(jump, ldltDecomposition_);
698 }
699 double squaredMahalanobis(const Eigen::Ref<const Eigen::VectorXd> &jump) const {
700 return jump.dot(ldltDecomposition_.solve(jump));
701 }
702
703 Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma = 1.0) {
704 Eigen::VectorXd z = Eigen::VectorXd::Zero(mean_.size());
705 for(size_t i = 0; i < mean_.size(); i++) {
706 z(i) = distN_(rng) * std::sqrt(std::abs(ldltDecomposition_.vectorD()(i)));
707 }
708 return mean_ + (ldltDecomposition_.transpositionsP().transpose() * (ldltDecomposition_.matrixL() * z)) * gamma;
709 }
710
711 Eigen::VectorXd get() const {
712 return mean_;
713 }
714 void set(const Eigen::Ref<const Eigen::VectorXd> &x) {
715 mean_ = x;
716 }
717 void setMean(const Eigen::Ref<const Eigen::VectorXd> &mean) {
718 mean_ = mean;
719 }
720 void setLdltDecomposition(const Eigen::LDLT<Eigen::MatrixXd> &ldltDecomposition) {
722 }
723
724 // Implement canonical transformation
725 Eigen::MatrixXd toCanonical(const Eigen::MatrixXd& x) const {
726 Eigen::MatrixXd centered = x.colwise() - mean_;
727 Eigen::MatrixXd canonical = ldltDecomposition_.solve(centered);
728 return canonical;
729 }
730
731 Eigen::MatrixXd toPhysical(const Eigen::MatrixXd& z) const {
732 Eigen::MatrixXd original = ldltDecomposition_.matrixL() * z;
733 original = ldltDecomposition_.transpositionsP().transpose() * original;
734 original.colwise() += mean_;
735 return original;
736 }
737
738 size_t dimension() const {
739 return mean_.size();
740 }
741
742 static MultivariateNormalDistribution canonical(const size_t dim) {
743 Eigen::VectorXd mean = Eigen::VectorXd::Zero(dim);
744 Eigen::MatrixXd cov = Eigen::MatrixXd::Identity(dim, dim);
745 return MultivariateNormalDistribution(mean, cov);
746 }
747};
748
749
750class MultivariateMixtureDistribution : public MultivariateDistribution<MultivariateMixtureDistribution> {
751 private:
752 std::vector<std::shared_ptr<MultivariateNormalDistribution>> components_;
753 std::vector<double> weights_;
754 public:
756 const std::vector<std::shared_ptr<MultivariateNormalDistribution>>& components,
757 const std::vector<double>& weights)
758 : components_(components), weights_(weights) {}
759
760 Eigen::VectorXd sample(std::default_random_engine &rng) {
761 std::discrete_distribution<size_t> dist_weights(weights_.begin(), weights_.end());
762 size_t idx = dist_weights(rng);
763 return components_[idx]->sample(rng);
764 }
765
766 double logPDF(const Eigen::Ref<const Eigen::VectorXd> &x) const {
767 double pdf = 0.0;
768 for (size_t i = 0; i < components_.size(); ++i) {
769 pdf += weights_[i] * std::exp(components_[i]->logPDF(x));
770 }
771 return std::log(pdf);
772 }
773
774 size_t dimension() const {
775 return components_.empty() ? 0 : components_[0]->dimension();
776 }
777};
778
779
780class MultivariateStudentDistribution : public ProposalDistribution<MultivariateStudentDistribution> {
781 private:
782 Eigen::VectorXd mean_;
783 Eigen::LDLT<Eigen::MatrixXd> ldltDecomposition_;
784 double dofs_;
785 std::normal_distribution<double> distN_;
786 public:
787
788 template <typename LDLTDerived>
789 MultivariateStudentDistribution(const Eigen::Ref<const Eigen::VectorXd> &mean, const Eigen::LDLT<LDLTDerived> &ldltDecomposition, double nu)
790 : mean_(mean), dofs_(nu), distN_(0., 1.) {
791 Eigen::VectorXd d = ldltDecomposition.vectorD();
792 Eigen::MatrixXd D = d.asDiagonal();
793 Eigen::MatrixXd L = ldltDecomposition.matrixL().toDenseMatrix();
794 Eigen::MatrixXd cov = L * D * L.transpose();
795 ldltDecomposition_.compute(cov);
796 }
797 MultivariateStudentDistribution(const Eigen::Ref<const Eigen::VectorXd> &mean, const Eigen::Ref<const Eigen::MatrixXd> &cov, double nu)
798 : mean_(mean), dofs_(nu), distN_(0., 1.) {
799 ldltDecomposition_.compute(cov);
800 }
802
803 static double logPDF(const Eigen::Ref<const Eigen::VectorXd> &res, const Eigen::LDLT<Eigen::MatrixXd> &ldltDecomposition, const double &nu) {
804 size_t dim = res.size();
805 Eigen::VectorXd alpha = ldltDecomposition.solve(res);
806 double quad = res.dot(alpha);
807 double logDet = ldltDecomposition.vectorD().array().log().sum();
808 double logGammaTerm = std::lgamma(0.5 * (nu + dim)) - std::lgamma(0.5 * nu);
809 double logNormTerm = -0.5 * dim * std::log(nu * M_PI);
810 double logDetTerm = -0.5 * logDet;
811 double logQuadTerm = -0.5 * (nu + dim) * std::log(1 + quad / nu);
812 return logGammaTerm + logNormTerm + logDetTerm + logQuadTerm;
813 }
814
815 double logPDF(const Eigen::Ref<const Eigen::VectorXd> &x) const {
816 return logPDF(mean_ - x, ldltDecomposition_, dofs_);
817 }
818 double logJumpPDF(const Eigen::Ref<const Eigen::VectorXd> &jump) {
819 return logPDF(jump, ldltDecomposition_, dofs_);
820 }
821 double squaredMahalanobis(const Eigen::Ref<const Eigen::VectorXd> &jump) const {
822 return jump.dot(ldltDecomposition_.solve(jump));
823 }
824
825 Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma = 1.0) {
826 Eigen::VectorXd z = Eigen::VectorXd::Zero(mean_.size());
827 for(size_t i = 0; i < mean_.size(); i++) {
828 z(i) = distN_(rng);
829 double chi = 0.0;
830 for(size_t j = 0; j < dofs_; j++) {
831 chi += std::pow(distN_(rng), 2);
832 }
833 z(i) = std::sqrt(std::abs(ldltDecomposition_.vectorD()(i))) * z(i) / std::sqrt(chi / dofs_);
834 }
835 return mean_ + (ldltDecomposition_.transpositionsP().transpose() * (ldltDecomposition_.matrixL() * z)) * gamma;
836 }
837
838 Eigen::VectorXd get() const {
839 return mean_;
840 }
841 void set(const Eigen::Ref<const Eigen::VectorXd> &x) {
842 mean_ = x;
843 }
844 void setMean(const Eigen::Ref<const Eigen::VectorXd> &mean) {
845 mean_ = mean;
846 }
847 void setLdltDecomposition(const Eigen::LDLT<Eigen::MatrixXd> &ldltDecomposition) {
849 }
850 void setDoFs(double nu) {
851 dofs_ = nu;
852 }
853
854 Eigen::MatrixXd toCanonical(const Eigen::MatrixXd& x) const {
855 Eigen::MatrixXd centered = x.colwise() - mean_;
856 Eigen::MatrixXd canonical = ldltDecomposition_.solve(centered);
857 return canonical;
858 }
859
860 Eigen::MatrixXd toPhysical(const Eigen::MatrixXd& z) const {
861 Eigen::MatrixXd original = ldltDecomposition_.matrixL() * z;
862 original = ldltDecomposition_.transpositionsP().transpose() * original;
863 original.colwise() += mean_;
864 return original;
865 }
866
867 size_t dimension() const {
868 return mean_.size();
869 }
870
871 static MultivariateStudentDistribution canonical(const size_t dim, const double nu) {
872 Eigen::VectorXd mean = Eigen::VectorXd::Zero(dim);
873 Eigen::MatrixXd cov = Eigen::MatrixXd::Identity(dim, dim);
874 return MultivariateStudentDistribution(mean, cov, nu);
875 }
876};
877
878
879class MultivariateUniformDistribution : public MultivariateDistribution<MultivariateUniformDistribution> {
880 private:
881 Eigen::VectorXd lowerBound_;
882 Eigen::VectorXd upperBound_;
883 std::uniform_real_distribution<double> distU_;
884 public:
885
886 MultivariateUniformDistribution(const Eigen::Ref<const Eigen::VectorXd> &lowerBound,
887 const Eigen::Ref<const Eigen::VectorXd> &upperBound)
888 : lowerBound_(lowerBound), upperBound_(upperBound), distU_(0.0, 1.0) {}
889
891
892 Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma = 1.0) {
893 Eigen::VectorXd rv(lowerBound_.size());
894 for(size_t i = 0; i < lowerBound_.size(); i++) {
895 // Now samples exactly between [lowerBound, upperBound]
896 rv(i) = lowerBound_(i) + (upperBound_(i) - lowerBound_(i)) * distU_(rng) * gamma;
897 }
898 return rv;
899 }
900
901 Eigen::MatrixXd toCanonical(const Eigen::MatrixXd& x) const {
902
903 Eigen::RowVectorXd a = lowerBound_.transpose();
904 Eigen::RowVectorXd b = upperBound_.transpose();
905
906 Eigen::MatrixXd scaled = (x.rowwise() - a).array().rowwise() / (b - a).array();
907
908 // 2. Do the global scalar math on the resulting array: 2.0 * scaled - 1.0
909 return (2.0 * scaled.array() - 1.0).matrix();
910 }
911
912 Eigen::MatrixXd toPhysical(const Eigen::MatrixXd& z) const {
913
914 Eigen::RowVectorXd a = lowerBound_.transpose();
915 Eigen::RowVectorXd b = upperBound_.transpose();
916
917 Eigen::MatrixXd original = (z.array() + 1.0) / 2.0;
918 original = original.array().rowwise() * (b - a).array();
919 original.rowwise() += a;
920
921 return original;
922 }
923
924 size_t dimension() const {
925 return lowerBound_.size();
926 }
927
929 Eigen::VectorXd lowerBound = -Eigen::VectorXd::Ones(dim);
930 Eigen::VectorXd upperBound = Eigen::VectorXd::Ones(dim);
931 return MultivariateUniformDistribution(lowerBound, upperBound);
932 }
933};
934
935
936class UniformSphereDistribution : public MultivariateDistribution<UniformSphereDistribution> {
937 private:
938 std::normal_distribution<double> distN_{0., 1.};
939 std::size_t dim_{1};
940 public:
941
942 UniformSphereDistribution(size_t dim): dim_(dim), distN_(0., 1.) {}
944
945 double logPDF(const Eigen::Ref<const Eigen::VectorXd> &x) const {
946 return 0.0;
947 }
948 Eigen::VectorXd sample(std::default_random_engine &rng) {
949 Eigen::VectorXd x(dim_);
950 for(size_t i = 0; i < dim_; i++) {
951 x(i) = distN_(rng);
952 }
953 return x / x.norm();
954 }
955
956
957 Eigen::MatrixXd toCanonical(const Eigen::MatrixXd& x) const {
958 Eigen::MatrixXd canonical = x.normalized();
959 return canonical;
960 }
961
962 Eigen::MatrixXd toPhysical(const Eigen::MatrixXd& z) const {
963 Eigen::MatrixXd original = z.normalized();
964 return original;
965 }
966
967 size_t dimension() const {
968 return dim_;
969 }
970};
971
972
973class NormalInverseWishartDistribution : public MultivariateDistribution<NormalInverseWishartDistribution> {
974 private:
975 Eigen::VectorXd mean_;
976 double kappa_;
977 double nu_;
978 size_t dim_;
979 Eigen::LDLT<Eigen::MatrixXd> covLDLT_;
981 std::normal_distribution<double> distN_{0., 1.};
982
983 public:
984
986 const Eigen::Ref<const Eigen::VectorXd> &mean,
987 double kappa, double nu,
988 const Eigen::Ref<const Eigen::MatrixXd> &psi
989 ) : mean_(mean), kappa_(kappa), nu_(nu - mean.size() + 1), dim_(mean.size()) {
990 if(psi.rows() != psi.cols() || psi.rows() != dim_) throw std::invalid_argument("Scale matrix Ψ must be square and match the dimensionality of the mean");
991 if(kappa_ <= 0) throw std::invalid_argument("κ must be positive");
992 if(nu <= dim_ - 1) throw std::invalid_argument("ν must be greater than dimension - 1");
993
994 double scaling = (kappa_ + 1.0) / (kappa_ * nu_);
995 Eigen::MatrixXd scaledPsi = scaling * psi;
996 covLDLT_.compute(scaledPsi);
997 if(covLDLT_.info() != Eigen::Success) throw std::invalid_argument("Scaled covariance matrix must be positive definite");
998 logDeterminant_ = covLDLT_.vectorD().array().log().sum();
999 }
1001
1002 double logPDF(const Eigen::Ref<const Eigen::VectorXd> &x) const {
1003 Eigen::VectorXd res = x - mean_;
1005 }
1006
1007 Eigen::VectorXd sample(std::default_random_engine &rng) {
1008 const auto &L = covLDLT_.matrixL();
1009 const auto &P = covLDLT_.transpositionsP();
1010 const Eigen::VectorXd D = covLDLT_.vectorD();
1011
1012 Eigen::VectorXd z = Eigen::VectorXd::Zero(dim_);
1013 for(size_t i = 0; i < dim_; ++i) {
1014 z(i) = distN_(rng) * std::sqrt(std::abs(D(i)));
1015 }
1016 Eigen::VectorXd y = P.transpose() * (L * z);
1017
1018 std::chi_squared_distribution<double> distChi(nu_);
1019 double s = distChi(rng);
1020 return mean_ + y / std::sqrt(s / nu_);
1021 }
1022
1023 const Eigen::VectorXd &mean() const {
1024 return mean_;
1025 }
1026 const double &kappa() const {
1027 return kappa_;
1028 }
1029 const double &nu() const {
1030 return nu_;
1031 }
1032 const Eigen::MatrixXd covariance() const {
1033 return covLDLT_.reconstructedMatrix();
1034 }
1035
1036 Eigen::MatrixXd toCanonical(const Eigen::MatrixXd& x) const {
1037 Eigen::MatrixXd centered = x.colwise() - mean_;
1038 Eigen::MatrixXd canonical = covLDLT_.solve(centered);
1039 return canonical;
1040 }
1041
1042 Eigen::MatrixXd toPhysical(const Eigen::MatrixXd& z) const {
1043 Eigen::MatrixXd original = covLDLT_.matrixL() * z;
1044 original = covLDLT_.transpositionsP().transpose() * original;
1045 original.colwise() += mean_;
1046 return original;
1047 }
1048
1049 size_t dimension() const {
1050 return dim_;
1051 }
1052
1053 static NormalInverseWishartDistribution canonical(const size_t dim, double kappa, double nu) {
1054 Eigen::VectorXd mean = Eigen::VectorXd::Zero(dim);
1055 Eigen::MatrixXd psi = Eigen::MatrixXd::Identity(dim, dim);
1057 }
1058
1066 static NormalInverseWishartDistribution empiricalPrior(const Eigen::MatrixXd &data, double expected_clusters, double kappa0) {
1067
1068 int D = static_cast<int>(data.cols());
1069 double N = static_cast<double>(data.rows());
1070
1071 // 1. Compute empirical global mean (1 x D) -> Convert to Column Vector (D x 1)
1072 Eigen::VectorXd mu0 = data.colwise().mean().transpose();
1073
1074 // 2. Set degrees of freedom to the weakest valid setting
1075 double nu0 = D + 2.0;
1076
1077 // 3. Compute empirical covariance matrix (D x D)
1078 // Centering the data: subtract the mean row from every row
1079 Eigen::MatrixXd centered = data.rowwise() - data.colwise().mean();
1080
1081 // Covariance = (Centered^T * Centered) / (N - 1)
1082 Eigen::MatrixXd global_cov = (centered.transpose() * centered) / (N - 1.0);
1083
1084 // 4. Scale Psi0 (the scale matrix) based on expected cluster density
1085 // We multiply by (nu0 - D - 1) to ensure the expected value of the prior covariance
1086 // matches the fraction of the global variance exactly.
1087 double scale_factor = (nu0 - static_cast<double>(D) - 1.0) / expected_clusters;
1088 Eigen::MatrixXd Psi0 = global_cov * scale_factor;
1089
1090 // Fix potential numerical edge-cases where columns have zero variance
1091 Psi0.diagonal().array() += 1e-6;
1092
1093 // 5. Return the constructed instance
1094 // (Assuming your constructor takes mu0, kappa0, nu0, and Psi0)
1095 return NormalInverseWishartDistribution(mu0, kappa0, nu0, Psi0);
1096 }
1097};
1098
1099} // namespace cmp::distribution
1100
1103#endif // DISTRIBUTION_HPP
Definition distribution.h:403
double quantile(const double &p) const
Definition distribution.h:446
double getBeta() const
Definition distribution.h:476
void setAlpha(double alpha)
Definition distribution.h:461
std::gamma_distribution< double > distGammaBeta_
Gamma distribution shape-beta helper.
Definition distribution.h:408
double ddLogPDF(const double &x) const
Definition distribution.h:437
double sample(std::default_random_engine &rng)
Definition distribution.h:450
double beta_
Scale parameter beta.
Definition distribution.h:406
double dLogPDF(const double &x) const
Definition distribution.h:432
double alpha_
Shape parameter alpha.
Definition distribution.h:405
std::gamma_distribution< double > distGammaAlpha_
Gamma distribution shape-alpha helper.
Definition distribution.h:407
double logPDF(const double &x) const
Definition distribution.h:422
void setBeta(double beta)
Definition distribution.h:467
double getAlpha() const
Definition distribution.h:473
double CDF(const double &x) const
Definition distribution.h:442
BetaDistribution(double alpha, double beta)
Definition distribution.h:411
Definition distribution.h:337
double beta_
Rate parameter (often denoted as theta = 1/beta).
Definition distribution.h:340
double dLogPDF(const double &x) const
Definition distribution.h:361
double ddLogPDF(const double &x) const
Definition distribution.h:366
void setBeta(double beta)
Definition distribution.h:389
std::gamma_distribution< double > distGamma_
Gamma distribution helper for sampling.
Definition distribution.h:341
GammaDistribution(double alpha, double beta)
Definition distribution.h:345
double getBeta() const
Definition distribution.h:398
double sample(std::default_random_engine &rng)
Definition distribution.h:379
double logPDF(const double &x) const
Definition distribution.h:354
double CDF(const double &x) const
Definition distribution.h:371
double alpha_
Shape parameter (often denoted as k).
Definition distribution.h:339
void setAlpha(double alpha)
Definition distribution.h:384
double quantile(const double &p) const
Definition distribution.h:375
double getAlpha() const
Definition distribution.h:395
Definition distribution.h:302
double dLogPDF(const double &x) const
Definition distribution.h:314
double ddLogPDF(const double &x) const
Definition distribution.h:317
double alpha_
Shape parameter alpha.
Definition distribution.h:304
std::gamma_distribution< double > distGamma_
Gamma distribution helper for sampling.
Definition distribution.h:306
double quantile(const double &p) const
Definition distribution.h:323
void setAlpha(double alpha)
Definition distribution.h:329
double CDF(const double &x) const
Definition distribution.h:320
InverseGammaDistribution(double alpha, double beta)
Definition distribution.h:308
double logPDF(const double &x) const
Definition distribution.h:311
void setBeta(double beta)
Definition distribution.h:332
double sample(std::default_random_engine &rng)
Definition distribution.h:326
double beta_
Scale parameter beta.
Definition distribution.h:305
Definition distribution.h:482
double ddLogPDF(const double &x) const
Definition distribution.h:497
double std_
Log-standard deviation parameter.
Definition distribution.h:485
LogNormalDistribution(double mu, double sigma)
Definition distribution.h:488
double quantile(const double &p) const
Definition distribution.h:503
void setMean(double mu)
Definition distribution.h:509
std::normal_distribution< double > distN_
Normal distribution generator helper.
Definition distribution.h:486
double sample(std::default_random_engine &rng)
Definition distribution.h:506
double logPDF(const double &x) const
Definition distribution.h:491
double CDF(const double &x) const
Definition distribution.h:500
void setStd(double sigma)
Definition distribution.h:512
double dLogPDF(const double &x) const
Definition distribution.h:494
double mean_
Log-mean parameter.
Definition distribution.h:484
CRTP base class for all multivariate probability distributions.
Definition distribution.h:139
Eigen::VectorXd sample(std::default_random_engine &rng)
Draws a single vector sample from the joint distribution.
Definition distribution.h:157
Eigen::MatrixXd toCanonical(const Eigen::MatrixXd &x) const
Transforms physical samples to standard canonical space.
Definition distribution.h:167
Eigen::MatrixXd fromCanonical(const Eigen::MatrixXd &x) const
Transforms standard canonical samples back to physical space.
Definition distribution.h:177
double logPDF(const Eigen::Ref< const Eigen::VectorXd > &x) const
Computes the joint log probability density function (log-PDF) of the distribution.
Definition distribution.h:147
size_t dimension() const
Returns the dimensionality of the multivariate space.
Definition distribution.h:184
double logPDF(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition distribution.h:766
std::vector< double > weights_
Mixing weights for each component.
Definition distribution.h:753
MultivariateMixtureDistribution(const std::vector< std::shared_ptr< MultivariateNormalDistribution > > &components, const std::vector< double > &weights)
Definition distribution.h:755
std::vector< std::shared_ptr< MultivariateNormalDistribution > > components_
Gaussian components of the mixture.
Definition distribution.h:752
size_t dimension() const
Definition distribution.h:774
Eigen::VectorXd sample(std::default_random_engine &rng)
Definition distribution.h:760
static double ddLogPDF(const Eigen::Ref< const Eigen::VectorXd > &res, const Eigen::LDLT< Eigen::MatrixXd > &ldltDecomposition, const Eigen::Ref< const Eigen::MatrixXd > &cov_gradient_l, const Eigen::Ref< const Eigen::MatrixXd > &cov_gradient_k, const Eigen::Ref< const Eigen::MatrixXd > &cov_hessian)
Definition distribution.h:680
double logPDF(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition distribution.h:693
double logJumpPDF(const Eigen::Ref< const Eigen::VectorXd > &jump)
Definition distribution.h:696
void setLdltDecomposition(const Eigen::LDLT< Eigen::MatrixXd > &ldltDecomposition)
Definition distribution.h:720
Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma=1.0)
Definition distribution.h:703
void setMean(const Eigen::Ref< const Eigen::VectorXd > &mean)
Definition distribution.h:717
MultivariateNormalDistribution(const Eigen::Ref< const Eigen::VectorXd > &mean, const Eigen::Ref< const Eigen::MatrixXd > &cov)
Definition distribution.h:661
static double dLogPDF(const Eigen::Ref< const Eigen::VectorXd > &res, const Eigen::LDLT< Eigen::MatrixXd > &ldltDecomposition, const Eigen::Ref< const Eigen::MatrixXd > &cov_gradient, const Eigen::Ref< const Eigen::VectorXd > &mean_gradient)
Definition distribution.h:675
Eigen::LDLT< Eigen::MatrixXd > ldltDecomposition_
LDLT decomposition of the covariance matrix.
Definition distribution.h:657
std::normal_distribution< double > distN_
Univariate normal helper for coordinate-wise sampling.
Definition distribution.h:658
Eigen::VectorXd get() const
Definition distribution.h:711
Eigen::VectorXd mean_
Mean vector.
Definition distribution.h:656
size_t dimension() const
Definition distribution.h:738
static MultivariateNormalDistribution canonical(const size_t dim)
Definition distribution.h:742
double squaredMahalanobis(const Eigen::Ref< const Eigen::VectorXd > &jump) const
Definition distribution.h:699
void set(const Eigen::Ref< const Eigen::VectorXd > &x)
Definition distribution.h:714
Eigen::MatrixXd toPhysical(const Eigen::MatrixXd &z) const
Definition distribution.h:731
static double logPDF(const Eigen::Ref< const Eigen::VectorXd > &res, const Eigen::LDLT< Eigen::MatrixXd > &ldltDecomposition)
Definition distribution.h:671
MultivariateNormalDistribution(const Eigen::Ref< const Eigen::VectorXd > &mean, const Eigen::LDLT< MatrixType > &ldltDecomposition)
Definition distribution.h:666
Eigen::MatrixXd toCanonical(const Eigen::MatrixXd &x) const
Definition distribution.h:725
Eigen::MatrixXd toPhysical(const Eigen::MatrixXd &z) const
Definition distribution.h:860
Eigen::VectorXd mean_
Mean vector.
Definition distribution.h:782
Eigen::MatrixXd toCanonical(const Eigen::MatrixXd &x) const
Definition distribution.h:854
std::normal_distribution< double > distN_
Normal distribution helper for coordinate sampling.
Definition distribution.h:785
static MultivariateStudentDistribution canonical(const size_t dim, const double nu)
Definition distribution.h:871
Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma=1.0)
Definition distribution.h:825
Eigen::VectorXd get() const
Definition distribution.h:838
void setMean(const Eigen::Ref< const Eigen::VectorXd > &mean)
Definition distribution.h:844
void setLdltDecomposition(const Eigen::LDLT< Eigen::MatrixXd > &ldltDecomposition)
Definition distribution.h:847
MultivariateStudentDistribution(const Eigen::Ref< const Eigen::VectorXd > &mean, const Eigen::LDLT< LDLTDerived > &ldltDecomposition, double nu)
Definition distribution.h:789
Eigen::LDLT< Eigen::MatrixXd > ldltDecomposition_
LDLT decomposition of the covariance scale matrix.
Definition distribution.h:783
double squaredMahalanobis(const Eigen::Ref< const Eigen::VectorXd > &jump) const
Definition distribution.h:821
double logPDF(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition distribution.h:815
MultivariateStudentDistribution(const Eigen::Ref< const Eigen::VectorXd > &mean, const Eigen::Ref< const Eigen::MatrixXd > &cov, double nu)
Definition distribution.h:797
double logJumpPDF(const Eigen::Ref< const Eigen::VectorXd > &jump)
Definition distribution.h:818
void setDoFs(double nu)
Definition distribution.h:850
void set(const Eigen::Ref< const Eigen::VectorXd > &x)
Definition distribution.h:841
static double logPDF(const Eigen::Ref< const Eigen::VectorXd > &res, const Eigen::LDLT< Eigen::MatrixXd > &ldltDecomposition, const double &nu)
Definition distribution.h:803
double dofs_
Degrees of freedom parameter (nu).
Definition distribution.h:784
size_t dimension() const
Definition distribution.h:867
size_t dimension() const
Definition distribution.h:924
MultivariateUniformDistribution(const Eigen::Ref< const Eigen::VectorXd > &lowerBound, const Eigen::Ref< const Eigen::VectorXd > &upperBound)
Definition distribution.h:886
static MultivariateUniformDistribution canonical(const size_t dim)
Definition distribution.h:928
Eigen::VectorXd lowerBound_
Lower bounds vector.
Definition distribution.h:881
std::uniform_real_distribution< double > distU_
Uniform distribution helper for [0, 1] scaling.
Definition distribution.h:883
Eigen::MatrixXd toCanonical(const Eigen::MatrixXd &x) const
Definition distribution.h:901
Eigen::MatrixXd toPhysical(const Eigen::MatrixXd &z) const
Definition distribution.h:912
Eigen::VectorXd upperBound_
Upper bounds vector.
Definition distribution.h:882
Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma=1.0)
Definition distribution.h:892
Definition distribution.h:216
double mean_
Mean parameter.
Definition distribution.h:218
void setMean(double mean)
Definition distribution.h:248
std::normal_distribution< double > distN_
Normal distribution generator helper.
Definition distribution.h:220
double quantile(const double &p) const
Definition distribution.h:241
double ddLogPDF(const double &x) const
Definition distribution.h:235
double std_
Standard deviation parameter.
Definition distribution.h:219
double std() const
Definition distribution.h:257
double sample(std::default_random_engine &rng)
Definition distribution.h:244
double logPDF(const double &x) const
Definition distribution.h:229
static double logPDF(const double &res, const double &std)
Definition distribution.h:225
NormalDistribution(double mean, double sd)
Definition distribution.h:222
double CDF(const double &x) const
Definition distribution.h:238
double dLogPDF(const double &x) const
Definition distribution.h:232
void setStd(double std)
Definition distribution.h:251
double mean() const
Definition distribution.h:254
double logPDF(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition distribution.h:1002
static NormalInverseWishartDistribution canonical(const size_t dim, double kappa, double nu)
Definition distribution.h:1053
const double & kappa() const
Definition distribution.h:1026
const Eigen::VectorXd & mean() const
Definition distribution.h:1023
double logDeterminant_
Log-determinant of the scale covariance matrix.
Definition distribution.h:980
Eigen::VectorXd sample(std::default_random_engine &rng)
Definition distribution.h:1007
Eigen::MatrixXd toCanonical(const Eigen::MatrixXd &x) const
Definition distribution.h:1036
static NormalInverseWishartDistribution empiricalPrior(const Eigen::MatrixXd &data, double expected_clusters, double kappa0)
Computes an empirical Normal-Inverse-Wishart prior from the provided dataset. Useful for initializing...
Definition distribution.h:1066
const double & nu() const
Definition distribution.h:1029
size_t dimension() const
Definition distribution.h:1049
Eigen::LDLT< Eigen::MatrixXd > covLDLT_
LDLT decomposition of the scaling matrix.
Definition distribution.h:979
NormalInverseWishartDistribution(const Eigen::Ref< const Eigen::VectorXd > &mean, double kappa, double nu, const Eigen::Ref< const Eigen::MatrixXd > &psi)
Definition distribution.h:985
std::normal_distribution< double > distN_
Normal distribution helper for coordinate sampling.
Definition distribution.h:981
double nu_
Degrees of freedom parameter nu.
Definition distribution.h:977
Eigen::VectorXd mean_
Mean parameter vector.
Definition distribution.h:975
const Eigen::MatrixXd covariance() const
Definition distribution.h:1032
Eigen::MatrixXd toPhysical(const Eigen::MatrixXd &z) const
Definition distribution.h:1042
size_t dim_
Dimensionality of the parameter space.
Definition distribution.h:978
double kappa_
Degrees of freedom scaling parameter kappa.
Definition distribution.h:976
Definition distribution.h:564
double CDF(const double &t) const
Definition distribution.h:582
double ddLogPDF(const double &x) const
Definition distribution.h:579
double quantile(const double &q) const
Definition distribution.h:585
PowerLawDistribution(double alpha, double lowerBound=1.0)
Definition distribution.h:570
double lowerBound_
Lower bound parameter.
Definition distribution.h:567
double degree_
Power law degree parameter (exponent).
Definition distribution.h:566
void setDegree(double degree)
Definition distribution.h:591
double logPDF(const double &x) const
Definition distribution.h:573
double sample(std::default_random_engine &rng)
Definition distribution.h:588
std::uniform_real_distribution< double > distU_
Uniform distribution helper for sampling.
Definition distribution.h:568
double dLogPDF(const double &x) const
Definition distribution.h:576
Definition distribution.h:190
Eigen::VectorXd get() const
Definition distribution.h:204
double squaredMahalanobis(const Eigen::Ref< const Eigen::VectorXd > &jump) const
Definition distribution.h:198
double logJumpPDF(const Eigen::Ref< const Eigen::VectorXd > &jump)
Definition distribution.h:192
Eigen::VectorXd sample(std::default_random_engine &rng, const double &gamma)
Definition distribution.h:195
void set(const Eigen::Ref< const Eigen::VectorXd > &x)
Definition distribution.h:207
Eigen::VectorXd sample(std::default_random_engine &rng)
Definition distribution.h:201
std::uniform_real_distribution< double > distU_
Uniform generator helper.
Definition distribution.h:602
SmoothUniformDistribution(double lowerBound, double upperBound, double sigma)
Definition distribution.h:605
void setLowerBound(double a)
Definition distribution.h:639
void setStd(double sigma)
Definition distribution.h:645
double std_
Standard deviation of smoothing Gaussian.
Definition distribution.h:601
double logPDF(const double &x) const
Definition distribution.h:608
void setUpperBound(double b)
Definition distribution.h:642
double dLogPDF(const double &x) const
Definition distribution.h:611
double CDF(const double &t) const
Definition distribution.h:619
double lowerBound_
Lower boundary.
Definition distribution.h:599
double sample(std::default_random_engine &rng)
Definition distribution.h:635
double quantile(const double &p) const
Definition distribution.h:625
std::normal_distribution< double > distN_
Normal generator helper.
Definition distribution.h:603
double ddLogPDF(const double &x) const
Definition distribution.h:614
double upperBound_
Upper boundary.
Definition distribution.h:600
Definition distribution.h:518
double mean_
Mean parameter.
Definition distribution.h:521
double std_
Scale standard deviation parameter.
Definition distribution.h:522
double quantile(const double &p) const
Definition distribution.h:541
double dLogPDF(const double &x) const
Definition distribution.h:532
void setDoFs(double dofs)
Definition distribution.h:552
double sample(std::default_random_engine &rng)
Definition distribution.h:544
double dofs_
Degrees of freedom parameter.
Definition distribution.h:520
double ddLogPDF(const double &x) const
Definition distribution.h:535
std::normal_distribution< double > normDist_
Normal distribution helper for sampling.
Definition distribution.h:524
std::student_t_distribution< double > distN_
Student-t distribution helper.
Definition distribution.h:523
double CDF(const double &x) const
Definition distribution.h:538
double logPDF(const double &x) const
Definition distribution.h:529
void setMean(double mu)
Definition distribution.h:555
void setStd(double sigma)
Definition distribution.h:558
StudentDistribution(double nu, double mu, double sigma)
Definition distribution.h:526
Definition distribution.h:263
double logPDF(const double &x) const
Definition distribution.h:272
UniformDistribution(double a, double b)
Definition distribution.h:269
void setLowerBound(double a)
Definition distribution.h:293
double CDF(const double &x) const
Definition distribution.h:282
double lowerBound_
Lower bound parameter.
Definition distribution.h:265
double upperBound_
Upper bound parameter.
Definition distribution.h:266
double sample(std::default_random_engine &rng)
Definition distribution.h:290
double dLogPDF(const double &x) const
Definition distribution.h:276
double ddLogPDF(const double &x) const
Definition distribution.h:279
std::uniform_real_distribution< double > distU_
Uniform distribution generator helper.
Definition distribution.h:267
void setUpperBound(double b)
Definition distribution.h:296
double quantile(const double &p) const
Definition distribution.h:287
std::normal_distribution< double > distN_
Normal distribution helper for generating spherical coords.
Definition distribution.h:938
UniformSphereDistribution(size_t dim)
Definition distribution.h:942
Eigen::MatrixXd toCanonical(const Eigen::MatrixXd &x) const
Definition distribution.h:957
size_t dimension() const
Definition distribution.h:967
double logPDF(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition distribution.h:945
Eigen::MatrixXd toPhysical(const Eigen::MatrixXd &z) const
Definition distribution.h:962
std::size_t dim_
Dimensionality of the sphere's embedding space.
Definition distribution.h:939
Eigen::VectorXd sample(std::default_random_engine &rng)
Definition distribution.h:948
CRTP base class for all univariate probability distributions.
Definition distribution.h:62
double quantile(const double &p) const
Computes the quantile function (inverse CDF).
Definition distribution.h:110
double dLogPDF(const double &x) const
Computes the first derivative of the log-PDF.
Definition distribution.h:80
double sample(std::default_random_engine &rng)
Draws a single pseudo-random sample from the distribution.
Definition distribution.h:120
double CDF(const double &x) const
Computes the cumulative distribution function (CDF).
Definition distribution.h:100
double ddLogPDF(const double &x) const
Computes the second derivative of the log-PDF.
Definition distribution.h:90
double logPDF(const double &x) const
Computes the log probability density function (log-PDF) of the distribution.
Definition distribution.h:70
Definition distribution.h:17
double erfinv(float x)
Definition distribution.h:24
double CDF_normal(const double &x)
Definition distribution.h:34
double sech(const double &x)
Definition distribution.h:38
Eigen::LDLT< Eigen::MatrixXd > ldltDecomposition(const Eigen::Ref< const Eigen::MatrixXd > &cov)
Computes the LDLT decomposition of a symmetric matrix.
Definition cmp_defines.h:99