autoppl  v0.8
A C++ template library for probabilistic programming
base_mcmc.hpp
Go to the documentation of this file.
1 #pragma once
4 #include <autoppl/util/value.hpp>
6 
7 namespace ppl {
8 namespace mcmc {
9 
10 template <class ExprType
11  , class ConfigType
12  , class Sampler>
13 inline MCMCResult<> base_mcmc(const ExprType& expr,
14  const ConfigType& config,
15  Sampler f)
16 {
17  using program_t = util::convert_to_program_t<ExprType>;
18  program_t program = expr;
19 
20  auto pack = program.activate();
21  size_t n_cont = std::get<0>(pack).uc_offset;
22  size_t n_disc = std::get<1>(pack).uc_offset;
23  MCMCResult<Eigen::RowMajor> res(config.samples, n_cont, n_disc);
24 
25  f(program, config, pack, res); // call actual sampling algorithm and populate res
26 
27  // Note: discrete cannot be constrained, so we only need to transform continuous
28 
29  // Compute total size of purely only constrained parameters.
30  // Note that this is NOT the same pack.c_offset after activating.
31  // The latter is always >= the former, but may be > (see PosDef constraint for example).
32  size_t n_cont_c = 0;
33  auto n_cont_c__ = [&](auto& eq_node) {
34  auto& var = eq_node.get_variable();
35  using var_t = std::decay_t<decltype(var)>;
36  if constexpr (util::is_param_v<var_t> &&
38  n_cont_c += var.size();
39  }
40  };
41  program.get_model().traverse(n_cont_c__);
42 
43  // Create transformed result object
44  // Note that the number of cols for continuous sample is n_cont_c + 1,
45  // where +1 is for the log-pdf.
46  //
47  // Computing logpdf solves two issues:
48  // 1) we can save logpdf to get summary
49  // 2) calling logpdf automatically evaluates all expressions properly
50  // such that, in particular, constrained values are evaluated properly.
51 
52  MCMCResult<> t_res(config.samples, n_cont_c + 1, n_disc);
53  std::swap(t_res.name, res.name);
54  std::swap(t_res.warmup_time, res.warmup_time);
55  std::swap(t_res.sampling_time, res.sampling_time);
56  t_res.disc_samples.swap(res.disc_samples);
57 
58  // Transform every unconstrained params to constrained
59  auto& cont_pack = std::get<0>(pack);
60  auto& disc_pack = std::get<1>(pack);
61  Eigen::Matrix<util::disc_param_t, Eigen::Dynamic, 1> disc_uc_val(disc_pack.uc_offset);
62  Eigen::VectorXd cont_uc_val(cont_pack.uc_offset);
63  Eigen::VectorXd cont_tp_val(cont_pack.tp_offset);
64  Eigen::VectorXd cont_c_val(cont_pack.c_offset);
65  Eigen::Matrix<size_t, Eigen::Dynamic, 1> cont_v_val(cont_pack.v_offset);
66  cont_c_val.setZero();
67  cont_v_val.setZero();
68 
69  util::cont_ptr_pack_t cont_ptr_pack;
70  cont_ptr_pack.uc_val = cont_uc_val.data();
71  cont_ptr_pack.tp_val = cont_tp_val.data();
72  cont_ptr_pack.c_val = cont_c_val.data();
73  cont_ptr_pack.v_val = cont_v_val.data();
74  program.bind(cont_ptr_pack);
75 
76  util::disc_ptr_pack_t disc_ptr_pack;
77  disc_ptr_pack.uc_val = disc_uc_val.data();
78  program.bind(disc_ptr_pack);
79 
80  for (int i = 0; i < res.cont_samples.rows(); ++i) {
81  disc_uc_val = t_res.disc_samples.row(i);
82  cont_uc_val = res.cont_samples.row(i);
83  auto lpdf = program.log_pdf();
84  size_t offset = 0;
85  auto copy__ = [&](auto& eq_node) {
86  auto& var = eq_node.get_variable();
87  using var_t = std::decay_t<decltype(var)>;
88  if constexpr (util::is_param_v<var_t> &&
90  Eigen::Map<Eigen::MatrixXd> mp(nullptr, 0, 0);
91  if constexpr (util::is_scl_v<var_t>) {
92  util::bind(mp, &var.get(), 1, 1);
93  } else {
94  util::bind(mp, var.get().data(), 1, var.size());
95  }
96  t_res.cont_samples.block(i, offset, 1, var.size()) = mp;
97  offset += var.size();
98  }
99  };
100  program.get_model().traverse(copy__);
101  t_res.cont_samples(i, offset) = lpdf;
102  }
103 
104  return t_res;
105 }
106 
107 } // namespace mcmc
108 } // namespace ppl
ppl::mcmc::base_mcmc
MCMCResult base_mcmc(const ExprType &expr, const ConfigType &config, Sampler f)
Definition: base_mcmc.hpp:13
ppl::util::PtrPack::c_val
CValPtrType c_val
Definition: ptr_pack.hpp:37
ppl::MCMCResult
Definition: result.hpp:17
ppl::util::var_traits
Definition: var_traits.hpp:40
ptr_pack.hpp
ppl::MCMCResult::warmup_time
double warmup_time
Definition: result.hpp:24
ppl::util::bind
void bind(T &x, ValPtrType begin, size_t rows=1, size_t cols=1)
Definition: value.hpp:61
ppl::util::PtrPack::uc_val
UCValPtrType uc_val
Definition: ptr_pack.hpp:33
ppl::MCMCResult::cont_samples
cont_samples_t cont_samples
Definition: result.hpp:21
ppl::util::var_t
typename details::var< V, T >::type var_t
Definition: shape_traits.hpp:132
ppl::MCMCResult::disc_samples
disc_samples_t disc_samples
Definition: result.hpp:22
value.hpp
ppl::MCMCResult::name
std::string name
Definition: result.hpp:23
ppl::util::PtrPack::tp_val
TPValPtrType tp_val
Definition: ptr_pack.hpp:35
ppl::MCMCResult::sampling_time
double sampling_time
Definition: result.hpp:25
ppl
Definition: bounded.hpp:11
ppl::util::PtrPack
Definition: ptr_pack.hpp:14
traits.hpp
ppl::util::convert_to_program_t
typename details::convert_to_program< T >::type convert_to_program_t
Definition: traits.hpp:182
result.hpp
ppl::util::PtrPack::v_val
size_t * v_val
Definition: ptr_pack.hpp:38