MUQ  0.4.3
MIKernel.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 
14 MIKernel::MIKernel(boost::property_tree::ptree const& pt,
15  std::shared_ptr<AbstractSamplingProblem> problem,
16  std::shared_ptr<AbstractSamplingProblem> coarse_problem,
17  std::shared_ptr<MCMCProposal> proposal,
18  std::shared_ptr<MCMCProposal> coarse_proposal,
19  std::shared_ptr<MIInterpolation> proposalInterpolation,
20  std::shared_ptr<SingleChainMCMC> coarse_chain)
21  : TransitionKernel(pt, problem),
22  coarse_problem(coarse_problem),
23  proposal(proposal),
24  coarse_proposal(coarse_proposal),
25  proposalInterpolation(proposalInterpolation),
26  coarse_chain(coarse_chain) {}
27 
28 
30 
31 void MIKernel::PostStep(unsigned int const t, std::vector<std::shared_ptr<SamplingState>> const& state){
32  proposal->Adapt(t,state);
33 }
34 
35 std::vector<std::shared_ptr<SamplingState>> MIKernel::Step(unsigned int const t, std::shared_ptr<SamplingState> prevState){
36  assert(proposal);
37 
38  // If no coarse sample is specified, assume it's the first one
39  std::shared_ptr<SamplingState> coarsePrevState;
40  if(prevState->HasMeta("coarseSample")) {
41  coarsePrevState = AnyCast(prevState->meta["coarseSample"]);
42  } else {
43  coarsePrevState = coarse_chain->GetSamples()->at(0);
44  }
45 
46  // New fine proposal
47  std::shared_ptr<SamplingState> prop = proposal->Sample(prevState);
48  std::shared_ptr<SamplingState> coarseProp = coarse_proposal->Sample(coarsePrevState);
49  std::shared_ptr<SamplingState> fineProp = proposalInterpolation->Interpolate (coarseProp, prop);
50 
51  // The following metadata is needed by the expensive sampling problem
52  if(prevState->HasMeta("iteration")) {
53  fineProp->meta["iteration"] = prevState->meta["iteration"];
54  }
55  if(coarsePrevState->HasMeta("iteration")) {
56  coarseProp->meta["iteration"] = coarsePrevState->meta["iteration"];
57  } else {
58  coarseProp->meta["iteration"] = (unsigned int)0;
59  coarsePrevState->meta["iteration"] = (unsigned int)0;
60  }
61  coarsePrevState->meta["IsProposal"] = false;
62  fineProp->meta["IsProposal"] = true;
63  coarseProp->meta["IsProposal"] = true;
64 
65  // compute acceptance probability
66  double propTarget;
67  double currentTarget;
68  double propTargetCoarse;
69  double currentTargetCoarse;
70 
71  if(prevState->HasMeta("LogTarget") && (prevState->HasMeta("QOI") || problem->numBlocksQOI == 0)){
72  currentTarget = AnyCast(prevState->meta["LogTarget"]);
73  }else{
74  currentTarget = problem->LogDensity(prevState);
75  prevState->meta["LogTarget"] = currentTarget;
76  if (problem->numBlocksQOI > 0) {
77  prevState->meta["QOI"] = problem->QOI();
78  }
79  }
80 
81  if(coarsePrevState->HasMeta("LogTarget") && (coarsePrevState->HasMeta("QOI") || coarse_problem->numBlocksQOI == 0)){
82  currentTargetCoarse = AnyCast(coarsePrevState->meta["LogTarget"]);
83  }else{
84  currentTargetCoarse = coarse_problem->LogDensity(coarsePrevState);
85  coarsePrevState->meta["LogTarget"] = currentTargetCoarse;
86  if (coarse_problem->numBlocksQOI > 0) {
87  coarsePrevState->meta["QOI"] = coarse_problem->QOI();
88  }
89  }
90 
91  propTarget = problem->LogDensity(fineProp);
92  assert(coarseProp->HasMeta("LogTarget"));
93  propTargetCoarse = AnyCast(coarseProp->meta["LogTarget"]);
94 
95  fineProp->meta["LogTarget"] = propTarget;
96  fineProp->meta["coarseSample"] = coarseProp; // Hook up fine sample to coarse one
97 
98  // Aceptance probability
99  const double forwardPropDens = proposal->LogDensity(prevState, fineProp);
100  const double backPropDens = proposal->LogDensity(fineProp, prevState);
101  const double alpha = std::exp(propTarget + currentTargetCoarse + backPropDens
102  -(currentTarget + propTargetCoarse + forwardPropDens));
103 
104  // accept/reject
105  numCalls++;
106  if(RandomGenerator::GetUniform()<alpha) {
107  numAccepts++;
108  if (problem->numBlocksQOI > 0) {
109  fineProp->meta["QOI"] = problem->QOI();
110  }
111  return std::vector<std::shared_ptr<SamplingState>>(1,fineProp);
112  } else {
113  // Return copy of previous state in order to attach the new coarse proposal to it
114  auto prevStateCopy = std::make_shared<SamplingState>(prevState->state);
115  prevStateCopy->meta = prevState->meta;
116  prevStateCopy->meta["coarseSample"] = coarseProp;
117  return std::vector<std::shared_ptr<SamplingState>>(1,prevStateCopy);
118  }
119 }
120 
121 void MIKernel::PrintStatus(const std::string prefix) const
122 {
123  std::stringstream msg;
124  msg << std::setprecision(2);
125  msg << prefix << "MIKernel acceptance Rate = " << 100.0*double(numAccepts)/double(numCalls) << "%";
126 
127  std::cout << msg.str() << std::endl;
128 }
std::shared_ptr< AbstractSamplingProblem > coarse_problem
Definition: MIKernel.h:40
std::shared_ptr< SingleChainMCMC > coarse_chain
Definition: MIKernel.h:47
std::shared_ptr< MCMCProposal > proposal
Definition: MIKernel.h:44
std::shared_ptr< MIInterpolation > proposalInterpolation
Definition: MIKernel.h:46
virtual void PostStep(unsigned int const t, std::vector< std::shared_ptr< SamplingState >> const &state) override
Allow the kernel to adapt given a new state.
Definition: MIKernel.cpp:31
std::shared_ptr< MCMCProposal > coarse_proposal
Definition: MIKernel.h:45
virtual std::vector< std::shared_ptr< SamplingState > > Step(unsigned int const t, std::shared_ptr< SamplingState > prevState) override
Definition: MIKernel.cpp:35
Defines the transition kernel used by an MCMC algorithm.
std::shared_ptr< AbstractSamplingProblem > problem
The sampling problem that evaluates/samples the target distribution.
Class for easily casting boost::any's in assignment operations.
Definition: AnyHelpers.h:34