MUQ  0.4.3
MHKernel.cpp
Go to the documentation of this file.
3 
6 
7 #include <iomanip>
8 
9 namespace pt = boost::property_tree;
10 using namespace muq::Utilities;
11 using namespace muq::Modeling;
12 using namespace muq::SamplingAlgorithms;
13 
15 
16 MHKernel::MHKernel(pt::ptree const& pt, std::shared_ptr<AbstractSamplingProblem> problem) : TransitionKernel(pt, problem)
17 {
18 
19  // Extract the proposal parts from the ptree
20  std::string proposalName = pt.get<std::string>("Proposal");
21 
22  boost::property_tree::ptree subTree = pt.get_child(proposalName);
23  subTree.put("BlockIndex", blockInd);
24 
25  // Construct the proposal
26  proposal = MCMCProposal::Construct(subTree, problem);
27  assert(proposal);
28 }
29 
30 MHKernel::MHKernel(pt::ptree const& pt,
31  std::shared_ptr<AbstractSamplingProblem> problem,
32  std::shared_ptr<MCMCProposal> proposalIn) : TransitionKernel(pt, problem),
33  proposal(proposalIn) {}
34 
35 
36 void MHKernel::PostStep(unsigned int const t, std::vector<std::shared_ptr<SamplingState>> const& state){
37  proposal->Adapt(t,state);
38 }
39 
40 std::vector<std::shared_ptr<SamplingState>> MHKernel::Step(unsigned int const t, std::shared_ptr<SamplingState> prevState){
41 
42  assert(proposal);
43 
44  // propose a new point
45  std::shared_ptr<SamplingState> prop = proposal->Sample(prevState);
46 
47  // The following metadata is needed by the expensive sampling problem
48  if(prevState->HasMeta("iteration"))
49  prop->meta["iteration"] = prevState->meta["iteration"];
50  prop->meta["IsProposal"] = true;
51 
52  // compute acceptance probability
53  double propTarget;
54  double currentTarget;
55 
56  if( prevState->HasMeta("LogTarget") && (prevState->HasMeta("QOI") || problem->numBlocksQOI == 0) && !reeval ){
57  currentTarget = AnyCast( prevState->meta["LogTarget"]);
58  }else{
59  currentTarget = problem->LogDensity(prevState);
60  if (problem->numBlocksQOI > 0) {
61  prevState->meta["QOI"] = problem->QOI();
62  }
63  prevState->meta["LogTarget"] = currentTarget;
64  }
65 
66  try{
67  propTarget = problem->LogDensity(prop);
68 
69  }catch(std::runtime_error &e){
70 
71  // If we couldn't compute the log density, reject the proposal
72  return std::vector<std::shared_ptr<SamplingState>>(1, prevState);
73  }
74 
75  prop->meta["LogTarget"] = propTarget;
76 
77  // Aceptance probability
78  const double forwardPropDens = proposal->LogDensity(prevState, prop);
79  const double backPropDens = proposal->LogDensity(prop, prevState);
80  const double alpha = std::exp(propTarget - forwardPropDens - currentTarget + backPropDens);
81 
82  // accept/reject
83  numCalls++;
84  if( RandomGenerator::GetUniform()<alpha ) {
85  if (problem->numBlocksQOI > 0) {
86  prop->meta["QOI"] = problem->QOI();
87  }
88  numAccepts++;
89 
90  prop->meta["IsProposal"] = false;
91  return std::vector<std::shared_ptr<SamplingState>>(1, prop);
92  } else {
93  return std::vector<std::shared_ptr<SamplingState>>(1, prevState);
94  }
95 }
96 
97 void MHKernel::PrintStatus(const std::string prefix) const
98 {
99  std::stringstream out;
100  out << std::fixed << std::setw(3);
101  out.precision(0);
102  out << "MHKernel acceptance Rate = " << 100.0*double(numAccepts)/double(numCalls) << "%";
103  std::cout << prefix << out.str() << std::endl;
104 }
REGISTER_TRANSITION_KERNEL(MHKernel) MHKernel
Definition: MHKernel.cpp:14
An implementation of the standard Metropolis-Hastings transition kernel.
Definition: MHKernel.h:22
std::shared_ptr< MCMCProposal > proposal
Definition: MHKernel.h:45
virtual std::vector< std::shared_ptr< SamplingState > > Step(unsigned int const t, std::shared_ptr< SamplingState > prevState) override
Definition: MHKernel.cpp:40
Defines the transition kernel used by an MCMC algorithm.
std::shared_ptr< AbstractSamplingProblem > problem
The sampling problem that evaluates/samples the target distribution.
const bool reeval
true: reevaluate the log density (even if one already exists), false: use stored log density
Class for easily casting boost::any's in assignment operations.
Definition: AnyHelpers.h:34