https://mooseframework.inl.gov
LMC.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "LMC.h"
11 #include "MooseRandom.h"
12 #include "MathUtils.h"
13 
14 registerMooseObject("StochasticToolsApp", LMC);
15 
18 {
20  params.addClassDescription("Covariance function for multioutput Gaussian Processes based on the "
21  "Linear Model of Coregionalization (LMC).");
22  params.addParam<unsigned int>(
23  "num_latent_funcs", 1., "The number of latent functions for the expansion of the outputs.");
24  params.makeParamRequired<unsigned int>("num_outputs");
25  params.makeParamRequired<std::vector<UserObjectName>>("covariance_functions");
26  return params;
27 }
28 
29 LMC::LMC(const InputParameters & parameters)
30  : CovarianceFunctionBase(parameters),
31  _num_expansion_terms(getParam<unsigned int>("num_latent_funcs"))
32 {
33  // We use a random number generator to obtain the initial guess for the
34  // hyperparams
35  MooseRandom generator_latent;
36  generator_latent.seed(0, 1980);
37 
38  // First add and initialize the a A coefficients in the (aa^T+lambda*I) matrix
39  for (const auto exp_i : make_range(_num_expansion_terms))
40  {
41  const std::string a_coeff_name = "acoeff_" + std::to_string(exp_i);
42  const std::string a_coeff_name_with_prefix = _name + ":" + a_coeff_name;
43  _a_coeffs.push_back(
44  &addVectorRealHyperParameter(a_coeff_name, std::vector(_num_outputs, 1.0), true));
45 
46  auto & acoeff_vector = _hp_map_vector_real[a_coeff_name_with_prefix];
47  for (const auto out_i : make_range(_num_outputs))
48  acoeff_vector[out_i] = 3.0 * generator_latent.rand(0) + 1.0;
49  }
50 
51  // Then add and initialize the lambda coefficients in the (aa^T+lambda*I) matrix
52  for (const auto exp_i : make_range(_num_expansion_terms))
53  {
54  const std::string lambda_name = "lambda_" + std::to_string(exp_i);
55  const std::string lambda_name_with_prefix = _name + ":" + lambda_name;
56  _lambdas.push_back(
57  &addVectorRealHyperParameter(lambda_name, std::vector(_num_outputs, 1.0), true));
58 
59  auto & lambda_vector = _hp_map_vector_real[lambda_name_with_prefix];
60  for (const auto out_i : make_range(_num_outputs))
61  lambda_vector[out_i] = 3.0 * generator_latent.rand(0) + 1.0;
62  }
63 }
64 
65 void
67  const RealEigenMatrix & x,
68  const RealEigenMatrix & xp,
69  const bool is_self_covariance) const
70 {
71  // Create temporary vectors for constructing the covariance matrix
72  RealEigenMatrix K_params = RealEigenMatrix::Zero(x.rows(), xp.rows());
73  RealEigenMatrix B = RealEigenMatrix::Zero(_num_outputs, _num_outputs);
74  K = RealEigenMatrix::Zero(x.rows() * _num_outputs, xp.rows() * _num_outputs);
75  RealEigenMatrix K_working =
76  RealEigenMatrix::Zero(x.rows() * _num_outputs, xp.rows() * _num_outputs);
77 
78  // For every expansion term we add the contribution to the covariance matrix
79  for (const auto exp_i : make_range(_num_expansion_terms))
80  {
81  _covariance_functions[exp_i]->computeCovarianceMatrix(K_params, x, xp, is_self_covariance);
82  computeBMatrix(B, exp_i);
83  MathUtils::kron(K_working, B, K_params);
84  K += K_working;
85  }
86 }
87 
88 bool
90  const RealEigenMatrix & x,
91  const std::string & hyper_param_name,
92  unsigned int ind) const
93 {
94  // Early return in the paramter name is longer than the expected [name] prefix.
95  // We prefix the parameter names with the name of the covariance function.
96  if (name().length() + 1 > hyper_param_name.length())
97  return false;
98 
99  // Strip the prefix from the given parameter name
100  const std::string name_without_prefix = hyper_param_name.substr(name().length() + 1);
101 
102  // Check if the parameter is tunable
103  if (_tunable_hp.find(hyper_param_name) != _tunable_hp.end())
104  {
105  const std::string acoeff_prefix = "acoeff_";
106  const std::string lambda_prefix = "lambda_";
107 
108  // Allocate storage for the factors of the total gradient matrix
109  RealEigenMatrix dBdhp = RealEigenMatrix::Zero(_num_outputs, _num_outputs);
110  RealEigenMatrix K_params = RealEigenMatrix::Zero(x.rows(), x.rows());
111 
112  if (name_without_prefix.find(acoeff_prefix) != std::string::npos)
113  {
114  // Automatically grab the expansion index
115  const int number = std::stoi(name_without_prefix.substr(acoeff_prefix.length()));
116  computeAGradient(dBdhp, number, ind);
117  _covariance_functions[number]->computeCovarianceMatrix(K_params, x, x, true);
118  }
119  else if (name_without_prefix.find(lambda_prefix) != std::string::npos)
120  {
121  // Automatically grab the expansion index
122  const int number = std::stoi(name_without_prefix.substr(lambda_prefix.length()));
123  computeLambdaGradient(dBdhp, number, ind);
124  _covariance_functions[number]->computeCovarianceMatrix(K_params, x, x, true);
125  }
126  MathUtils::kron(dKdhp, dBdhp, K_params);
127  return true;
128  }
129  else
130  {
131  // Allocate storage for the matrix factors
132  RealEigenMatrix B_tmp = RealEigenMatrix::Zero(_num_outputs, _num_outputs);
133  RealEigenMatrix B = RealEigenMatrix::Zero(_num_outputs, _num_outputs);
134  RealEigenMatrix dKdhp_sub = RealEigenMatrix::Zero(x.rows(), x.rows());
135 
136  // First, check the dependent covariances
137  bool found = false;
138  for (const auto dependent_covar : _covariance_functions)
139  if (!found)
140  found = dependent_covar->computedKdhyper(dKdhp_sub, x, hyper_param_name, ind);
141 
142  if (!found)
143  mooseError("Hyperparameter ", hyper_param_name, "not found!");
144 
145  // Then we compute the output covariance
146  for (const auto exp_i : make_range(_num_expansion_terms))
147  {
148  computeBMatrix(B_tmp, exp_i);
149  B += B_tmp;
150  }
151 
152  MathUtils::kron(dKdhp, B, dKdhp_sub);
153 
154  return true;
155  }
156 
157  return false;
158 }
159 
160 void
161 LMC::computeBMatrix(RealEigenMatrix & Bmat, const unsigned int exp_i) const
162 {
163  const auto & a_coeffs = *_a_coeffs[exp_i];
164  const auto & lambda_coeffs = *_lambdas[exp_i];
165 
166  for (const auto row_i : make_range(_num_outputs))
167  for (const auto col_i : make_range(_num_outputs))
168  {
169  Bmat(row_i, col_i) = a_coeffs[row_i] * a_coeffs[col_i];
170  if (row_i == col_i)
171  Bmat(row_i, col_i) += lambda_coeffs[col_i];
172  }
173 }
174 
175 void
177  const unsigned int exp_i,
178  const unsigned int index) const
179 {
180  const auto & a_coeffs = *_a_coeffs[exp_i];
181  // Add asserts here
182  grad.setZero();
183  for (const auto col_i : make_range(_num_outputs))
184  grad(index, col_i) = a_coeffs[col_i];
185  const RealEigenMatrix transpose = grad.transpose();
186  grad = grad + transpose;
187 }
188 
189 void
191  const unsigned int /*exp_i*/,
192  const unsigned int index) const
193 {
194  grad.setZero();
195  grad(index, index) = 1.0;
196 }
void computeBMatrix(RealEigenMatrix &Bmat, const unsigned int exp_i) const
Computes the covariance matrix for the outputs (using the latent coefficients) We use a $B = a_i a_i...
Definition: LMC.C:161
std::unordered_set< std::string > _tunable_hp
list of tunable hyper-parameters
void computeAGradient(RealEigenMatrix &grad, const unsigned int exp_i, const unsigned int index) const
Computes the gradient of $B$ with respect to the entries in $a_i$ in the following expression: $B = ...
Definition: LMC.C:176
const unsigned int _num_expansion_terms
The number of expansion terms in the output ovariance matrix.
Definition: LMC.h:67
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void kron(RealEigenMatrix &product, const RealEigenMatrix &mat_A, const RealEigenMatrix &mat_B)
static const std::string K
Definition: NS.h:170
void seed(std::size_t i, unsigned int seed)
bool computedKdhyper(RealEigenMatrix &dKdhp, const RealEigenMatrix &x, const std::string &hyper_param_name, unsigned int ind) const override
Redirect dK/dhp for hyperparameter "hp".
Definition: LMC.C:89
LMC(const InputParameters &parameters)
Definition: LMC.C:29
std::vector< CovarianceFunctionBase * > _covariance_functions
Vector of pointers to the dependent covariance functions.
Base class for covariance functions that are used in Gaussian Processes.
registerMooseObject("StochasticToolsApp", LMC)
static InputParameters validParams()
const std::vector< Real > & addVectorRealHyperParameter(const std::string &name, const std::vector< Real > value, const bool is_tunable)
Register a vector hyperparameter to this covariance function.
virtual const std::string & name() const
std::vector< const std::vector< Real > * > _a_coeffs
The vectors in the $B = a_i a_i^T + diag(lambda_i)$ expansion.
Definition: LMC.h:72
static InputParameters validParams()
Definition: LMC.C:17
const unsigned int _num_outputs
The number of outputs this covariance function is used to describe.
std::vector< const std::vector< Real > * > _lambdas
Definition: LMC.h:73
const std::vector< double > x
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic > RealEigenMatrix
const std::string _name
std::string grad(const std::string &var)
Definition: NS.h:91
void computeCovarianceMatrix(RealEigenMatrix &K, const RealEigenMatrix &x, const RealEigenMatrix &xp, const bool is_self_covariance) const override
Generates the Covariance Matrix given two sets of points in the parameter space.
Definition: LMC.C:66
IntRange< T > make_range(T beg, T end)
std::unordered_map< std::string, std::vector< Real > > _hp_map_vector_real
Map of vector-valued hyperparameters.
void makeParamRequired(const std::string &name)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
Real rand(std::size_t i)
void computeLambdaGradient(RealEigenMatrix &grad, const unsigned int exp_i, const unsigned int index) const
Computes the gradient of $B$ with respect to the entries in $lambda_i$ in the following expression: $...
Definition: LMC.C:190
Covariance function for multi-output Gaussian Processes based on the linear model of coregionalizatio...
Definition: LMC.h:18
void ErrorVector unsigned int