Stochastic Loading Module
normal_multivar.cc
1 #include <iostream>
2 #include <stdexcept>
3 // Boost random generator
4 #include <boost/random/mersenne_twister.hpp>
5 #include <boost/random/normal_distribution.hpp>
6 // Eigen dense matrices
7 #include <Eigen/Dense>
8 
9 #include "factory.h"
10 #include "normal_multivar.h"
11 
12 namespace numeric_utils {
13 
15  : RandomGenerator()
16 {
17  generator_ = boost::random::mt19937(seed_);
18  distribution_ = boost::random::normal_distribution<double>();
19 }
20 
22  : RandomGenerator()
23 {
24  seed_ = seed;
25  generator_ = boost::random::mt19937(seed_);
26  distribution_ = boost::random::normal_distribution<double>();
27 }
28 
30  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>& random_numbers,
31  const Eigen::VectorXd& means, const Eigen::MatrixXd& cov,
32  unsigned int cases) {
33 
34  bool success = true;
35  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> lower_cholesky;
36 
37  try {
38  auto llt = cov.llt();
39  lower_cholesky = llt.matrixL();
40 
41  if (llt.info() == Eigen::NumericalIssue) {
42  throw std::runtime_error(
43  "\nERROR: In NormalMultivar::generate method: Input covariance matrix is not "
44  "positive semi-definite\n");
45  }
46  } catch (const std::exception& e) {
47  std::cerr << "\nERROR: In normal multivariate random number generation: "
48  << e.what() << std::endl;
49  success = false;
50  }
51 
52  random_numbers.resize(cov.rows(), cases);
53 
54  // Generate random numbers based on distribution and generator type for
55  // requested number of cases
56  for (unsigned int i = 0; i < random_numbers.cols(); ++i) {
57  for (unsigned int j = 0; j < random_numbers.rows(); ++j) {
58  random_numbers(j, i) = distribution_(generator_);
59  }
60  }
61 
62  // Transform from unit normal distribution based on covariance and mean values
63  for (unsigned int i = 0; i < random_numbers.cols(); ++i) {
64  random_numbers.col(i) = lower_cholesky * random_numbers.col(i) + means;
65  }
66 
67  return success;
68 }
69 
70 std::string NormalMultiVar::name() const {
71  return "NormalMultiVar";
72 }
73 } // namespace numeric_utils
bool generate(Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > &random_numbers, const Eigen::VectorXd &means, const Eigen::MatrixXd &cov, unsigned int cases=1) override
std::string name() const override