MUQ  0.4.3
AMProposal.cpp
Go to the documentation of this file.
2 
6 
7 namespace pt = boost::property_tree;
8 using namespace muq::Utilities;
9 using namespace muq::SamplingAlgorithms;
10 using namespace muq::Modeling;
11 
12 
14 
15 AMProposal::AMProposal(pt::ptree pt,
16  std::shared_ptr<AbstractSamplingProblem> const& prob,
17  Eigen::MatrixXd const& initialCov) : MCMCProposal(pt,prob),
18  propCov(initialCov),
19  adaptSteps(pt.get<unsigned int>("AdaptSteps")),
20  adaptStart(pt.get<unsigned int>("AdaptStart")),
21  adaptEnd(pt.get<unsigned int>("AdaptEnd",std::numeric_limits<unsigned int>::max())),
22  adaptScale(pt.get("AdaptScale",2.4*2.4/initialCov.rows()))
23 {
24  propChol = propCov.selfadjointView<Eigen::Lower>().llt();
25  newSamps.resize(propCov.rows(), adaptSteps);
26  numAdaptSamps = 1;
27 }
28 
29 AMProposal::AMProposal(pt::ptree pt ,
30  std::shared_ptr<AbstractSamplingProblem> const& prob) : AMProposal(pt,prob, ConstructCovariance(pt,prob))
31 
32 {}
33 
34 Eigen::MatrixXd AMProposal::ConstructCovariance(pt::ptree const& pt ,
35  std::shared_ptr<AbstractSamplingProblem> const& prob)
36 {
37  int dim = prob->blockSizes(pt.get("BlockIndex",0));
38  double propVar = pt.get("InitialVariance",1.0);
39  return propVar * Eigen::MatrixXd::Identity(dim,dim);
40 }
41 
42 
43 void AMProposal::Adapt(unsigned int const t, std::vector<std::shared_ptr<SamplingState>> const& states) {
44 
45 
46  if((t>=adaptStart)&&(t<adaptEnd)){
47 
48  if((numAdaptSamps==1)&&(numNewSamps==0)){
49  mean = states.at(0)->state.at(blockInd);
50  }
51 
52  // Copy the states into the matrix of new samples
53  for(unsigned int i=0; (i<states.size())&&(numNewSamps<adaptSteps); i++){
54  newSamps.col(numNewSamps) = states.at(i)->state.at(blockInd);
55  numNewSamps++;
56  }
57 
58  if((t%adaptSteps==0)&&(numNewSamps>0)){
59 
60  Eigen::VectorXd oldMean;
61  std::swap(mean,oldMean);
62 
63  // Update the mean, covariance, and Cholesky factorization
64  mean = (oldMean*numAdaptSamps + newSamps.leftCols(numNewSamps).rowwise().mean()*numNewSamps)/(numAdaptSamps+numNewSamps);
65 
66  propChol.rankUpdate(oldMean, double(numAdaptSamps));
67  propChol.rankUpdate(mean, -1.0*double(numAdaptSamps+numNewSamps));
68 
69  for(unsigned int i=0; i<numNewSamps; ++i)
70  propChol.rankUpdate(newSamps.col(i), 1.0);
71 
73  numNewSamps = 0;
74  }
75  }
76 }
77 
78 
79 Eigen::MatrixXd AMProposal::ProposalCovariance() const
80 {
81  return adaptScale*propChol.reconstructedMatrix()/double(numAdaptSamps);
82 }
83 
84 std::shared_ptr<SamplingState> AMProposal::Sample(std::shared_ptr<SamplingState> const& currentState)
85 {
86 
87  // the mean of the proposal is the current point
88  Eigen::VectorXd const& xc = currentState->state.at(blockInd);
89 
90  std::vector<Eigen::VectorXd> props = currentState->state;
91  props.at(blockInd) = xc + std::sqrt(adaptScale/double(numAdaptSamps))*(propChol.matrixL() * RandomGenerator::GetNormal(xc.size())).eval();
92 
93  // store the new state in the output
94  return std::make_shared<SamplingState>(props, 1.0);
95 }
96 
97 double AMProposal::LogDensity(std::shared_ptr<SamplingState> const& currState,
98  std::shared_ptr<SamplingState> const& propState)
99 {
100  Eigen::VectorXd diff = (propState->state.at(blockInd) - currState->state.at(blockInd))/std::sqrt(adaptScale/double(numAdaptSamps));
101  return -0.5*diff.dot(propChol.solve(diff));
102 }
REGISTER_MCMC_PROPOSAL(AMProposal) AMProposal
Definition: AMProposal.cpp:13
An implemental of the Adaptive Metropolis algorithm.
Definition: AMProposal.h:21
virtual std::shared_ptr< SamplingState > Sample(std::shared_ptr< SamplingState > const &currentState) override
Definition: AMProposal.cpp:84
Eigen::LLT< Eigen::MatrixXd, Eigen::Lower > propChol
The Cholesky factorization of the current proposal covariance.
Definition: AMProposal.h:76
virtual Eigen::MatrixXd ProposalCovariance() const
Definition: AMProposal.cpp:79
Eigen::VectorXd mean
The current mean.
Definition: AMProposal.h:70
Eigen::MatrixXd newSamps
Samples seen between visits.
Definition: AMProposal.h:63
virtual void Adapt(unsigned int const t, std::vector< std::shared_ptr< SamplingState >> const &states) override
Adapt the proposal after each step.
Definition: AMProposal.cpp:43
const unsigned int adaptStart
When should we start adapting?
Definition: AMProposal.h:82
const unsigned int adaptEnd
After how many iterations should we stop adapting?
Definition: AMProposal.h:85
unsigned int numAdaptSamps
Total number of samples that have been used so far to compute mean and covariance.
Definition: AMProposal.h:67
const unsigned int adaptSteps
How frequently should we update the adaption?
Definition: AMProposal.h:79
virtual double LogDensity(std::shared_ptr< SamplingState > const &currState, std::shared_ptr< SamplingState > const &propState) override
Definition: AMProposal.cpp:97
std::shared_ptr< AbstractSamplingProblem > prob
Definition: MCMCProposal.h:81
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.h:3956