1 #ifndef __STAN__MCMC__NUTS_DIAG_H__
2 #define __STAN__MCMC__NUTS_DIAG_H__
9 #include <boost/random/normal_distribution.hpp>
10 #include <boost/random/mersenne_twister.hpp>
11 #include <boost/random/variate_generator.hpp>
12 #include <boost/random/uniform_01.hpp>
32 template <
class BaseRNG = boost::mt19937>
37 const double _maxchange;
46 std::vector<double> _step_sizes;
48 std::vector<double> _x_sum;
49 std::vector<double> _xsq_sum;
62 inline static bool compute_criterion(std::vector<double>& xplus,
63 std::vector<double>& xminus,
64 std::vector<double>& mplus,
65 std::vector<double>& mminus,
66 std::vector<double>& step_sizes) {
67 std::vector<double> total_direction;
70 for (
size_t i = 0; i < total_direction.size(); ++i)
71 total_direction[i] /= step_sizes[i];
107 double epsilon_pm = 0.0,
108 bool epsilon_adapt =
true,
111 BaseRNG base_rng = BaseRNG(std::time(0)),
112 const std::vector<double>* params_r = 0,
113 const std::vector<int>* params_i = 0)
128 _step_sizes(model.num_params_r(), 1.0),
129 _x_sum(model.num_params_r(), 0),
130 _xsq_sum(model.num_params_r(), 0),
153 for (
size_t i = 0; i < mminus.size(); ++i)
155 std::vector<double> mplus(mminus);
160 std::vector<double> gradminus(this->
_g);
161 std::vector<double> gradplus(this->
_g);
162 std::vector<double> xminus(this->
_x);
163 std::vector<double> xplus(this->
_x);
169 bool criterion =
true;
172 std::vector<double> newx, newgrad, dummy1, dummy2, dummy3;
174 double prob_sum = -1;
176 int n_considered = 0;
185 double range = high - low;
190 while (criterion && (_maxdepth < 0 || depth < _maxdepth)) {
193 build_tree(xminus, mminus, gradminus, u, direction, depth,
194 H0, xminus, mminus, gradminus, dummy1, dummy2, dummy3,
195 newx, newgrad, newlogp, newnvalid, criterion, prob_sum,
198 build_tree(xplus, mplus, gradplus, u, direction, depth,
199 H0, dummy1, dummy2, dummy3, xplus, mplus, gradplus,
200 newx, newgrad, newlogp, newnvalid, criterion, prob_sum,
205 criterion = compute_criterion(xplus, xminus, mplus, mminus,_step_sizes);
211 this->
_logp = newlogp;
220 double adapt_stat = prob_sum / float(n_considered);
223 double adapt_g = adapt_stat - this->
_delta;
224 std::vector<double> gvec(1, -adapt_g);
225 std::vector<double> result;
230 _next_diag_adapt *= 2;
231 double step_size_sq_sum = 0;
232 for (
size_t i = 0; i < _step_sizes.size(); i++) {
233 double Ex = _x_sum[i] / _x_sum_n;
234 double Exsq = _xsq_sum[i] / _x_sum_n;
237 _step_sizes[i] =
sqrt(Exsq - Ex*Ex);
238 step_size_sq_sum += _step_sizes[i] * _step_sizes[i];
240 if (step_size_sq_sum > 0.0) {
242 double normalizer =
sqrt((
double)_step_sizes.size())
243 /
sqrt(step_size_sq_sum);
244 for (
size_t i = 0; i < _step_sizes.size(); i++)
245 _step_sizes[i] *= normalizer;
247 for (
size_t i = 0; i < _step_sizes.size(); i++)
248 _step_sizes[i] = 1.0;
252 std::vector<double> result;
254 double avg_eta = 1.0 / this->
n_steps();
267 o << _lastdepth <<
',';
273 o <<
"# (mcmc::nuts_diag) adaptation finished" <<
'\n';
274 o <<
"# step size=" << this->
_epsilon <<
'\n';
275 o <<
"# parameter step size multipliers:\n";
277 for (
size_t k = 0; k < _step_sizes.size(); ++k) {
286 names.push_back(
"treedepth__");
288 names.push_back(
"stepsize__");
293 values.push_back(_lastdepth);
333 const std::vector<double>& m,
334 const std::vector<double>&
grad,
339 std::vector<double>& xminus,
340 std::vector<double>& mminus,
341 std::vector<double>& gradminus,
342 std::vector<double>& xplus,
343 std::vector<double>& mplus,
344 std::vector<double>& gradplus,
345 std::vector<double>& newx,
346 std::vector<double>& newgrad,
357 xminus, mminus, gradminus,
364 gradplus = gradminus;
367 newH = -std::numeric_limits<double>::infinity();
369 criterion = newH - u > _maxchange;
376 for (
size_t i = 0; i < newx.size(); i++) {
377 _x_sum[i] += newx[i];
378 _xsq_sum[i] += newx[i] * newx[i];
382 build_tree(x, m, grad, u, direction, depth-1, H0, xminus, mminus,
383 gradminus, xplus, mplus, gradplus, newx, newgrad, newlogp,
384 nvalid, criterion, prob_sum, n_considered);
386 std::vector<double> dummy1, dummy2, dummy3;
387 std::vector<double> newx2;
388 std::vector<double> newgrad2;
395 build_tree(xminus, mminus, gradminus, u, direction, depth-1, H0,
396 xminus, mminus, gradminus, dummy1, dummy2, dummy3,
397 newx2, newgrad2, newlogp2, nvalid2, criterion2,
398 prob_sum2, n_considered2);
400 build_tree(xplus, mplus, gradplus, u, direction, depth-1, H0,
401 dummy1, dummy2, dummy3, xplus, mplus, gradplus,
402 newx2, newgrad2, newlogp2, nvalid2, criterion2,
403 prob_sum2, n_considered2);
406 <
float(nvalid2) /
float(nvalid+nvalid2))){
411 n_considered += n_considered2;
412 prob_sum += prob_sum2;
413 criterion &= criterion2;
416 criterion &= compute_criterion(xplus, xminus, mplus, mminus, _step_sizes);