https://mooseframework.inl.gov
PMCMCDecision.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 "PMCMCDecision.h"
11 #include "Sampler.h"
12 #include "DenseMatrix.h"
13 
14 registerMooseObject("StochasticToolsApp", PMCMCDecision);
15 
18 {
21  params.addClassDescription("Generic reporter which decides whether or not to accept a proposed "
22  "sample in parallel Markov chain Monte Carlo type of algorithms.");
23  params.addRequiredParam<ReporterName>("output_value",
24  "Value of the model output from the SubApp.");
25  params.addParam<ReporterValueName>(
26  "outputs_required",
27  "outputs_required",
28  "Modified value of the model output from this reporter class.");
29  params.addParam<ReporterValueName>("inputs", "inputs", "Uncertain inputs to the model.");
30  params.addParam<ReporterValueName>("tpm", "tpm", "The transition probability matrix.");
31  params.addParam<ReporterValueName>("variance", "variance", "Model variance term.");
32  params.addParam<ReporterValueName>(
33  "noise", "noise", "Model noise term to pass to Likelihoods object.");
34  params.addRequiredParam<SamplerName>("sampler", "The sampler object.");
35  params.addRequiredParam<std::vector<UserObjectName>>("likelihoods", "Names of likelihoods.");
36  return params;
37 }
38 
40  : GeneralReporter(parameters),
41  LikelihoodInterface(parameters),
42  _output_value(getReporterValue<std::vector<Real>>("output_value", REPORTER_MODE_DISTRIBUTED)),
43  _outputs_required(declareValue<std::vector<Real>>("outputs_required")),
44  _inputs(declareValue<std::vector<std::vector<Real>>>("inputs")),
45  _tpm(declareValue<std::vector<Real>>("tpm")),
46  _variance(declareValue<std::vector<Real>>("variance")),
47  _noise(declareValue<Real>("noise")),
48  _sampler(getSampler("sampler")),
49  _pmcmc(dynamic_cast<const PMCMCBase *>(&_sampler)),
50  _rnd_vec(_pmcmc->getRandomNumbers()),
51  _new_var_samples(_pmcmc->getVarSamples()),
52  _priors(_pmcmc->getPriors()),
53  _var_prior(_pmcmc->getVarPrior()),
54  _local_comm(_sampler.getLocalComm()),
55  _check_step(std::numeric_limits<int>::max())
56 {
57  // Filling the `likelihoods` vector with the user-provided distributions.
58  for (const UserObjectName & name : getParam<std::vector<UserObjectName>>("likelihoods"))
60 
61  // Check whether the selected sampler is an MCMC sampler or not
62  if (!_pmcmc)
63  paramError("sampler", "The selected sampler is not of type MCMC.");
64 
65  // Fetching the sampler characteristics
69 
70  // Resizing the data arrays to transmit to the output file
71  _inputs.resize(_props);
72  for (unsigned int i = 0; i < _props; ++i)
75  _tpm.resize(_props);
76  _variance.resize(_props);
77 }
78 
79 void
80 PMCMCDecision::computeEvidence(std::vector<Real> & evidence, const DenseMatrix<Real> & input_matrix)
81 {
82  std::vector<Real> out1(_num_confg_values);
83  std::vector<Real> out2(_num_confg_values);
84  for (unsigned int i = 0; i < evidence.size(); ++i)
85  {
86  evidence[i] = 0.0;
87  for (unsigned int j = 0; j < _priors.size(); ++j)
88  evidence[i] += (std::log(_priors[j]->pdf(input_matrix(i, j))) -
89  std::log(_priors[j]->pdf(_data_prev(i, j))));
90  for (unsigned int j = 0; j < _num_confg_values; ++j)
91  {
92  out1[j] = _outputs_required[j * _props + i];
93  out2[j] = _outputs_prev[j * _props + i];
94  }
95  if (_var_prior)
96  {
97  evidence[i] += (std::log(_var_prior->pdf(_new_var_samples[i])) -
98  std::log(_var_prior->pdf(_var_prev[i])));
99  _noise = std::sqrt(_new_var_samples[i]);
100  for (unsigned int j = 0; j < _likelihoods.size(); ++j)
101  evidence[i] += _likelihoods[j]->function(out1);
102  _noise = std::sqrt(_var_prev[i]);
103  for (unsigned int j = 0; j < _likelihoods.size(); ++j)
104  evidence[i] -= _likelihoods[j]->function(out2);
105  }
106  else
107  for (unsigned int j = 0; j < _likelihoods.size(); ++j)
108  evidence[i] += (_likelihoods[j]->function(out1) - _likelihoods[j]->function(out2));
109  }
110 }
111 
112 void
114  const std::vector<Real> & /*evidence*/)
115 {
116  tv.assign(_props, 1.0);
117 }
118 
119 void
120 PMCMCDecision::nextSamples(std::vector<Real> & req_inputs,
121  DenseMatrix<Real> & input_matrix,
122  const std::vector<Real> & tv,
123  const unsigned int & parallel_index)
124 {
125  if (tv[parallel_index] >= _rnd_vec[parallel_index])
126  {
127  for (unsigned int k = 0; k < _sampler.getNumberOfCols() - _num_confg_params; ++k)
128  req_inputs[k] = input_matrix(parallel_index, k);
129  _variance[parallel_index] = _new_var_samples[parallel_index];
130  }
131  else
132  {
133  for (unsigned int k = 0; k < _sampler.getNumberOfCols() - _num_confg_params; ++k)
134  {
135  req_inputs[k] = _data_prev(parallel_index, k);
136  input_matrix(parallel_index, k) = _data_prev(parallel_index, k);
137  }
138  if (_var_prior)
139  _variance[parallel_index] = _var_prev[parallel_index];
140  for (unsigned int k = 0; k < _num_confg_values; ++k)
141  _outputs_required[k * _props + parallel_index] = _outputs_prev[k * _props + parallel_index];
142  }
143 }
144 
145 void
147 {
149  {
151  return;
152  }
153 
154  // Gather inputs and outputs from the sampler and subApps
156  for (dof_id_type ss = _sampler.getLocalRowBegin(); ss < _sampler.getLocalRowEnd(); ++ss)
157  {
158  const auto data = _sampler.getNextLocalRow();
159  for (unsigned int j = 0; j < _sampler.getNumberOfCols(); ++j)
160  data_in(ss, j) = data[j];
161  }
162  _local_comm.sum(data_in.get_values());
165 
166  // Compute the evidence and transition vectors
167  std::vector<Real> evidence(_props);
168  if (_t_step > _pmcmc->decisionStep())
169  {
170  computeEvidence(evidence, data_in);
171  computeTransitionVector(_tpm, evidence);
172  }
173  else
174  _tpm.assign(_props, 1.0);
175 
176  // Accept/reject the proposed samples and assign the correct outputs
177  std::vector<Real> req_inputs(_sampler.getNumberOfCols() - _num_confg_params);
178  for (unsigned int i = 0; i < _props; ++i)
179  {
180  nextSamples(req_inputs, data_in, _tpm, i);
181  _inputs[i] = req_inputs;
182  }
183 
184  // Compute the next seeds to facilitate proposals (not always required)
185  nextSeeds();
186 
187  // Store data from previous step
188  _data_prev = data_in;
191 
192  // Track the current step
194 }
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
dof_id_type _num_confg_values
Storage for the number of experimental configuration values.
dof_id_type getNumberOfConfigValues() const
Return the number of configuration parameters.
Definition: PMCMCBase.h:29
PMCMCDecision will help making sample accept/reject decisions in MCMC schemes (for e...
Definition: PMCMCDecision.h:22
virtual Real pdf(const Real &x) const=0
dof_id_type getNumberOfConfigParams() const
Return the number of configuration parameters.
Definition: PMCMCBase.h:34
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
virtual void computeEvidence(std::vector< Real > &evidence, const DenseMatrix< Real > &input_matrix)
Compute the evidence (aka, betterness of the proposed sample vs the previous)
Definition: PMCMCDecision.C:80
Real & _noise
Model noise term to pass to Likelihoods object.
Definition: PMCMCDecision.h:81
std::vector< Real > getNextLocalRow()
dof_id_type getLocalRowBegin() const
static InputParameters validParams()
dof_id_type _num_confg_params
Storage for the number of experimental configuration parameters.
virtual void execute() override
dof_id_type getNumberOfLocalRows() const
virtual const std::string & name() const
const std::vector< Real > & _output_value
Model output value from SubApp.
Definition: PMCMCDecision.h:66
void addRequiredParam(const std::string &name, const std::string &doc_string)
std::vector< Real > & _variance
Model variance term.
Definition: PMCMCDecision.h:78
auto max(const L &left, const R &right)
int _check_step
Ensure that the MCMC algorithm proceeds in a sequential fashion.
dof_id_type getNumParallelProposals() const
Return the number of parallel proposals.
Definition: PMCMCBase.h:39
libMesh::Parallel::Communicator & _local_comm
Communicator that was split based on samples that have rows.
PMCMCDecision(const InputParameters &parameters)
Definition: PMCMCDecision.C:39
DenseMatrix< Real > _data_prev
Storage for previous inputs.
std::vector< Real > _var_prev
Storage for previous variances.
const PMCMCBase *const _pmcmc
MCMC sampler base.
Definition: PMCMCDecision.h:90
const T & getParam(const std::string &name) const
virtual void computeTransitionVector(std::vector< Real > &tv, const std::vector< Real > &evidence)
Compute the transition probability vector (after the computation of evidence)
void paramError(const std::string &param, Args... args) const
const ReporterMode REPORTER_MODE_DISTRIBUTED
static InputParameters validParams()
virtual void nextSeeds()
Compute the next set of seeds to facilitate proposals.
Definition: PMCMCDecision.h:63
dof_id_type getLocalRowEnd() const
const Distribution * _var_prior
Storage for the prior over the variance.
dof_id_type getNumberOfRows() const
const std::vector< const Distribution * > _priors
Storage for the priors.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
registerMooseObject("StochasticToolsApp", PMCMCDecision)
dof_id_type _props
Storage for the number of parallel proposals.
Definition: PMCMCDecision.h:93
LikelihoodFunctionBase * getLikelihoodFunctionByName(const UserObjectName &name) const
Lookup a LikelihoodFunction object by name and return pointer.
virtual void nextSamples(std::vector< Real > &req_inputs, DenseMatrix< Real > &input_matrix, const std::vector< Real > &tv, const unsigned int &parallel_index)
Resample inputs given the transition vector (after transition vector computed)
static InputParameters validParams()
Definition: PMCMCDecision.C:17
virtual int decisionStep() const
Return the step after which decision making can begin.
Definition: PMCMCBase.h:64
void addClassDescription(const std::string &doc_string)
std::vector< const LikelihoodFunctionBase * > _likelihoods
Storage for the likelihood objects to be utilized.
Definition: PMCMCDecision.h:84
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< Real > _outputs_prev
Storage for previous outputs.
Sampler & _sampler
The MCMC sampler.
Definition: PMCMCDecision.h:87
const std::vector< Real > & _new_var_samples
Storage for new proposed variance samples.
Definition: PMCMCDecision.h:99
const std::vector< Real > & _rnd_vec
Storage for the random numbers for decision making.
Definition: PMCMCDecision.h:96
std::vector< Real > & _outputs_required
Transfer the right outputs to the file.
Definition: PMCMCDecision.h:69
std::vector< Real > & _tpm
Transition probability matrix.
Definition: PMCMCDecision.h:75
static const std::string k
Definition: NS.h:130
void ErrorVector unsigned int
std::vector< std::vector< Real > > & _inputs
Model input data that is uncertain.
Definition: PMCMCDecision.h:72
dof_id_type getNumberOfCols() const
uint8_t dof_id_type
A base class used to perform Parallel Markov Chain Monte Carlo (MCMC) sampling.
Definition: PMCMCBase.h:19