10 namespace pt = boost::property_tree;
18 DRKernel::DRKernel(pt::ptree
const& pt,
19 std::shared_ptr<AbstractSamplingProblem> problem) :
DRKernel(pt,
21 CreateProposals(pt, problem),
30 void DRKernel::SetBlockInd(
int newBlockInd)
34 proposal->SetBlockInd(newBlockInd);
38 std::shared_ptr<AbstractSamplingProblem> problem,
39 std::vector<std::shared_ptr<MCMCProposal>> proposalsIn) :
DRKernel(pt, problem, proposalsIn, std::vector<double>(proposalsIn.size(),1.0)){}
42 std::shared_ptr<AbstractSamplingProblem> problem,
43 std::vector<std::shared_ptr<MCMCProposal>> proposalsIn,
45 proposals(proposalsIn),
55 for(
unsigned int i=0; i<
propScales.size(); ++i){
56 if(std::abs(
propScales.at(i)-1.0)>std::numeric_limits<double>::epsilon()){
64 std::vector<std::shared_ptr<SamplingState>>
const& state){
67 proposal->Adapt(t,state);
72 std::shared_ptr<SamplingState>
const& state)
const
74 std::shared_ptr<SamplingState> prop =
proposals.at(stage)->Sample(state);
82 std::shared_ptr<SamplingState>
const& x,
83 std::shared_ptr<SamplingState>
const& y)
const
87 const double dim = x->state.at(
blockInd).size();
89 std::shared_ptr<SamplingState> yCopy = std::make_shared<SamplingState>(*y);
93 return proposals.at(stage)->LogDensity(x,y);
99 std::vector<std::shared_ptr<SamplingState>>
DRKernel::Step(
unsigned int const t,
100 std::shared_ptr<SamplingState> prevState){
102 const unsigned int numStages =
proposals.size();
104 std::vector<double> logDensities;
105 logDensities.reserve(numStages);
106 std::vector<std::shared_ptr<SamplingState>> proposedPoints;
107 proposedPoints.reserve(numStages);
111 double currentTarget;
112 if( prevState->HasMeta(
"LogTarget") && !
reeval ){
113 currentTarget =
AnyCast( prevState->meta[
"LogTarget"]);
115 currentTarget =
problem->LogDensity(prevState);
116 if (
problem->numBlocksQOI > 0) {
117 prevState->meta[
"QOI"] =
problem->QOI();
119 prevState->meta[
"LogTarget"] = currentTarget;
122 logDensities.push_back( currentTarget );
123 proposedPoints.push_back( prevState );
125 std::shared_ptr<SamplingState> proposedState;
126 Eigen::VectorXd alphas = Eigen::VectorXd::Zero(numStages);
129 for (
int stage = 0; stage < numStages; ++stage) {
137 if(prevState->HasMeta(
"iteration"))
138 proposedState->meta[
"iteration"] = proposedState->meta[
"iteration"];
139 proposedState->meta[
"IsProposal"] =
true;
142 double propTarget =
problem->LogDensity(proposedState);
143 proposedState->meta[
"LogTarget"] = propTarget;
146 logDensities.push_back( propTarget );
147 proposedPoints.push_back( proposedState );
150 alphas(stage) =
Alpha(logDensities, proposedPoints);
154 if (RandomGenerator::GetUniform() < alphas(stage)) {
156 if (
problem->numBlocksQOI > 0) {
157 proposedState->meta[
"QOI"] =
problem->QOI();
161 proposedState->meta[
"IsProposal"] =
false;
163 return std::vector<std::shared_ptr<SamplingState>>(1, proposedState);
168 return std::vector<std::shared_ptr<SamplingState>>(1,prevState);
173 std::string proposalList = pt.get<std::string>(
"Proposal");
176 std::vector<double> output;
179 if(proposalNames.size()>1){
180 output.resize(proposalNames.size(), 1.0);
184 int numStages = pt.get<
int>(
"NumStages");
187 std::string scaleType = pt.get<std::string>(
"ScaleFunction",
"Power");
188 double scale = pt.get(
"Scale", 2.0);
190 output.resize(numStages);
192 if(scaleType==
"Power"){
193 for(
int i=0; i<numStages; ++i)
194 output.at(i) = scale / std::pow(2.0,
double(i));
196 }
else if(scaleType==
"Linear") {
197 for(
int i=0; i<numStages; ++i)
198 output.at(i) = scale / (double(i)+1.0);
201 std::string msg =
"ERROR: In DRKernel::CreateScales, invalid scale function \"" + scaleType +
"\" specified in options. Valid options are \"Power\" or \"Linear\"";
202 throw std::invalid_argument(msg);
212 std::stringstream msg;
213 msg << std::setprecision(2);
214 msg << prefix <<
"DR: Number of calls = " <<
numProposalCalls.transpose() <<
"\n";
215 msg << prefix <<
"DR: Cumulative Accept Rate = ";
218 msg << std::setw(4) << std::fixed << std::setprecision(1) << rate / numCalls <<
"%";
222 msg <<
", " << std::setw(4) << std::fixed << std::setprecision(1) << rate / numCalls <<
"%";
225 std::cout << msg.str() << std::endl;
228 std::vector<std::shared_ptr<MCMCProposal>>
DRKernel::CreateProposals(pt::ptree
const& pt, std::shared_ptr<AbstractSamplingProblem>
const& problem)
231 std::string proposalList = pt.get<std::string>(
"Proposal");
233 std::vector<std::shared_ptr<MCMCProposal>>
proposals;
236 for(
auto& proposalName : proposalNames){
237 boost::property_tree::ptree subTree = pt.get_child(proposalName);
238 subTree.put(
"BlockIndex", pt.get(
"BlockIndex",0));
248 int numStages = pt.get(
"NumStages",-1);
REGISTER_TRANSITION_KERNEL(DRKernel) DRKernel
An implementation of the delayed rejection kernel.
std::vector< double > propScales
double EvaluateProposal(unsigned int stage, std::shared_ptr< SamplingState > const &x, std::shared_ptr< SamplingState > const &y) const
double Alpha(VecType1 &likelies, VecType2 &proposed_points) const
std::set< std::shared_ptr< MCMCProposal > > uniqueProps
DRKernel(boost::property_tree::ptree const &pt, std::shared_ptr< AbstractSamplingProblem > problem)
static std::vector< double > CreateScales(boost::property_tree::ptree const &pt)
Eigen::VectorXi numProposalCalls
Eigen::VectorXi numProposalAccepts
std::vector< std::shared_ptr< MCMCProposal > > proposals
virtual std::vector< std::shared_ptr< SamplingState > > Step(unsigned int const t, std::shared_ptr< SamplingState > prevState) override
static std::vector< std::shared_ptr< MCMCProposal > > CreateProposals(boost::property_tree::ptree const &pt, std::shared_ptr< AbstractSamplingProblem > const &problem)
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.
std::shared_ptr< SamplingState > SampleProposal(unsigned int stage, std::shared_ptr< SamplingState > const &state) const
static std::shared_ptr< MCMCProposal > Construct(boost::property_tree::ptree const &pt, std::shared_ptr< AbstractSamplingProblem > const &probIn)
Static constructor for the transition kernel.
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
virtual void PrintStatus() const
Class for easily casting boost::any's in assignment operations.
std::vector< std::string > Split(std::string str, char delim=',')
Split a string into parts based on a particular character delimiter. Also Strips whitespace from part...